aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile2
-rw-r--r--lib/asn1/c_src/Makefile7
-rw-r--r--lib/crypto/Makefile4
-rw-r--r--lib/crypto/c_src/Makefile.in7
-rw-r--r--lib/crypto/c_src/crypto.c132
-rw-r--r--lib/crypto/test/crypto_SUITE.erl6
-rw-r--r--lib/dialyzer/src/dialyzer_contracts.erl2
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/para/myqueue.erl17
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/para/myqueue_params.erl15
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/keydel.erl29
-rw-r--r--lib/diameter/doc/src/diameter.xml12
-rw-r--r--lib/diameter/doc/src/notes.xml63
-rw-r--r--lib/diameter/include/diameter_gen.hrl56
-rw-r--r--lib/diameter/src/base/diameter_codec.erl21
-rw-r--r--lib/diameter/src/base/diameter_config.erl5
-rw-r--r--lib/diameter/src/base/diameter_lib.erl62
-rw-r--r--lib/diameter/src/base/diameter_peer.erl5
-rw-r--r--lib/diameter/src/base/diameter_peer_fsm.erl7
-rw-r--r--lib/diameter/src/base/diameter_reg.erl5
-rw-r--r--lib/diameter/src/base/diameter_service.erl9
-rw-r--r--lib/diameter/src/base/diameter_stats.erl18
-rw-r--r--lib/diameter/src/base/diameter_sync.erl5
-rw-r--r--lib/diameter/src/base/diameter_watchdog.erl51
-rw-r--r--lib/diameter/src/diameter.appup.src36
-rw-r--r--lib/diameter/src/info/diameter_info.erl7
-rw-r--r--lib/diameter/src/transport/diameter_sctp.erl3
-rw-r--r--lib/diameter/test/diameter_examples_SUITE.erl2
-rw-r--r--lib/diameter/test/diameter_gen_sctp_SUITE.erl8
-rw-r--r--lib/diameter/test/diameter_relay_SUITE.erl44
-rw-r--r--lib/diameter/test/diameter_stats_SUITE.erl6
-rw-r--r--lib/diameter/test/diameter_transport_SUITE.erl5
-rw-r--r--lib/diameter/test/diameter_util.erl16
-rw-r--r--lib/diameter/test/diameter_watchdog_SUITE.erl7
-rw-r--r--lib/diameter/vsn.mk2
-rw-r--r--lib/erl_docgen/priv/css/otp_doc.css4
-rw-r--r--lib/erl_interface/src/Makefile.in63
-rw-r--r--lib/hipe/cerl/erl_bif_types.erl11
-rw-r--r--lib/hipe/cerl/erl_types.erl26
-rw-r--r--lib/inets/src/http_client/httpc_handler.erl10
-rw-r--r--lib/kernel/doc/src/notes.xml3
-rw-r--r--lib/kernel/doc/src/ref_man.xml.src68
-rw-r--r--lib/kernel/src/inet_config.erl3
-rw-r--r--lib/kernel/src/os.erl2
-rw-r--r--lib/kernel/test/erl_prim_loader_SUITE.erl71
-rw-r--r--lib/kernel/test/file_SUITE.erl22
-rw-r--r--lib/kernel/test/gen_tcp_misc_SUITE.erl16
-rw-r--r--lib/kernel/test/prim_file_SUITE.erl12
-rw-r--r--lib/kernel/test/standard_error_SUITE.erl31
-rw-r--r--lib/odbc/doc/src/odbc.xml12
-rw-r--r--lib/odbc/src/odbc.erl9
-rw-r--r--lib/odbc/test/odbc_connect_SUITE.erl30
-rw-r--r--lib/ose/Makefile37
-rw-r--r--lib/ose/doc/html/.gitignore0
-rw-r--r--lib/ose/doc/man3/.gitignore0
-rw-r--r--lib/ose/doc/man6/.gitignore0
-rw-r--r--lib/ose/doc/pdf/.gitignore0
-rw-r--r--lib/ose/doc/src/.gitignore1
-rw-r--r--lib/ose/doc/src/Makefile133
-rw-r--r--lib/ose/doc/src/book.xml49
-rw-r--r--lib/ose/doc/src/notes.xml109
-rw-r--r--lib/ose/doc/src/ose_app.xml38
-rw-r--r--lib/ose/doc/src/ose_erl_driver.xml111
-rw-r--r--lib/ose/doc/src/ose_intro.xml154
-rw-r--r--lib/ose/doc/src/ose_signals_chapter.xml240
-rw-r--r--lib/ose/doc/src/part.xml39
-rw-r--r--lib/ose/doc/src/ref_man.xml40
-rw-r--r--lib/ose/ebin/.gitignore0
-rw-r--r--lib/ose/include/.gitignore0
-rw-r--r--lib/ose/info2
-rw-r--r--lib/ose/src/Makefile107
-rw-r--r--lib/ose/src/ose.app.src28
-rw-r--r--lib/ose/src/ose.appup.src23
-rw-r--r--lib/ose/src/ose.erl453
-rw-r--r--lib/ose/test/Makefile67
-rw-r--r--lib/ose/test/ose.cover2
-rw-r--r--lib/ose/test/ose.spec1
-rw-r--r--lib/ose/test/ose_SUITE.erl766
-rw-r--r--lib/ose/vsn.mk1
-rw-r--r--lib/public_key/doc/src/public_key.xml11
-rw-r--r--lib/runtime_tools/c_src/Makefile.in7
-rw-r--r--lib/runtime_tools/c_src/trace_file_drv.c24
-rw-r--r--lib/runtime_tools/doc/src/notes.xml17
-rw-r--r--lib/runtime_tools/vsn.mk2
-rw-r--r--lib/ssh/doc/src/ssh.xml18
-rw-r--r--lib/ssh/src/Makefile1
-rw-r--r--lib/ssh/src/ssh.app.src1
-rw-r--r--lib/ssh/src/ssh.erl26
-rw-r--r--lib/ssh/src/ssh_connection_handler.erl42
-rw-r--r--lib/ssh/src/ssh_math.erl42
-rw-r--r--lib/ssh/src/ssh_message.erl17
-rw-r--r--lib/ssh/src/ssh_transport.erl376
-rw-r--r--lib/ssh/src/ssh_transport.hrl61
-rw-r--r--lib/ssh/test/ssh_basic_SUITE.erl132
-rw-r--r--lib/ssh/test/ssh_connection_SUITE.erl14
-rw-r--r--lib/ssh/test/ssh_protocol_SUITE.erl102
-rw-r--r--lib/ssh/test/ssh_protocol_SUITE_data/dh_group_test3
-rw-r--r--lib/ssh/test/ssh_sftp_SUITE.erl189
-rw-r--r--lib/ssh/test/ssh_sftp_SUITE_data/sftp_tar_test_data_高兴/f3.txt1
-rw-r--r--lib/ssh/test/ssh_sftp_SUITE_data/sftp_tar_test_data_高兴/g四.txt1
-rw-r--r--lib/ssh/test/ssh_sftpd_SUITE.erl14
-rw-r--r--lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl6
-rw-r--r--lib/ssh/test/ssh_test_lib.erl22
-rw-r--r--lib/ssh/test/ssh_to_openssh_SUITE.erl152
-rw-r--r--lib/ssh/test/ssh_trpt_test_lib.erl129
-rw-r--r--lib/ssh/test/ssh_upgrade_SUITE.erl10
-rw-r--r--lib/ssl/doc/src/ssl.xml8
-rw-r--r--lib/stdlib/doc/src/ets.xml2
-rw-r--r--lib/stdlib/src/qlc_pt.erl8
-rw-r--r--lib/stdlib/src/slave.erl23
-rw-r--r--lib/stdlib/test/filename_SUITE.erl35
-rw-r--r--lib/stdlib/test/qlc_SUITE.erl15
-rw-r--r--lib/tools/c_src/Makefile.in8
-rw-r--r--lib/tools/doc/src/make.xml2
-rw-r--r--lib/wx/api_gen/gen_util.erl4
-rw-r--r--lib/wx/api_gen/wx_extra/wxEvtHandler.c_src2
-rw-r--r--lib/wx/api_gen/wx_extra/wxEvtHandler.erl2
-rw-r--r--lib/wx/api_gen/wx_gen.erl10
-rw-r--r--lib/wx/api_gen/wx_gen_cpp.erl18
-rw-r--r--lib/wx/api_gen/wxapi.conf38
-rw-r--r--lib/wx/c_src/gen/wxe_events.cpp8
-rw-r--r--lib/wx/c_src/gen/wxe_init.cpp468
-rw-r--r--lib/wx/c_src/wxe_impl.cpp42
-rw-r--r--lib/wx/c_src/wxe_impl.h5
-rw-r--r--lib/wx/include/wx.hrl474
-rw-r--r--lib/wx/src/gen/wxEvtHandler.erl2
-rw-r--r--lib/wx/src/gen/wxMouseCaptureLostEvent.erl65
-rw-r--r--lib/wx/src/wxe_server.erl35
-rw-r--r--lib/wx/test/wx_class_SUITE.erl36
-rw-r--r--lib/wx/test/wx_event_SUITE.erl11
129 files changed, 2466 insertions, 3745 deletions
diff --git a/lib/Makefile b/lib/Makefile
index 34c2fe9a9e..64143a39e0 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -36,7 +36,7 @@ ALL_ERLANG_APPLICATIONS = xmerl edoc erl_docgen snmp otp_mibs erl_interface \
public_key ssl observer odbc diameter \
cosTransactions cosEvent cosTime cosNotification \
cosProperty cosFileTransfer cosEventDomain et megaco webtool \
- eunit ssh typer percept eldap dialyzer hipe ose
+ eunit ssh typer percept eldap dialyzer hipe
ifdef BUILD_ALL
ERLANG_APPLICATIONS += $(ALL_ERLANG_APPLICATIONS)
diff --git a/lib/asn1/c_src/Makefile b/lib/asn1/c_src/Makefile
index 2b72e1a214..e0d4f09a70 100644
--- a/lib/asn1/c_src/Makefile
+++ b/lib/asn1/c_src/Makefile
@@ -97,12 +97,7 @@ endif
_create_dirs := $(shell mkdir -p $(OBJDIR) $(LIBDIR))
-ifneq ($(findstring ose,$(TARGET)),ose)
opt: $(NIF_SHARED_OBJ_FILE)
-else
-# Do not build dynamic files on OSE
-opt:
-endif
debug: opt
@@ -140,9 +135,7 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
$(INSTALL_DIR) "$(RELSYSDIR)/priv/lib"
-ifneq ($(findstring ose,$(TARGET)),ose)
$(INSTALL_PROGRAM) $(NIF_SHARED_OBJ_FILE) "$(RELSYSDIR)/priv/lib"
-endif
$(INSTALL_DIR) "$(RELSYSDIR)/c_src"
$(INSTALL_DATA) *.c "$(RELSYSDIR)/c_src"
diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile
index 24db75bf91..fbf108c410 100644
--- a/lib/crypto/Makefile
+++ b/lib/crypto/Makefile
@@ -24,11 +24,7 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
# Macros
#
-ifneq ($(findstring ose,$(TARGET)),ose)
SUB_DIRECTORIES = src c_src doc/src
-else
-SUB_DIRECTORIES = src doc/src
-endif
static_lib: SUB_DIRECTORIES = c_src
include vsn.mk
diff --git a/lib/crypto/c_src/Makefile.in b/lib/crypto/c_src/Makefile.in
index e66c0ca916..e7f750b60a 100644
--- a/lib/crypto/c_src/Makefile.in
+++ b/lib/crypto/c_src/Makefile.in
@@ -127,12 +127,7 @@ ALL_STATIC_CFLAGS = $(DED_STATIC_CFLAGS) $(INCLUDES)
_create_dirs := $(shell mkdir -p $(OBJDIR) $(LIBDIR))
-ifneq ($(findstring ose,$(TARGET)),ose)
debug opt valgrind: $(NIF_LIB) $(CALLBACK_LIB)
-else
-# Do not build dynamic files on OSE
-debug opt valgrind:
-endif
static_lib: $(NIF_ARCHIVE)
@@ -203,14 +198,12 @@ release_spec: opt
$(INSTALL_DIR) "$(RELSYSDIR)/priv/obj"
$(INSTALL_DIR) "$(RELSYSDIR)/priv/lib"
$(INSTALL_DATA) $(NIF_MAKEFILE) "$(RELSYSDIR)/priv/obj"
-ifneq ($(findstring ose,$(TARGET)),ose)
$(INSTALL_PROGRAM) $(CRYPTO_OBJS) "$(RELSYSDIR)/priv/obj"
$(INSTALL_PROGRAM) $(NIF_LIB) "$(RELSYSDIR)/priv/lib"
ifeq ($(DYNAMIC_CRYPTO_LIB),yes)
$(INSTALL_PROGRAM) $(CALLBACK_OBJS) "$(RELSYSDIR)/priv/obj"
$(INSTALL_PROGRAM) $(CALLBACK_LIB) "$(RELSYSDIR)/priv/lib"
endif
-endif
release_docs_spec:
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index 9de8dc74c2..e9cac30c9c 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -507,47 +507,6 @@ static void hmac_context_dtor(ErlNifEnv* env, struct hmac_context*);
#define PRINTF_ERR1(FMT,A1)
#define PRINTF_ERR2(FMT,A1,A2)
-#ifdef __OSE__
-
-/* For crypto on OSE we have to initialize the crypto library on each
- process that uses it. So since we do not know which scheduler is going
- to execute the nif we have to check before each nif call that we have
- initialized crypto in that process. */
-
-#include "ose.h"
-#include "openssl/osessl.h"
-
-static ErlNifTSDKey crypto_init_key;
-static int check_ose_crypto(void);
-static int init_ose_crypto(void);
-
-static int check_ose_crypto() {
- int key = (int)enif_tsd_get(crypto_init_key);
- if (!key) {
- if (!CRYPTO_OSE5_init()) {
- PRINTF_ERR0("CRYPTO: Call to CRYPTO_OSE5_init failed");
- return 0;
- }
- enif_tsd_set(crypto_init_key,1);
- }
- return 1;
-}
-
-static int init_ose_crypto() {
- /* Crypto nif upgrade does not work on OSE so no need to
- destroy this key */
- enif_tsd_key_create("crypto_init_key", &crypto_init_key);
- return check_ose_crypto();
-}
-
-#define INIT_OSE_CRYPTO() init_ose_crypto()
-#define CHECK_OSE_CRYPTO() check_ose_crypto()
-#else
-#define INIT_OSE_CRYPTO() 1
-#define CHECK_OSE_CRYPTO()
-#endif
-
-
static int verify_lib_version(void)
{
const unsigned long libv = SSLeay();
@@ -609,9 +568,6 @@ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info)
ErlNifBinary lib_bin;
char lib_buf[1000];
- if (!INIT_OSE_CRYPTO())
- return 0;
-
if (!verify_lib_version())
return 0;
@@ -853,7 +809,6 @@ static ERL_NIF_TERM md5(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Data) */
ErlNifBinary ibin;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
return enif_make_badarg(env);
}
@@ -865,7 +820,6 @@ static ERL_NIF_TERM md5(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
static ERL_NIF_TERM md5_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* () */
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
MD5_Init((MD5_CTX *) enif_make_new_binary(env, MD5_CTX_LEN, &ret));
return ret;
}
@@ -874,7 +828,6 @@ static ERL_NIF_TERM md5_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
MD5_CTX* new_ctx;
ErlNifBinary ctx_bin, data_bin;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_binary(env, argv[0], &ctx_bin)
|| ctx_bin.size != MD5_CTX_LEN
|| !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
@@ -891,7 +844,6 @@ static ERL_NIF_TERM md5_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
ErlNifBinary ctx_bin;
MD5_CTX ctx_clone;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != MD5_CTX_LEN) {
return enif_make_badarg(env);
}
@@ -904,7 +856,6 @@ static ERL_NIF_TERM ripemd160(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
{/* (Data) */
ErlNifBinary ibin;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
return enif_make_badarg(env);
}
@@ -916,7 +867,6 @@ static ERL_NIF_TERM ripemd160(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
static ERL_NIF_TERM ripemd160_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* () */
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
RIPEMD160_Init((RIPEMD160_CTX *) enif_make_new_binary(env, RIPEMD160_CTX_LEN, &ret));
return ret;
}
@@ -925,7 +875,6 @@ static ERL_NIF_TERM ripemd160_update(ErlNifEnv* env, int argc, const ERL_NIF_TER
RIPEMD160_CTX* new_ctx;
ErlNifBinary ctx_bin, data_bin;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_binary(env, argv[0], &ctx_bin)
|| ctx_bin.size != RIPEMD160_CTX_LEN
|| !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
@@ -942,7 +891,6 @@ static ERL_NIF_TERM ripemd160_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM
ErlNifBinary ctx_bin;
RIPEMD160_CTX ctx_clone;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != RIPEMD160_CTX_LEN) {
return enif_make_badarg(env);
}
@@ -956,7 +904,6 @@ static ERL_NIF_TERM sha(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Data) */
ErlNifBinary ibin;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
return enif_make_badarg(env);
}
@@ -968,7 +915,6 @@ static ERL_NIF_TERM sha(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
static ERL_NIF_TERM sha_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* () */
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
SHA1_Init((SHA_CTX *) enif_make_new_binary(env, SHA_CTX_LEN, &ret));
return ret;
}
@@ -977,7 +923,6 @@ static ERL_NIF_TERM sha_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
SHA_CTX* new_ctx;
ErlNifBinary ctx_bin, data_bin;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != SHA_CTX_LEN
|| !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
return enif_make_badarg(env);
@@ -993,7 +938,6 @@ static ERL_NIF_TERM sha_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
ErlNifBinary ctx_bin;
SHA_CTX ctx_clone;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != SHA_CTX_LEN) {
return enif_make_badarg(env);
}
@@ -1007,7 +951,6 @@ static ERL_NIF_TERM sha224_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
#ifdef HAVE_SHA224
ErlNifBinary ibin;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
return enif_make_badarg(env);
}
@@ -1023,7 +966,6 @@ static ERL_NIF_TERM sha224_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
{/* () */
#ifdef HAVE_SHA224
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
SHA224_Init((SHA256_CTX *) enif_make_new_binary(env, sizeof(SHA256_CTX), &ret));
return ret;
#else
@@ -1036,7 +978,6 @@ static ERL_NIF_TERM sha224_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE
SHA256_CTX* new_ctx;
ErlNifBinary ctx_bin, data_bin;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA256_CTX)
|| !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
return enif_make_badarg(env);
@@ -1056,7 +997,6 @@ static ERL_NIF_TERM sha224_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER
ErlNifBinary ctx_bin;
SHA256_CTX ctx_clone;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA256_CTX)) {
return enif_make_badarg(env);
}
@@ -1073,7 +1013,6 @@ static ERL_NIF_TERM sha256_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
#ifdef HAVE_SHA256
ErlNifBinary ibin;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
return enif_make_badarg(env);
}
@@ -1089,7 +1028,6 @@ static ERL_NIF_TERM sha256_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
{/* () */
#ifdef HAVE_SHA256
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
SHA256_Init((SHA256_CTX *) enif_make_new_binary(env, sizeof(SHA256_CTX), &ret));
return ret;
#else
@@ -1102,7 +1040,6 @@ static ERL_NIF_TERM sha256_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE
SHA256_CTX* new_ctx;
ErlNifBinary ctx_bin, data_bin;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA256_CTX)
|| !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
return enif_make_badarg(env);
@@ -1122,7 +1059,6 @@ static ERL_NIF_TERM sha256_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER
ErlNifBinary ctx_bin;
SHA256_CTX ctx_clone;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA256_CTX)) {
return enif_make_badarg(env);
}
@@ -1139,7 +1075,6 @@ static ERL_NIF_TERM sha384_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
#ifdef HAVE_SHA384
ErlNifBinary ibin;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
return enif_make_badarg(env);
}
@@ -1155,7 +1090,6 @@ static ERL_NIF_TERM sha384_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
{/* () */
#ifdef HAVE_SHA384
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
SHA384_Init((SHA512_CTX *) enif_make_new_binary(env, sizeof(SHA512_CTX), &ret));
return ret;
#else
@@ -1168,7 +1102,6 @@ static ERL_NIF_TERM sha384_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE
SHA512_CTX* new_ctx;
ErlNifBinary ctx_bin, data_bin;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA512_CTX)
|| !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
return enif_make_badarg(env);
@@ -1188,7 +1121,6 @@ static ERL_NIF_TERM sha384_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER
ErlNifBinary ctx_bin;
SHA512_CTX ctx_clone;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA512_CTX)) {
return enif_make_badarg(env);
}
@@ -1205,7 +1137,6 @@ static ERL_NIF_TERM sha512_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
#ifdef HAVE_SHA512
ErlNifBinary ibin;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
return enif_make_badarg(env);
}
@@ -1233,7 +1164,6 @@ static ERL_NIF_TERM sha512_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE
SHA512_CTX* new_ctx;
ErlNifBinary ctx_bin, data_bin;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA512_CTX)
|| !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
return enif_make_badarg(env);
@@ -1253,7 +1183,6 @@ static ERL_NIF_TERM sha512_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER
ErlNifBinary ctx_bin;
SHA512_CTX ctx_clone;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA512_CTX)) {
return enif_make_badarg(env);
}
@@ -1270,7 +1199,6 @@ static ERL_NIF_TERM md4(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Data) */
ErlNifBinary ibin;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
return enif_make_badarg(env);
}
@@ -1282,7 +1210,6 @@ static ERL_NIF_TERM md4(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
static ERL_NIF_TERM md4_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* () */
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
MD4_Init((MD4_CTX *) enif_make_new_binary(env, MD4_CTX_LEN, &ret));
return ret;
}
@@ -1291,7 +1218,6 @@ static ERL_NIF_TERM md4_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
MD4_CTX* new_ctx;
ErlNifBinary ctx_bin, data_bin;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != MD4_CTX_LEN
|| !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
return enif_make_badarg(env);
@@ -1307,7 +1233,6 @@ static ERL_NIF_TERM md4_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
ErlNifBinary ctx_bin;
MD4_CTX ctx_clone;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != MD4_CTX_LEN) {
return enif_make_badarg(env);
}
@@ -1322,7 +1247,6 @@ static ERL_NIF_TERM md5_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
ErlNifBinary key, data;
unsigned mac_sz;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
|| !enif_inspect_iolist_as_binary(env, argv[1], &data)
|| !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > MD5_LEN) {
@@ -1340,7 +1264,6 @@ static ERL_NIF_TERM sha_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
ErlNifBinary key, data;
unsigned mac_sz;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
|| !enif_inspect_iolist_as_binary(env, argv[1], &data)
|| !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA_LEN) {
@@ -1360,7 +1283,6 @@ static ERL_NIF_TERM sha224_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
ErlNifBinary key, data;
unsigned mac_sz;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
|| !enif_inspect_iolist_as_binary(env, argv[1], &data)
|| !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA224_DIGEST_LENGTH) {
@@ -1383,7 +1305,6 @@ static ERL_NIF_TERM sha256_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
ErlNifBinary key, data;
unsigned mac_sz;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
|| !enif_inspect_iolist_as_binary(env, argv[1], &data)
|| !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA256_DIGEST_LENGTH) {
@@ -1406,7 +1327,6 @@ static ERL_NIF_TERM sha384_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
ErlNifBinary key, data;
unsigned mac_sz;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
|| !enif_inspect_iolist_as_binary(env, argv[1], &data)
|| !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA384_DIGEST_LENGTH) {
@@ -1430,7 +1350,6 @@ static ERL_NIF_TERM sha512_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
ErlNifBinary key, data;
unsigned mac_sz;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
|| !enif_inspect_iolist_as_binary(env, argv[1], &data)
|| !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA512_DIGEST_LENGTH) {
@@ -1462,7 +1381,6 @@ static ERL_NIF_TERM hmac_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
const EVP_MD *md;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (argv[0] == atom_sha) md = EVP_sha1();
#ifdef HAVE_SHA224
@@ -1502,7 +1420,6 @@ static ERL_NIF_TERM hmac_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
ErlNifBinary data;
struct hmac_context* obj;
- CHECK_OSE_CRYPTO();
if (!enif_get_resource(env, argv[0], hmac_context_rtype, (void**)&obj)
|| !enif_inspect_iolist_as_binary(env, argv[1], &data)) {
@@ -1529,7 +1446,6 @@ static ERL_NIF_TERM hmac_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
unsigned int req_len = 0;
unsigned int mac_len;
- CHECK_OSE_CRYPTO();
if (!enif_get_resource(env,argv[0],hmac_context_rtype, (void**)&obj)
|| (argc == 2 && !enif_get_uint(env, argv[1], &req_len))) {
@@ -1564,7 +1480,6 @@ static ERL_NIF_TERM des_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
DES_cblock ivec_clone; /* writable copy */
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 8
|| !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 8
@@ -1587,7 +1502,6 @@ static ERL_NIF_TERM des_cfb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
DES_cblock ivec_clone; /* writable copy */
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 8
|| !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 8
@@ -1607,7 +1521,6 @@ static ERL_NIF_TERM des_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
ErlNifBinary key, text;
DES_key_schedule schedule;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 8 ||
!enif_inspect_iolist_as_binary(env, argv[1], &text) || text.size != 8) {
return enif_make_badarg(env);
@@ -1627,7 +1540,6 @@ static ERL_NIF_TERM des_ede3_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_T
DES_cblock ivec_clone; /* writable copy */
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_iolist_as_binary(env, argv[0], &key1) || key1.size != 8
|| !enif_inspect_iolist_as_binary(env, argv[1], &key2) || key2.size != 8
@@ -1657,7 +1569,6 @@ static ERL_NIF_TERM des_ede3_cfb_crypt_nif(ErlNifEnv* env, int argc, const ERL_N
DES_cblock ivec_clone; /* writable copy */
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_iolist_as_binary(env, argv[0], &key1) || key1.size != 8
|| !enif_inspect_iolist_as_binary(env, argv[1], &key2) || key2.size != 8
@@ -1714,7 +1625,6 @@ static ERL_NIF_TERM aes_cfb_128_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TE
int new_ivlen = 0;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
|| !(key.size == 16 || key.size == 24 || key.size == 32)
@@ -1744,7 +1654,6 @@ static ERL_NIF_TERM aes_ctr_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM
unsigned int num = 0;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
|| AES_set_encrypt_key(key.data, key.size*8, &aes_key) != 0
@@ -1777,7 +1686,6 @@ static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_N
unsigned char * ivec2_buf;
unsigned char * ecount2_buf;
- CHECK_OSE_CRYPTO();
if (!enif_get_tuple(env, argv[0], &state_arity, &state_term)
|| state_arity != 4
@@ -1816,7 +1724,6 @@ static ERL_NIF_TERM aes_gcm_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM
unsigned char *outp;
ERL_NIF_TERM out, out_tag;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
|| AES_set_encrypt_key(key.data, key.size*8, &aes_key) != 0
@@ -1866,7 +1773,6 @@ static ERL_NIF_TERM aes_gcm_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM
unsigned char *outp;
ERL_NIF_TERM out;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
|| AES_set_encrypt_key(key.data, key.size*8, &aes_key) != 0
@@ -1937,7 +1843,6 @@ static ERL_NIF_TERM chacha20_poly1305_encrypt(ErlNifEnv* env, int argc, const ER
unsigned char poly1305_key[32];
poly1305_state poly1305;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 32
|| !enif_inspect_binary(env, argv[1], &iv) || iv.size != CHACHA20_NONCE_LEN
@@ -1991,7 +1896,6 @@ static ERL_NIF_TERM chacha20_poly1305_decrypt(ErlNifEnv* env, int argc, const ER
unsigned char mac[POLY1305_TAG_LEN];
poly1305_state poly1305;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 32
|| !enif_inspect_binary(env, argv[1], &iv) || iv.size != CHACHA20_NONCE_LEN
@@ -2045,7 +1949,6 @@ static ERL_NIF_TERM aes_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
unsigned char* ret_ptr;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
|| (key_bin.size != 16 && key_bin.size != 32)
@@ -2074,7 +1977,6 @@ static ERL_NIF_TERM rand_bytes_1(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
unsigned bytes;
unsigned char* data;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_get_uint(env, argv[0], &bytes)) {
return enif_make_badarg(env);
}
@@ -2088,7 +1990,6 @@ static ERL_NIF_TERM strong_rand_bytes_nif(ErlNifEnv* env, int argc, const ERL_NI
unsigned bytes;
unsigned char* data;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_get_uint(env, argv[0], &bytes)) {
return enif_make_badarg(env);
}
@@ -2106,7 +2007,6 @@ static ERL_NIF_TERM rand_bytes_3(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
unsigned char* data;
unsigned top_mask, bot_mask;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_get_uint(env, argv[0], &bytes)
|| !enif_get_uint(env, argv[1], &top_mask)
|| !enif_get_uint(env, argv[2], &bot_mask)) {
@@ -2130,7 +2030,6 @@ static ERL_NIF_TERM strong_rand_mpint_nif(ErlNifEnv* env, int argc, const ERL_NI
unsigned dlen;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_get_uint(env, argv[0], &bits)
|| !enif_get_int(env, argv[1], &top)
@@ -2200,7 +2099,6 @@ static ERL_NIF_TERM rand_uniform_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER
unsigned dlen;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!get_bn_from_mpint(env, argv[0], &bn_from)
|| !get_bn_from_mpint(env, argv[1], &bn_rand)) {
@@ -2233,7 +2131,6 @@ static ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
unsigned extra_byte;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!get_bn_from_bin(env, argv[0], &bn_base)
|| !get_bn_from_bin(env, argv[1], &bn_exponent)
@@ -2277,7 +2174,6 @@ static ERL_NIF_TERM dss_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
DSA *dsa;
int i;
- CHECK_OSE_CRYPTO();
if (argv[0] == atom_sha) {
if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) {
@@ -2446,7 +2342,6 @@ static ERL_NIF_TERM rsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
struct digest_type_t* digp = NULL;
unsigned char* digest = NULL;
- CHECK_OSE_CRYPTO();
digp = get_digest_type(type);
if (!digp) {
@@ -2508,7 +2403,6 @@ static ERL_NIF_TERM aes_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
unsigned char* ret_ptr;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
|| (key_bin.size != 16 && key_bin.size != 32)
@@ -2569,7 +2463,6 @@ static ERL_NIF_TERM aes_ige_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE
unsigned char* ret_ptr;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
|| (key_bin.size != 16 && key_bin.size != 32)
@@ -2607,7 +2500,6 @@ static ERL_NIF_TERM do_exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
int i;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_iolist_as_binary(env,argv[0], &d1)
|| !enif_inspect_iolist_as_binary(env,argv[1], &d2)
@@ -2629,7 +2521,6 @@ static ERL_NIF_TERM rc4_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
RC4_KEY rc4_key;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_iolist_as_binary(env,argv[0], &key)
|| !enif_inspect_iolist_as_binary(env,argv[1], &data)) {
@@ -2647,7 +2538,6 @@ static ERL_NIF_TERM rc4_set_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
ErlNifBinary key;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_iolist_as_binary(env,argv[0], &key)) {
return enif_make_badarg(env);
@@ -2664,7 +2554,6 @@ static ERL_NIF_TERM rc4_encrypt_with_state(ErlNifEnv* env, int argc, const ERL_N
RC4_KEY* rc4_key;
ERL_NIF_TERM new_state, new_data;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_iolist_as_binary(env,argv[0], &state)
|| state.size != sizeof(RC4_KEY)
@@ -2686,7 +2575,6 @@ static ERL_NIF_TERM rc2_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
ERL_NIF_TERM ret;
unsigned char iv_copy[8];
- CHECK_OSE_CRYPTO();
if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
|| (key_bin.size != 5 && key_bin.size != 8 && key_bin.size != 16)
@@ -2748,7 +2636,6 @@ static ERL_NIF_TERM rsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
struct digest_type_t *digp;
unsigned char* digest;
- CHECK_OSE_CRYPTO();
digp = get_digest_type(argv[0]);
if (!digp) {
@@ -2816,7 +2703,6 @@ static ERL_NIF_TERM dss_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
DSA* dsa;
int i;
- CHECK_OSE_CRYPTO();
if (argv[0] == atom_sha) {
if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) {
@@ -2903,7 +2789,6 @@ static ERL_NIF_TERM rsa_public_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TER
int padding, i;
RSA* rsa;
- CHECK_OSE_CRYPTO();
rsa = RSA_new();
@@ -2953,7 +2838,6 @@ static ERL_NIF_TERM rsa_private_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TE
int padding, i;
RSA* rsa;
- CHECK_OSE_CRYPTO();
rsa = RSA_new();
@@ -3001,7 +2885,6 @@ static ERL_NIF_TERM dh_generate_parameters_nif(ErlNifEnv* env, int argc, const E
unsigned char *p_ptr, *g_ptr;
ERL_NIF_TERM ret_p, ret_g;
- CHECK_OSE_CRYPTO();
if (!enif_get_int(env, argv[0], &prime_len)
|| !enif_get_int(env, argv[1], &generator)) {
@@ -3030,7 +2913,6 @@ static ERL_NIF_TERM dh_check(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
int i;
ERL_NIF_TERM ret, head, tail;
- CHECK_OSE_CRYPTO();
dh_params = DH_new();
@@ -3066,7 +2948,6 @@ static ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_
ERL_NIF_TERM ret, ret_pub, ret_prv, head, tail;
int mpint; /* 0 or 4 */
- CHECK_OSE_CRYPTO();
dh_params = DH_new();
@@ -3112,7 +2993,6 @@ static ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_T
ErlNifBinary ret_bin;
ERL_NIF_TERM ret, head, tail;
- CHECK_OSE_CRYPTO();
dh_params = DH_new();
@@ -3154,7 +3034,6 @@ static ERL_NIF_TERM srp_value_B_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
unsigned dlen;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!get_bn_from_bin(env, argv[0], &bn_multiplier)
|| !get_bn_from_bin(env, argv[1], &bn_verifier)
@@ -3216,7 +3095,6 @@ static ERL_NIF_TERM srp_user_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_
unsigned dlen;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!get_bn_from_bin(env, argv[0], &bn_a)
|| !get_bn_from_bin(env, argv[1], &bn_u)
@@ -3297,7 +3175,6 @@ static ERL_NIF_TERM srp_host_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_
unsigned dlen;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!get_bn_from_bin(env, argv[0], &bn_verifier)
|| !get_bn_from_bin(env, argv[1], &bn_b)
@@ -3359,7 +3236,6 @@ static ERL_NIF_TERM bf_cfb64_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM
int bf_n = 0; /* blowfish ivec pos */
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
|| !enif_inspect_binary(env, argv[1], &ivec_bin)
@@ -3384,7 +3260,6 @@ static ERL_NIF_TERM bf_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
unsigned char bf_tkey[8]; /* blowfish ivec */
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
|| !enif_inspect_binary(env, argv[1], &ivec_bin)
@@ -3409,7 +3284,6 @@ static ERL_NIF_TERM bf_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
BF_KEY bf_key; /* blowfish key 8 */
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
|| !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)
@@ -3431,7 +3305,6 @@ static ERL_NIF_TERM blowfish_ofb64_encrypt(ErlNifEnv* env, int argc, const ERL_N
int bf_n = 0; /* blowfish ivec pos */
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
|| !enif_inspect_binary(env, argv[1], &ivec_bin)
@@ -3756,7 +3629,6 @@ static ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM
ERL_NIF_TERM priv_key;
ERL_NIF_TERM pub_key = atom_undefined;
- CHECK_OSE_CRYPTO();
if (!get_ec_key(env, argv[0], argv[1], atom_undefined, &key))
goto badarg;
@@ -3799,7 +3671,6 @@ static ERL_NIF_TERM ecdsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
struct digest_type_t *digp;
unsigned char* digest;
- CHECK_OSE_CRYPTO();
digp = get_digest_type(argv[0]);
if (!digp) {
@@ -3868,7 +3739,6 @@ static ERL_NIF_TERM ecdsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER
struct digest_type_t* digp = NULL;
unsigned char* digest = NULL;
- CHECK_OSE_CRYPTO();
digp = get_digest_type(type);
if (!digp) {
@@ -3933,7 +3803,6 @@ static ERL_NIF_TERM ecdh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF
EC_POINT *my_ecpoint;
EC_KEY *other_ecdh = NULL;
- CHECK_OSE_CRYPTO();
if (!get_ec_key(env, argv[1], argv[2], atom_undefined, &key))
return enif_make_badarg(env);
@@ -3978,7 +3847,6 @@ out_err:
static ERL_NIF_TERM rand_seed_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary seed_bin;
- CHECK_OSE_CRYPTO();
if (!enif_inspect_binary(env, argv[0], &seed_bin))
return enif_make_badarg(env);
RAND_seed(seed_bin.data,seed_bin.size);
diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl
index e84f5e1075..0b955c0965 100644
--- a/lib/crypto/test/crypto_SUITE.erl
+++ b/lib/crypto/test/crypto_SUITE.erl
@@ -118,10 +118,10 @@ init_per_suite(Config) ->
_ ->
Config
catch error:low_entropy ->
- %% Make sure we are on OSE, otherwise we want to crash
- {ose,_} = os:type(),
+ %% We are testing on an OS with low entropy in its random
+ %% seed. So we have to seed it with a binary to get started.
- %% This is NOT how you want to seed this, it is just here
+ %% 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(),
diff --git a/lib/dialyzer/src/dialyzer_contracts.erl b/lib/dialyzer/src/dialyzer_contracts.erl
index 0c29d524b5..1079c2e09b 100644
--- a/lib/dialyzer/src/dialyzer_contracts.erl
+++ b/lib/dialyzer/src/dialyzer_contracts.erl
@@ -46,7 +46,7 @@
-type file_contract() :: {file_line(), #contract{}, Extra :: [_]}.
--type plt_contracts() :: [{mfa(), #contract{}}]. % actually, an orddict()
+-type plt_contracts() :: orddict:orddict(mfa(), #contract{}).
%%-----------------------------------------------------------------------
%% Internal record for contracts whose components have not been processed
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/para/myqueue.erl b/lib/dialyzer/test/opaque_SUITE_data/src/para/myqueue.erl
new file mode 100644
index 0000000000..0f76680464
--- /dev/null
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/para/myqueue.erl
@@ -0,0 +1,17 @@
+-module(myqueue).
+
+-export([new/0, in/2]).
+
+-record(myqueue, {queue = queue:new() :: queue:queue({integer(), _})}).
+
+-opaque myqueue(Item) :: #myqueue{queue :: queue:queue({integer(), Item})}.
+
+-export_type([myqueue/1]).
+
+-spec new() -> myqueue(_).
+new() ->
+ #myqueue{queue=queue:new()}.
+
+-spec in(Item, myqueue(Item)) -> myqueue(Item).
+in(Item, #myqueue{queue=Q}) ->
+ #myqueue{queue=queue:in({1, Item}, Q)}.
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/para/myqueue_params.erl b/lib/dialyzer/test/opaque_SUITE_data/src/para/myqueue_params.erl
new file mode 100644
index 0000000000..8d766b7804
--- /dev/null
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/para/myqueue_params.erl
@@ -0,0 +1,15 @@
+-module(myqueue_params).
+
+-export([new/0, in/2]).
+
+-record(myqueue_params, {myqueue = myqueue:new() :: myqueue:myqueue(integer())}).
+
+-type myqueue_params() :: #myqueue_params{myqueue ::
+ myqueue:myqueue(integer())}.
+-spec new() -> myqueue_params().
+new() ->
+ #myqueue_params{myqueue=myqueue:new()}.
+
+-spec in(integer(), myqueue_params()) -> myqueue_params().
+in(Item, #myqueue_params{myqueue=Q} = P) when is_integer(Item) ->
+ P#myqueue_params{myqueue=myqueue:in(Item, Q)}.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/keydel.erl b/lib/dialyzer/test/small_SUITE_data/src/keydel.erl
new file mode 100644
index 0000000000..18a5c0670c
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/keydel.erl
@@ -0,0 +1,29 @@
+-module(keydel).
+
+-export([store/3]).
+
+-record(att, {f}).
+
+-type attachment() :: list().
+
+-opaque att() :: #att{} | attachment().
+
+-spec store(atom(), any(), att()) -> att().
+store(Field, undefined, Att) when is_list(Att) ->
+ lists:keydelete(Field, 1, Att);
+store(Field, Value, Att) when is_list(Att) ->
+ lists:keystore(Field, 1, Att, {Field, Value});
+store(Field, Value, Att) ->
+ store(Field, Value, upgrade(Att)).
+
+
+-spec upgrade(#att{}) -> attachment().
+upgrade(#att{} = Att) ->
+ Map = lists:zip(
+ record_info(fields, att),
+ lists:seq(2, record_info(size, att))
+ ),
+ %% Don't store undefined elements since that is default
+ [{F, element(I, Att)} || {F, I} <- Map, element(I, Att) /= undefined];
+upgrade(Att) ->
+ Att.
diff --git a/lib/diameter/doc/src/diameter.xml b/lib/diameter/doc/src/diameter.xml
index 1e1206aa2d..47247bc2ff 100644
--- a/lib/diameter/doc/src/diameter.xml
+++ b/lib/diameter/doc/src/diameter.xml
@@ -795,14 +795,6 @@ Messages larger than the specified number of bytes are discarded.</p>
Defaults to <c>16777215</c>, the maximum value of the 24-bit Message
Length field in a Diameter Header.</p>
-<warning>
-<p>
-This option should be set to as low a value as is sufficient for the
-Diameter applications and peers in question, since decoding incoming
-messages from a malicious peer can otherwise generate significant
-load.</p>
-</warning>
-
</item>
<tag><c>{restrict_connections, false
@@ -1232,9 +1224,7 @@ is not the length of the message in question, as received over the
transport interface documented in &man_transport;.</p>
<p>
-If <c>exit</c> then a warning report is emitted and the parent of the
-transport process in question exits, which causes the transport
-process itself to exit as described in &man_transport;.
+If <c>exit</c> then the transport process in question exits.
If <c>handle</c> then the message is processed as usual, a resulting
&app_handle_request; or &app_handle_answer; callback (if one takes
place) indicating the <c>5015</c> error (DIAMETER_INVALID_MESSAGE_LENGTH).
diff --git a/lib/diameter/doc/src/notes.xml b/lib/diameter/doc/src/notes.xml
index 299d4093da..c5f0d66f10 100644
--- a/lib/diameter/doc/src/notes.xml
+++ b/lib/diameter/doc/src/notes.xml
@@ -43,6 +43,67 @@ first.</p>
<!-- ===================================================================== -->
+<section><title>diameter 1.11</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Don't report 5005 (DIAMETER_AVP_MISSING) errors
+ unnecessarily.</p>
+ <p>
+ An AVP whose decode failed was reported as missing,
+ despite having been reported with another error as a
+ consequence of the failure.</p>
+ <p>
+ Own Id: OTP-12871</p>
+ </item>
+ <item>
+ <p>
+ Fix relay encode of nested, Grouped AVPs.</p>
+ <p>
+ A fault in OTP-12475 caused encode to fail if the first
+ AVP in a Grouped AVP was itself Grouped.</p>
+ <p>
+ Own Id: OTP-12879 Aux Id: OTP-12475 </p>
+ </item>
+ <item>
+ <p>
+ Improve decode performance.</p>
+ <p>
+ The time required to decode a message increased
+ quadratically with the number of AVPs in the worst case,
+ leading to extremely long execution times.</p>
+ <p>
+ Own Id: OTP-12891</p>
+ </item>
+ <item>
+ <p>
+ Match acceptable peer addresses case insensitively.</p>
+ <p>
+ Regular expressions passed in an 'accept' tuple to
+ diameter_tcp or diameter_sctp inappropriately matched
+ case.</p>
+ <p>
+ Own Id: OTP-12902</p>
+ </item>
+ <item>
+ <p>
+ Improve watchdog and statistics performance.</p>
+ <p>
+ Inefficient use of timers contributed to poor performance
+ at high load, as did ordering of the table statistics are
+ written to.</p>
+ <p>
+ Own Id: OTP-12912</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<!-- ===================================================================== -->
+
<section><title>diameter 1.10</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -134,7 +195,7 @@ first.</p>
<item>
<p>
Change license text from Erlang Public License to Apache
- Public License v2</p>
+ Public License v2.</p>
<p>
Own Id: OTP-12845</p>
</item>
diff --git a/lib/diameter/include/diameter_gen.hrl b/lib/diameter/include/diameter_gen.hrl
index a43ab4edb2..5624ee6626 100644
--- a/lib/diameter/include/diameter_gen.hrl
+++ b/lib/diameter/include/diameter_gen.hrl
@@ -186,9 +186,10 @@ decode_avps(Name, Recs) ->
= lists:foldl(fun(T,A) -> decode(Name, T, A) end,
{[], {newrec(Name), []}},
Recs),
- {Rec, Avps, Failed ++ missing(Rec, Name)}.
-%% Append 5005 errors so that a 5014 for the same AVP will take
-%% precedence in a Result-Code/Failed-AVP setting.
+ {Rec, Avps, Failed ++ missing(Rec, Name, Failed)}.
+%% Append 5005 errors so that errors are reported in the order
+%% encountered. Failed-AVP should typically contain the first
+%% encountered error accordg to the RFC.
newrec(Name) ->
'#new-'(name2rec(Name)).
@@ -201,20 +202,36 @@ newrec(Name) ->
%% 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.
-
-missing(Rec, Name) ->
- [{5005, empty_avp(F)} || F <- '#info-'(element(1, Rec), fields),
- A <- [avp_arity(Name, F)],
- false <- [have_arity(A, '#get-'(F, Rec))]].
+%% should be of correct minimum length and contain zeros.
+
+missing(Rec, Name, Failed) ->
+ Avps = lists:foldl(fun({_, #diameter_avp{code = C, vendor_id = V}}, A) ->
+ sets:add_element({C,V}, A)
+ end,
+ sets:new(),
+ Failed),
+ [{5005, A} || F <- '#info-'(element(1, Rec), fields),
+ not has_arity(avp_arity(Name, F), '#get-'(F, Rec)),
+ #diameter_avp{code = C, vendor_id = V}
+ = A <- [empty_avp(F)],
+ not sets:is_element({C,V}, Avps)].
%% Maximum arities have already been checked in building the record.
-have_arity({Min, _}, L) ->
- Min =< length(L);
-have_arity(N, V) ->
+has_arity({Min, _}, L) ->
+ has_prefix(Min, L);
+has_arity(N, V) ->
N /= 1 orelse V /= undefined.
+%% 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, tl(L)).
+
%% empty_avp/1
empty_avp(Name) ->
@@ -608,14 +625,17 @@ pack(undefined, 1, FieldName, Avp, Acc) ->
%% AVP MUST be included and contain a copy of the first instance of
%% the offending AVP that exceeded the maximum number of occurrences
%%
+
pack(_, 1, _, Avp, {Rec, Failed}) ->
{Rec, [{5009, Avp} | Failed]};
-pack(L, {_, Max}, _, Avp, {Rec, Failed})
- when length(L) == Max ->
- {Rec, [{5009, Avp} | Failed]};
-
-pack(L, _, FieldName, Avp, Acc) ->
- p(FieldName, fun(V) -> [V|L] end, Avp, Acc).
+pack(L, {_, Max}, FieldName, Avp, Acc) ->
+ case '*' /= Max andalso has_prefix(Max, L) of
+ true ->
+ {Rec, Failed} = Acc,
+ {Rec, [{5009, Avp} | Failed]};
+ false ->
+ p(FieldName, fun(V) -> [V|L] end, Avp, Acc)
+ end.
%% p/4
diff --git a/lib/diameter/src/base/diameter_codec.erl b/lib/diameter/src/base/diameter_codec.erl
index 34276a1674..bcdc5b3005 100644
--- a/lib/diameter/src/base/diameter_codec.erl
+++ b/lib/diameter/src/base/diameter_codec.erl
@@ -657,16 +657,23 @@ split_data(Bin, Len) ->
%% The normal case here is data as an #diameter_avp{} list or an
%% iolist, which are the cases that generated codec modules use. The
-%% other case is as a convenience in the relay case in which the
+%% other cases are a convenience in the relay case in which the
%% dictionary doesn't know about specific AVP's.
-%% Grouped AVP whose components need packing ...
-pack_avp([#diameter_avp{} = A | Avps]) ->
- pack_avp(A#diameter_avp{data = Avps});
-pack_avp(#diameter_avp{data = [#diameter_avp{} | _] = Avps} = A) ->
- pack_avp(A#diameter_avp{data = encode_avps(Avps)});
+%% Decoded Grouped AVP with decoded components: ignore components
+%% since they're already encoded in the Grouped AVP.
+pack_avp([#diameter_avp{} = Grouped | _Components]) ->
+ pack_avp(Grouped);
-%% ... data as a type/value tuple ...
+%% Grouped AVP whose components need packing. It's intentional that
+%% this isn't equivalent to [Grouped | Components]: here the
+%% components need to be encoded before wrapping with the Grouped AVP,
+%% and the list is flat, nesting being accomplished in the data
+%% fields.
+pack_avp(#diameter_avp{data = [#diameter_avp{} | _] = Components} = Grouped) ->
+ pack_avp(Grouped#diameter_avp{data = encode_avps(Components)});
+
+%% Data as a type/value tuple ...
pack_avp(#diameter_avp{data = {Type, Value}} = A)
when is_atom(Type) ->
pack_avp(A#diameter_avp{data = diameter_types:Type(encode, Value)});
diff --git a/lib/diameter/src/base/diameter_config.erl b/lib/diameter/src/base/diameter_config.erl
index 5ae4ff1f46..b7d8345b6c 100644
--- a/lib/diameter/src/base/diameter_config.erl
+++ b/lib/diameter/src/base/diameter_config.erl
@@ -38,8 +38,7 @@
-module(diameter_config).
-behaviour(gen_server).
--compile({no_auto_import, [monitor/2, now/0]}).
--import(diameter_lib, [now/0]).
+-compile({no_auto_import, [monitor/2]}).
-export([start_service/2,
stop_service/1,
@@ -70,7 +69,7 @@
-include("diameter_internal.hrl").
%% Server state.
--record(state, {id = now()}).
+-record(state, {id = diameter_lib:now()}).
%% Registered name of the server.
-define(SERVER, ?MODULE).
diff --git a/lib/diameter/src/base/diameter_lib.erl b/lib/diameter/src/base/diameter_lib.erl
index b5b37dcf62..43b0ca24ab 100644
--- a/lib/diameter/src/base/diameter_lib.erl
+++ b/lib/diameter/src/base/diameter_lib.erl
@@ -103,32 +103,18 @@ fmt(T) ->
%% # now/0
%% ---------------------------------------------------------------------------
--type timestamp() :: {non_neg_integer(), 0..999999, 0..999999}.
--type now() :: integer() %% monotonic time
- | timestamp().
-
-spec now()
- -> now().
-
-%% Use monotonic time if it exists, fall back to erlang:now()
-%% otherwise.
+ -> integer().
now() ->
- try
- erlang:monotonic_time()
- catch
- error: undef -> erlang:now()
- end.
+ erlang:monotonic_time().
%% ---------------------------------------------------------------------------
%% # timestamp/1
%% ---------------------------------------------------------------------------
--spec timestamp(NowT :: now())
- -> timestamp().
-
-timestamp({_,_,_} = T) -> %% erlang:now()
- T;
+-spec timestamp(integer())
+ -> erlang:timestamp().
timestamp(MonoT) -> %% monotonic time
MicroSecs = monotonic_to_microseconds(MonoT + erlang:time_offset()),
@@ -142,30 +128,27 @@ monotonic_to_microseconds(MonoT) ->
%% # now_diff/1
%% ---------------------------------------------------------------------------
--spec now_diff(NowT :: now())
+-spec now_diff(T0 :: integer())
-> {Hours, Mins, Secs, MicroSecs}
when Hours :: non_neg_integer(),
Mins :: 0..59,
Secs :: 0..59,
MicroSecs :: 0..999999.
-%% Return timer:now_diff(now(), NowT) as an {H, M, S, MicroS} tuple
-%% instead of as integer microseconds.
+%% Return time difference as an {H, M, S, MicroS} tuple instead of as
+%% integer microseconds.
-now_diff(Time) ->
- time(micro_diff(Time)).
+now_diff(T0) ->
+ time(micro_diff(T0)).
%% ---------------------------------------------------------------------------
%% # micro_diff/1
%% ---------------------------------------------------------------------------
--spec micro_diff(NowT :: now())
+-spec micro_diff(T0 :: integer())
-> MicroSecs
when MicroSecs :: non_neg_integer().
-micro_diff({_,_,_} = T0) ->
- timer:now_diff(erlang:now(), T0);
-
micro_diff(T0) -> %% monotonic time
monotonic_to_microseconds(erlang:monotonic_time() - T0).
@@ -173,16 +156,12 @@ micro_diff(T0) -> %% monotonic time
%% # micro_diff/2
%% ---------------------------------------------------------------------------
--spec micro_diff(T1 :: now(), T0 :: now())
+-spec micro_diff(T1 :: integer(), T0 :: integer())
-> MicroSecs
when MicroSecs :: non_neg_integer().
-micro_diff(T1, T0)
- when is_integer(T1), is_integer(T0) -> %% monotonic time
- monotonic_to_microseconds(T1 - T0);
-
-micro_diff(T1, T0) -> %% at least one erlang:now()
- timer:now_diff(timestamp(T1), timestamp(T0)).
+micro_diff(T1, T0) -> %% monotonic time
+ monotonic_to_microseconds(T1 - T0).
%% ---------------------------------------------------------------------------
%% # time/1
@@ -190,19 +169,13 @@ micro_diff(T1, T0) -> %% at least one erlang:now()
%% Return an elapsed time as an {H, M, S, MicroS} tuple.
%% ---------------------------------------------------------------------------
--spec time(NowT | Diff)
+-spec time(Diff :: non_neg_integer())
-> {Hours, Mins, Secs, MicroSecs}
- when NowT :: timestamp(),
- Diff :: non_neg_integer(),
- Hours :: non_neg_integer(),
+ when Hours :: non_neg_integer(),
Mins :: 0..59,
Secs :: 0..59,
MicroSecs :: 0..999999.
-time({_,_,_} = NowT) -> %% time of day
- %% 24 hours = 24*60*60*1000000 = 86400000000 microsec
- time(timer:now_diff(NowT, {0,0,0}) rem 86400000000);
-
time(Micro) -> %% elapsed time
Seconds = Micro div 1000000,
H = Seconds div 3600,
@@ -215,7 +188,7 @@ time(Micro) -> %% elapsed time
%% ---------------------------------------------------------------------------
-spec seed()
- -> {timestamp(), {integer(), integer(), integer()}}.
+ -> {erlang:timestamp(), {integer(), integer(), integer()}}.
%% Return an argument for random:seed/1.
@@ -225,9 +198,6 @@ seed() ->
%% seed/1
-seed({_,_,_} = T) ->
- T;
-
seed(T) -> %% monotonic time
{erlang:phash2(node()), T, erlang:unique_integer()}.
diff --git a/lib/diameter/src/base/diameter_peer.erl b/lib/diameter/src/base/diameter_peer.erl
index acec91c43f..2759f17e64 100644
--- a/lib/diameter/src/base/diameter_peer.erl
+++ b/lib/diameter/src/base/diameter_peer.erl
@@ -21,9 +21,6 @@
-module(diameter_peer).
-behaviour(gen_server).
--compile({no_auto_import, [now/0]}).
--import(diameter_lib, [now/0]).
-
%% Interface towards transport modules ...
-export([recv/2,
up/1,
@@ -60,7 +57,7 @@
-define(SERVER, ?MODULE).
%% Server state.
--record(state, {id = now()}).
+-record(state, {id = diameter_lib:now()}).
%% Default transport_module/config.
-define(DEFAULT_TMOD, diameter_tcp).
diff --git a/lib/diameter/src/base/diameter_peer_fsm.erl b/lib/diameter/src/base/diameter_peer_fsm.erl
index f5e04d3eae..2b23183d18 100644
--- a/lib/diameter/src/base/diameter_peer_fsm.erl
+++ b/lib/diameter/src/base/diameter_peer_fsm.erl
@@ -315,7 +315,7 @@ handle_info(T, #state{} = State) ->
?LOG(stop, Reason),
{stop, {shutdown, Reason}, State};
stop ->
- ?LOG(stop, T),
+ ?LOG(stop, truncate(T)),
{stop, {shutdown, T}, State}
catch
exit: {diameter_codec, encode, T} = Reason ->
@@ -348,6 +348,11 @@ code_change(_, State, _) ->
%% ---------------------------------------------------------------------------
%% ---------------------------------------------------------------------------
+truncate({'DOWN' = T, _, process, Pid, _}) ->
+ {T, Pid};
+truncate(T) ->
+ T.
+
putr(Key, Val) ->
put({?MODULE, Key}, Val).
diff --git a/lib/diameter/src/base/diameter_reg.erl b/lib/diameter/src/base/diameter_reg.erl
index ce29baae45..7f198080ba 100644
--- a/lib/diameter/src/base/diameter_reg.erl
+++ b/lib/diameter/src/base/diameter_reg.erl
@@ -25,8 +25,7 @@
-module(diameter_reg).
-behaviour(gen_server).
--compile({no_auto_import, [monitor/2, now/0]}).
--import(diameter_lib, [now/0]).
+-compile({no_auto_import, [monitor/2]}).
-export([add/1,
add_new/1,
@@ -68,7 +67,7 @@
%% Table entry containing the Term -> Pid mapping.
-define(MAPPING(Term, Pid), {Term, Pid}).
--record(state, {id = now(),
+-record(state, {id = diameter_lib:now(),
q = []}). %% [{From, Pat}]
%% ===========================================================================
diff --git a/lib/diameter/src/base/diameter_service.erl b/lib/diameter/src/base/diameter_service.erl
index 5cb7fa5abe..e47b975768 100644
--- a/lib/diameter/src/base/diameter_service.erl
+++ b/lib/diameter/src/base/diameter_service.erl
@@ -25,9 +25,6 @@
-module(diameter_service).
-behaviour(gen_server).
--compile({no_auto_import, [now/0]}).
--import(diameter_lib, [now/0]).
-
%% towards diameter_service_sup
-export([start_link/1]).
@@ -115,7 +112,7 @@
%% to determine whether or not we need to call the process for a
%% pick_peer callback in the statefull case.
-record(state,
- {id = now(),
+ {id = diameter_lib:now(),
service_name :: diameter:service_name(), %% key in ?STATE_TABLE
service :: #diameter_service{},
watchdogT = ets_new(watchdogs) %% #watchdog{} at start
@@ -144,7 +141,7 @@
ref :: match(reference()), %% key into diameter_config
options :: match([diameter:transport_opt()]),%% from start_transport
state = ?WD_INITIAL :: match(wd_state()),
- started = now(), %% at process start
+ started = diameter_lib:now(),%% at process start
peer = false :: match(boolean() | pid())}).
%% true at accepted, pid() at okay/reopen
@@ -154,7 +151,7 @@
{pid :: pid(),
apps :: [{0..16#FFFFFFFF, diameter:app_alias()}], %% {Id, Alias}
caps :: #diameter_caps{},
- started = now(), %% at process start
+ started = diameter_lib:now(), %% at process start
watchdog :: pid()}). %% key into watchdogT
%% ---------------------------------------------------------------------------
diff --git a/lib/diameter/src/base/diameter_stats.erl b/lib/diameter/src/base/diameter_stats.erl
index 83e562e7fe..8c10464e98 100644
--- a/lib/diameter/src/base/diameter_stats.erl
+++ b/lib/diameter/src/base/diameter_stats.erl
@@ -25,9 +25,6 @@
-module(diameter_stats).
-behaviour(gen_server).
--compile({no_auto_import, [now/0]}).
--import(diameter_lib, [now/0]).
-
-export([reg/2, reg/1,
incr/3, incr/1,
read/1,
@@ -61,7 +58,7 @@
-define(SERVER, ?MODULE).
%% Server state.
--record(state, {id = now()}).
+-record(state, {id = diameter_lib:now()}).
-type counter() :: any().
-type ref() :: any().
@@ -143,9 +140,14 @@ read(Refs, B) ->
L.
to_refdict(L) ->
- lists:foldl(fun({{C,R}, N}, D) -> orddict:append(R, {C,N}, D) end,
- orddict:new(),
- L).
+ lists:foldl(fun append/2, orddict:new(), L).
+
+%% Order both references and counters in the returned list.
+append({{Ctr, Ref}, N}, Dict) ->
+ orddict:update(Ref,
+ fun(D) -> orddict:store(Ctr, N, D) end,
+ [{Ctr, N}],
+ Dict).
%% ---------------------------------------------------------------------------
%% # sum(Refs)
@@ -221,7 +223,7 @@ uptime() ->
%% ----------------------------------------------------------
init([]) ->
- ets:new(?TABLE, [named_table, ordered_set, public]),
+ ets:new(?TABLE, [named_table, set, public, {write_concurrency, true}]),
{ok, #state{}}.
%% ----------------------------------------------------------
diff --git a/lib/diameter/src/base/diameter_sync.erl b/lib/diameter/src/base/diameter_sync.erl
index 3309224399..7fb6888e21 100644
--- a/lib/diameter/src/base/diameter_sync.erl
+++ b/lib/diameter/src/base/diameter_sync.erl
@@ -28,9 +28,6 @@
-module(diameter_sync).
-behaviour(gen_server).
--compile({no_auto_import, [now/0]}).
--import(diameter_lib, [now/0]).
-
-export([call/4, call/5,
cast/4, cast/5,
carp/1, carp/2]).
@@ -73,7 +70,7 @@
%% Server state.
-record(state,
- {time = now(),
+ {time = diameter_lib:now(),
pending = 0 :: non_neg_integer(), %% outstanding requests
monitor = new() :: ets:tid(), %% MonitorRef -> {Name, From}
queue = new() :: ets:tid()}). %% Name -> queue of {Pid, Ref}
diff --git a/lib/diameter/src/base/diameter_watchdog.erl b/lib/diameter/src/base/diameter_watchdog.erl
index c6d0a0b6ed..3c0d8f6f6e 100644
--- a/lib/diameter/src/base/diameter_watchdog.erl
+++ b/lib/diameter/src/base/diameter_watchdog.erl
@@ -66,7 +66,9 @@
%% end PCB
parent = self() :: pid(), %% service process
transport :: pid() | undefined, %% peer_fsm process
- tref :: reference(), %% reference for current watchdog timer
+ tref :: reference() %% reference for current watchdog timer
+ | integer() %% monotonic time
+ | undefined,
dictionary :: module(), %% common dictionary
receive_data :: term(),
%% term passed into diameter_service with incoming message
@@ -94,7 +96,7 @@ start({_,_} = Type, T) ->
Ack = make_ref(),
{ok, Pid} = diameter_watchdog_sup:start_child({Ack, Type, self(), T}),
try
- {erlang:monitor(process, Pid), Pid}
+ {monitor(process, Pid), Pid}
after
send(Pid, Ack)
end.
@@ -121,7 +123,7 @@ i({Ack, T, Pid, {RecvData,
#diameter_service{applications = Apps,
capabilities = Caps}
= Svc}}) ->
- erlang:monitor(process, Pid),
+ monitor(process, Pid),
wait(Ack, Pid),
{_, Seed} = diameter_lib:seed(),
random:seed(Seed),
@@ -246,11 +248,16 @@ handle_info(T, #watchdog{} = State) ->
event(T, State, S), %% before 'watchdog'
{noreply, S};
stop ->
- ?LOG(stop, T),
+ ?LOG(stop, truncate(T)),
event(T, State, State#watchdog{status = down}),
{stop, {shutdown, T}, State}
end.
+truncate({'DOWN' = T, _, process, Pid, _}) ->
+ {T, Pid};
+truncate(T) ->
+ T.
+
close({'DOWN', _, process, TPid, {shutdown, Reason}},
#watchdog{transport = TPid,
parent = Pid}) ->
@@ -447,11 +454,12 @@ transition({recv, TPid, Name, Pkt}, #watchdog{transport = TPid} = S) ->
%% Current watchdog has timed out.
transition({timeout, TRef, tw}, #watchdog{tref = TRef} = S) ->
- set_watchdog(timeout(S));
+ set_watchdog(0, timeout(S));
-%% Timer was canceled after message was already sent.
-transition({timeout, _, tw}, #watchdog{}) ->
- ok;
+%% Message has arrived since the timer was started: subtract time
+%% already elapsed from new timer.
+transition({timeout, _, tw}, #watchdog{tref = T0} = S) ->
+ set_watchdog(diameter_lib:micro_diff(T0) div 1000, S);
%% State query.
transition({state, Pid}, #watchdog{status = S}) ->
@@ -527,18 +535,27 @@ role() ->
%% set_watchdog/1
-set_watchdog(#watchdog{tw = TwInit,
- tref = TRef}
- = S) ->
- cancel(TRef),
- S#watchdog{tref = erlang:start_timer(tw(TwInit), self(), tw)};
+%% Timer not yet set.
+set_watchdog(#watchdog{tref = undefined} = S) ->
+ set_watchdog(0, S);
+
+%% Timer already set: start at new one only at expiry.
+set_watchdog(#watchdog{} = S) ->
+ S#watchdog{tref = diameter_lib:now()};
+
set_watchdog(stop = No) ->
No.
-cancel(undefined) ->
- ok;
-cancel(TRef) ->
- erlang:cancel_timer(TRef).
+%% set_watchdog/2
+
+set_watchdog(Ms, #watchdog{tw = TwInit} = S) ->
+ S#watchdog{tref = erlang:start_timer(tw(TwInit, Ms), self(), tw)}.
+
+%% A callback could return anything, so ensure the result isn't
+%% negative. Don't prevent abuse, even though the smallest valid
+%% timeout is 4000.
+tw(TwInit, Ms) ->
+ max(tw(TwInit) - Ms, 0).
tw(T)
when is_integer(T), T >= 6000 ->
diff --git a/lib/diameter/src/diameter.appup.src b/lib/diameter/src/diameter.appup.src
index 86d231179c..788ea790fa 100644
--- a/lib/diameter/src/diameter.appup.src
+++ b/lib/diameter/src/diameter.appup.src
@@ -42,7 +42,23 @@
{"1.8", [{restart_application, diameter}]}, %% 17.4
{"1.9", [{restart_application, diameter}]}, %% 17.5
{"1.9.1", [{restart_application, diameter}]}, %% 17.5.3
- {"1.9.2", [{restart_application, diameter}]} %% 17.5.5
+ {"1.9.2", [{restart_application, diameter}]}, %% 17.5.5
+ {"1.9.2.1", [{restart_application, diameter}]}, %% 17.5.6.3
+ {"1.10", [{load_module, diameter_codec}, %% 18.0
+ {load_module, diameter_peer_fsm},
+ {load_module, diameter_watchdog},
+ {load_module, diameter_stats},
+ {load_module, diameter_config},
+ {load_module, diameter_lib},
+ {load_module, diameter_peer},
+ {load_module, diameter_reg},
+ {load_module, diameter_service},
+ {load_module, diameter_sync},
+ {load_module, diameter_gen_base_rfc6733},
+ {load_module, diameter_gen_acct_rfc6733},
+ {load_module, diameter_gen_base_rfc3588},
+ {load_module, diameter_gen_base_accounting},
+ {load_module, diameter_gen_relay}]}
],
[
{"0.9", [{restart_application, diameter}]},
@@ -66,6 +82,22 @@
{"1.8", [{restart_application, diameter}]},
{"1.9", [{restart_application, diameter}]},
{"1.9.1", [{restart_application, diameter}]},
- {"1.9.2", [{restart_application, diameter}]}
+ {"1.9.2", [{restart_application, diameter}]},
+ {"1.9.2.1", [{restart_application, diameter}]},
+ {"1.10", [{load_module, diameter_gen_relay},
+ {load_module, diameter_gen_base_accounting},
+ {load_module, diameter_gen_base_rfc3588},
+ {load_module, diameter_gen_acct_rfc6733},
+ {load_module, diameter_gen_base_rfc6733},
+ {load_module, diameter_sync},
+ {load_module, diameter_service},
+ {load_module, diameter_reg},
+ {load_module, diameter_peer},
+ {load_module, diameter_lib},
+ {load_module, diameter_config},
+ {load_module, diameter_stats},
+ {load_module, diameter_watchdog},
+ {load_module, diameter_peer_fsm},
+ {load_module, diameter_codec}]}
]
}.
diff --git a/lib/diameter/src/info/diameter_info.erl b/lib/diameter/src/info/diameter_info.erl
index 2e08662a9e..59a3b94ee4 100644
--- a/lib/diameter/src/info/diameter_info.erl
+++ b/lib/diameter/src/info/diameter_info.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2010-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.
@@ -52,8 +52,6 @@
p/1,
p/3]).
--compile({no_auto_import,[max/2]}).
-
-export([collect/2]).
-define(LONG_TIMEOUT, 30000).
@@ -684,9 +682,6 @@ pt(T) ->
recsplit(SFun, Rec) ->
fun(Fs,Vs) -> SFun(element(1, Rec), Fs, Vs) end.
-max(A, B) ->
- if A > B -> A; true -> B end.
-
keyfetch(Key, List) ->
{Key,V} = lists:keyfind(Key, 1, List),
V.
diff --git a/lib/diameter/src/transport/diameter_sctp.erl b/lib/diameter/src/transport/diameter_sctp.erl
index 3e08b78ea1..678dc9b5d6 100644
--- a/lib/diameter/src/transport/diameter_sctp.erl
+++ b/lib/diameter/src/transport/diameter_sctp.erl
@@ -21,9 +21,6 @@
-module(diameter_sctp).
-behaviour(gen_server).
--compile({no_auto_import, [now/0]}).
--import(diameter_lib, [now/0]).
-
%% interface
-export([start/3]).
diff --git a/lib/diameter/test/diameter_examples_SUITE.erl b/lib/diameter/test/diameter_examples_SUITE.erl
index 2c10daec50..e4ed2b227d 100644
--- a/lib/diameter/test/diameter_examples_SUITE.erl
+++ b/lib/diameter/test/diameter_examples_SUITE.erl
@@ -299,7 +299,7 @@ slave(_) ->
T0 = diameter_lib:now(),
{ok, Node} = ct_slave:start(?MODULE, ?TIMEOUTS),
T1 = diameter_lib:now(),
- T2 = rpc:call(Node, erlang, now, []),
+ T2 = rpc:call(Node, diameter_lib, now, []),
{ok, Node} = ct_slave:stop(?MODULE),
now_diff([T0, T1, T2, diameter_lib:now()]).
diff --git a/lib/diameter/test/diameter_gen_sctp_SUITE.erl b/lib/diameter/test/diameter_gen_sctp_SUITE.erl
index c739643dbe..cbd7fc8ec5 100644
--- a/lib/diameter/test/diameter_gen_sctp_SUITE.erl
+++ b/lib/diameter/test/diameter_gen_sctp_SUITE.erl
@@ -300,10 +300,10 @@ connect2(Pid, PortNr, Bin) ->
%% T2 = time after listening process received our message
%% T3 = time after reply is received
- T1 = diameter_util:timestamp(),
+ T1 = diameter_lib:now(),
ok = send(Sock, Id, Bin),
T2 = unmark(recv(Sock, Id)),
- T3 = diameter_util:timestamp(),
+ T3 = diameter_lib:now(),
{diameter_lib:micro_diff(T2, T1), %% Outbound
diameter_lib:micro_diff(T3, T2)}. %% Inbound
@@ -330,13 +330,13 @@ send(Sock, Id, Bin) ->
%% mark/1
mark(Bin) ->
- Info = term_to_binary(diameter_util:timestamp()),
+ Info = term_to_binary(diameter_lib:now()),
<<Info/binary, Bin/binary>>.
%% unmark/1
unmark(Bin) ->
- {_,_,_} = binary_to_term(Bin).
+ binary_to_term(Bin).
%% ===========================================================================
diff --git a/lib/diameter/test/diameter_relay_SUITE.erl b/lib/diameter/test/diameter_relay_SUITE.erl
index fd83c2cd7f..f766f54a80 100644
--- a/lib/diameter/test/diameter_relay_SUITE.erl
+++ b/lib/diameter/test/diameter_relay_SUITE.erl
@@ -334,13 +334,39 @@ realm(Host) ->
call(Server) ->
Realm = realm(Server),
+ %% Include some arbitrary AVPs to exercise encode/decode, that
+ %% are received back in the STA.
+ Avps = [#diameter_avp{code = 111,
+ data = [#diameter_avp{code = 222,
+ data = <<222:24>>},
+ #diameter_avp{code = 333,
+ data = <<333:16>>}]},
+ #diameter_avp{code = 444,
+ data = <<444:24>>},
+ #diameter_avp{code = 555,
+ data = [#diameter_avp{code = 666,
+ data = [#diameter_avp
+ {code = 777,
+ data = <<7>>}]},
+ #diameter_avp{code = 888,
+ data = <<8>>},
+ #diameter_avp{code = 999,
+ data = <<9>>}]}],
+
Req = ['STR', {'Destination-Realm', Realm},
{'Destination-Host', [Server]},
{'Termination-Cause', ?LOGOUT},
- {'Auth-Application-Id', ?APP_ID}],
+ {'Auth-Application-Id', ?APP_ID},
+ {'AVP', Avps}],
+
#diameter_base_STA{'Result-Code' = ?SUCCESS,
'Origin-Host' = Server,
- 'Origin-Realm' = Realm}
+ 'Origin-Realm' = Realm,
+ %% Unknown AVPs can't be decoded as Grouped since
+ %% types aren't known.
+ 'AVP' = [#diameter_avp{code = 111},
+ #diameter_avp{code = 444},
+ #diameter_avp{code = 555}]}
= call(Req, [{filter, realm}]).
call(Req, Opts) ->
@@ -434,9 +460,18 @@ request(_Pkt, #diameter_caps{origin_host = {OH, _}})
request(#diameter_packet{msg = #diameter_base_STR{'Session-Id' = SId,
'Origin-Host' = Host,
'Origin-Realm' = Realm,
- 'Route-Record' = Route}},
+ 'Route-Record' = Route,
+ 'AVP' = Avps}},
#diameter_caps{origin_host = {OH, _},
origin_realm = {OR, _}}) ->
+
+ %% Payloads of unknown AVPs aren't decoded, so we don't know that
+ %% some types here are Grouped.
+ [#diameter_avp{code = 111, vendor_id = undefined},
+ #diameter_avp{code = 444, vendor_id = undefined, data = <<444:24>>},
+ #diameter_avp{code = 555, vendor_id = undefined}]
+ = Avps,
+
%% The request should have the Origin-Host/Realm of the original
%% sender.
R = realm(?CLIENT),
@@ -447,4 +482,5 @@ request(#diameter_packet{msg = #diameter_base_STR{'Session-Id' = SId,
{reply, #diameter_base_STA{'Result-Code' = ?SUCCESS,
'Session-Id' = SId,
'Origin-Host' = OH,
- 'Origin-Realm' = OR}}.
+ 'Origin-Realm' = OR,
+ 'AVP' = Avps}}.
diff --git a/lib/diameter/test/diameter_stats_SUITE.erl b/lib/diameter/test/diameter_stats_SUITE.erl
index 39cb6ae30d..4716082394 100644
--- a/lib/diameter/test/diameter_stats_SUITE.erl
+++ b/lib/diameter/test/diameter_stats_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2010-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.
@@ -96,7 +96,7 @@ read(_) ->
7 = ?stat:incr(C1, Ref, 7),
Self = self(),
[{Ref, [{C1,7}]}, {Self, [{C1,2}, {C2,1}]}]
- = lists:sort(?stat:read([self(), Ref, make_ref()])),
+ = ?stat:read([self(), Ref, make_ref()]),
[] = ?stat:read([]),
[] = ?stat:read([make_ref()]),
?stat:flush([self(), Ref, make_ref()]).
@@ -116,7 +116,7 @@ sum(_) ->
[{Self, [{C1,1}, {C2,2}]}]
= ?stat:sum([self()]),
[{Ref, [{C1,7}]}, {Self, [{C1,1}, {C2,2}]}]
- = lists:sort(?stat:flush([self(), Ref])).
+ = ?stat:flush([self(), Ref]).
flush(_) ->
Ref = make_ref(),
diff --git a/lib/diameter/test/diameter_transport_SUITE.erl b/lib/diameter/test/diameter_transport_SUITE.erl
index 701fe070d0..53d2d6660e 100644
--- a/lib/diameter/test/diameter_transport_SUITE.erl
+++ b/lib/diameter/test/diameter_transport_SUITE.erl
@@ -54,7 +54,7 @@
%% Receive a message.
-define(RECV(Pat, Ret), receive Pat -> Ret end).
--define(RECV(Pat), ?RECV(Pat, diameter_util:timestamp())).
+-define(RECV(Pat), ?RECV(Pat, diameter_lib:now())).
%% Sockets are opened on the loopback address.
-define(ADDR, {127,0,0,1}).
@@ -417,8 +417,7 @@ gen_accept(tcp, LSock) ->
gen_send(sctp, Sock, Bin) ->
{OS, _IS, Id} = getr(assoc),
- {_, _, Us} = diameter_util:timestamp(),
- gen_sctp:send(Sock, Id, Us rem OS, Bin);
+ gen_sctp:send(Sock, Id, erlang:unique_integer([positive]) rem OS, Bin);
gen_send(tcp, Sock, Bin) ->
gen_tcp:send(Sock, Bin).
diff --git a/lib/diameter/test/diameter_util.erl b/lib/diameter/test/diameter_util.erl
index c727d10ddf..52b747e99c 100644
--- a/lib/diameter/test/diameter_util.erl
+++ b/lib/diameter/test/diameter_util.erl
@@ -31,7 +31,6 @@
fold/3,
foldl/3,
scramble/1,
- timestamp/0,
seed/0,
unique_string/0,
have_sctp/0]).
@@ -189,12 +188,6 @@ s(Acc, L) ->
s([T|Acc], H ++ Rest).
%% ---------------------------------------------------------------------------
-%% timestamp/0
-
-timestamp() ->
- diameter_lib:timestamp(diameter_lib:now()).
-
-%% ---------------------------------------------------------------------------
%% seed/0
seed() ->
@@ -205,14 +198,7 @@ seed() ->
%% unique_string/0
unique_string() ->
- try erlang:unique_integer() of
- N ->
- integer_to_list(N)
- catch
- error: undef -> %% OTP < 18
- {M,S,U} = timestamp(),
- tl(lists:append(["-" ++ integer_to_list(N) || N <- [M,S,U]]))
- end.
+ integer_to_list(erlang:unique_integer()).
%% ---------------------------------------------------------------------------
%% have_sctp/0
diff --git a/lib/diameter/test/diameter_watchdog_SUITE.erl b/lib/diameter/test/diameter_watchdog_SUITE.erl
index 016801383b..6d22ddcc18 100644
--- a/lib/diameter/test/diameter_watchdog_SUITE.erl
+++ b/lib/diameter/test/diameter_watchdog_SUITE.erl
@@ -49,7 +49,8 @@
accept/1,
connect/3,
send/2,
- setopts/2]).
+ setopts/2,
+ close/1]).
-include("diameter.hrl").
-include("diameter_ct.hrl").
@@ -421,7 +422,6 @@ suspect(TRef, false, SvcName, N) ->
%% abuse/1
abuse(F) ->
-
[] = run([[abuse, F, T] || T <- [listen, connect]]).
abuse(F, [_,_,_|_] = Args) ->
@@ -546,6 +546,9 @@ setopts(Sock, Opts) ->
send(Sock, Bin) ->
send(getr(config), Sock, Bin).
+close(Sock) ->
+ gen_tcp:close(Sock).
+
%% send/3
%% First outgoing message from a new transport process is CER/CEA.
diff --git a/lib/diameter/vsn.mk b/lib/diameter/vsn.mk
index 1e3135680d..041d21b261 100644
--- a/lib/diameter/vsn.mk
+++ b/lib/diameter/vsn.mk
@@ -17,5 +17,5 @@
# %CopyrightEnd%
APPLICATION = diameter
-DIAMETER_VSN = 1.10
+DIAMETER_VSN = 1.11
APP_VSN = $(APPLICATION)-$(DIAMETER_VSN)$(PRE_VSN)
diff --git a/lib/erl_docgen/priv/css/otp_doc.css b/lib/erl_docgen/priv/css/otp_doc.css
index 0b531db701..347782eb1e 100644
--- a/lib/erl_docgen/priv/css/otp_doc.css
+++ b/lib/erl_docgen/priv/css/otp_doc.css
@@ -37,7 +37,7 @@ a:visited { color: blue; text-decoration: none }
top: 0;
bottom: 0;
left: 0;
- width: 200px;
+ width: 300px;
overflow:auto;
margin: 0;
padding: 1px;
@@ -45,7 +45,7 @@ a:visited { color: blue; text-decoration: none }
}
#content {
- margin-left: 240px; /* set left value to WidthOfFrameDiv */
+ margin-left: 340px; /* set left value to WidthOfFrameDiv */
}
.frontpage
diff --git a/lib/erl_interface/src/Makefile.in b/lib/erl_interface/src/Makefile.in
index 777d709b1e..d6176ec053 100644
--- a/lib/erl_interface/src/Makefile.in
+++ b/lib/erl_interface/src/Makefile.in
@@ -126,11 +126,7 @@ else
WARNFLAGS = @WFLAGS@
endif
-ifneq ($(findstring ose,$(TARGET)),ose)
CFLAGS = @LIB_CFLAGS@ $(WARNFLAGS) $(INCFLAGS) $(TYPE_FLAGS)
-else
-CFLAGS = @CFLAGS@ $(INCFLAGS)
-endif
PROG_CFLAGS = @CFLAGS@ $(WARNFLAGS) $(INCFLAGS) $(TYPE_FLAGS) -Ilegacy
ifeq ($(findstring vxworks,$(TARGET)),vxworks)
@@ -210,12 +206,8 @@ MDD_ERLLIB = $(OBJDIR)/$(LIBPRE)erl_interface_mdd$(LIBEXT)
# Specify targets to build
###########################################################################
-ifneq ($(findstring ose,$(TARGET)),ose)
EXE_TARGETS = \
$(ERL_CALL)
-else
-EXE_TARGETS =
-endif
ifeq ($(USING_VC),yes)
@@ -480,44 +472,6 @@ ERLSOURCES = \
SOURCES = $(EISOURCES) $(ERLSOURCES)
-OSE_EISOURCES = \
- $(DECODESRC) \
- $(ENCODESRC) \
- misc/ei_decode_term.c \
- misc/ei_format.c \
- misc/ei_locking.c \
- misc/ei_malloc.c \
- misc/ei_printterm.c \
- misc/ei_pthreads.c \
- misc/ei_trace.c \
- misc/ei_x_encode.c \
- misc/eimd5.c \
- misc/get_type.c \
- misc/show_msg.c \
- misc/ei_compat.c \
- registry/hash_dohash.c \
- registry/hash_foreach.c \
- registry/hash_freetab.c \
- registry/hash_insert.c \
- registry/hash_isprime.c \
- registry/hash_lookup.c \
- registry/hash_newtab.c \
- registry/hash_remove.c \
- registry/hash_resize.c \
- registry/hash_rlookup.c
-
-OSE_ERLSOURCES = \
- legacy/decode_term.c \
- legacy/encode_term.c \
- legacy/erl_error.c \
- legacy/erl_eterm.c \
- legacy/erl_fix_alloc.c \
- legacy/erl_format.c \
- legacy/erl_malloc.c \
- legacy/erl_marshal.c
-
-OSE_SOURCES = $(OSE_EISOURCES) $(OSE_ERLSOURCES)
-
NEVERUSED = \
whereis.c \
ei_send.c \
@@ -532,13 +486,8 @@ ERLCALL = \
# Note that encode/decode_term.c defines ei functions that is
# located in the erl_interface library, not ei library.
-ifneq ($(findstring ose,$(TARGET)),ose)
ST_EIOBJECTS = $(addprefix $(ST_OBJDIR)/,$(notdir $(EISOURCES:.c=.o)))
ST_ERLOBJECTS = $(addprefix $(ST_OBJDIR)/,$(notdir $(ERLSOURCES:.c=.o)))
-else
-ST_EIOBJECTS = $(addprefix $(ST_OBJDIR)/,$(notdir $(OSE_EISOURCES:.c=.o)))
-ST_ERLOBJECTS = $(addprefix $(ST_OBJDIR)/,$(notdir $(OSE_ERLSOURCES:.c=.o)))
-endif
MT_EIOBJECTS = $(addprefix $(MT_OBJDIR)/,$(notdir $(EISOURCES:.c=.o)))
MT_ERLOBJECTS = $(addprefix $(MT_OBJDIR)/,$(notdir $(ERLSOURCES:.c=.o)))
MD_EIOBJECTS = $(addprefix $(MD_OBJDIR)/,$(notdir $(EISOURCES:.c=.o)))
@@ -587,14 +536,6 @@ $(TARGET)/config.h:
$(V_at)echo "#define HAVE_SOCKLEN_T 1" >> $@
endif
-ifeq ($(findstring ose,$(TARGET)),ose)
-$(TARGET)/config.h:
- $(gen_verbose)
- $(V_at)echo "/* Generated by Makefile */" > $@
- $(V_at)echo "#define HAVE_STRERROR 1" >> $@
- $(V_at)echo "#define HAVE_SOCKLEN_T 1" >> $@
-endif
-
###########################################################################
# Default rules, normal and threaded
###########################################################################
@@ -719,9 +660,6 @@ $(ST_OBJDIR)/erl_start.o: prog/erl_start.c
$(V_CC) $(CFLAGS) -c $< -o $@
else
-ifeq ($(findstring ose,$(TARGET)),ose)
-$(ERL_CALL):
-else
ifdef THR_DEFS
$(ERL_CALL): $(ERLCALL) ../include/ei.h $(MT_EILIB)
$(ld_verbose)$(PURIFY) $(CC) $(PROG_CFLAGS) $(THR_DEFS) $(LDFLAGS) -o $@ $(ERLCALL) \
@@ -733,7 +671,6 @@ $(ERL_CALL): $(ERLCALL) ../include/ei.h $(ST_EILIB)
endif
endif
endif
-endif
###########################################################################
# Fake application targets used to test header files and linking
diff --git a/lib/hipe/cerl/erl_bif_types.erl b/lib/hipe/cerl/erl_bif_types.erl
index 41a6c731c9..dc149c0d8c 100644
--- a/lib/hipe/cerl/erl_bif_types.erl
+++ b/lib/hipe/cerl/erl_bif_types.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2003-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.
@@ -93,7 +93,7 @@
t_list/0,
t_list/1,
t_list_elements/2,
- t_list_termination/1,
+ t_list_termination/2,
t_mfa/0,
t_module/0,
t_nil/0,
@@ -913,8 +913,7 @@ type(erlang, system_info, 1, Xs, Opaques) ->
t_list(t_pid());
['os_type'] ->
t_tuple([t_sup([t_atom('unix'),
- t_atom('win32'),
- t_atom('ose')]),
+ t_atom('win32')]),
t_atom()]);
['os_version'] ->
t_sup(t_tuple([t_non_neg_fixnum(),
@@ -1336,8 +1335,8 @@ type(lists, foldr, 3, Xs, _Opaques) -> type(lists, foldl, 3, Xs); % same
type(lists, keydelete, 3, Xs, Opaques) ->
strict(lists, keydelete, 3, Xs,
fun ([_, _, L]) ->
- Term = t_list_termination(L),
- t_sup(Term, erl_types:lift_list_to_pos_empty(L))
+ Term = t_list_termination(L, Opaques),
+ t_sup(Term, erl_types:lift_list_to_pos_empty(L, Opaques))
end, Opaques);
type(lists, keyfind, 3, Xs, Opaques) ->
strict(lists, keyfind, 3, Xs,
diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl
index 25cf1a7ae1..cc4fee0853 100644
--- a/lib/hipe/cerl/erl_types.erl
+++ b/lib/hipe/cerl/erl_types.erl
@@ -150,7 +150,7 @@
t_list/0,
t_list/1,
t_list_elements/1, t_list_elements/2,
- t_list_termination/1,
+ t_list_termination/1, t_list_termination/2,
t_map/0,
t_map/1,
t_matchstate/0,
@@ -209,7 +209,7 @@
record_field_diffs_to_string/2,
subst_all_vars_to_any/1,
subst_all_remote/2,
- lift_list_to_pos_empty/1,
+ lift_list_to_pos_empty/1, lift_list_to_pos_empty/2,
is_opaque_type/2,
is_erl_type/1,
atom_to_string/1
@@ -1510,6 +1510,11 @@ t_list_elements(Type, Opaques) ->
list_elements(?list(Contents, _, _)) -> Contents;
list_elements(?nil) -> ?none.
+-spec t_list_termination(erl_type(), opaques()) -> erl_type().
+
+t_list_termination(Type, Opaques) ->
+ do_opaque(Type, Opaques, fun t_list_termination/1).
+
-spec t_list_termination(erl_type()) -> erl_type().
t_list_termination(?nil) -> ?nil;
@@ -1585,6 +1590,11 @@ is_maybe_improper_list(_) -> false.
%% %% false = t_is_subtype(t_nil(), Termination),
%% ?list(Content, Termination, ?any).
+-spec lift_list_to_pos_empty(erl_type(), opaques()) -> erl_type().
+
+lift_list_to_pos_empty(Type, Opaques) ->
+ do_opaque(Type, Opaques, fun lift_list_to_pos_empty/1).
+
-spec lift_list_to_pos_empty(erl_type()) -> erl_type().
lift_list_to_pos_empty(?nil) -> ?nil;
@@ -4244,9 +4254,8 @@ type_from_form(Name, Args, TypeNames, ET, M, MR, V, D, L) ->
Rep2 = case t_is_none(Rep1) of
true -> Rep1;
false ->
- Args2 = [subst_all_vars_to_any(ArgType) ||
- ArgType <- ArgTypes],
- t_opaque(Module, Name, Args2, Rep1)
+ ArgTypes2 = subst_all_vars_to_any_list(ArgTypes),
+ t_opaque(Module, Name, ArgTypes2, Rep1)
end,
{Rep2, L2};
error ->
@@ -4298,7 +4307,9 @@ remote_from_form(RemMod, Name, Args, TypeNames, ET, M, MR, V, D, L) ->
NewRep1 = choose_opaque_type(NewRep, Type),
NewRep2 = case t_is_none(NewRep1) of
true -> NewRep1;
- false -> t_opaque(Mod, Name, ArgTypes, NewRep1)
+ false ->
+ ArgTypes2 = subst_all_vars_to_any_list(ArgTypes),
+ t_opaque(Mod, Name, ArgTypes2, NewRep1)
end,
{NewRep2, L2};
error ->
@@ -4313,6 +4324,9 @@ remote_from_form(RemMod, Name, Args, TypeNames, ET, M, MR, V, D, L) ->
end
end.
+subst_all_vars_to_any_list(Types) ->
+ [subst_all_vars_to_any(Type) || Type <- Types].
+
%% Opaque types (both local and remote) are problematic when it comes
%% to the limits (TypeNames, D, and L). The reason is that if any() is
%% substituted for a more specialized subtype of an opaque type, the
diff --git a/lib/inets/src/http_client/httpc_handler.erl b/lib/inets/src/http_client/httpc_handler.erl
index 3f979de078..205348524a 100644
--- a/lib/inets/src/http_client/httpc_handler.erl
+++ b/lib/inets/src/http_client/httpc_handler.erl
@@ -421,6 +421,16 @@ handle_cast({cancel, RequestId},
{profile, ProfileName},
{canceled, Canceled}]),
{noreply, State#state{canceled = [RequestId | Canceled]}};
+handle_cast({cancel, RequestId},
+ #state{profile_name = ProfileName,
+ request = undefined,
+ canceled = Canceled} = State) ->
+ ?hcrv("cancel", [{request_id, RequestId},
+ {curr_req_id, undefined},
+ {profile, ProfileName},
+ {canceled, Canceled}]),
+ {noreply, State};
+
handle_cast(stream_next, #state{session = Session} = State) ->
activate_once(Session),
diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml
index b8db22aba7..e759f214df 100644
--- a/lib/kernel/doc/src/notes.xml
+++ b/lib/kernel/doc/src/notes.xml
@@ -423,8 +423,7 @@
Erlang/OTP has been ported to the realtime operating
system OSE. The port supports both smp and non-smp
emulator. For details around the port and how to started
- see the User's Guide in the <seealso
- marker="ose:ose_intro">ose</seealso> application. </p>
+ see the User's Guide in the ose application. </p>
<p>
Note that not all parts of Erlang/OTP has been ported. </p>
<p>
diff --git a/lib/kernel/doc/src/ref_man.xml.src b/lib/kernel/doc/src/ref_man.xml.src
deleted file mode 100644
index 7eb48a5f1d..0000000000
--- a/lib/kernel/doc/src/ref_man.xml.src
+++ /dev/null
@@ -1,68 +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>1996</year><year>2013</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT 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 Reference Manual</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
- and so on.</p>
- </description>
- <xi:include href="kernel_app.xml"/>
- <xi:include href="application.xml"/>
- <xi:include href="auth.xml"/>
- <xi:include href="code.xml"/>
- <xi:include href="disk_log.xml"/>
- <xi:include href="erl_boot_server.xml"/>
- <xi:include href="erl_ddll.xml"/>
- <xi:include href="erl_prim_loader_stub.xml"/>
- <xi:include href="erlang_stub.xml"/>
- <xi:include href="error_handler.xml"/>
- <xi:include href="error_logger.xml"/>
- <xi:include href="file.xml"/>
- <xi:include href="gen_tcp.xml"/>
- <xi:include href="gen_udp.xml"/>
- <xi:include href="gen_sctp.xml"/>
- <xi:include href="global.xml"/>
- <xi:include href="global_group.xml"/>
- <xi:include href="heart.xml"/>
- <xi:include href="inet.xml"/>
- <xi:include href="inet_res.xml"/>
- <xi:include href="init_stub.xml"/>
- <xi:include href="net_adm.xml"/>
- <xi:include href="net_kernel.xml"/>
- <xi:include href="os.xml"/>
- <xi:include href="pg2.xml"/>
- <xi:include href="rpc.xml"/>
- <xi:include href="seq_trace.xml"/>
- <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/src/inet_config.erl b/lib/kernel/src/inet_config.erl
index 803fae846e..a0d5344f11 100644
--- a/lib/kernel/src/inet_config.erl
+++ b/lib/kernel/src/inet_config.erl
@@ -188,9 +188,6 @@ do_load_resolv({win32,Type}, longnames) ->
win32_load_from_registry(Type),
inet_db:set_lookup([native]);
-do_load_resolv({ose,_}, _) ->
- inet_db:set_lookup([file]);
-
do_load_resolv(_, _) ->
inet_db:set_lookup([native]).
diff --git a/lib/kernel/src/os.erl b/lib/kernel/src/os.erl
index 3330b38d84..ffb899e5ca 100644
--- a/lib/kernel/src/os.erl
+++ b/lib/kernel/src/os.erl
@@ -93,7 +93,7 @@ unsetenv(_) ->
%%% End of BIFs
-spec type() -> {Osfamily, Osname} when
- Osfamily :: unix | win32 | ose,
+ Osfamily :: unix | win32,
Osname :: atom().
type() ->
diff --git a/lib/kernel/test/erl_prim_loader_SUITE.erl b/lib/kernel/test/erl_prim_loader_SUITE.erl
index 0803cf428f..ffcde5e458 100644
--- a/lib/kernel/test/erl_prim_loader_SUITE.erl
+++ b/lib/kernel/test/erl_prim_loader_SUITE.erl
@@ -260,46 +260,41 @@ multiple_slaves(doc) ->
["Start nodes in parallell, all using the 'inet' loading method, ",
"verify that the boot server manages"];
multiple_slaves(Config) when is_list(Config) ->
- case os:type() of
- {ose,_} ->
- {comment, "OSE: multiple nodes not supported"};
- _ ->
- ?line Name = erl_prim_test_multiple_slaves,
- ?line Host = host(),
- ?line Cookie = atom_to_list(erlang:get_cookie()),
- ?line IpStr = ip_str(Host),
- ?line LFlag = get_loader_flag(os:type()),
- ?line Args = LFlag ++ " -hosts " ++ IpStr ++
- " -setcookie " ++ Cookie,
-
- NoOfNodes = 10, % no of slave nodes to be started
-
- NamesAndNodes =
- lists:map(fun(N) ->
- NameN = atom_to_list(Name) ++
- integer_to_list(N),
- NodeN = NameN ++ "@" ++ Host,
- {list_to_atom(NameN),list_to_atom(NodeN)}
- end, lists:seq(1, NoOfNodes)),
-
- ?line Nodes = start_multiple_nodes(NamesAndNodes, Args, []),
-
- %% "queue up" the nodes to wait for the boot server to respond
- %% (note: test_server supervises each node start by accept()
- %% on a socket, the timeout value for the accept has to be quite
- %% long for this test to work).
- ?line test_server:sleep(test_server:seconds(5)),
- %% start the code loading circus!
- ?line {ok,BootPid} = erl_boot_server:start_link([Host]),
- %% give the nodes a chance to boot up before attempting to stop them
- ?line test_server:sleep(test_server:seconds(10)),
+ ?line Name = erl_prim_test_multiple_slaves,
+ ?line Host = host(),
+ ?line Cookie = atom_to_list(erlang:get_cookie()),
+ ?line IpStr = ip_str(Host),
+ ?line LFlag = get_loader_flag(os:type()),
+ ?line Args = LFlag ++ " -hosts " ++ IpStr ++
+ " -setcookie " ++ Cookie,
+
+ NoOfNodes = 10, % no of slave nodes to be started
+
+ NamesAndNodes =
+ lists:map(fun(N) ->
+ NameN = atom_to_list(Name) ++
+ integer_to_list(N),
+ NodeN = NameN ++ "@" ++ Host,
+ {list_to_atom(NameN),list_to_atom(NodeN)}
+ end, lists:seq(1, NoOfNodes)),
+
+ ?line Nodes = start_multiple_nodes(NamesAndNodes, Args, []),
+
+ %% "queue up" the nodes to wait for the boot server to respond
+ %% (note: test_server supervises each node start by accept()
+ %% on a socket, the timeout value for the accept has to be quite
+ %% long for this test to work).
+ ?line test_server:sleep(test_server:seconds(5)),
+ %% start the code loading circus!
+ ?line {ok,BootPid} = erl_boot_server:start_link([Host]),
+ %% give the nodes a chance to boot up before attempting to stop them
+ ?line test_server:sleep(test_server:seconds(10)),
- ?line wait_and_shutdown(lists:reverse(Nodes), 30),
+ ?line wait_and_shutdown(lists:reverse(Nodes), 30),
- ?line unlink(BootPid),
- ?line exit(BootPid, kill),
- ok
- end.
+ ?line unlink(BootPid),
+ ?line exit(BootPid, kill),
+ ok.
start_multiple_nodes([{Name,Node} | NNs], Args, Started) ->
?line {ok,Node} = start_node(Name, Args, [{wait, false}]),
diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl
index 8856be31c2..5263130574 100644
--- a/lib/kernel/test/file_SUITE.erl
+++ b/lib/kernel/test/file_SUITE.erl
@@ -167,12 +167,7 @@ init_per_suite(Config) when is_list(Config) ->
ok ->
[{sasl,started}]
end,
- ok = case os:type() of
- {ose,_} ->
- ok;
- _ ->
- application:start(os_mon)
- end,
+ application:start(os_mon),
case os:type() of
{win32, _} ->
@@ -198,12 +193,7 @@ end_per_suite(Config) when is_list(Config) ->
ok
end,
- case os:type() of
- {ose,_} ->
- ok;
- _ ->
- application:stop(os_mon)
- end,
+ application:stop(os_mon),
case proplists:get_value(sasl, Config) of
started ->
application:stop(sasl);
@@ -888,10 +878,7 @@ open1(Config) when is_list(Config) ->
?line io:format(Fd1,Str,[]),
?line {ok,0} = ?FILE_MODULE:position(Fd1,bof),
?line Str = io:get_line(Fd1,''),
- ?line case io:get_line(Fd2,'') of
- Str -> Str;
- eof -> Str
- end,
+ ?line Str = io:get_line(Fd2,''),
?line ok = ?FILE_MODULE:close(Fd2),
?line {ok,0} = ?FILE_MODULE:position(Fd1,bof),
?line ok = ?FILE_MODULE:truncate(Fd1),
@@ -2346,9 +2333,6 @@ e_rename(Config) when is_list(Config) ->
%% At least Windows NT can
%% successfully move a file to
%% another drive.
- ok;
- {ose, _} ->
- %% disabled for now
ok
end,
[] = flush(),
diff --git a/lib/kernel/test/gen_tcp_misc_SUITE.erl b/lib/kernel/test/gen_tcp_misc_SUITE.erl
index 81c6dcd0fd..3adca83ec9 100644
--- a/lib/kernel/test/gen_tcp_misc_SUITE.erl
+++ b/lib/kernel/test/gen_tcp_misc_SUITE.erl
@@ -58,14 +58,6 @@
oct_acceptor/1,
otp_7731_server/1, zombie_server/2, do_iter_max_socks/2]).
-init_per_testcase(wrapping_oct, Config) when is_list(Config) ->
- Dog = case os:type() of
- {ose,_} ->
- test_server:timetrap(test_server:minutes(20));
- _Else ->
- test_server:timetrap(test_server:seconds(600))
- end,
- [{watchdog, Dog}|Config];
init_per_testcase(iter_max_socks, Config) when is_list(Config) ->
Dog = case os:type() of
{win32,_} ->
@@ -74,14 +66,6 @@ init_per_testcase(iter_max_socks, Config) when is_list(Config) ->
test_server:timetrap(test_server:seconds(240))
end,
[{watchdog, Dog}|Config];
-init_per_testcase(accept_system_limit, Config) when is_list(Config) ->
- case os:type() of
- {ose,_} ->
- {skip,"Skip in OSE"};
- _ ->
- Dog = test_server:timetrap(test_server:seconds(240)),
- [{watchdog,Dog}|Config]
- end;
init_per_testcase(wrapping_oct, Config) when is_list(Config) ->
Dog = test_server:timetrap(test_server:seconds(600)),
[{watchdog, Dog}|Config];
diff --git a/lib/kernel/test/prim_file_SUITE.erl b/lib/kernel/test/prim_file_SUITE.erl
index 3e6d8492f7..366231d2cc 100644
--- a/lib/kernel/test/prim_file_SUITE.erl
+++ b/lib/kernel/test/prim_file_SUITE.erl
@@ -455,10 +455,7 @@ open1(Config) when is_list(Config) ->
?line ?PRIM_FILE:write(Fd1,Str),
?line {ok,0} = ?PRIM_FILE:position(Fd1,bof),
?line {ok, Str} = ?PRIM_FILE:read(Fd1,Length),
- ?line case ?PRIM_FILE:read(Fd2,Length) of
- {ok,Str} -> Str;
- eof -> Str
- end,
+ ?line {ok, Str} = ?PRIM_FILE:read(Fd2,Length),
?line ok = ?PRIM_FILE:close(Fd2),
?line {ok,0} = ?PRIM_FILE:position(Fd1,bof),
?line ok = ?PRIM_FILE:truncate(Fd1),
@@ -1629,7 +1626,7 @@ e_rename(Config) when is_list(Config) ->
%% successfully move a file to
%% another drive.
ok;
- {unix, _ } ->
+ _ ->
OtherFs = "/tmp",
?line NameOnOtherFs =
filename:join(OtherFs,
@@ -1653,10 +1650,7 @@ e_rename(Config) when is_list(Config) ->
Else ->
Else
end,
- Com;
- {ose, _} ->
- %% disabled for now
- ok
+ Com
end,
?line test_server:timetrap_cancel(Dog),
Comment.
diff --git a/lib/kernel/test/standard_error_SUITE.erl b/lib/kernel/test/standard_error_SUITE.erl
index e8917bbd47..97ead9b9fd 100644
--- a/lib/kernel/test/standard_error_SUITE.erl
+++ b/lib/kernel/test/standard_error_SUITE.erl
@@ -21,13 +21,13 @@
-module(standard_error_SUITE).
-export([all/0,suite/0]).
--export([badarg/1,getopts/1]).
+-export([badarg/1,getopts/1,output/1]).
suite() ->
[{ct_hooks,[ts_install_cth]}].
all() ->
- [badarg,getopts].
+ [badarg,getopts,output].
badarg(Config) when is_list(Config) ->
{'EXIT',{badarg,_}} = (catch io:put_chars(standard_error, [oops])),
@@ -37,3 +37,30 @@ badarg(Config) when is_list(Config) ->
getopts(Config) when is_list(Config) ->
[{encoding,latin1}] = io:getopts(standard_error),
ok.
+
+%% Test that writing a lot of output to standard_error does not cause the
+%% processes handling it to terminate like this:
+%%
+%% =ERROR REPORT==== 9-Aug-2015::23:19:23 ===
+%% ** Generic server standard_error_sup terminating
+%% ** Last message in was {'EXIT',<0.28.0>,eagain}
+%% ** When Server state == {state,standard_error,undefined,<0.28.0>,
+%% {local,standard_error_sup}}
+%% ** Reason for termination ==
+%% ** eagain
+%%
+%% This problem, observed with Erlang 18.0.2, was fixed in fd_driver by
+%% properly handling EAGAIN if it arises on file descriptor writes.
+%%
+output(Config) when is_list(Config) ->
+ Ref = monitor(process, standard_error_sup),
+ Chars = [ [["1234567890" || _ <- lists:seq(1,10)], $\s,
+ integer_to_list(L), $\r, $\n] || L <- lists:seq(1, 100) ],
+ ok = io:put_chars(standard_error, Chars),
+ receive
+ {'DOWN', Ref, process, _, _} ->
+ error(standard_error_noproc)
+ after
+ 500 ->
+ ok
+ end.
diff --git a/lib/odbc/doc/src/odbc.xml b/lib/odbc/doc/src/odbc.xml
index 01bc0cb7ff..6a2a3587e4 100644
--- a/lib/odbc/doc/src/odbc.xml
+++ b/lib/odbc/doc/src/odbc.xml
@@ -221,6 +221,18 @@
and their meanings are dependent on the database being used.</item>
<item><c>Reason</c> is as per the <c>Reason</c> field when extended errors are not enabled.</item>
</list>
+
+ <note>
+ <p>The current implementation spawns a port programm
+ written in C that utilizes the actual ODBC driver. There
+ is a default timeout of 5000 msec for this port programm
+ to connect to the Erlang ODBC application. This timeout
+ can be changed by setting an application specific
+ environment variable 'port_timeout' with the number of
+ milliseconds for the ODBC application. E.g.: [{odbc,
+ [{port_timeout, 60000}]}] to set it to 60 seconds.
+ </p>
+ </note>
</desc>
</func>
<func>
diff --git a/lib/odbc/src/odbc.erl b/lib/odbc/src/odbc.erl
index 4901821e9c..12560bfb6e 100644
--- a/lib/odbc/src/odbc.erl
+++ b/lib/odbc/src/odbc.erl
@@ -26,6 +26,8 @@
-include("odbc_internal.hrl").
+-define(ODBC_PORT_TIMEOUT, 5000).
+
%% API --------------------------------------------------------------------
-export([start/0, start/1, stop/0,
@@ -523,10 +525,10 @@ handle_msg({connect, ODBCCmd, AutoCommitMode, SrollableCursors},
NewState = State#state{auto_commit_mode = AutoCommitMode,
scrollable_cursors = SrollableCursors},
- case gen_tcp:accept(ListenSocketSup, 5000) of
+ case gen_tcp:accept(ListenSocketSup, port_timeout()) of
{ok, SupSocket} ->
gen_tcp:close(ListenSocketSup),
- case gen_tcp:accept(ListenSocketOdbc, 5000) of
+ case gen_tcp:accept(ListenSocketOdbc, port_timeout()) of
{ok, OdbcSocket} ->
gen_tcp:close(ListenSocketOdbc),
odbc_send(OdbcSocket, ODBCCmd),
@@ -983,3 +985,6 @@ string_terminate_value(Binary) when is_binary(Binary) ->
<<Binary/binary,0:16>>;
string_terminate_value(null) ->
null.
+
+port_timeout() ->
+ application:get_env(?MODULE, port_timeout, ?ODBC_PORT_TIMEOUT).
diff --git a/lib/odbc/test/odbc_connect_SUITE.erl b/lib/odbc/test/odbc_connect_SUITE.erl
index 93e949faf6..2d4173a008 100644
--- a/lib/odbc/test/odbc_connect_SUITE.erl
+++ b/lib/odbc/test/odbc_connect_SUITE.erl
@@ -120,7 +120,16 @@ end_per_suite(_Config) ->
%% 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(connect_port_timeout, Config) ->
+ odbc:stop(),
+ application:load(odbc),
+ application:set_env(odbc, port_timeout, 0),
+ odbc:start(),
+ init_per_testcase_common(Config);
init_per_testcase(_TestCase, Config) ->
+ init_per_testcase_common(Config).
+
+init_per_testcase_common(Config) ->
test_server:format("ODBCINI = ~p~n", [os:getenv("ODBCINI")]),
Dog = test_server:timetrap(?default_timeout),
Temp = lists:keydelete(connection_ref, 1, Config),
@@ -135,7 +144,16 @@ init_per_testcase(_TestCase, Config) ->
%% A list of key/value pairs, holding the test case configuration.
%% Description: Cleanup after each test case
%%--------------------------------------------------------------------
+
+end_per_testcase(connect_port_timeout, Config) ->
+ application:unset_env(odbc, port_timeout),
+ odbc:stop(),
+ odbc:start(),
+ end_per_testcase_common(Config);
end_per_testcase(_TestCase, Config) ->
+ end_per_testcase_common(Config).
+
+end_per_testcase_common(Config) ->
Table = ?config(tableName, Config),
{ok, Ref} = odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()),
Result = odbc:sql_query(Ref, "DROP TABLE " ++ Table),
@@ -423,6 +441,18 @@ connect_timeout(Config) when is_list(Config) ->
%% Need to return ok here "{'EXIT',timeout} return value" will
%% be interpreted as that the testcase has timed out.
ok.
+
+%%-------------------------------------------------------------------------
+connect_port_timeout(doc) ->
+ ["Test the timeout for the port program to connect back to the odbc "
+ "application within the connect function."];
+connect_port_timeout(suite) -> [];
+connect_port_timeout(Config) when is_list(Config) ->
+ %% Application environment var 'port_timeout' has been set to 0 by
+ %% init_per_testcase/2.
+ {error,timeout} = odbc:connect(?RDBMS:connection_string(),
+ odbc_test_lib:platform_options()).
+
%%-------------------------------------------------------------------------
timeout(doc) ->
["Test that timeouts don't cause unwanted behavior sush as receiving"
diff --git a/lib/ose/Makefile b/lib/ose/Makefile
deleted file mode 100644
index 6119b75c3f..0000000000
--- a/lib/ose/Makefile
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1996-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%
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-#
-# Macros
-#
-
-SUB_DIRECTORIES = src doc/src
-
-include vsn.mk
-VSN = $(OSE_VSN)
-
-SPECIAL_TARGETS =
-
-#
-# Default Subdir Targets
-#
-include $(ERL_TOP)/make/otp_subdir.mk
diff --git a/lib/ose/doc/html/.gitignore b/lib/ose/doc/html/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/ose/doc/html/.gitignore
+++ /dev/null
diff --git a/lib/ose/doc/man3/.gitignore b/lib/ose/doc/man3/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/ose/doc/man3/.gitignore
+++ /dev/null
diff --git a/lib/ose/doc/man6/.gitignore b/lib/ose/doc/man6/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/ose/doc/man6/.gitignore
+++ /dev/null
diff --git a/lib/ose/doc/pdf/.gitignore b/lib/ose/doc/pdf/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/ose/doc/pdf/.gitignore
+++ /dev/null
diff --git a/lib/ose/doc/src/.gitignore b/lib/ose/doc/src/.gitignore
deleted file mode 100644
index 860e9e703e..0000000000
--- a/lib/ose/doc/src/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-ose.xml
diff --git a/lib/ose/doc/src/Makefile b/lib/ose/doc/src/Makefile
deleted file mode 100644
index 7ebd4125ba..0000000000
--- a/lib/ose/doc/src/Makefile
+++ /dev/null
@@ -1,133 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1997-2012. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES 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=$(OSE_VSN)
-APPLICATION=ose
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
-
-# ----------------------------------------------------
-# Help application directory specification
-# ----------------------------------------------------
-EDOC_DIR = $(ERL_TOP)/lib/edoc
-SYNTAX_TOOLS_DIR = $(ERL_TOP)/lib/syntax_tools
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-XML_APPLICATION_FILES = ref_man.xml
-
-XML_REF3_FILES = \
- ose.xml \
- ose_erl_driver.xml
-
-XML_REF6_FILES = ose_app.xml
-
-XML_PART_FILES = part.xml
-XML_CHAPTER_FILES = notes.xml ose_intro.xml ose_signals_chapter.xml
-
-BOOK_FILES = book.xml
-
-XML_FILES = \
- $(BOOK_FILES) $(XML_CHAPTER_FILES) \
- $(XML_PART_FILES) $(XML_REF3_FILES) $(XML_REF6_FILES) \
- $(XML_APPLICATION_FILES)
-
-# ----------------------------------------------------
-
-HTML_FILES = $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html) \
- $(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html)
-
-INFO_FILE = ../../info
-
-MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-MAN6_FILES = $(XML_REF6_FILES:%_app.xml=$(MAN6DIR)/%.6)
-
-HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
-
-TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-
-SPECS_FILES =
-
-TOP_SPECS_FILE =
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-XML_FLAGS +=
-
-SPECS_FLAGS = -I../../include -I../../../kernel/include
-
-OSE_SRC_DIR = ../../src
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-docs: man pdf html
-
-$(TOP_PDF_FILE): $(XML_FILES)
-
-pdf: $(TOP_PDF_FILE)
-
-html: $(HTML_REF_MAN_FILE)
-
-man: $(MAN3_FILES) $(MAN6_FILES)
-
-ose.xml: $(OSE_SRC_DIR)/ose.erl
- escript $(DOCGEN)/priv/bin/xml_from_edoc.escript\
- $(OSE_SRC_DIR)/$(@:%.xml=%.erl)
-
-debug opt:
-
-clean clean_docs:
- rm -rf $(HTMLDIR)/*
- rm -f $(MAN3DIR)/*
- rm -f $(MAN6DIR)/*
- rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
- rm -f $(SPECDIR)/*
- rm -f errs core *~
-
-# ----------------------------------------------------
-# 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"
- $(INSTALL_DIR) "$(RELEASE_PATH)/man/man6"
- $(INSTALL_DATA) $(MAN6_FILES) "$(RELEASE_PATH)/man/man6"
-
-release_spec:
diff --git a/lib/ose/doc/src/book.xml b/lib/ose/doc/src/book.xml
deleted file mode 100644
index d62e0d32f4..0000000000
--- a/lib/ose/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>2014</year><year>2014</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT 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>OSE</title>
- <prepared>Lukas Larsson</prepared>
- <docno></docno>
- <date>2014-01-08</date>
- <rev>1.0</rev>
- <file>book.xml</file>
- </header>
- <insidecover>
- </insidecover>
- <pagetext>OSE</pagetext>
- <preamble>
- <contents level="2"></contents>
- </preamble>
- <parts>
- <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/ose/doc/src/notes.xml b/lib/ose/doc/src/notes.xml
deleted file mode 100644
index 06881b6c99..0000000000
--- a/lib/ose/doc/src/notes.xml
+++ /dev/null
@@ -1,109 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2014</year><year>2014</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT 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>OSE Release Notes</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- <file>notes.xml</file>
- </header>
- <p>This document describes the changes made to the OSE application.</p>
-
-<section><title>Ose 1.1</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>Ose 1.0.2</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- Add missing release notes for the OSE application.</p>
- <p>
- Own Id: OTP-12177</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Ose 1.0.1</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- Fix some spelling mistakes in documentation</p>
- <p>
- Own Id: OTP-12152</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Ose 1.0</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Erlang/OTP has been ported to the realtime operating
- system OSE. The port supports both smp and non-smp
- emulator. For details around the port and how to started
- see the User's Guide in the <seealso
- marker="ose:ose_intro">ose</seealso> application. </p>
- <p>
- Note that not all parts of Erlang/OTP has been ported. </p>
- <p>
- Notable things that work are: non-smp and smp emulators,
- OSE signal interaction, crypto, asn1, run_erl/to_erl,
- tcp, epmd, distribution and most if not all non-os
- specific functionality of Erlang.</p>
- <p>
- Notable things that does not work are: udp/sctp, os_mon,
- erl_interface, binding of schedulers.</p>
- <p>
- Own Id: OTP-11334</p>
- </item>
- </list>
- </section>
-
-</section>
-
-</chapter>
diff --git a/lib/ose/doc/src/ose_app.xml b/lib/ose/doc/src/ose_app.xml
deleted file mode 100644
index d555f0ec4f..0000000000
--- a/lib/ose/doc/src/ose_app.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE appref SYSTEM "appref.dtd">
-
-<appref>
- <header>
- <copyright>
- <year>2014</year><year>2014</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT 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>Enea OSE</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <app>ose</app>
- <appsummary>The OSE Application</appsummary>
- <description>
- <p>The OSE application contains modules and documentation that only
- applies when running Erlang/OTP on Enea OSE.</p>
- </description>
-
-</appref>
diff --git a/lib/ose/doc/src/ose_erl_driver.xml b/lib/ose/doc/src/ose_erl_driver.xml
deleted file mode 100644
index b804c29d2d..0000000000
--- a/lib/ose/doc/src/ose_erl_driver.xml
+++ /dev/null
@@ -1,111 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE cref SYSTEM "cref.dtd">
-
-<cref>
- <header>
- <copyright>
- <year>2013</year><year>2014</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT 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_driver for Enea OSE</title>
- <prepared>Lukas Larsson</prepared>
- <docno></docno>
- <date>2014-01-08</date>
- <rev>A</rev>
- <file>ose_erl_driver.xml</file>
- </header>
- <lib>ose_erl_driver</lib>
- <libsummary>Linked-in drivers in Enea OSE</libsummary>
- <description>
- <p>Writing Linked-in drivers that also work on Enea OSE is very similar for
- how you would do it for Unix. The difference from Unix is that
- driver_select, ready_input and ready_output all work with signals
- instead of file descriptors. This means that the driver_select is
- used to specify which type of signal should trigger calls to
- ready_input/ready_output. The functions described below are available
- to driver programmers on Enea OSE to facilitate this.
- </p>
- </description>
- <section>
- <title>DATA TYPES</title>
-
- <taglist>
- <tag><marker id="union_SIGNAL"/>union SIGNAL</tag>
- <item>See the Enea OSE SPI documentation for a description.</item>
- <tag><marker id="SIGSELECT"/>SIGSELECT</tag>
- <item>See the Enea OSE SPI documentation for a description.</item>
- <tag><marker id="ErlDrvEvent"/>ErlDrvEvent</tag>
- <item>The <c>ErlDrvEvent</c> is a handle to a signal number and id combination. It is passed to <seealso marker="erts:erl_driver#driver_select">driver_select(3)</seealso>.</item>
- <tag><marker id="ErlDrvOseEventId"/>ErlDrvOseEventId</tag>
- <item>This is the id used to associate a specific signal to a
- certain driver instance. </item>
- </taglist>
- </section>
- <funcs>
- <func>
- <name><ret>union SIGNAL *</ret><nametext>erl_drv_ose_get_signal(ErlDrvEvent drv_event)</nametext></name>
- <desc>
- <marker id="erl_drv_ose_get_signal"></marker>
- <p>Fetch the next signal associated with <c>drv_event</c>.
- Signals will be returned in the order which they were received and
- when no more signals are available <c>NULL</c> will be returned.
- Use this function in the ready_input/ready_output callbacks
- to get signals.</p>
- </desc>
- </func>
- <func>
- <name><ret>ErlDrvEvent</ret><nametext>erl_drv_ose_event_alloc(SIGSELECT signo, ErlDrvOseEventId id, ErlDrvOseEventId (*resolve_signal)(union SIGNAL* sig), void *extra)</nametext></name>
- <desc>
- <marker id="erl_drv_ose_event_alloc"></marker>
- <p>Create a new <c>ErlDrvEvent</c> associated with <c>signo</c>,
- <c>id</c> and uses the <c>resolve_signal</c> function to extract
- the <c>id</c> from a signal with <c>signo</c>. The <c>extra</c>
- parameter can be used for additional data. See
- <seealso marker="ose_signals_chapter#driver">
- Signals in a Linked-in driver</seealso> in the OSE User's Guide.
- </p>
- </desc>
- </func>
- <func>
- <name><ret>void</ret><nametext>erl_drv_ose_event_free(ErlDrvEvent drv_event)</nametext></name>
- <desc>
- <marker id="erl_drv_ose_event_free"></marker>
- <p>Free a <c>ErlDrvEvent</c>. This should always be done in the
- <seealso marker="erts:driver_entry#stop_select">stop_select</seealso>
- callback when the event is no longer being used.</p>
- </desc>
- </func>
- <func>
- <name><ret>void</ret><nametext>erl_drv_ose_event_fetch(ErlDrvEvent drv_event, SIGSELECT *signo, ErlDrvOseEventId *id, void **extra)</nametext></name>
- <desc>
- <marker id="erl_drv_ose_event_fetch"></marker>
- <p>Write the signal number, id and any extra data associated with <c>drv_event</c>
- into <c>*signo</c> and <c>*id</c> respectively. <c>NULL</c> can be
- also passed as <c>signo</c> or <c>id</c> in order to ignore that field.
- </p>
- </desc>
- </func>
- </funcs>
- <section>
- <title>SEE ALSO</title>
- <p>
- <seealso marker="erts:driver_entry">driver_entry(3)</seealso>,
- <seealso marker="erts:erl_driver">erl_driver(3)</seealso>
- </p>
- </section>
-</cref>
diff --git a/lib/ose/doc/src/ose_intro.xml b/lib/ose/doc/src/ose_intro.xml
deleted file mode 100644
index 982516c8bd..0000000000
--- a/lib/ose/doc/src/ose_intro.xml
+++ /dev/null
@@ -1,154 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2013</year><year>2014</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT 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>Lukas Larsson</prepared>
- <docno></docno>
- <date>2014-01-08</date>
- <rev>A</rev>
- <file>ose_intro.xml</file>
- </header>
-
- <section>
- <title>Features</title>
- </section>
-
- <section>
- <title>Starting Erlang/OTP</title>
- <p>
- Starting Erlang/OTP on OSE is not as simple as on Unix/Windows (yet).
- First of all you have to explicitly use the beam (or beam.smp) executables
- found in erts-X.Y.Z/bin as the load module that you run. This in turn
- means that you have to supply the raw beam arguments to the emulator
- when starting. Fortunately <c>erl</c> on Unix/Windows has a
- undocumented flag called <c>-emu_args_exit</c> that can be used to
- figure out what the arguments to beam look like. For example:</p>
- <code># erl +Mut false +A 10 +S 4:4 +Muycs256 +P 2096 +Q 2096 -emu_args_exit
--Mut
-false
--A
-10
--S
-4:4
--Muycs256
--P
-2096
--Q
-2096
---
--root
-/usr/local/lib/erlang
--progname
-erl
---
--home
-/home/erlang
---</code>
- <p>
- The arguments are printed on separate lines to make it possible to know
- what has to be quoted with &quot;. Each line is one quotable unit.
- So taking the arguments above you can supply them to pm_create or
- just execute directly on the command line. For example:</p>
- <code>rtose@acp3400> pm_install erlang /mst/erlang/erts-6.0/bin/beam.smp
-rtose@acp3400> pm_create -c ARGV="-Mut false -A 10 -S 4:4 -Muycs256 -P 2096 -Q 2099 -- -root /mst/erlang -progname erl -- -home /mst/erlang --" erlang
-pid: 0x110059
-rtose@acp3400> pm_start 0x110059</code>
- <p>
- Also note that since we are running erl to figure out the arguments on a
- separate machine the paths have to be updated. In the example above
- <c>/usr/local/lib/erlang</c> was replaced by <c>/mst/erlang/</c>. The
- goal is to in future releases not have to do the special argument handling
- but for now (OTP 17.0) you have to do it.
- </p>
- <note>
- Because of a limitation in the way the OSE handles stdio when starting
- load modules using pm_install/create the Erlang shell only reads every
- other command from stdin. However if you start Erlang using run_erl
- you do not have this problem. So it is highly recommended that you
- start Erlang using run_erl.
- </note>
- </section>
-
- <section>
- <title>run_erl and to_erl</title>
- <p>
- In OSE run_erl and to_erl are combined into a single load module called
- run_erl_lm. Installing and starting the load module will add two new
- shell commands called run_erl and to_erl. They work in exactly the same
- way as the unix variants of run_erl and to_erl, except that the read
- and write pipes have to be placed under the /pipe vm. One additional
- option also exists to run_erl on ose:
- <taglist>
- <tag><c>-block Name</c></tag>
- <item>The name of the install handle and block that will be created/used by
- installing and exectuting the first part of the command. If nothing
- if given the basename of the load module will be used for this value.
- Example:
- <code>pm_install erlang /path/to/erlang/vm/beam.smp
-run_erl -daemon -block erlang /pipe/ /mst/erlang_logs/ "beam.smp -A 1 -- -root /mst/erlang -- -home /mst --"</code>
- </item>
- </taglist>
- The same argument munching as when starting Erlang/OTP without run_erl
- has to be done. If <c>-daemon</c> is given then all error printouts
- are sent to the ramlog.
- See also
- <seealso marker="erts:run_erl">run_erl</seealso> for more details.
- </p>
- <p>
- Below is an example of how to get started with <c>run_erl_lm</c>.
- <code>rtose@acp3400> pm_install run_erl_lm /mst/erlang/erts-6.0/bin/run_erl_lm
-rtose@acp3400> pm_create run_erl_lm
-pid: 0x1c005d
-rtose@acp3400> pm_start 0x1c005d
-rtose@acp3400> mkdir /mst/erlang_log
-rtose@acp3400> run_erl -daemon /pipe/ /mst/erlang_log/ "/mst/erlang/erts-6.0/bin/beam.smp -A 1 -- -root /mst/erlang -- -home /mst --"
-rtose@acp3400> to_erl
-Attaching to /pipe/erlang.pipe.1 (^C to exit)
-os:type().
-{ose,release}
-2>
-'to_erl' terminated.</code>
- Note that Ctrl-C is used instead of Ctrl-D to exit the to_erl shell.
- </p>
- </section>
-
- <section>
- <title>epmd</title>
- <p>
- In OSE epmd will not be started automatically so if you want to use
- Erlang distribution you have to manually start epmd.
- </p>
- </section>
-
- <section>
- <title>VM Process Priorities</title>
- <p>
- It is possible to set the priorities you want for the OSE processes that
- thr emulator creates in the lmconf. An example of how to do it can be
- found in the default lmconf file in
- $ERL_TOP/erts/emulator/sys/ose/beam.lmconf.
- </p>
- </section>
-
-</chapter>
diff --git a/lib/ose/doc/src/ose_signals_chapter.xml b/lib/ose/doc/src/ose_signals_chapter.xml
deleted file mode 100644
index bcf2259577..0000000000
--- a/lib/ose/doc/src/ose_signals_chapter.xml
+++ /dev/null
@@ -1,240 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2013</year><year>2014</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT 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>Interacting with Enea OSE</title>
- <prepared>Lukas Larsson</prepared>
- <docno></docno>
- <date>2014-01-08</date>
- <rev>A</rev>
- <file>ose_signals_chapter.xml</file>
- </header>
-
- <marker id="introduction"></marker>
- <section>
- <title>Introduction</title>
- <p>The main way which programs on Enea OSE interact is through the
- usage of message passing, much the same way as Erlang processes
- communicate. There are two ways in which an Erlang programmer can
- interact with the signals sent from other Enea OSE processes; either
- through the provided <c>ose</c> module, or by writing a custom linked-in
- driver. This User's Guide describes and provides examples for both
- approaches.
- </p>
- </section>
-
- <marker id="erlang"></marker>
- <section>
- <title>Signals in Erlang</title>
- <p>Erlang/OTP on OSE provides a erlang module called
- <seealso marker="ose:ose">ose</seealso> that can be used to interact
- with other OSE processes using message passing. The api in the module
- is very similar to the native OSE api, so for details of how the
- functions work please refer to the official OSE documenation. Below
- is an example usage of the API.
- </p>
- <code>1> P1 = ose:open("p1").
-#Port&gt;0.344>
-2> ose:hunt(P1,"p2").
-{#Port&gt;0.344>,1}
-3> P2 = ose:open("p2").
-#Port&gt;0.355>
-4> flush().
-Shell got {mailbox_up,#Port&gt;0.344>,{#Port&gt;0.344>,1},852189}
-ok
-5> ose:listen(P1,[1234]).
-ok
-6> ose:send(P2,ose:get_id(P1),1234,&gt;&gt;"hello">>).
-ok
-7> flush().
-Shell got {message,#Port&gt;0.344>,{852189,1245316,1234,&gt;&gt;"hello">>}}
-ok</code>
- </section>
-
- <marker id="driver"></marker>
- <section>
- <title>Signals in a Linked-in driver</title>
- <p>
- Writing Linked-in drivers for OSE is very similar to how it is done
- for Unix/Windows. It is only the way in which the driver subscribes
- and consumed external events that is different. In Unix (and Windows)
- file descriptiors (and Event Objects) are used to select on. On OSE
- we use signals to deliver the same functionality. There are two large
- differences between a signal and an fd.
- </p>
- <p>
- In OSE it is not possible for a signal number to be a unique identifier
- for a resource in the same way as an fd is. For example; let's say we
- implement a driver that does an asynchronous hunt that uses signal
- number 1234 as the hunt_sig. If we want to be able to have multiple
- hunt ports running at the same time we have to have someway of routing
- the signal to the correct port. This is achieved by supplying a secondary
- id that can be retrieved through the meta-data or payload of the signal,
- e.g:
- <code>ErlDrvEvent event = erl_drv_ose_event_alloc(1234,port,resolver);</code>
- The event you get back from
- <seealso marker="ose_erl_driver#erl_drv_ose_event_alloc">
- erl_drv_ose_event_alloc</seealso> can then be used by
- <seealso marker="erts:erl_driver#driver_select">driver_select</seealso>
- to subscribe to signals. The first argument is just the signal number
- that we are interested in. The second is the id that we choose to use,
- in this case the port id that we got in the
- <seealso marker="erts:driver_entry#start">start</seealso> callback is
- used. The third argument is a function pointer to a function that can
- be used to figure out the id from a given signal. The fourth argument can
- point to any additional data you might want to associate with the event.
- There is a complete. You can examine the data contained in the event with
- <seealso marker="ose_erl_driver#erl_drv_ose_event_fetch">erl_drv_ose_event_fetch</seealso>
- , eg:
- <code>erl_drv_ose_event_fetch(event, &amp;signal, &amp;port, (void **)&amp;extra);</code>
- example of what this could look like in
- <seealso marker="#example">the next section</seealso>.
- <note>It is very important to issue the driver_select call before
- any of the signals you are interested in are sent. If driver_select
- is called after the signal is sent, there is a high probability that it
- will be lost.</note>
- </p>
- <p>
- The other difference from unix is that in OSE the payload of the event
- (i.e. the signal data) is already received when the ready_output/input
- callbacks are called. This means that you access the data of a signal
- by calling <seealso marker="ose_erl_driver#erl_drv_ose_get_signal">
- erl_drv_ose_get_signal</seealso>. Additionally multiple signals might be
- associated with the event, so you should call
- <seealso marker="ose_erl_driver#erl_drv_ose_get_signal">
- erl_drv_ose_get_signal</seealso> until <c>NULL</c> is returned.
- </p>
- </section>
-
- <marker id="example"></marker>
- <section>
- <title>Example Linked-in driver</title>
-<code>#include "erl_driver.h"
-#include "ose.h"
-
-struct huntsig {
- SIGSELECT signo;
- ErlDrvPort port;
-};
-
-union SIGNAL {
- SIGSELECT signo;
- struct huntsig;
-}
-
-/* Here we have to get the id from the signal. In this case we use the
- port id since we have control over the data structure of the signal.
- It is however possible to use anything in here. The only restriction
- is that the same id has to be used for all signals of the same number.*/
-ErlDrvOseEventId resolver(union SIGNAL *sig) {
- return (ErlDrvOseEventId)sig->huntsig.port;
-}
-
-static int drv_init(void) { return 0; };
-
-static ErlDrvData drv_start(ErlDrvPort port, char *command) {
- return (ErlDrvData)port;
-}
-
-static ErlDrvSSizeT control(ErlDrvData driver_data, unsigned int cmd,
- char *buf, ErlDrvSizeT len,
- char **rbuf, ErlDrvSizeT rlen) {
- ErlDrvPort port = (ErlDrvPort)driver_data;
-
- /* An example of extra data to associate with the event */
- char *extra_data = driver_alloc(80);
- snprintf("extra_data, "Event, sig_no: 1234, and port: %d", port);
-
- /* Create a new event to select on */
- ErlDrvOseEvent evt = erl_drv_ose_event_alloc(1234,port,resolver, extra_data);
-
- /* Make sure to do the select call _BEFORE_ the signal arrives.
- The signal might get lost if the hunt call is done before the
- select. */
- driver_select(port,evt,ERL_DRV_READ|ERL_DRV_USE,1);
-
- union SIGNAL *sig = alloc(sizeof(union SIGNAL),1234);
- sig->huntsig.port = port;
- hunt("testprocess",0,NULL,&amp;sig);
- return 0;
-}
-
-static void ready_input(ErlDrvData driver_data, ErlDrvEvent evt) {
- char *extra_data;
- /* Get the first signal payload from the event */
- union SIGNAL *sig = erl_drv_ose_get_signal(evt);
- ErlDrvPort port = (ErlDrvPort)driver_data;
- while (sig != NULL) {
- if (sig->signo == 1234) {
- /* Print out the string we added as the extra parameter */
- erl_drv_ose_event_fetch(evt, NULL, NULL, (void **)&amp;extra_data);
- printf("We've received: %s\n", extra_data);
-
- /* If it is our signal we send a message with the sender of the signal
- to the controlling erlang process */
- ErlDrvTermData reply[] = { ERL_DRV_UINT, (ErlDrvUInt)sender(&amp;sig) };
- erl_drv_send_term(port,reply,sizeof(reply) / sizeof(reply[0]));
- }
-
- /* Cleanup the signal and deselect on the event.
- Note that the event itself has to be free'd in the stop_select
- callback. */
- free_buf(&amp;sig);
- driver_select(port,evt,ERL_DRV_READ|ERL_DRV_USE,0);
-
- /* There could be more than one signal waiting in this event, so
- we have to loop until sig == NULL */
- sig = erl_drv_ose_get_signal(evt);
- }
-}
-
-static void stop_select(ErlDrvEvent event, void *reserved)
-{
- /* Free the extra_data */
- erl_drv_ose_event_fetch(evt, NULL, NULL, (void **)&amp;extra_data);
- driver_free(extra_data);
-
- /* Free the event itself */
- erl_drv_ose_event_free(event);
-}
-
-/**
- * Setup the driver entry for the Erlang runtime
- **/
-ErlDrvEntry ose_signal_driver_entry = {
- .init = drv_init,
- .start = drv_start,
- .stop = drv_stop,
- .ready_input = ready_input,
- .driver_name = DRIVER_NAME,
- .control = control,
- .extended_marker = ERL_DRV_EXTENDED_MARKER,
- .major_version = ERL_DRV_EXTENDED_MAJOR_VERSION,
- .minor_version = ERL_DRV_EXTENDED_MINOR_VERSION,
- .driver_flags = ERL_DRV_FLAG_USE_PORT_LOCKING,
- .stop_select = stop_select
-};
-</code>
- </section>
-
-</chapter>
diff --git a/lib/ose/doc/src/part.xml b/lib/ose/doc/src/part.xml
deleted file mode 100644
index 0c9ebd16c0..0000000000
--- a/lib/ose/doc/src/part.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>2014</year>
- <year>2014</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT 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>OSE User's Guide</title>
- <prepared>Lukas Larsson</prepared>
- <docno></docno>
- <date>2014-01-08</date>
- <rev>1.0</rev>
- <file>part.xml</file>
- </header>
- <description>
- <p><em>OSE</em>.</p>
- </description>
- <xi:include href="ose_intro.xml"/>
- <xi:include href="ose_signals_chapter.xml"/>
-</part>
diff --git a/lib/ose/doc/src/ref_man.xml b/lib/ose/doc/src/ref_man.xml
deleted file mode 100644
index 964e5ab8ff..0000000000
--- a/lib/ose/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>2014</year><year>2014</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT 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>OSE Reference Manual</title>
- <prepared>Lukas Larsson</prepared>
- <docno></docno>
- <date>2014-01-08</date>
- <rev>1.0</rev>
- <file>ref_man.xml</file>
- </header>
- <description>
- <p>The Standard Erlang Libraries application, <em>STDLIB</em>,
- contains modules for manipulating lists, strings and files etc.</p>
- <br></br>
- </description>
- <xi:include href="ose_app.xml"/>
- <xi:include href="ose.xml"/>
- <xi:include href="ose_erl_driver.xml"/>
-</application>
diff --git a/lib/ose/ebin/.gitignore b/lib/ose/ebin/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/ose/ebin/.gitignore
+++ /dev/null
diff --git a/lib/ose/include/.gitignore b/lib/ose/include/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/ose/include/.gitignore
+++ /dev/null
diff --git a/lib/ose/info b/lib/ose/info
deleted file mode 100644
index 85c07dbe82..0000000000
--- a/lib/ose/info
+++ /dev/null
@@ -1,2 +0,0 @@
-group: misc Miscellaneous Applications
-short: Description of Enea OSE specific functionality
diff --git a/lib/ose/src/Makefile b/lib/ose/src/Makefile
deleted file mode 100644
index a89e9392e9..0000000000
--- a/lib/ose/src/Makefile
+++ /dev/null
@@ -1,107 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1996-2013. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES 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=$(OSE_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/ose-$(VSN)
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-MODULES= \
- ose
-
-HRL_FILES=
-
-INTERNAL_HRL_FILES=
-
-ERL_FILES= $(MODULES:%=%.erl)
-
-TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) $(APP_TARGET) $(APPUP_TARGET)
-
-APP_FILE= ose.app
-
-APP_SRC= $(APP_FILE).src
-APP_TARGET= $(EBIN)/$(APP_FILE)
-
-APPUP_FILE= ose.appup
-
-APPUP_SRC= $(APPUP_FILE).src
-APPUP_TARGET= $(EBIN)/$(APPUP_FILE)
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-
-ifeq ($(NATIVE_LIBS_ENABLED),yes)
-ERL_COMPILE_FLAGS += +native
-endif
-ERL_COMPILE_FLAGS += -I../include -I../../kernel/include -Werror
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-
-debug opt: $(TARGET_FILES)
-
-clean:
- rm -f $(TARGET_FILES)
- rm -f core
- rm -f erl_parse.erl
-
-docs:
-
-# ----------------------------------------------------
-# Special Build Targets
-# ----------------------------------------------------
-
-$(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);' $< > $@
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec: opt
- $(INSTALL_DIR) "$(RELSYSDIR)/src"
- $(INSTALL_DATA) $(ERL_FILES) "$(RELSYSDIR)/src"
- $(INSTALL_DIR) "$(RELSYSDIR)/include"
- $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
- $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
-
-release_docs_spec:
-
-# ----------------------------------------------------
-# Dependencies -- alphabetically, please
-# ----------------------------------------------------
diff --git a/lib/ose/src/ose.app.src b/lib/ose/src/ose.app.src
deleted file mode 100644
index 036779eb16..0000000000
--- a/lib/ose/src/ose.app.src
+++ /dev/null
@@ -1,28 +0,0 @@
-%% This is an -*- erlang -*- file.
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES 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, ose,
- [{description, "Enea OSE specific modules"},
- {vsn, "%VSN%"},
- {modules, [ose]},
- {registered,[]},
- {applications, [stdlib,kernel]},
- {env, []},
- {runtime_dependencies, ["stdlib-2.0","erts-6.0"]}]}.
diff --git a/lib/ose/src/ose.appup.src b/lib/ose/src/ose.appup.src
deleted file mode 100644
index 28b6da3439..0000000000
--- a/lib/ose/src/ose.appup.src
+++ /dev/null
@@ -1,23 +0,0 @@
-%% -*- erlang -*-
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2013. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES 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%",
- [
- ],
- [
- ]}.
diff --git a/lib/ose/src/ose.erl b/lib/ose/src/ose.erl
deleted file mode 100644
index 5534dba4d4..0000000000
--- a/lib/ose/src/ose.erl
+++ /dev/null
@@ -1,453 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2013. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES 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 Interface module for OSE messaging and process monitoring from Erlang
-%%
-%% For each mailbox created through {@link open/1} a OSE phantom process with
-%% that name is started. Since phantom processes are used the memory footprint
-%% of each mailbox is quite small.
-%%
-%% To receive messages you first have to subscribe to the specific message
-%% numbers that you are interested in with {@link listen/2}. The messages
-%% will be sent to the Erlang process that created the mailbox.
-%%
-%% @end
-%%
--module(ose).
-
-%%==============================================================================
-%% Exported API
-%%==============================================================================
--export([open/1,
- close/1,
- get_id/1,
- get_name/2,
- hunt/2,
- dehunt/2,
- attach/2,
- detach/2,
- send/4,
- send/5,
- listen/2
- ]).
-
-%%==============================================================================
-%% Types
-%%==============================================================================
--opaque mailbox() :: port().
-%% Mailbox handle. Implemented as an erlang port.
-
--opaque mailbox_id() :: integer().
-%% Mailbox ID, this is the same as the process id of an OSE process.
-%% An integer.
-
--type message_number() :: 0..4294967295.
-%% OSE Signal number
-
--opaque hunt_ref() :: {mailbox(),integer()}.
-%% Reference from a hunt request. This term will be included
-%% in a successful hunt response.
-
--opaque attach_ref() :: {mailbox(),integer()}.
-%% Reference from an attach request. This term will be included
-%% in the term returned when the attached mailbox disappears.
-
--export_type([mailbox_id/0,
- message_number/0,
- mailbox/0,
- hunt_ref/0,
- attach_ref/0]).
-
-%%==============================================================================
-%% Defines
-%%==============================================================================
--define(DRIVER_NAME, "ose_signal_drv").
--define(GET_SPID, 1).
--define(GET_NAME, 2).
--define(HUNT, 100).
--define(DEHUNT, 101).
--define(ATTACH, 102).
--define(DETACH, 103).
--define(SEND, 104).
--define(SEND_W_S, 105).
--define(LISTEN, 106).
--define(OPEN, 200).
-
--define(INT_32BIT(Int),(is_integer(Int) andalso (Int >= 0) andalso (Int < (1 bsl 32)))).
-
-%%==============================================================================
-%% API functions
-%%==============================================================================
-
-%%------------------------------------------------------------------------------
-%% @doc Create a mailbox with the given name and return a port that handles
-%% the mailbox.
-%%
-%% An OSE phantom process with the given name will be created that will send any
-%% messages sent through this mailbox. Any messages sent to the new OSE process
-%% will automatically be converted to an Erlang message and sent to the Erlang
-%% process that calls this function. See {@link listen/2} for details about the
-%% format of the message sent.
-%%
-%% The caller gets linked to the created mailbox.
-%%
-%% raises: `badarg' | `system_limit'
-%%
-%% @see listen/2
-%% @end
-%%------------------------------------------------------------------------------
--spec open(Name) -> Port when
- Name :: iodata(),
- Port :: mailbox().
-open(Name) ->
- try open_port({spawn_driver,?DRIVER_NAME}, [binary]) of
- Port ->
- try port_command(Port,[?OPEN,Name]) of
- true ->
- receive
- {ose_drv_reply,Port,{error,Error}} ->
- close(Port),
- erlang:error(Error,[Name]);
- {ose_drv_reply,Port,ok} ->
- Port
- end
- catch
- error:badarg -> close(Port),erlang:error(badarg,[Name])
- end
- catch
- error:badarg -> erlang:error(badarg,[Name])
- end.
-
-%%------------------------------------------------------------------------------
-%% @doc Close a mailbox
-%%
-%% This kills the OSE phantom process associated with this mailbox.
-%%
-%% Will also consume any ``{'EXIT',Port,_}'' message from the port that comes
-%% due to the port closing when the calling process traps exits.
-%%
-%% raises: `badarg'
-%% @end
-%%------------------------------------------------------------------------------
--spec close(Port) -> ok when
- Port :: mailbox().
-close(Port) when is_port(Port) ->
- %% Copied from prim_inet
- case erlang:process_info(self(), trap_exit) of
- {trap_exit,true} ->
- link(Port),
- catch erlang:port_close(Port),
- receive {'EXIT',Port,_} -> ok end;
- {trap_exit,false} ->
- catch erlang:port_close(Port),
- ok
- end;
-close(NotPort) ->
- erlang:error(badarg,[NotPort]).
-
-%%------------------------------------------------------------------------------
-%% @doc Get the mailbox id for the given port.
-%%
-%% The mailbox id is the same as the OSE process id of the OSE phantom process
-%% that this mailbox represents.
-%%
-%% raises: `badarg'
-%% @end
-%%------------------------------------------------------------------------------
--spec get_id(Port) -> Pid when
- Port :: mailbox(),
- Pid :: mailbox_id().
-get_id(Port) ->
- try port_control(Port, ?GET_SPID, <<>>) of
- <<Spid:32>> -> Spid
- catch error:_Error ->
- erlang:error(badarg,[Port])
- end.
-
-%%------------------------------------------------------------------------------
-%% @doc Get the mailbox name for the given mailbox id.
-%%
-%% The mailbox name is the name of the OSE process with process id Pid.
-%%
-%% This call will fail with badarg if the underlying system does not support
-%% getting the name from a process id.
-%%
-%% raises: `badarg'
-%% @end
-%%------------------------------------------------------------------------------
--spec get_name(Port, Pid) -> Name | undefined when
- Port :: mailbox(),
- Pid :: mailbox_id(),
- Name :: binary().
-get_name(Port, Pid) when ?INT_32BIT(Pid) ->
- try port_control(Port, ?GET_NAME, <<Pid:32>>) of
- [] -> undefined;
- Res -> Res
- catch error:_Error ->
- erlang:error(badarg,[Port,Pid])
- end;
-get_name(Port, Pid) ->
- erlang:error(badarg,[Port,Pid]).
-
-
-%%------------------------------------------------------------------------------
-%% @doc Hunt for OSE process by name.
-%%
-%% Will send `{mailbox_up, Port, Ref, MboxId}'
-%% to the calling process when the OSE process becomes available.
-%%
-%% Returns a reference term that can be used to cancel the hunt
-%% using {@link dehunt/2}.
-%%
-%% raises: `badarg'
-%%
-%% @end
-%%------------------------------------------------------------------------------
--spec hunt(Port, HuntPath) -> Ref when
- Port :: mailbox(),
- HuntPath :: iodata(),
- Ref :: hunt_ref().
-hunt(Port, HuntPath) ->
- try port_command(Port, [?HUNT,HuntPath]) of
- true ->
- receive
- {ose_drv_reply,Port,{error,Error}} ->
- erlang:error(Error,[Port,HuntPath]);
- {ose_drv_reply,Port,Ref} ->
- Ref
- end
- catch error:_Error ->
- erlang:error(badarg,[Port,HuntPath])
- end.
-
-%%------------------------------------------------------------------------------
-%% @doc Stop hunting for OSE process.
-%%
-%% If a message for this hunt has been sent but not received
-%% by the calling process, it is removed from the message queue.
-%% Note that this only works if the same process that did
-%% the hunt does the dehunt.
-%%
-%% raises: `badarg'
-%%
-%% @see hunt/2
-%% @end
-%%------------------------------------------------------------------------------
--spec dehunt(Port, Ref) -> ok when
- Port :: mailbox(),
- Ref :: hunt_ref().
-dehunt(Port, {Port,Ref}) when ?INT_32BIT(Ref) ->
- try port_command(Port, <<?DEHUNT:8, Ref:32>>) of
- true ->
- receive
- {ose_drv_reply,Port,{error,enoent}} ->
- %% enoent could mean that it is in the message queue
- receive
- {mailbox_up, Port, {Port,Ref}, _} ->
- ok
- after 0 ->
- ok
- end;
- {ose_drv_reply,Port,ok} ->
- ok
- end
- catch error:_Error ->
- erlang:error(badarg,[Port,{Port,Ref}])
- end;
-dehunt(Port,Ref) ->
- erlang:error(badarg,[Port,Ref]).
-
-%%------------------------------------------------------------------------------
-%% @doc Attach to an OSE process.
-%%
-%% Will send `{mailbox_down, Port, Ref, MboxId}'
-%% to the calling process if the OSE process exits.
-%%
-%% Returns a reference that can be used to cancel the attachment
-%% using {@link detach/2}.
-%%
-%% raises: `badarg' | `enomem'
-%%
-%% @end
-%%------------------------------------------------------------------------------
--spec attach(Port,Pid) -> Ref when
- Port :: mailbox(),
- Pid :: mailbox_id(),
- Ref :: attach_ref().
-attach(Port, Spid) when ?INT_32BIT(Spid) ->
- try port_command(Port, <<?ATTACH:8, Spid:32>>) of
- true ->
- receive
- {ose_drv_reply,Port,{error,Error}} ->
- erlang:error(Error,[Port,Spid]);
- {ose_drv_reply,Port,Ref} ->
- Ref
- end
- catch error:_Error ->
- erlang:error(badarg,[Port,Spid])
- end;
-attach(Port,Spid) ->
- erlang:error(badarg,[Port,Spid]).
-
-
-%%------------------------------------------------------------------------------
-%% @doc Remove attachment to an OSE process.
-%%
-%% If a message for this monitor has been sent but not received
-%% by the calling process, it is removed from the message queue.
-%% Note that this only works of the same process
-%% that did the attach does the detach.
-%%
-%% raises: `badarg'
-%%
-%% @see attach/2
-%% @end
-%%------------------------------------------------------------------------------
--spec detach(Port,Ref) -> ok when
- Port :: mailbox(),
- Ref :: attach_ref().
-detach(Port, {Port,Ref} ) when ?INT_32BIT(Ref) ->
- try port_command(Port, <<?DETACH:8, Ref:32>>) of
- true ->
- receive
- {ose_drv_reply,Port,{error,enoent}} ->
- %% enoent could mean that it is in the message queue
- receive
- {mailbox_down,Port,{Port,Ref},_} ->
- ok
- after 0 ->
- ok
- end;
- {ose_drv_reply,Port,ok} ->
- ok
- end
- catch error:_Error ->
- erlang:error(badarg,[Port,{Port,Ref}])
- end;
-detach(Port,Ref) ->
- erlang:error(badarg,[Port,Ref]).
-
-%%------------------------------------------------------------------------------
-%% @doc Send an OSE message.
-%%
-%% The message is sent from the OSE process' own ID that is: `get_id(Port)'.
-%%
-%% raises: `badarg'
-%%
-%% @see send/5
-%% @end
-%%------------------------------------------------------------------------------
--spec send(Port,Pid,SigNo,SigData) -> ok when
- Port :: mailbox(),
- Pid :: mailbox_id(),
- SigNo :: message_number(),
- SigData :: iodata().
-send(Port, Spid, SigNo, SigData) when ?INT_32BIT(Spid), ?INT_32BIT(SigNo) ->
- try erlang:port_command(Port, [<<?SEND:8, Spid:32, SigNo:32>>, SigData]) of
- true -> ok
- catch error:_Error ->
- erlang:error(badarg,[Port,Spid,SigNo,SigData])
- end;
-send(Port,Spid,SigNo,SigData) ->
- erlang:error(badarg,[Port,Spid,SigNo,SigData]).
-
-
-%%------------------------------------------------------------------------------
-%% @doc Send an OSE message with different sender.
-%%
-%% As {@link send/4} but the sender will be `SenderPid'.
-%%
-%% raises: `badarg'
-%%
-%% @see send/4
-%% @end
-%%------------------------------------------------------------------------------
--spec send(Port,Pid,SenderPid,SigNo,SigData) -> ok when
- Port :: mailbox(),
- Pid :: mailbox_id(),
- SenderPid :: mailbox_id(),
- SigNo :: message_number(),
- SigData :: iodata().
-send(Port, Spid, SenderPid, SigNo, SigData)
- when ?INT_32BIT(Spid), ?INT_32BIT(SenderPid), ?INT_32BIT(SigNo) ->
- try erlang:port_command(Port, [<<?SEND_W_S:8, Spid:32, SenderPid:32,
- SigNo:32>>, SigData]) of
- true -> ok
- catch error:_Error ->
- erlang:error(badarg,[Port,Spid,SenderPid,SigNo,SigData])
- end;
-send(Port,Spid,SenderPid,SigNo,SigData) ->
- erlang:error(badarg,[Port,Spid,SenderPid,SigNo,SigData]).
-
-%%------------------------------------------------------------------------------
-%% @doc Start listening for specified OSE signal numbers.
-%%
-%% The mailbox will send `{message,Port,{FromMboxId,ToMboxId,MsgNo,MsgData}}'
-%% to the process that created the mailbox when an OSE message with any
-%% of the specified `SigNos' arrives.
-%%
-%% Repeated calls to listen will replace the current set of signal numbers to
-%% listen to. i.e
-%%
-%% ```1>ose:listen(MsgB,[1234,12345]).
-%% ok
-%% 2> ose:listen(MsgB,[1234,123456]).
-%% ok.'''
-%%
-%% The above will first listen for signals with numbers 1234 and 12345, and then
-%% replace that with only listening to 1234 and 123456.
-%%
-%% With the current implementation it is not possible to listen to all signal
-%% numbers.
-%%
-%% raises: `badarg' | `enomem'
-%%
-%% @end
-%%------------------------------------------------------------------------------
--spec listen(Port, SigNos) -> ok when
- Port :: mailbox(),
- SigNos :: list(message_number()).
-listen(Port, SigNos) when is_list(SigNos) ->
- USSigNos = lists:usort(SigNos),
- BinSigNos = try
- << <<SigNo:32>> ||
- SigNo <- USSigNos,
- ?INT_32BIT(SigNo) orelse erlang:error(badarg)
- >>
- catch _:_ ->
- erlang:error(badarg,[Port,SigNos])
- end,
- try port_command(Port, [?LISTEN, BinSigNos]) of
- true ->
- receive
- {ose_drv_reply,Port,{error,Error}} ->
- erlang:error(Error,[Port,SigNos]);
- {ose_drv_reply,Port,Else} ->
- Else
- end
- catch error:_Error ->
- erlang:error(badarg,[Port,SigNos])
- end;
-listen(Port, SigNos) ->
- erlang:error(badarg,[Port,SigNos]).
-
-
-%%%=============================================================================
-%%% Internal functions
-%%%=============================================================================
diff --git a/lib/ose/test/Makefile b/lib/ose/test/Makefile
deleted file mode 100644
index 7e2080ba38..0000000000
--- a/lib/ose/test/Makefile
+++ /dev/null
@@ -1,67 +0,0 @@
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-
-MODULES= \
- ose_SUITE
-
-ERL_FILES= $(MODULES:%=%.erl)
-
-TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
-
-INSTALL_PROGS= $(TARGET_FILES)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/ose_test
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-
-ERL_MAKE_FLAGS +=
-ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include \
- -I$(ERL_TOP)/lib/kernel/include
-
-EBIN = .
-
-EMAKEFILE=Emakefile
-COVERFILE=ose.cover
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-
-make_emakefile:
- $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES) \
- > $(EMAKEFILE)
-
-tests debug opt: make_emakefile
- erl $(ERL_MAKE_FLAGS) -make
-
-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
-
-release_tests_spec: make_emakefile
- $(INSTALL_DIR) "$(RELSYSDIR)"
- $(INSTALL_DATA) ose.spec $(EMAKEFILE) \
- $(ERL_FILES) $(COVERFILE) "$(RELSYSDIR)"
- chmod -R u+w "$(RELSYSDIR)"
- @tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -)
-
-release_docs_spec:
diff --git a/lib/ose/test/ose.cover b/lib/ose/test/ose.cover
deleted file mode 100644
index 7b846cfaf6..0000000000
--- a/lib/ose/test/ose.cover
+++ /dev/null
@@ -1,2 +0,0 @@
-%% -*- erlang -*-
-{incl_app,ose,details}.
diff --git a/lib/ose/test/ose.spec b/lib/ose/test/ose.spec
deleted file mode 100644
index c897e8cd16..0000000000
--- a/lib/ose/test/ose.spec
+++ /dev/null
@@ -1 +0,0 @@
-{suites,"../ose_test",all}.
diff --git a/lib/ose/test/ose_SUITE.erl b/lib/ose/test/ose_SUITE.erl
deleted file mode 100644
index 31d950bd03..0000000000
--- a/lib/ose/test/ose_SUITE.erl
+++ /dev/null
@@ -1,766 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2013. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES 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(ose_SUITE).
-
-%-compile(export_all).
-
--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([
- basic/1,stress/1,multi_msg_numbers/1,multi_mailboxes/1,
- hunt/1,multi_hunt/1,dehunt/1,multi_dehunt/1,
- attach/1,multi_attach/1,detach/1,multi_detach/1,
- open_errors/1,close_errors/1,get_id_errors/1,get_name_errors/1,
- hunt_errors/1,dehunt_errors/1,attach_errors/1,detach_errors/1,
- send_errors/1,send_w_s_errors/1,listen_errors/1
- ]).
-
--define(INTERFACE,ose).
-
-
-init_per_testcase(_Func, Config) ->
- Config.
-end_per_testcase(_Func, _Config) ->
- ok.
-
-suite() -> [{timeout,{30,seconds}}].
-
-all() ->
- [
- basic,stress,multi_msg_numbers,multi_mailboxes,
- hunt,multi_hunt,dehunt,multi_dehunt,
- attach,multi_attach,detach,multi_detach,
-
- open_errors,close_errors,get_id_errors,get_name_errors,
- hunt_errors,dehunt_errors,attach_errors,detach_errors,
- send_errors,send_w_s_errors,listen_errors
- ].
-
-groups() ->
- [].
-
-init_per_suite(Config) ->
- case os:type() of
- {ose,_} ->
- Config;
- _Else ->
- {skip,"Only run on OSE"}
- end.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-basic(_Config) ->
-
- [P1,P2] = multi_open(2,[42]),
- P1Id = ?INTERFACE:get_id(P1),
- P2Id = ?INTERFACE:get_id(P2),
-
- ok = ?INTERFACE:send(P2,P1Id,42,<<"ping">>),
- receive
- {message,P1,V1} ->
- {P2Id,P1Id,42,<<"ping">>} = V1,
- ?INTERFACE:send(P1,P2Id,42,<<"pong">>);
- Else1 ->
- ct:fail({got_wrong_message,Else1})
- end,
-
- receive
- {message,P2,V2} ->
- {P1Id,P2Id,42,<<"pong">>} = V2;
- Else2 ->
- ct:fail({got_wrong_message,Else2})
- end,
-
- ?INTERFACE:close(P1),
- ?INTERFACE:close(P2).
-
-%% Send 1000 messages and see if we can cope and that msg order is preserved
-stress(_Config) ->
-
- Iterations = 1000,
-
- [P1,P2] = multi_open(2,[42]),
- P1Id = ?INTERFACE:get_id(P1),
- P2Id = ?INTERFACE:get_id(P2),
-
- spawn(fun() ->
- n(fun(N) ->
- Msg = [<<"ping">>|integer_to_list(N)],
- ?INTERFACE:send(P2,P1Id,42,Msg)
- end,Iterations)
- end),
- timer:sleep(100),
- n(fun(N) ->
- receive
- {message,P1,Value} ->
- Int = integer_to_binary(N),
- {P2Id,P1Id,42,<<"ping",Int/binary>>} = Value,
- ok;
- Else ->
- ct:fail({got_wrong_message,Else})
- end
- end,Iterations),
-
- ?INTERFACE:close(P1),
- ?INTERFACE:close(P2).
-
-%% Listen to 1000 different message numbers and send some random messages
-multi_msg_numbers(_Config) ->
-
- Iterations = 100,
-
- [P1,P2] = multi_open(2,lists:seq(2000,3000)),
- P1Id = ?INTERFACE:get_id(P1),
-
- n(fun(_) ->
- Num = random:uniform(1000)+2000,
- ?INTERFACE:send(P2,P1Id,Num,<<"ping",(integer_to_binary(Num))/binary>>)
- end,Iterations),
-
- n(fun(_) ->
- receive
- {message,P1,{_,_,Id,<<"ping",Num/binary>>}} when Id > 2000;
- Id =< 3000 ->
- Id = binary_to_integer(Num),
- ok;
- Else ->
- ct:fail({got_wrong_message,Else})
- end
- end,Iterations),
-
- ?INTERFACE:close(P1),
- ?INTERFACE:close(P2).
-
-
-%% Create 100 mailboxes and send messages to them
-multi_mailboxes(_Config) ->
-
- Mailboxes = 100,
-
- [P1|MBs] = multi_open(Mailboxes,[42]),
-
- [?INTERFACE:send(P1,?INTERFACE:get_id(P),42,[<<"ping">>,?INTERFACE:get_name(P,?INTERFACE:get_id(P))]) || P <- MBs],
-
- [receive
- {message,P,Value} ->
- Name = ?INTERFACE:get_name(P,?INTERFACE:get_id(P)),
- {_,_,42,<<"ping",Name/binary>>} = Value,
- ok
- end || P <- MBs],
-
- [?INTERFACE:close(P) || P <- [P1|MBs]],
- ok.
-
-hunt(_Config) ->
- [P1,P2] = multi_open(2,[]),
-
- Ref = ?INTERFACE:hunt(P1,"p2"),
- receive
- {mailbox_up,P1,Ref,Pid} ->
- Pid = ?INTERFACE:get_id(P2),
- ?INTERFACE:close(P1),
- ?INTERFACE:close(P2);
- Else ->
- ct:fail({got_wrong_message,Else,Ref})
- end.
-
-multi_hunt(_Config) ->
-
- Iterations = 100,
-
- P = ?INTERFACE:open("p"),
-
- Refs = [?INTERFACE:hunt(P,"p"++integer_to_list(N))|| N <- lists:seq(1,Iterations)],
-
- Pids = [begin
- Prt = ?INTERFACE:open("p"++integer_to_list(N)),
- Pid = ?INTERFACE:get_id(Prt),
- ?INTERFACE:close(Prt),
- Pid
- end || N <- lists:seq(1,Iterations)],
-
- [receive
- {mailbox_up,P,Ref,Pid} ->
- ok
- after 10 ->
- ct:fail({did_not_get,Pid,Ref})
- end || {Pid,Ref} <- lists:zip(Pids,Refs)],
- ?INTERFACE:close(P).
-
-
-dehunt(_Config) ->
- [P1] = multi_open(1,[]),
- Ref = ?INTERFACE:hunt(P1,"p2"),
- receive
- _Else -> ct:fail({got,_Else})
- after 1000 ->
- ok
- end,
- P2 = ?INTERFACE:open("p2"),
-
- % Make sure any messages are sent
- receive after 10 -> ok end,
-
- ok = ?INTERFACE:dehunt(P1,Ref),
-
- % Make sure no messages are received
- receive
- _Else2 -> ct:fail({got,_Else2})
- after 1000 ->
- ?INTERFACE:close(P1),
- ?INTERFACE:close(P2)
- end.
-
-%%%
-%%% This testcase basically:
-%%% spawn 10 processes that in parallel
-%%% adds some hunts for different OSE processes
-%%% maybe create hunted OSE process
-%%% dehunt half of the hunts
-%%% create more hunts
-%%% if not created create hunted OSE process
-%%% veryify that all expected hunt messages are received
-%%% verify that all processes exited correctly
-%%%
-%%% This complex test is done to make sure that the internal handling
-%%% of dehunt works as expected.
-%%%
-multi_dehunt(_Config) ->
- [P1] = multi_open(1,[]),
-
- Scenario =
- fun(Iterations) ->
-
- Hunted = "p"++integer_to_list(Iterations),
- %% Start a couple of hunts
- Refs = [?INTERFACE:hunt(P1,Hunted) || _ <- lists:seq(1,Iterations)],
-
- %% We alternate if the process is opened before or after the dehunt
- P2O = if Iterations rem 2 == 0 ->
- ?INTERFACE:open(Hunted);
- true ->
- undefined
- end,
-
- %% Remove half of them
- {RemRefs,_} = lists:mapfoldl(fun(Ref,Acc) when Acc rem 2 == 0 ->
- ok = ?INTERFACE:dehunt(P1,Ref),
- {[],Acc+1};
- (Ref,Acc) ->
- {Ref,Acc+1}
- end,0,Refs),
-
- %% Add some new ones
- NewRefs = [?INTERFACE:hunt(P1,Hunted)
- || _ <- lists:seq(1,Iterations div 4)]
- ++ lists:flatten(RemRefs),
-
- P2 = if P2O == undefined ->
- ?INTERFACE:open(Hunted);
- true ->
- P2O
- end,
- P2Id = ?INTERFACE:get_id(P2),
-
- %% Receive all the expected ones
- lists:foreach(fun(Ref) ->
- receive
- {mailbox_up,P1,Ref,P2Id} ->
- ok
- after 1000 ->
- io:format("Flush: ~p~n",[flush()]),
- io:format("~p~n",[{Iterations,{did_not_get, Ref}}]),
- ok = Ref
- end
- end,NewRefs),
-
- %% Check that no other have arrived
- receive
- _Else ->
- io:format("Flush: ~p~n",[flush()]),
- io:format("~p~n",[{Iterations,{got, _Else}}]),
- ok = _Else
- after 100 ->
- ok
- end,
- ?INTERFACE:close(P2)
- end,
-
- Self = self(),
-
- n(fun(N) ->
- spawn(fun() -> Self !
- Scenario(N*25)
- end),
- ok
- end,10),
-
- n(fun(_N) ->
- receive ok -> ok
- after 60000 -> ct:fail(failed)
- end
- end,10),
- ?INTERFACE:close(P1).
-
-attach(_Config) ->
- [P1,P2] = multi_open(2,[]),
-
- P2Id = ?INTERFACE:get_id(P2),
- Ref = ?INTERFACE:attach(P1,P2Id),
- ?INTERFACE:close(P2),
- receive
- {mailbox_down,P1,Ref,P2Id} ->
- ?INTERFACE:close(P1);
- _Else ->
- ct:fail({got,_Else, {P1,Ref,P2Id}})
- after 1000 ->
- ct:fail({did_not_get,P1,Ref,P2Id})
- end.
-
-multi_attach(_Config) ->
-
- Iterations = 100,
-
- [P1|Pids] = multi_open(Iterations,[]),
-
- Refs = [{?INTERFACE:get_id(Pid),?INTERFACE:attach(P1,?INTERFACE:get_id(Pid))} || Pid <- Pids],
-
- [?INTERFACE:close(Pid) || Pid <- Pids],
-
- [receive
- {mailbox_down,P1,Ref,Pid} ->
- ok
- after 10000 ->
- ct:fail({did_not_get,Pid,Ref})
- end || {Pid,Ref} <- Refs],
- ?INTERFACE:close(P1).
-
-detach(_Config) ->
- [P1,P2] = multi_open(2,[]),
- P2Id = ?INTERFACE:get_id(P2),
- Ref = ?INTERFACE:attach(P1,P2Id),
- receive
- _Else -> ct:fail({got,_Else})
- after 100 ->
- ok
- end,
-
- ?INTERFACE:close(P2),
-
- % Make sure any messages are sent
- receive after 10 -> ok end,
-
- ?INTERFACE:detach(P1,Ref),
-
- % Make sure no messages are received
- receive
- _Else2 -> ct:fail({got,_Else2})
- after 1000 ->
- ?INTERFACE:close(P1)
- end.
-
-%%%
-%%% This testcase basically:
-%%% spawn 10 processes that in parallel
-%%% adds some attach for different OSE processes
-%%% maybe close OSE process
-%%% dehunt half of the hunts
-%%% create more hunts
-%%% if not closed close attached OSE process
-%%% veryify that all expected attach messages are received
-%%% verify that all processes exited correctly
-%%%
-%%% This complex test is done to make sure that the internal handling
-%%% of dehunt works as expected.
-%%%
-multi_detach(_Config) ->
- [P1] = multi_open(1,[]),
-
- Scenario =
- fun(Iterations) ->
-
- Attached = ?INTERFACE:open("p"++integer_to_list(Iterations)),
- AttachedId = ?INTERFACE:get_id(Attached),
- %% Start a couple of attachs
- Refs = [?INTERFACE:attach(P1,AttachedId) || _ <- lists:seq(1,Iterations)],
-
- %% We alternate if the process is closed before or after the detach
- P2O = if Iterations rem 2 == 0 ->
- ?INTERFACE:close(Attached);
- true ->
- undefined
- end,
-
- %% Remove half of them
- {RemRefs,_} = lists:mapfoldl(fun(Ref,Acc) when Acc rem 2 == 0 ->
- ok = ?INTERFACE:detach(P1,Ref),
- {[],Acc+1};
- (Ref,Acc) ->
- {Ref,Acc+1}
- end,0,Refs),
-
- %% Add some new ones
- NewRefs = [?INTERFACE:attach(P1,AttachedId)
- || _ <- lists:seq(1,Iterations div 4)]
- ++ lists:flatten(RemRefs),
-
- if P2O == undefined ->
- ?INTERFACE:close(Attached);
- true ->
- P2O
- end,
-
- %% Receive all the expected ones
- lists:foreach(fun(Ref) ->
- receive
- {mailbox_down,P1,Ref,AttachedId} ->
- ok
- after 1000 ->
- io:format("Flush: ~p~n",[flush()]),
- io:format("~p~n",[{Iterations,{did_not_get, Ref}}]),
- ok = Ref
- end
- end,NewRefs),
-
- %% Check that no other have arrived
- receive
- _Else ->
- io:format("Flush: ~p~n",[flush()]),
- io:format("~p~n",[{Iterations,{got, _Else}}]),
- ok = _Else
- after 100 ->
- ok
- end
- end,
-
- Self = self(),
-
- n(fun(N) ->
- spawn(fun() -> Self !
- Scenario(N*5)
- end),
- ok
- end,10),
-
- n(fun(_N) ->
- receive ok -> ok
- after 60000 -> ct:fail(failed)
- end
- end,10),
- ?INTERFACE:close(P1).
-
-
-open_errors(_Config) ->
- {'EXIT',{badarg,[{?INTERFACE,open,[inval],_}|_]}} =
- (catch ?INTERFACE:open(inval)),
- {'EXIT',{badarg,[{?INTERFACE,open,[["p"|1]],_}|_]}} =
- (catch ?INTERFACE:open(["p"|1])),
- {'EXIT',{badarg,[{?INTERFACE,open,[["p",1234]],_}|_]}} =
- (catch ?INTERFACE:open(["p",1234])),
-
- ok.
-
-close_errors(_Config) ->
- {'EXIT',{badarg,[{?INTERFACE,close,[inval],_}|_]}} =
- (catch ?INTERFACE:close(inval)),
-
- P1 = ?INTERFACE:open("p1"),
- ok = ?INTERFACE:close(P1),
- ok = ?INTERFACE:close(P1).
-
-
-get_id_errors(_Config) ->
- {'EXIT',{badarg,[{?INTERFACE,get_id,[inval],_}|_]}} =
- (catch ?INTERFACE:get_id(inval)),
-
- P1 = ?INTERFACE:open("p1"),
- ok = ?INTERFACE:close(P1),
- {'EXIT',{badarg,[{?INTERFACE,get_id,[P1],_}|_]}} =
- (catch ?INTERFACE:get_id(P1)),
-
- ok.
-
-get_name_errors(_Config) ->
- P1 = ?INTERFACE:open("p1"),
- {'EXIT',{badarg,[{?INTERFACE,get_name,[P1,inval],_}|_]}} =
- (catch ?INTERFACE:get_name(P1,inval)),
-
- undefined = ?INTERFACE:get_name(P1,1234),
-
- P2 = ?INTERFACE:open("p2"),
- P2Id = ?INTERFACE:get_id(P2),
- ok = ?INTERFACE:close(P1),
- {'EXIT',{badarg,[{?INTERFACE,get_name,[P1,P2Id],_}|_]}} =
- (catch ?INTERFACE:get_name(P1,P2Id)),
- ?INTERFACE:close(P2),
-
- P3 = ?INTERFACE:open([255]),
- <<255>> = ?INTERFACE:get_name(P3, ?INTERFACE:get_id(P3)),
- ?INTERFACE:close(P3),
-
- ok.
-
-hunt_errors(_Config) ->
-
- {'EXIT',{badarg,[{?INTERFACE,hunt,[inval,"hello"],_}|_]}} =
- (catch ?INTERFACE:hunt(inval,"hello")),
-
- P1 = ?INTERFACE:open("p1"),
- {'EXIT',{badarg,[{?INTERFACE,hunt,[P1,["hello",12345]],_}|_]}} =
- (catch ?INTERFACE:hunt(P1,["hello",12345])),
-
- P2 = ?INTERFACE:open(<<255>>),
- P2Pid = ?INTERFACE:get_id(P2),
- Ref = ?INTERFACE:hunt(P1,[255]),
- receive
- {mailbox_up,P1,Ref,P2Pid} ->
- ok;
- Else ->
- ct:fail({got,Else,{mailbox_up,P1,Ref,P2Pid}})
- after 150 ->
- ct:fail({did_not_get,{mailbox_up,P1,Ref,P2Pid}})
- end,
-
- ok = ?INTERFACE:close(P1),
- ok = ?INTERFACE:close(P2),
- {'EXIT',{badarg,[{?INTERFACE,hunt,[P1,["hello"]],_}|_]}} =
- (catch ?INTERFACE:hunt(P1,["hello"])),
-
- ok.
-
-dehunt_errors(_Config) ->
- P1 = ?INTERFACE:open("p1"),
- Ref = ?INTERFACE:hunt(P1,"p2"),
-
- {'EXIT',{badarg,[{?INTERFACE,dehunt,[inval,Ref],_}|_]}} =
- (catch ?INTERFACE:dehunt(inval,Ref)),
-
- {'EXIT',{badarg,[{?INTERFACE,dehunt,[P1,inval],_}|_]}} =
- (catch ?INTERFACE:dehunt(P1,inval)),
-
- ok = ?INTERFACE:dehunt(P1,Ref),
- ok = ?INTERFACE:dehunt(P1,Ref),
-
- ok = ?INTERFACE:close(P1),
-
- {'EXIT',{badarg,[{?INTERFACE,dehunt,[P1,Ref],_}|_]}} =
- (catch ?INTERFACE:dehunt(P1,Ref)),
-
- case ?INTERFACE of
- ose -> ok;
- _ ->
- P2 = ?INTERFACE:open("p2"),
- ok = ?INTERFACE:close(P2)
- end,
-
- receive
- Else -> ct:fail({got,Else})
- after 100 ->
- ok
- end.
-
-attach_errors(_Config) ->
- P1 = ?INTERFACE:open("p1"),
- P2 = ?INTERFACE:open("p2"),
- P2Id = ?INTERFACE:get_id(P2),
-
- {'EXIT',{badarg,[{?INTERFACE,attach,[inval,P2Id],_}|_]}} =
- (catch ?INTERFACE:attach(inval,P2Id)),
-
- {'EXIT',{badarg,[{?INTERFACE,attach,[P1,[12345]],_}|_]}} =
- (catch ?INTERFACE:attach(P1,[12345])),
-
- ok = ?INTERFACE:close(P1),
- ok = ?INTERFACE:close(P2),
- {'EXIT',{badarg,[{?INTERFACE,attach,[P1,P2Id],_}|_]}} =
- (catch ?INTERFACE:attach(P1,P2Id)),
-
- ok.
-
-detach_errors(_Config) ->
- P1 = ?INTERFACE:open("p1"),
- P2 = ?INTERFACE:open("p2"),
- P2Id = ?INTERFACE:get_id(P2),
-
- Ref = ?INTERFACE:attach(P1,P2Id),
-
- {'EXIT',{badarg,[{?INTERFACE,detach,[inval,Ref],_}|_]}} =
- (catch ?INTERFACE:detach(inval,Ref)),
-
- {'EXIT',{badarg,[{?INTERFACE,detach,[P1,inval],_}|_]}} =
- (catch ?INTERFACE:detach(P1,inval)),
-
- ok = ?INTERFACE:detach(P1,Ref),
- ok = ?INTERFACE:detach(P1,Ref),
-
- case ?INTERFACE of
- ose -> ok;
- _ ->
- ok = ?INTERFACE:close(P1)
- end,
-
- ok = ?INTERFACE:close(P2),
- ok = ?INTERFACE:close(P1),
-
- {'EXIT',{badarg,[{?INTERFACE,detach,[P1,Ref],_}|_]}} =
- (catch ?INTERFACE:detach(P1,Ref)),
-
- receive
- Else -> ct:fail({got,Else})
- after 100 ->
- ok
- end.
-
-send_errors(_Config) ->
- P1 = ?INTERFACE:open("p1"),
- P2 = ?INTERFACE:open("p2"),
- P2Id = ?INTERFACE:get_id(P2),
-
- {'EXIT',{badarg,[{?INTERFACE,send,[inval,P2Id,42,"hello"],_}|_]}} =
- (catch ?INTERFACE:send(inval,P2Id,42,"hello")),
- {'EXIT',{badarg,[{?INTERFACE,send,[P1,inval,42,"hello"],_}|_]}} =
- (catch ?INTERFACE:send(P1,inval,42,"hello")),
- {'EXIT',{badarg,[{?INTERFACE,send,[P1,P2Id,inval,"hello"],_}|_]}} =
- (catch ?INTERFACE:send(P1,P2Id,inval,"hello")),
- {'EXIT',{badarg,[{?INTERFACE,send,[P1,P2Id,42,inval],_}|_]}} =
- (catch ?INTERFACE:send(P1,P2Id,42,inval)),
-
- ok = ?INTERFACE:close(P2),
- ok = ?INTERFACE:send(P1,P2Id,42,"hello"),
- ok = ?INTERFACE:close(P1),
-
- {'EXIT',{badarg,[{?INTERFACE,send,[P1,P2Id,42,"hello"],_}|_]}} =
- (catch ?INTERFACE:send(P1,P2Id,42,"hello")),
-
- receive
- Else -> ct:fail({got,Else})
- after 100 ->
- ok
- end.
-
-send_w_s_errors(_Config) ->
- P1 = ?INTERFACE:open("p1"),
- P1Id = ?INTERFACE:get_id(P1),
- P2 = ?INTERFACE:open("p2"),
- P2Id = ?INTERFACE:get_id(P2),
- P3 = ?INTERFACE:open("p3"),
- P3Id = ?INTERFACE:get_id(P3),
-
- {'EXIT',{badarg,[{?INTERFACE,send,[inval,P2Id,P1Id,42,"hello"],_}|_]}} =
- (catch ?INTERFACE:send(inval,P2Id,P1Id,42,"hello")),
- {'EXIT',{badarg,[{?INTERFACE,send,[P2,-1,P1Id,42,"hello"],_}|_]}} =
- (catch ?INTERFACE:send(P2,-1,P1Id,42,"hello")),
- {'EXIT',{badarg,[{?INTERFACE,send,[P2,P2Id,1 bsl 32,42,"hello"],_}|_]}} =
- (catch ?INTERFACE:send(P2,P2Id,1 bsl 32,42,"hello")),
- {'EXIT',{badarg,[{?INTERFACE,send,[P2,P2Id,P1Id,inval,"hello"],_}|_]}} =
- (catch ?INTERFACE:send(P2,P2Id,P1Id,inval,"hello")),
- {'EXIT',{badarg,[{?INTERFACE,send,[P2,P2Id,P1Id,42,inval],_}|_]}} =
- (catch ?INTERFACE:send(P2,P2Id,P1Id,42,inval)),
-
- ok = ?INTERFACE:close(P3),
- ok = ?INTERFACE:send(P2,P3Id,P1Id,42,"hello"),
-
- ok = ?INTERFACE:close(P1),
- ok = ?INTERFACE:send(P2,P2Id,P1Id,42,"hello"),
- ok = ?INTERFACE:close(P2),
-
- {'EXIT',{badarg,[{?INTERFACE,send,[P1,P2Id,P1Id,42,"hello"],_}|_]}} =
- (catch ?INTERFACE:send(P1,P2Id,P1Id,42,"hello")),
-
- receive
- Else -> ct:fail({got,Else})
- after 100 ->
- ok
- end.
-
-listen_errors(_Config) ->
-
- P1 = ?INTERFACE:open("p1"),
- P1Id = ?INTERFACE:get_id(P1),
-
- {'EXIT',{badarg,[{?INTERFACE,listen,[inval,[42]],_}|_]}} =
- (catch ?INTERFACE:listen(inval,[42])),
- {'EXIT',{badarg,[{?INTERFACE,listen,[P1,inval],_}|_]}} =
- (catch ?INTERFACE:listen(P1,inval)),
- {'EXIT',{badarg,[{?INTERFACE,listen,[P1,[1 bsl 33]],_}|_]}} =
- (catch ?INTERFACE:listen(P1,[1 bsl 33])),
-
- ok = ?INTERFACE:listen(P1,[42,42,42,42,42,42,42,42,42,42,42,42,42]),
-
- case ?INTERFACE of
- ose -> ok;
- _ ->
- ?INTERFACE:send(P1,P1Id,42,"hello"),
- timer:sleep(50),
- ?INTERFACE:listen(P1,[]),
- ?INTERFACE:send(P1,P1Id,42,"hello2"),
-
- receive
- {message,P1,42,"hello"} -> ok
- end,
-
- receive
- Else -> ct:fail({got,Else})
- after 100 ->
- ok
- end
- end,
-
- ok = ?INTERFACE:close(P1),
- {'EXIT',{badarg,[{?INTERFACE,listen,[P1,[42]],_}|_]}} =
- (catch ?INTERFACE:listen(P1,[42])),
-
- ok.
-
-%%
-%% Internal functions
-%%
-multi_open(N,ListenNums) ->
- multi_open(N,ListenNums,[]).
-
-multi_open(0,_,Acc) ->
- Acc;
-multi_open(N,ListenNums,Acc) ->
- P = ?INTERFACE:open("p"++integer_to_list(N)),
- ok = ?INTERFACE:listen(P,ListenNums),
- multi_open(N-1,ListenNums,[P|Acc]).
-
-n(_F,0) ->
- ok;
-n(F,N) ->
- ok = F(N),
- n(F,N-1).
-
-
-flush() ->
- receive
- Msg ->
- [Msg|flush()]
- after 0 ->
- []
- end.
diff --git a/lib/ose/vsn.mk b/lib/ose/vsn.mk
deleted file mode 100644
index fb1cf8219f..0000000000
--- a/lib/ose/vsn.mk
+++ /dev/null
@@ -1 +0,0 @@
-OSE_VSN = 1.1
diff --git a/lib/public_key/doc/src/public_key.xml b/lib/public_key/doc/src/public_key.xml
index 394fe54428..209de2bdf7 100644
--- a/lib/public_key/doc/src/public_key.xml
+++ b/lib/public_key/doc/src/public_key.xml
@@ -108,8 +108,9 @@
<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>
+ <p><c>| 'EcpkParameters'</c></p>
</item>
<tag><c>pem_entry () =</c></tag>
@@ -433,7 +434,7 @@
<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'{}</v>
+ <v>Cert = der_encoded() | #'OTPCertificate'{} | #'CertificateList'{}</v>
<v>IssuerCert = der_encoded() | #'OTPCertificate'{}</v>
</type>
<desc>
@@ -698,7 +699,7 @@ fun(#'DistributionPoint'{}, #'CertificateList'{},
<name>pkix_sign(#'OTPTBSCertificate'{}, Key) -> der_encoded()</name>
<fsummary>Signs certificate.</fsummary>
<type>
- <v>Key = rsa_public_key() | dsa_public_key()</v>
+ <v>Key = rsa_private_key() | dsa_private_key()</v>
</type>
<desc>
<p>Signs an 'OTPTBSCertificate'. Returns the corresponding
@@ -713,7 +714,7 @@ fun(#'DistributionPoint'{}, #'CertificateList'{},
<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</v>
+ <v>SignatureType = rsa | dsa | ecdsa</v>
</type>
<desc>
<p>Translates signature algorithm OID to Erlang digest and signature types.
@@ -726,7 +727,7 @@ fun(#'DistributionPoint'{}, #'CertificateList'{},
<fsummary>Verifies PKIX x.509 certificate signature.</fsummary>
<type>
<v>Cert = der_encoded()</v>
- <v>Key = rsa_public_key() | dsa_public_key()</v>
+ <v>Key = rsa_public_key() | dsa_public_key() | ec_public_key()</v>
</type>
<desc>
<p>Verifies PKIX x.509 certificate signature.</p>
diff --git a/lib/runtime_tools/c_src/Makefile.in b/lib/runtime_tools/c_src/Makefile.in
index 448b8c62c2..aeacee0655 100644
--- a/lib/runtime_tools/c_src/Makefile.in
+++ b/lib/runtime_tools/c_src/Makefile.in
@@ -102,12 +102,7 @@ endif
_create_dirs := $(shell mkdir -p $(OBJDIR) $(LIBDIR))
-ifneq ($(findstring ose,$(TARGET)),ose)
debug opt valgrind: $(SOLIBS) $(OBJDIR) $(LIBDIR) $(NIF_LIB)
-else
-# We do not build this on OSE
-debug opt valgrind:
-endif
DYNTRACE_OBJS = $(before_DTrace_OBJS)
@@ -159,10 +154,8 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
$(INSTALL_DIR) "$(RELSYSDIR)/priv/obj"
$(INSTALL_DIR) "$(RELSYSDIR)/priv/lib"
-ifneq ($(findstring ose,$(TARGET)),ose)
$(INSTALL_PROGRAM) $(DYNTRACE_OBJS) "$(RELSYSDIR)/priv/obj"
$(INSTALL_PROGRAM) $(NIF_LIB) $(SOLIBS) "$(RELSYSDIR)/priv/lib"
-endif
release_docs_spec:
diff --git a/lib/runtime_tools/c_src/trace_file_drv.c b/lib/runtime_tools/c_src/trace_file_drv.c
index 7549161e05..a63a7d3ad9 100644
--- a/lib/runtime_tools/c_src/trace_file_drv.c
+++ b/lib/runtime_tools/c_src/trace_file_drv.c
@@ -327,9 +327,11 @@ static ErlDrvData trace_file_start(ErlDrvPort port, char *buff)
| O_BINARY
#endif
, 0777)) < 0) {
+ int saved_errno = errno;
if (wrap)
driver_free(wrap);
driver_free(data);
+ errno = saved_errno;
return ERL_DRV_ERROR_ERRNO;
}
@@ -525,14 +527,19 @@ static void *my_alloc(size_t size)
** A write wrapper that regards it as an error if not all data was written.
*/
static int do_write(FILETYPE fd, unsigned char *buff, int siz) {
- int w = write(fd, buff, siz);
- if (w != siz) {
- if (w >= 0) {
- errno = ENOSPC;
+ int w;
+ while (1) {
+ w = write(fd, buff, siz);
+ if (w < 0 && errno == EINTR)
+ continue;
+ else if (w != siz) {
+ if (w >= 0) {
+ errno = ENOSPC;
+ }
+ return -1;
}
- return -1;
+ return siz;
}
- return siz;
}
/*
@@ -627,8 +634,10 @@ static void close_unlink_port(TraceFileData *data)
*/
static int wrap_file(TraceFileData *data) {
if (my_flush(data) < 0) {
+ int saved_errno = errno;
close(data->fd);
data->fd = -1;
+ errno = saved_errno;
return -1;
}
close(data->fd);
@@ -644,12 +653,15 @@ static int wrap_file(TraceFileData *data) {
next_name(&data->wrap->del);
}
next_name(&data->wrap->cur);
+try_open:
data->fd = open(data->wrap->cur.name, O_WRONLY | O_TRUNC | O_CREAT
#ifdef O_BINARY
| O_BINARY
#endif
, 0777);
if (data->fd < 0) {
+ if (errno == EINTR)
+ goto try_open;
data->fd = -1;
return -1;
}
diff --git a/lib/runtime_tools/doc/src/notes.xml b/lib/runtime_tools/doc/src/notes.xml
index 71b244ec6b..5aebea98ce 100644
--- a/lib/runtime_tools/doc/src/notes.xml
+++ b/lib/runtime_tools/doc/src/notes.xml
@@ -32,6 +32,23 @@
<p>This document describes the changes made to the Runtime_Tools
application.</p>
+<section><title>Runtime_Tools 1.9.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The <c>trace_file_drv</c> did not handle <c>EINTR</c>
+ correct which caused it to fail when the runtime system
+ received a signal.</p>
+ <p>
+ Own Id: OTP-12890 Aux Id: seq12885 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Runtime_Tools 1.9</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/runtime_tools/vsn.mk b/lib/runtime_tools/vsn.mk
index 3aadc46ab6..83e3612561 100644
--- a/lib/runtime_tools/vsn.mk
+++ b/lib/runtime_tools/vsn.mk
@@ -1 +1 @@
-RUNTIME_TOOLS_VSN = 1.9
+RUNTIME_TOOLS_VSN = 1.9.1
diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml
index d24025ca4d..cf5e8f1aff 100644
--- a/lib/ssh/doc/src/ssh.xml
+++ b/lib/ssh/doc/src/ssh.xml
@@ -43,7 +43,7 @@
<item>Supported public key algorithms: ssh-rsa and ssh-dss.</item>
<item>Supported MAC algorithms: hmac-sha2-256 and hmac-sha1.</item>
<item>Supported encryption algorithms: aes128-ctr, aes128-cb and 3des-cbc.</item>
- <item>Supported key exchange algorithms: diffie-hellman-group1-sha1.</item>
+ <item>Supported key exchange algorithms: diffie-hellman-group1-sha1, diffie-hellman-group14-sha1, diffie-hellman-group-exchange-sha1 and diffie-hellman-group-exchange-sha256.</item>
<item>Supported compression algorithms: none, zlib, [email protected],</item>
<item>Supports unicode filenames if the emulator and the underlaying OS support it.
See section DESCRIPTION in the
@@ -240,6 +240,13 @@ kex is implicit but public_key is set explicitly.</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>{512, 1024, 4096}</c>.
+ </p>
+ </item>
+
<tag><c><![CDATA[{connect_timeout, timeout()}]]></c></tag>
<item>
<p>Sets a time-out on the transport layer
@@ -449,6 +456,15 @@ kex is implicit but public_key is set explicitly.</p>
</warning>
</item>
+ <tag><c><![CDATA[{dh_gex_groups, [{Size=integer(),G=integer(),P=integer()}] | {file,filename()} }]]></c></tag>
+ <item>
+ <p>Sets the groups that the server may choose among when diffie-hellman-group-exchange is negotiated.
+ See RFC 4419 for details.
+ </p>
+ <p>If the parameter is <c>{file,filename()}</c>, the file must exist and have one or more three-tuples terminated by a dot. The interpretation is as if the tuples had been given directly in the option. The file is read when the daemon starts.
+ </p>
+ </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
diff --git a/lib/ssh/src/Makefile b/lib/ssh/src/Makefile
index 61d71d2cf7..98fb90d7c4 100644
--- a/lib/ssh/src/Makefile
+++ b/lib/ssh/src/Makefile
@@ -67,7 +67,6 @@ MODULES= \
ssh_file \
ssh_io \
ssh_info \
- ssh_math \
ssh_message \
ssh_no_io \
ssh_sftp \
diff --git a/lib/ssh/src/ssh.app.src b/lib/ssh/src/ssh.app.src
index bc01c539e0..4a76fd9cd3 100644
--- a/lib/ssh/src/ssh.app.src
+++ b/lib/ssh/src/ssh.app.src
@@ -24,7 +24,6 @@
ssh_file,
ssh_io,
ssh_info,
- ssh_math,
ssh_no_io,
ssh_server_key_api,
ssh_sftp,
diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl
index 370f086600..5b2e0a988c 100644
--- a/lib/ssh/src/ssh.erl
+++ b/lib/ssh/src/ssh.erl
@@ -373,6 +373,10 @@ handle_option([{auth_method_kb_interactive_data, _} = Opt | Rest], SocketOptions
handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
handle_option([{preferred_algorithms,_} = Opt | Rest], SocketOptions, SshOptions) ->
handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+handle_option([{dh_gex_groups,_} = Opt | Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+handle_option([{dh_gex_limits,_} = Opt | Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
handle_option([{quiet_mode, _} = Opt|Rest], SocketOptions, SshOptions) ->
handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
handle_option([{idle_time, _} = Opt | Rest], SocketOptions, SshOptions) ->
@@ -411,6 +415,28 @@ handle_ssh_option({user_interaction, Value} = Opt) when is_boolean(Value) ->
Opt;
handle_ssh_option({preferred_algorithms,[_|_]} = Opt) ->
handle_pref_algs(Opt);
+handle_ssh_option({dh_gex_groups,L=[{I1,I2,I3}|_]}) when is_integer(I1), I1>0,
+ is_integer(I2), I2>0,
+ is_integer(I3), I3>0 ->
+ {dh_gex_groups, lists:map(fun({N,G,P}) -> {N,{G,P}} end, L)};
+handle_ssh_option({dh_gex_groups,{file,File=[C|_]}}=Opt) when is_integer(C), C>0 ->
+ %% A string, (file name)
+ case file:consult(File) of
+ {ok, List} ->
+ try handle_ssh_option({dh_gex_groups,List}) of
+ {dh_gex_groups,_} = NewOpt ->
+ NewOpt
+ catch
+ _:_ ->
+ throw({error, {{eoptions, Opt}, "Bad format in file"}})
+ end;
+ Error ->
+ throw({error, {{eoptions, Opt},{"Error reading file",Error}}})
+ end;
+handle_ssh_option({dh_gex_limits,{Min,I,Max}} = Opt) when is_integer(Min), Min>0,
+ is_integer(I), I>=Min,
+ is_integer(Max), Max>=I ->
+ Opt;
handle_ssh_option({connect_timeout, Value} = Opt) when is_integer(Value); Value == infinity ->
Opt;
handle_ssh_option({max_sessions, Value} = Opt) when is_integer(Value), Value>0 ->
diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl
index a9c60d0674..c059834b27 100644
--- a/lib/ssh/src/ssh_connection_handler.erl
+++ b/lib/ssh/src/ssh_connection_handler.erl
@@ -46,7 +46,9 @@
get_print_info/1]).
%% gen_fsm callbacks
--export([hello/2, kexinit/2, key_exchange/2, new_keys/2,
+-export([hello/2, kexinit/2, key_exchange/2,
+ key_exchange_dh_gex_init/2, key_exchange_dh_gex_reply/2,
+ new_keys/2,
userauth/2, connected/2,
error/2]).
@@ -417,27 +419,39 @@ key_exchange(#ssh_msg_kexdh_reply{} = Msg,
send_msg(NewKeys, State),
{next_state, new_keys, next_packet(State#state{ssh_params = Ssh})};
-key_exchange(#ssh_msg_kex_dh_gex_group{} = Msg,
+key_exchange(#ssh_msg_kex_dh_gex_request{} = Msg,
#state{ssh_params = #ssh{role = server} = Ssh0} = State) ->
- {ok, NextKexMsg, Ssh1} = ssh_transport:handle_kex_dh_gex_group(Msg, Ssh0),
- send_msg(NextKexMsg, State),
- {ok, NewKeys, Ssh} = ssh_transport:new_keys_message(Ssh1),
- send_msg(NewKeys, State),
- {next_state, new_keys, next_packet(State#state{ssh_params = Ssh})};
+ {ok, GexGroup, Ssh} = ssh_transport:handle_kex_dh_gex_request(Msg, Ssh0),
+ send_msg(GexGroup, State),
+ {next_state, key_exchange_dh_gex_init, next_packet(State#state{ssh_params = Ssh})};
-key_exchange(#ssh_msg_kex_dh_gex_request{} = Msg,
+key_exchange(#ssh_msg_kex_dh_gex_group{} = Msg,
#state{ssh_params = #ssh{role = client} = Ssh0} = State) ->
- {ok, NextKexMsg, Ssh} = ssh_transport:handle_kex_dh_gex_request(Msg, Ssh0),
- send_msg(NextKexMsg, State),
- {next_state, new_keys, next_packet(State#state{ssh_params = Ssh})};
+ {ok, KexGexInit, Ssh} = ssh_transport:handle_kex_dh_gex_group(Msg, Ssh0),
+ send_msg(KexGexInit, State),
+ {next_state, key_exchange_dh_gex_reply, next_packet(State#state{ssh_params = Ssh})}.
-key_exchange(#ssh_msg_kex_dh_gex_reply{} = Msg,
- #state{ssh_params = #ssh{role = client} = Ssh0} = State) ->
- {ok, NewKeys, Ssh} = ssh_transport:handle_kex_dh_gex_reply(Msg, Ssh0),
+%%--------------------------------------------------------------------
+-spec key_exchange_dh_gex_init(#ssh_msg_kex_dh_gex_init{}, #state{}) -> gen_fsm_state_return().
+%%--------------------------------------------------------------------
+key_exchange_dh_gex_init(#ssh_msg_kex_dh_gex_init{} = Msg,
+ #state{ssh_params = #ssh{role = server} = Ssh0} = State) ->
+ {ok, KexGexReply, Ssh1} = ssh_transport:handle_kex_dh_gex_init(Msg, Ssh0),
+ send_msg(KexGexReply, State),
+ {ok, NewKeys, Ssh} = ssh_transport:new_keys_message(Ssh1),
send_msg(NewKeys, State),
{next_state, new_keys, next_packet(State#state{ssh_params = Ssh})}.
%%--------------------------------------------------------------------
+-spec key_exchange_dh_gex_reply(#ssh_msg_kex_dh_gex_reply{}, #state{}) -> gen_fsm_state_return().
+%%--------------------------------------------------------------------
+key_exchange_dh_gex_reply(#ssh_msg_kex_dh_gex_reply{} = Msg,
+ #state{ssh_params = #ssh{role = client} = Ssh0} = State) ->
+ {ok, NewKeys, Ssh1} = ssh_transport:handle_kex_dh_gex_reply(Msg, Ssh0),
+ send_msg(NewKeys, State),
+ {next_state, new_keys, next_packet(State#state{ssh_params = Ssh1})}.
+
+%%--------------------------------------------------------------------
-spec new_keys(#ssh_msg_newkeys{}, #state{}) -> gen_fsm_state_return().
%%--------------------------------------------------------------------
diff --git a/lib/ssh/src/ssh_math.erl b/lib/ssh/src/ssh_math.erl
deleted file mode 100644
index cace85bc93..0000000000
--- a/lib/ssh/src/ssh_math.erl
+++ /dev/null
@@ -1,42 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2013. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES 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: SSH math utilities
-
--module(ssh_math).
-
--export([ipow/3]).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% INTEGER utils
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%% calculate A^B mod M
-ipow(A, B, M) when M > 0, B >= 0 ->
- crypto:bytes_to_integer(crypto:mod_pow(A, B, M)).
-
-
-
-
-
diff --git a/lib/ssh/src/ssh_message.erl b/lib/ssh/src/ssh_message.erl
index 1f0f6fb15f..7b786b8fff 100644
--- a/lib/ssh/src/ssh_message.erl
+++ b/lib/ssh/src/ssh_message.erl
@@ -237,7 +237,7 @@ encode(#ssh_msg_kex_dh_gex_request{
max = Max
}) ->
ssh_bits:encode([?SSH_MSG_KEX_DH_GEX_REQUEST, Min, N, Max],
- [byte, uint32, uint32, uint32, uint32]);
+ [byte, uint32, uint32, uint32]);
encode(#ssh_msg_kex_dh_gex_request_old{n = N}) ->
ssh_bits:encode([?SSH_MSG_KEX_DH_GEX_REQUEST_OLD, N],
[byte, uint32]);
@@ -257,7 +257,7 @@ encode(#ssh_msg_kex_dh_gex_reply{
}) ->
EncKey = encode_host_key(Key),
EncSign = encode_sign(Key, Signature),
- ssh_bits:encode([?SSH_MSG_KEXDH_REPLY, EncKey, F, EncSign], [byte, binary, mpint, binary]);
+ ssh_bits:encode([?SSH_MSG_KEX_DH_GEX_REPLY, EncKey, F, EncSign], [byte, binary, mpint, binary]);
encode(#ssh_msg_ignore{data = Data}) ->
ssh_bits:encode([?SSH_MSG_IGNORE, Data], [byte, string]);
@@ -442,6 +442,19 @@ decode(<<?BYTE(?SSH_MSG_KEX_DH_GEX_GROUP),
p = Prime,
g = Generator
};
+decode(<<?BYTE(?SSH_MSG_KEX_DH_GEX_INIT), ?UINT32(Len), E:Len/big-signed-integer-unit:8>>) ->
+ #ssh_msg_kex_dh_gex_init{
+ e = E
+ };
+decode(<<?BYTE(?SSH_MSG_KEX_DH_GEX_REPLY),
+ ?UINT32(Len0), Key:Len0/binary,
+ ?UINT32(Len1), F:Len1/big-signed-integer-unit:8,
+ ?UINT32(Len2), Hashsign:Len2/binary>>) ->
+ #ssh_msg_kex_dh_gex_reply{
+ public_host_key = decode_host_key(Key),
+ f = F,
+ h_sig = decode_sign(Hashsign)
+ };
decode(<<?BYTE(?SSH_MSG_KEXDH_REPLY), ?UINT32(Len0), Key:Len0/binary,
?UINT32(Len1), F:Len1/big-signed-integer-unit:8,
?UINT32(Len2), Hashsign:Len2/binary>>) ->
diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl
index 2e7391e1f8..38a0b7ec7c 100644
--- a/lib/ssh/src/ssh_transport.erl
+++ b/lib/ssh/src/ssh_transport.erl
@@ -39,7 +39,7 @@
key_exchange_init_msg/1,
key_init/3, new_keys_message/1,
handle_kexinit_msg/3, handle_kexdh_init/2,
- handle_kex_dh_gex_group/2, handle_kex_dh_gex_reply/2,
+ handle_kex_dh_gex_group/2, handle_kex_dh_gex_init/2, handle_kex_dh_gex_reply/2,
handle_new_keys/2, handle_kex_dh_gex_request/2,
handle_kexdh_reply/2,
unpack/3, decompress/2, ssh_packet/2, pack/2, msg_data/1,
@@ -66,6 +66,8 @@ algo_classes() -> [kex, public_key, cipher, mac, compression].
default_algorithms(compression) ->
%% Do not announce '[email protected]' because there seem to be problems
supported_algorithms(compression, same(['[email protected]']));
+default_algorithms(kex) ->
+ supported_algorithms(kex, []);
default_algorithms(Alg) ->
supported_algorithms(Alg).
@@ -73,23 +75,29 @@ default_algorithms(Alg) ->
supported_algorithms() -> [{K,supported_algorithms(K)} || K <- algo_classes()].
supported_algorithms(kex) ->
- ['diffie-hellman-group1-sha1'];
+ select_crypto_supported(
+ [{'diffie-hellman-group14-sha1', [{hashs,sha}]},
+ {'diffie-hellman-group1-sha1', [{hashs,sha}]},
+ {'diffie-hellman-group-exchange-sha256', [{hashs,sha256}]},
+ {'diffie-hellman-group-exchange-sha1', [{hashs,sha}]}
+ ]);
supported_algorithms(public_key) ->
ssh_auth:default_public_key_algorithms();
supported_algorithms(cipher) ->
- Supports = crypto:supports(),
- CipherAlgos = [{aes_ctr, 'aes128-ctr'}, {aes_cbc128, 'aes128-cbc'}, {des3_cbc, '3des-cbc'}],
- Algs = [SshAlgo ||
- {CryptoAlgo, SshAlgo} <- CipherAlgos,
- lists:member(CryptoAlgo, proplists:get_value(ciphers, Supports, []))],
- same(Algs);
+ same(
+ select_crypto_supported(
+ [{'aes128-ctr', [{ciphers,aes_ctr}]},
+ {'aes128-cbc', [{ciphers,aes_cbc128}]},
+ {'3des-cbc', [{ciphers,des3_cbc}]}
+ ]
+ ));
supported_algorithms(mac) ->
- Supports = crypto:supports(),
- HashAlgos = [{sha256, 'hmac-sha2-256'}, {sha, 'hmac-sha1'}],
- Algs = [SshAlgo ||
- {CryptoAlgo, SshAlgo} <- HashAlgos,
- lists:member(CryptoAlgo, proplists:get_value(hashs, Supports, []))],
- same(Algs);
+ same(
+ select_crypto_supported(
+ [{'hmac-sha2-256', [{hashs,sha256}]},
+ {'hmac-sha1', [{hashs,sha}]}
+ ]
+ ));
supported_algorithms(compression) ->
same(['none','zlib','[email protected]']).
@@ -100,7 +108,15 @@ supported_algorithms(Key, [{client2server,BL1},{server2client,BL2}]) ->
supported_algorithms(Key, BlackList) ->
supported_algorithms(Key) -- BlackList.
-
+select_crypto_supported(L) ->
+ Sup = crypto:supports(),
+ [Name || {Name,CryptoRequires} <- L,
+ crypto_supported(CryptoRequires, Sup)].
+
+crypto_supported(Conditions, Supported) ->
+ lists:all(fun({Tag,CryptoName}) ->
+ lists:member(CryptoName, proplists:get_value(Tag,Supported,[]))
+ end, Conditions).
same(Algs) -> [{client2server,Algs}, {server2client,Algs}].
@@ -135,7 +151,7 @@ ssh_vsn() ->
_:_ -> ""
end.
-random_id(Nlo, Nup) ->
+random_id(Nlo, Nup) ->
[crypto:rand_uniform($a,$z+1) || _<- lists:duplicate(crypto:rand_uniform(Nlo,Nup+1),x) ].
hello_version_msg(Data) ->
@@ -144,7 +160,7 @@ hello_version_msg(Data) ->
next_seqnum(SeqNum) ->
(SeqNum + 1) band 16#ffffffff.
-decrypt_first_block(Bin, #ssh{decrypt_block_size = BlockSize} = Ssh0) ->
+decrypt_first_block(Bin, #ssh{decrypt_block_size = BlockSize} = Ssh0) ->
<<EncBlock:BlockSize/binary, EncData/binary>> = Bin,
{Ssh, <<?UINT32(PacketLen), _/binary>> = DecData} =
decrypt(Ssh0, EncBlock),
@@ -279,34 +295,50 @@ verify_algorithm(#alg{compress = undefined}) -> false;
verify_algorithm(#alg{decompress = undefined}) -> false;
verify_algorithm(#alg{kex = 'diffie-hellman-group1-sha1'}) -> true;
+verify_algorithm(#alg{kex = 'diffie-hellman-group14-sha1'}) -> true;
verify_algorithm(#alg{kex = 'diffie-hellman-group-exchange-sha1'}) -> true;
+verify_algorithm(#alg{kex = 'diffie-hellman-group-exchange-sha256'}) -> true;
verify_algorithm(_) -> false.
-key_exchange_first_msg('diffie-hellman-group1-sha1', Ssh0) ->
- {G, P} = dh_group1(),
+%%%----------------------------------------------------------------
+%%%
+%%% Key exchange initialization
+%%%
+key_exchange_first_msg(Kex, Ssh0) when Kex == 'diffie-hellman-group1-sha1' ;
+ Kex == 'diffie-hellman-group14-sha1' ->
+ {G, P} = dh_group(Kex),
{Private, Public} = dh_gen_key(G, P, 1024),
+ %% Public = G^Private mod P (def)
{SshPacket, Ssh1} = ssh_packet(#ssh_msg_kexdh_init{e = Public}, Ssh0),
{ok, SshPacket,
Ssh1#ssh{keyex_key = {{Private, Public}, {G, P}}}};
-key_exchange_first_msg('diffie-hellman-group-exchange-sha1', Ssh0) ->
+key_exchange_first_msg(Kex, Ssh0) when Kex == 'diffie-hellman-group-exchange-sha1' ;
+ Kex == 'diffie-hellman-group-exchange-sha256' ->
Min = ?DEFAULT_DH_GROUP_MIN,
NBits = ?DEFAULT_DH_GROUP_NBITS,
Max = ?DEFAULT_DH_GROUP_MAX,
{SshPacket, Ssh1} =
ssh_packet(#ssh_msg_kex_dh_gex_request{min = Min,
- n = NBits, max = Max},
+ n = NBits,
+ max = Max},
Ssh0),
{ok, SshPacket,
Ssh1#ssh{keyex_info = {Min, Max, NBits}}}.
-
-handle_kexdh_init(#ssh_msg_kexdh_init{e = E}, Ssh0) ->
- {G, P} = dh_group1(),
+%%%----------------------------------------------------------------
+%%%
+%%% diffie-hellman-group1-sha1
+%%% diffie-hellman-group14-sha1
+%%%
+handle_kexdh_init(#ssh_msg_kexdh_init{e = E},
+ Ssh0 = #ssh{algorithms = #alg{kex=Kex}}) ->
+ %% server
+ {G, P} = dh_group(Kex),
if
1=<E, E=<(P-1) ->
{Private, Public} = dh_gen_key(G, P, 1024),
- K = ssh_math:ipow(E, Private, P),
+ K = dh_compute_key(G, P, E, Private),
Key = get_host_key(Ssh0),
H = kex_h(Ssh0, Key, E, Public, K),
H_SIG = sign_host_key(Ssh0, Key, H),
@@ -314,27 +346,173 @@ handle_kexdh_init(#ssh_msg_kexdh_init{e = E}, Ssh0) ->
f = Public,
h_sig = H_SIG
}, Ssh0),
-
{ok, SshPacket, Ssh1#ssh{keyex_key = {{Private, Public}, {G, P}},
shared_secret = K,
exchanged_hash = H,
session_id = sid(Ssh1, H)}};
+
true ->
- Error = {error,bad_e_from_peer},
- Disconnect = #ssh_msg_disconnect{
- code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
- description = "Key exchange failed, 'f' out of bounds",
- language = "en"},
- throw({Error, Disconnect})
+ throw({{error,bad_e_from_peer},
+ #ssh_msg_disconnect{
+ code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ description = "Key exchange failed, 'e' out of bounds",
+ language = ""}
+ })
end.
+handle_kexdh_reply(#ssh_msg_kexdh_reply{public_host_key = HostKey,
+ f = F,
+ h_sig = H_SIG},
+ #ssh{keyex_key = {{Private, Public}, {G, P}}} = Ssh0) ->
+ %% client
+ if
+ 1=<F, F=<(P-1)->
+ K = dh_compute_key(G, P, F, Private),
+ H = kex_h(Ssh0, HostKey, Public, F, K),
+
+ case verify_host_key(Ssh0, HostKey, H, H_SIG) of
+ ok ->
+ {SshPacket, Ssh} = ssh_packet(#ssh_msg_newkeys{}, Ssh0),
+ {ok, SshPacket, Ssh#ssh{shared_secret = K,
+ exchanged_hash = H,
+ session_id = sid(Ssh, H)}};
+ Error ->
+ throw({Error,
+ #ssh_msg_disconnect{
+ code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ description = "Key exchange failed",
+ language = "en"}
+ })
+ end;
+
+ true ->
+ throw({{error,bad_f_from_peer},
+ #ssh_msg_disconnect{
+ code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ description = "Key exchange failed, 'f' out of bounds",
+ language = ""}
+ })
+ end.
+
+
+%%%----------------------------------------------------------------
+%%%
+%%% diffie-hellman-group-exchange-sha1
+%%%
+handle_kex_dh_gex_request(#ssh_msg_kex_dh_gex_request{min = Min,
+ n = NBits,
+ max = Max},
+ Ssh0=#ssh{opts=Opts}) when Min=<NBits, NBits=<Max ->
+ %% server
+ {G, P} = dh_gex_group(Min, NBits, Max, proplists:get_value(dh_gex_groups,Opts)),
+ {Private, Public} = dh_gen_key(G, P, 1024),
+ {SshPacket, Ssh} =
+ ssh_packet(#ssh_msg_kex_dh_gex_group{p = P, g = G}, Ssh0),
+ {ok, SshPacket,
+ Ssh#ssh{keyex_key = {{Private, Public}, {G, P}},
+ keyex_info = {Min, Max, NBits}
+ }};
+handle_kex_dh_gex_request(_, _) ->
+ throw({{error,bad_ssh_msg_kex_dh_gex_request},
+ #ssh_msg_disconnect{
+ code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ description = "Key exchange failed, bad values in ssh_msg_kex_dh_gex_request",
+ language = ""}
+ }).
+
handle_kex_dh_gex_group(#ssh_msg_kex_dh_gex_group{p = P, g = G}, Ssh0) ->
- {Private, Public} = dh_gen_key(G,P,1024),
+ %% client
+ {Private, Public} = dh_gen_key(G, P, 1024),
{SshPacket, Ssh1} =
- ssh_packet(#ssh_msg_kex_dh_gex_init{e = Public}, Ssh0),
+ ssh_packet(#ssh_msg_kex_dh_gex_init{e = Public}, Ssh0), % Pub = G^Priv mod P (def)
+
{ok, SshPacket,
Ssh1#ssh{keyex_key = {{Private, Public}, {G, P}}}}.
+handle_kex_dh_gex_init(#ssh_msg_kex_dh_gex_init{e = E},
+ #ssh{keyex_key = {{Private, Public}, {G, P}},
+ keyex_info = {Min, Max, NBits}} =
+ Ssh0) ->
+ %% server
+ if
+ 1=<E, E=<(P-1) ->
+ K = dh_compute_key(G, P, E, Private),
+ if
+ 1<K, K<(P-1) ->
+ HostKey = get_host_key(Ssh0),
+ H = kex_h(Ssh0, HostKey, Min, NBits, Max, P, G, E, Public, K),
+ H_SIG = sign_host_key(Ssh0, HostKey, H),
+ {SshPacket, Ssh} =
+ ssh_packet(#ssh_msg_kex_dh_gex_reply{public_host_key = HostKey,
+ f = Public,
+ h_sig = H_SIG}, Ssh0),
+ {ok, SshPacket, Ssh#ssh{shared_secret = K,
+ exchanged_hash = H,
+ session_id = sid(Ssh, H)
+ }};
+ true ->
+ throw({{error,bad_K},
+ #ssh_msg_disconnect{
+ code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ description = "Key exchange failed, 'K' out of bounds",
+ language = ""}
+ })
+ end;
+ true ->
+ throw({{error,bad_e_from_peer},
+ #ssh_msg_disconnect{
+ code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ description = "Key exchange failed, 'e' out of bounds",
+ language = ""}
+ })
+ end.
+
+handle_kex_dh_gex_reply(#ssh_msg_kex_dh_gex_reply{public_host_key = HostKey,
+ f = F,
+ h_sig = H_SIG},
+ #ssh{keyex_key = {{Private, Public}, {G, P}},
+ keyex_info = {Min, Max, NBits}} =
+ Ssh0) ->
+ %% client
+ if
+ 1=<F, F=<(P-1)->
+ K = dh_compute_key(G, P, F, Private),
+ if
+ 1<K, K<(P-1) ->
+ H = kex_h(Ssh0, HostKey, Min, NBits, Max, P, G, Public, F, K),
+
+ case verify_host_key(Ssh0, HostKey, H, H_SIG) of
+ ok ->
+ {SshPacket, Ssh} = ssh_packet(#ssh_msg_newkeys{}, Ssh0),
+ {ok, SshPacket, Ssh#ssh{shared_secret = K,
+ exchanged_hash = H,
+ session_id = sid(Ssh, H)}};
+ _Error ->
+ throw(#ssh_msg_disconnect{
+ code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ description = "Key exchange failed",
+ language = ""}
+ )
+ end;
+
+ true ->
+ throw({{error,bad_K},
+ #ssh_msg_disconnect{
+ code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ description = "Key exchange failed, 'K' out of bounds",
+ language = ""}
+ })
+ end;
+ true ->
+ throw({{error,bad_f_from_peer},
+ #ssh_msg_disconnect{
+ code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ description = "Key exchange failed, 'f' out of bounds",
+ language = ""}
+ })
+ end.
+
+%%%----------------------------------------------------------------
handle_new_keys(#ssh_msg_newkeys{}, Ssh0) ->
try install_alg(Ssh0) of
#ssh{} = Ssh ->
@@ -346,69 +524,6 @@ handle_new_keys(#ssh_msg_newkeys{}, Ssh0) ->
language = "en"})
end.
-
-%% %% Select algorithms
-handle_kexdh_reply(#ssh_msg_kexdh_reply{public_host_key = HostKey, f = F,
- h_sig = H_SIG},
- #ssh{keyex_key = {{Private, Public}, {_G, P}}} = Ssh0) when 1=<F, F=<(P-1)->
- K = ssh_math:ipow(F, Private, P),
- H = kex_h(Ssh0, HostKey, Public, F, K),
-
- case verify_host_key(Ssh0, HostKey, H, H_SIG) of
- ok ->
- {SshPacket, Ssh} = ssh_packet(#ssh_msg_newkeys{}, Ssh0),
- {ok, SshPacket, Ssh#ssh{shared_secret = K,
- exchanged_hash = H,
- session_id = sid(Ssh, H)}};
- Error ->
- Disconnect = #ssh_msg_disconnect{
- code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
- description = "Key exchange failed",
- language = "en"},
- throw({Error, Disconnect})
- end;
-handle_kexdh_reply(#ssh_msg_kexdh_reply{}, _SSH) ->
- Error = {error,bad_f_from_peer},
- Disconnect = #ssh_msg_disconnect{
- code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
- description = "Key exchange failed, 'f' out of bounds",
- language = "en"},
- throw({Error, Disconnect}).
-
-
-handle_kex_dh_gex_request(#ssh_msg_kex_dh_gex_request{min = _Min,
- n = _NBits,
- max = _Max}, Ssh0) ->
- {G,P} = dh_group1(), %% TODO real imp this seems to be a hack?!
- {Private, Public} = dh_gen_key(G, P, 1024),
- {SshPacket, Ssh} =
- ssh_packet(#ssh_msg_kex_dh_gex_group{p = P, g = G}, Ssh0),
- {ok, SshPacket,
- Ssh#ssh{keyex_key = {{Private, Public}, {G, P}}}}.
-
-handle_kex_dh_gex_reply(#ssh_msg_kex_dh_gex_reply{public_host_key = HostKey,
- f = F,
- h_sig = H_SIG},
- #ssh{keyex_key = {{Private, Public}, {G, P}},
- keyex_info = {Min, Max, NBits}} =
- Ssh0) ->
- K = ssh_math:ipow(F, Private, P),
- H = kex_h(Ssh0, HostKey, Min, NBits, Max, P, G, Public, F, K),
-
- case verify_host_key(Ssh0, HostKey, H, H_SIG) of
- ok ->
- {SshPacket, Ssh} = ssh_packet(#ssh_msg_newkeys{}, Ssh0),
- {ok, SshPacket, Ssh#ssh{shared_secret = K,
- exchanged_hash = H,
- session_id = sid(Ssh, H)}};
- _Error ->
- Disconnect = #ssh_msg_disconnect{
- code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
- description = "Key exchange failed",
- language = "en"},
- throw(Disconnect)
- end.
-
%% select session id
sid(#ssh{session_id = undefined}, H) ->
H;
@@ -511,7 +626,6 @@ select_algorithm(Role, Client, Server) ->
decompress = Decompression,
c_lng = C_Lng,
s_lng = S_Lng},
-%%ct:pal("~p~n Client=~p~n Server=~p~n Alg=~p~n",[Role,Client,Server,Alg]),
{ok, Alg}.
select_encrypt_decrypt(client, Client, Server) ->
@@ -706,6 +820,7 @@ verify(PlainText, Hash, Sig, Key) ->
%% key exchange
%%
%% diffie-hellman-group1-sha1 REQUIRED
+%% diffie-hellman-group14-sha1 REQUIRED
%%
%%
@@ -1001,7 +1116,7 @@ recv_mac_init(SSH) ->
recv_mac_final(SSH) ->
{ok, SSH#ssh { recv_mac = none, recv_mac_key = undefined }}.
-mac(none, _ , _, _) ->
+mac(none, _ , _, _) ->
<<>>;
mac('hmac-sha1', Key, SeqNum, Data) ->
crypto:hmac(sha, Key, [<<?UINT32(SeqNum)>>, Data]);
@@ -1020,8 +1135,12 @@ hash(SSH, Char, Bits) ->
case SSH#ssh.kex of
'diffie-hellman-group1-sha1' ->
fun(Data) -> crypto:hash(sha, Data) end;
+ 'diffie-hellman-group14-sha1' ->
+ fun(Data) -> crypto:hash(sha, Data) end;
'diffie-hellman-group-exchange-sha1' ->
fun(Data) -> crypto:hash(sha, Data) end;
+ 'diffie-hellman-group-exchange-sha256' ->
+ fun(Data) -> crypto:hash(sha256, Data) end;
_ ->
exit({bad_algorithm,SSH#ssh.kex})
end,
@@ -1071,8 +1190,11 @@ kex_h(SSH, Key, Min, NBits, Max, Prime, Gen, E, F, K) ->
ssh_message:encode_host_key(Key), Min, NBits, Max,
Prime, Gen, E,F,K], Ts)
end,
- crypto:hash(sha,L).
+ crypto:hash(sha((SSH#ssh.algorithms)#alg.kex), L).
+sha('diffie-hellman-group-exchange-sha1') -> sha;
+sha('diffie-hellman-group-exchange-sha256') -> sha256.
+
mac_key_size('hmac-sha1') -> 20*8;
mac_key_size('hmac-sha1-96') -> 20*8;
mac_key_size('hmac-md5') -> 16*8;
@@ -1096,13 +1218,63 @@ peer_name({Host, _}) ->
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-dh_group1() ->
- {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF}.
+dh_group('diffie-hellman-group1-sha1') -> ?dh_group1;
+dh_group('diffie-hellman-group14-sha1') -> ?dh_group14.
+
+dh_gex_default_groups() ->
+ [{1024, ?dh_group1 },
+ {2048, ?dh_group14},
+ {3072, ?dh_group15},
+ {4096, ?dh_group16}].
+
+
+dh_gex_group(Min, N, Max, undefined) ->
+ dh_gex_group(Min, N, Max, dh_gex_default_groups());
+dh_gex_group(Min, N, Max, Groups) ->
+ %% First try to find an exact match. If not an exact match, select the largest possible.
+ {_,Group} =
+ lists:foldl(
+ fun(_, {I,G}) when I==N ->
+ %% If we have an exact match already: use that one
+ {I,G};
+ ({I,G}, _) when I==N ->
+ %% If we now found an exact match: use that very one
+ {I,G};
+ ({I,G}, {Imax,_Gmax}) when Min=<I,I=<Max, % a) {I,G} fullfills the requirements
+ I>Imax -> % b) {I,G} is larger than current max
+ %% A group within the limits and better than the one we have
+ {I,G};
+ (_, IGmax) ->
+ %% Keep the one we have
+ IGmax
+ end, {-1,undefined}, Groups),
+
+ case Group of
+ undefined ->
+ throw(#ssh_msg_disconnect{
+ code = ?SSH_DISCONNECT_PROTOCOL_ERROR,
+ description = "No possible diffie-hellman-group-exchange group found",
+ language = ""});
+ _ ->
+ Group
+ end.
+
dh_gen_key(G, P, _) ->
{Public, Private} = crypto:generate_key(dh, [P, G]),
{crypto:bytes_to_integer(Private), crypto:bytes_to_integer(Public)}.
+dh_compute_key(G, P, OthersPublic, MyPrivate) ->
+ crypto:bytes_to_integer(
+ crypto:compute_key(dh, OthersPublic, MyPrivate, [P,G])
+ ).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Other utils
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
trim_tail(Str) ->
lists:reverse(trim_head(lists:reverse(Str))).
diff --git a/lib/ssh/src/ssh_transport.hrl b/lib/ssh/src/ssh_transport.hrl
index 2faf8a9316..9e1de171c2 100644
--- a/lib/ssh/src/ssh_transport.hrl
+++ b/lib/ssh/src/ssh_transport.hrl
@@ -188,49 +188,24 @@
-define(SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE, 14).
-define(SSH_DISCONNECT_ILLEGAL_USER_NAME, 15).
+%% groups
+
+%%% rfc 2489, ch 6.2
+-define(dh_group1,
+ {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF}).
+
+%%% rfc 3526, ch3
+-define(dh_group14,
+ {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF}).
+
+%%% rfc 3526, ch4
+-define(dh_group15,
+ {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF}).
+
+%%% rfc 3526, ch5
+-define(dh_group16,
+ {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF}).
+
-%%%----------------------------------------------------------------------
-%%% # DH_14_xxx
-%%% Description: Oakley group 14 prime numbers and generator. Used in
-%%% diffie-hellman-group1-sha1 key exchange method.
-%%%----------------------------------------------------------------------
-%%%----------------------------------------------------------------------
-%%% # DH_14_P
-%%% Description: Prime for this group
-%%%----------------------------------------------------------------------
-
--define(DH_14_P,
- <<000,000,000,129,000,255,255,255,255,255,255,255,255,201,015,218,
- 162,033,104,194,052,196,198,098,139,128,220,028,209,041,002,078,
- 008,138,103,204,116,002,011,190,166,059,019,155,034,081,074,008,
- 121,142,052,004,221,239,149,025,179,205,058,067,027,048,043,010,
- 109,242,095,020,055,079,225,053,109,109,081,194,069,228,133,181,
- 118,098,094,126,198,244,076,066,233,166,055,237,107,011,255,092,
- 182,244,006,183,237,238,056,107,251,090,137,159,165,174,159,036,
- 017,124,075,031,230,073,040,102,081,236,230,083,129,255,255,255,
- 255,255,255,255,255>>).
-
-%%%----------------------------------------------------------------------
-%%% # DH_14_G
-%%% Description: Generator for DH_14_P.
-%%%----------------------------------------------------------------------
-
--define(DH_14_G, <<0,0,0,1,2>>).
-
-%%%----------------------------------------------------------------------
-%%% # DH_14_Q
-%%% Description: Group order (DH_14_P - 1) / 2.
-%%%----------------------------------------------------------------------
-
--define(DH_14_Q,
- <<000,000,000,128,127,255,255,255,255,255,255,255,228,135,237,081,
- 016,180,097,026,098,099,049,069,192,110,014,104,148,129,039,004,
- 069,051,230,058,001,005,223,083,029,137,205,145,040,165,004,060,
- 199,026,002,110,247,202,140,217,230,157,033,141,152,021,133,054,
- 249,047,138,027,167,240,154,182,182,168,225,034,242,066,218,187,
- 049,047,063,099,122,038,033,116,211,027,246,181,133,255,174,091,
- 122,003,091,246,247,028,053,253,173,068,207,210,215,079,146,008,
- 190,037,143,243,036,148,051,040,246,115,041,192,255,255,255,255,
- 255,255,255,255>>).
-endif. % -ifdef(ssh_transport).
diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl
index bf9fe54c57..f30e86f193 100644
--- a/lib/ssh/test/ssh_basic_SUITE.erl
+++ b/lib/ssh/test/ssh_basic_SUITE.erl
@@ -42,6 +42,7 @@ suite() ->
all() ->
[app_test,
appup_test,
+ {group, key_exchange},
{group, dsa_key},
{group, rsa_key},
{group, dsa_pass_key},
@@ -92,6 +93,11 @@ groups() ->
max_sessions_sftp_start_channel_parallel,
max_sessions_sftp_start_channel_sequential
]},
+ {key_exchange, [], ['diffie-hellman-group-exchange-sha1',
+ 'diffie-hellman-group-exchange-sha256',
+ 'diffie-hellman-group1-sha1',
+ 'diffie-hellman-group14-sha1'
+ ]},
{dir_options, [], [user_dir_option,
system_dir_option]}
].
@@ -146,6 +152,11 @@ init_per_group(internal_error, Config) ->
ssh_test_lib:setup_dsa(DataDir, PrivDir),
file:delete(filename:join(PrivDir, "system/ssh_host_dsa_key")),
Config;
+init_per_group(key_exchange, Config) ->
+ DataDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ ssh_test_lib:setup_rsa(DataDir, PrivDir),
+ Config;
init_per_group(dir_options, Config) ->
PrivDir = ?config(priv_dir, Config),
%% Make unreadable dir:
@@ -193,6 +204,8 @@ init_per_group(_, Config) ->
end_per_group(hardening_tests, Config) ->
end_per_group(dsa_key, Config);
+end_per_group(key_exchange, Config) ->
+ end_per_group(rsa_key, Config);
end_per_group(dsa_key, Config) ->
PrivDir = ?config(priv_dir, Config),
ssh_test_lib:clean_dsa(PrivDir),
@@ -232,8 +245,8 @@ init_per_testcase(TC, Config) when TC==shell_no_unicode ;
Shell = ssh_test_lib:start_shell(Port, IO, UserDir,
[{silently_accept_hosts, true},
{user,"foo"},{password,"bar"}]),
- ct:pal("IO=~p, Shell=~p, self()=~p",[IO,Shell,self()]),
- ct:pal("file:native_name_encoding() = ~p,~nio:getopts() = ~p",
+ ct:log("IO=~p, Shell=~p, self()=~p",[IO,Shell,self()]),
+ ct:log("file:native_name_encoding() = ~p,~nio:getopts() = ~p",
[file:native_name_encoding(),io:getopts()]),
wait_for_erlang_first_line([{io,IO}, {shell,Shell}, {sftpd, Sftpd} | Config]);
init_per_testcase(_TestCase, Config) ->
@@ -607,7 +620,7 @@ shell(Config) when is_list(Config) ->
{'EXIT', _, _} ->
ct:fail(no_ssh_connection);
ErlShellStart ->
- ct:pal("Erlang shell start: ~p~n", [ErlShellStart]),
+ ct:log("Erlang shell start: ~p~n", [ErlShellStart]),
do_shell(IO, Shell)
end.
@@ -691,7 +704,7 @@ server_password_option(Config) when is_list(Config) ->
{user_interaction, false},
{user_dir, UserDir}]),
- ct:pal("Test of wrong password: Error msg: ~p ~n", [Reason]),
+ ct:log("Test of wrong password: Error msg: ~p ~n", [Reason]),
ssh:close(ConnectionRef),
ssh:stop_daemon(Pid).
@@ -818,6 +831,59 @@ ssh_msg_debug_fun_option_client(Config) ->
end.
%%--------------------------------------------------------------------
+'diffie-hellman-group-exchange-sha1'(Config) ->
+ kextest('diffie-hellman-group-exchange-sha1',Config).
+
+'diffie-hellman-group-exchange-sha256'(Config) ->
+ kextest('diffie-hellman-group-exchange-sha256',Config).
+
+'diffie-hellman-group1-sha1'(Config) ->
+ kextest('diffie-hellman-group1-sha1',Config).
+
+'diffie-hellman-group14-sha1'(Config) ->
+ kextest('diffie-hellman-group14-sha1',Config).
+
+
+kextest(Kex, Config) ->
+ case lists:member(Kex, ssh_transport:supported_algorithms(kex)) of
+ true ->
+ process_flag(trap_exit, true),
+ SystemDir = filename:join(?config(priv_dir, Config), system),
+ UserDir = ?config(priv_dir, Config),
+
+ {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
+ {user_dir, UserDir},
+ {user_passwords, [{"foo", "bar"}]},
+ {preferred_algorithms,
+ [{kex, [Kex]}]},
+ {failfun, fun ssh_test_lib:failfun/2}]),
+
+ ConnectionRef =
+ ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
+ {user, "foo"},
+ {password, "bar"},
+ {user_dir, UserDir},
+ {preferred_algorithms,
+ [{kex, [Kex]}]},
+ {user_interaction, false}]),
+
+ {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity),
+ success = ssh_connection:exec(ConnectionRef, ChannelId,
+ "1+1.", infinity),
+ Data = {ssh_cm, ConnectionRef, {data, ChannelId, 0, <<"2\n">>}},
+ case ssh_test_lib:receive_exec_result(Data) of
+ expected ->
+ ok;
+ Other ->
+ ct:fail(Other)
+ end,
+ ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId),
+ ssh:stop_daemon(Pid);
+ false ->
+ {skip, lists:concat([Kex, " is not supported"])}
+ end.
+
+%%--------------------------------------------------------------------
connectfun_disconnectfun_server(Config) ->
PrivDir = ?config(priv_dir, Config),
UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
@@ -1193,13 +1259,13 @@ peername_sockname(Config) when is_list(Config) ->
ssh:connection_info(ConnectionRef, [peer]),
[{sockname, {HostSockClient,PortSockClient} = ClientSock}] =
ssh:connection_info(ConnectionRef, [sockname]),
- ct:pal("Client: ~p ~p", [ClientPeer, ClientSock]),
+ ct:log("Client: ~p ~p", [ClientPeer, ClientSock]),
receive
{ssh_cm, ConnectionRef, {data, ChannelId, _, Response}} ->
{PeerNameSrv,SockNameSrv} = binary_to_term(Response),
{HostPeerSrv,PortPeerSrv} = PeerNameSrv,
{HostSockSrv,PortSockSrv} = SockNameSrv,
- ct:pal("Server: ~p ~p", [PeerNameSrv, SockNameSrv]),
+ ct:log("Server: ~p ~p", [PeerNameSrv, SockNameSrv]),
host_equal(HostPeerSrv, HostSockClient),
PortPeerSrv = PortSockClient,
host_equal(HostSockSrv, HostPeerClient),
@@ -1377,7 +1443,7 @@ packet_size_zero(Config) ->
receive
{ssh_cm,Conn,{data,Chan,_Type,_Msg1}} = M ->
- ct:pal("Got ~p",[M]),
+ ct:log("Got ~p",[M]),
ct:fail(doesnt_obey_max_packet_size_0)
after 5000 ->
ok
@@ -1454,7 +1520,7 @@ chan_exec(ConnectionRef, Cmnd, Expected) ->
ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId0);
{unexpected_msg,{ssh_cm, ConnectionRef, {exit_status, ChannelId0, 0}}
= ExitStatus0} ->
- ct:pal("0: Collected data ~p", [ExitStatus0]),
+ ct:log("0: Collected data ~p", [ExitStatus0]),
ssh_test_lib:receive_exec_result(Data0,
ConnectionRef, ChannelId0);
Other0 ->
@@ -1546,7 +1612,7 @@ ssh_connect_negtimeout(Config, Parallel) ->
{ok,Socket} = gen_tcp:connect(Host, Port, []),
Factor = 2,
- ct:pal("And now sleeping ~p*NegTimeOut (~p ms)...", [Factor, round(Factor * NegTimeOut)]),
+ ct:log("And now sleeping ~p*NegTimeOut (~p ms)...", [Factor, round(Factor * NegTimeOut)]),
ct:sleep(round(Factor * NegTimeOut)),
case inet:sockname(Socket) of
@@ -1577,22 +1643,22 @@ ssh_connect_nonegtimeout_connected(Config, Parallel) ->
{parallel_login, Parallel},
{negotiation_timeout, NegTimeOut},
{failfun, fun ssh_test_lib:failfun/2}]),
- ct:pal("~p Listen ~p:~p",[_Pid,_Host,Port]),
+ ct:log("~p Listen ~p:~p",[_Pid,_Host,Port]),
ct:sleep(500),
IO = ssh_test_lib:start_io_server(),
Shell = ssh_test_lib:start_shell(Port, IO, UserDir),
receive
Error = {'EXIT', _, _} ->
- ct:pal("~p",[Error]),
+ ct:log("~p",[Error]),
ct:fail(no_ssh_connection);
ErlShellStart ->
- ct:pal("---Erlang shell start: ~p~n", [ErlShellStart]),
+ ct:log("---Erlang shell start: ~p~n", [ErlShellStart]),
one_shell_op(IO, NegTimeOut),
one_shell_op(IO, NegTimeOut),
Factor = 2,
- ct:pal("And now sleeping ~p*NegTimeOut (~p ms)...", [Factor, round(Factor * NegTimeOut)]),
+ ct:log("And now sleeping ~p*NegTimeOut (~p ms)...", [Factor, round(Factor * NegTimeOut)]),
ct:sleep(round(Factor * NegTimeOut)),
one_shell_op(IO, NegTimeOut)
@@ -1601,7 +1667,7 @@ ssh_connect_nonegtimeout_connected(Config, Parallel) ->
one_shell_op(IO, TimeOut) ->
- ct:pal("One shell op: Waiting for prompter"),
+ ct:log("One shell op: Waiting for prompter"),
receive
ErlPrompt0 -> ct:log("Erlang prompt: ~p~n", [ErlPrompt0])
after TimeOut -> ct:fail("Timeout waiting for promter")
@@ -1704,7 +1770,7 @@ connect_fun(ssh_sftp__start_channel, _Config) ->
max_sessions(Config, ParallelLogin, Connect0) when is_function(Connect0,2) ->
Connect = fun(Host,Port) ->
R = Connect0(Host,Port),
- ct:pal("Connect(~p,~p) -> ~p",[Host,Port,R]),
+ ct:log("Connect(~p,~p) -> ~p",[Host,Port,R]),
R
end,
SystemDir = filename:join(?config(priv_dir, Config), system),
@@ -1717,7 +1783,7 @@ max_sessions(Config, ParallelLogin, Connect0) when is_function(Connect0,2) ->
{parallel_login, ParallelLogin},
{max_sessions, MaxSessions}
]),
- ct:pal("~p Listen ~p:~p for max ~p sessions",[Pid,Host,Port,MaxSessions]),
+ ct:log("~p Listen ~p:~p for max ~p sessions",[Pid,Host,Port,MaxSessions]),
try [Connect(Host,Port) || _ <- lists:seq(1,MaxSessions)]
of
Connections ->
@@ -1726,7 +1792,7 @@ max_sessions(Config, ParallelLogin, Connect0) when is_function(Connect0,2) ->
[_|_] = Connections,
%% Now try one more than alowed:
- ct:pal("Info Report might come here...",[]),
+ ct:log("Info Report might come here...",[]),
try Connect(Host,Port)
of
_ConnectionRef1 ->
@@ -1855,12 +1921,12 @@ basic_test(Config) ->
do_shell(IO, Shell) ->
receive
ErlPrompt0 ->
- ct:pal("Erlang prompt: ~p~n", [ErlPrompt0])
+ ct:log("Erlang prompt: ~p~n", [ErlPrompt0])
end,
IO ! {input, self(), "1+1.\r\n"},
receive
Echo0 ->
- ct:pal("Echo: ~p ~n", [Echo0])
+ ct:log("Echo: ~p ~n", [Echo0])
end,
receive
?NEWLINE ->
@@ -1868,7 +1934,7 @@ do_shell(IO, Shell) ->
end,
receive
Result0 = <<"2">> ->
- ct:pal("Result: ~p~n", [Result0])
+ ct:log("Result: ~p~n", [Result0])
end,
receive
?NEWLINE ->
@@ -1876,7 +1942,7 @@ do_shell(IO, Shell) ->
end,
receive
ErlPrompt1 ->
- ct:pal("Erlang prompt: ~p~n", [ErlPrompt1])
+ ct:log("Erlang prompt: ~p~n", [ErlPrompt1])
end,
exit(Shell, kill).
%%Does not seem to work in the testserver!
@@ -1887,7 +1953,7 @@ do_shell(IO, Shell) ->
%% end,
%% receive
%% Echo1 ->
- %% ct:pal("Echo: ~p ~n", [Echo1])
+ %% ct:log("Echo: ~p ~n", [Echo1])
%% end,
%% receive
%% ?NEWLINE ->
@@ -1895,7 +1961,7 @@ do_shell(IO, Shell) ->
%% end,
%% receive
%% Result1 ->
- %% ct:pal("Result: ~p~n", [Result1])
+ %% ct:log("Result: ~p~n", [Result1])
%% end,
%% receive
%% {'EXIT', Shell, killed} ->
@@ -1909,13 +1975,13 @@ wait_for_erlang_first_line(Config) ->
{'EXIT', _, _} ->
{fail,no_ssh_connection};
<<"Eshell ",_/binary>> = _ErlShellStart ->
- ct:pal("Erlang shell start: ~p~n", [_ErlShellStart]),
+ ct:log("Erlang shell start: ~p~n", [_ErlShellStart]),
Config;
Other ->
- ct:pal("Unexpected answer from ssh server: ~p",[Other]),
+ ct:log("Unexpected answer from ssh server: ~p",[Other]),
{fail,unexpected_answer}
after 10000 ->
- ct:pal("No answer from ssh-server"),
+ ct:log("No answer from ssh-server"),
{fail,timeout}
end.
@@ -1931,7 +1997,7 @@ new_do_shell(IO, N, Ops=[{Order,Arg}|More]) ->
PfxSize = size(Pfx),
receive
_X = <<"\r\n">> ->
- ct:pal("Skip newline ~p",[_X]),
+ ct:log("Skip newline ~p",[_X]),
new_do_shell(IO, N, Ops);
<<Pfx:PfxSize/binary,P1,"> ">> when (P1-$0)==N ->
@@ -1947,15 +2013,15 @@ new_do_shell(IO, N, Ops=[{Order,Arg}|More]) ->
ct:fail("new_do_shell error: ~p~n",[Err]);
RecBin when Order==expect ; Order==expect_echo ->
- ct:pal("received ~p",[RecBin]),
+ ct:log("received ~p",[RecBin]),
RecStr = string:strip(unicode:characters_to_list(RecBin)),
ExpStr = string:strip(Arg),
case lists:prefix(ExpStr, RecStr) of
true when Order==expect ->
- ct:pal("Matched ~ts",[RecStr]),
+ ct:log("Matched ~ts",[RecStr]),
new_do_shell(IO, N, More);
true when Order==expect_echo ->
- ct:pal("Matched echo ~ts",[RecStr]),
+ ct:log("Matched echo ~ts",[RecStr]),
new_do_shell(IO, N, More);
false ->
ct:fail("*** Expected ~p, but got ~p",[string:strip(ExpStr),RecStr])
@@ -1981,12 +2047,12 @@ prompt_prefix() ->
new_do_shell_prompt(IO, N, type, Str, More) ->
- ct:pal("Matched prompt ~p to trigger sending of next line to server",[N]),
+ ct:log("Matched prompt ~p to trigger sending of next line to server",[N]),
IO ! {input, self(), Str++"\r\n"},
- ct:pal("Promt '~p> ', Sent ~ts",[N,Str++"\r\n"]),
+ ct:log("Promt '~p> ', Sent ~ts",[N,Str++"\r\n"]),
new_do_shell(IO, N, [{expect_echo,Str}|More]); % expect echo of the sent line
new_do_shell_prompt(IO, N, Op, Str, More) ->
- ct:pal("Matched prompt ~p",[N]),
+ ct:log("Matched prompt ~p",[N]),
new_do_shell(IO, N, [{Op,Str}|More]).
%%--------------------------------------------------------------------
diff --git a/lib/ssh/test/ssh_connection_SUITE.erl b/lib/ssh/test/ssh_connection_SUITE.erl
index eb7c641d8a..fbcf06290a 100644
--- a/lib/ssh/test/ssh_connection_SUITE.erl
+++ b/lib/ssh/test/ssh_connection_SUITE.erl
@@ -186,7 +186,7 @@ big_cat(Config) when is_list(Config) ->
%% pre-adjust receive window so the other end doesn't block
ssh_connection:adjust_window(ConnectionRef, ChannelId0, size(Data)),
- ct:pal("sending ~p byte binary~n",[size(Data)]),
+ ct:log("sending ~p byte binary~n",[size(Data)]),
ok = ssh_connection:send(ConnectionRef, ChannelId0, Data, 10000),
ok = ssh_connection:send_eof(ConnectionRef, ChannelId0),
@@ -197,10 +197,10 @@ big_cat(Config) when is_list(Config) ->
{ok, Other} ->
case size(Data) =:= size(Other) of
true ->
- ct:pal("received and sent data are same"
+ ct:log("received and sent data are same"
"size but do not match~n",[]);
false ->
- ct:pal("sent ~p but only received ~p~n",
+ ct:log("sent ~p but only received ~p~n",
[size(Data), size(Other)])
end,
ct:fail(receive_data_mismatch);
@@ -450,7 +450,7 @@ gracefull_invalid_version(Config) when is_list(Config) ->
ok = gen_tcp:send(S, ["SSH-8.-1","\r\n"]),
receive
Verstring ->
- ct:pal("Server version: ~p~n", [Verstring]),
+ ct:log("Server version: ~p~n", [Verstring]),
receive
{tcp_closed, S} ->
ok
@@ -470,7 +470,7 @@ gracefull_invalid_start(Config) when is_list(Config) ->
ok = gen_tcp:send(S, ["foobar","\r\n"]),
receive
Verstring ->
- ct:pal("Server version: ~p~n", [Verstring]),
+ ct:log("Server version: ~p~n", [Verstring]),
receive
{tcp_closed, S} ->
ok
@@ -490,7 +490,7 @@ gracefull_invalid_long_start(Config) when is_list(Config) ->
ok = gen_tcp:send(S, [lists:duplicate(257, $a), "\r\n"]),
receive
Verstring ->
- ct:pal("Server version: ~p~n", [Verstring]),
+ ct:log("Server version: ~p~n", [Verstring]),
receive
{tcp_closed, S} ->
ok
@@ -511,7 +511,7 @@ gracefull_invalid_long_start_no_nl(Config) when is_list(Config) ->
ok = gen_tcp:send(S, [lists:duplicate(257, $a), "\r\n"]),
receive
Verstring ->
- ct:pal("Server version: ~p~n", [Verstring]),
+ ct:log("Server version: ~p~n", [Verstring]),
receive
{tcp_closed, S} ->
ok
diff --git a/lib/ssh/test/ssh_protocol_SUITE.erl b/lib/ssh/test/ssh_protocol_SUITE.erl
index d82cdaf2c7..dc02b940d7 100644
--- a/lib/ssh/test/ssh_protocol_SUITE.erl
+++ b/lib/ssh/test/ssh_protocol_SUITE.erl
@@ -56,7 +56,11 @@ groups() ->
lib_no_match
]},
{kex, [], [no_common_alg_server_disconnects,
- no_common_alg_client_disconnects
+ no_common_alg_client_disconnects,
+ gex_client_init_default_noexact,
+ gex_client_init_default_exact,
+ gex_client_init_option_groups,
+ gex_client_init_option_groups_file
]}
].
@@ -68,9 +72,32 @@ end_per_suite(Config) ->
stop_apps(Config).
+
+init_per_testcase(TC, Config) when TC == gex_client_init_default_noexact ;
+ TC == gex_client_init_default_exact ;
+ TC == gex_client_init_option_groups ;
+ TC == gex_client_init_option_groups_file ->
+ Opts = case TC of
+ gex_client_init_option_groups ->
+ [{dh_gex_groups, [{2345, 3, 41}]}];
+ gex_client_init_option_groups_file ->
+ DataDir = ?config(data_dir, Config),
+ F = filename:join(DataDir, "dh_group_test"),
+ [{dh_gex_groups, {file,F}}];
+ _ ->
+ []
+ end,
+ start_std_daemon(Config,
+ [{preferred_algorithms, ssh_transport:supported_algorithms()}
+ | Opts]);
init_per_testcase(_TestCase, Config) ->
check_std_daemon_works(Config, ?LINE).
+end_per_testcase(TC, Config) when TC == gex_client_init_default_noexact ;
+ TC == gex_client_init_default_exact ;
+ TC == gex_client_init_option_groups ;
+ TC == gex_client_init_option_groups_file ->
+ stop_std_daemon(Config);
end_per_testcase(_TestCase, Config) ->
check_std_daemon_works(Config, ?LINE).
@@ -213,7 +240,7 @@ lib_no_match(_Config) ->
no_common_alg_server_disconnects(Config) ->
{ok,_} =
ssh_trpt_test_lib:exec(
- [{set_options, [print_ops, print_seqnums, print_messages]},
+ [{set_options, [print_ops, {print_messages,detail}]},
{connect,
server_host(Config),server_port(Config),
[{silently_accept_hosts, true},
@@ -224,7 +251,7 @@ no_common_alg_server_disconnects(Config) ->
receive_hello,
{send, hello},
{match, #ssh_msg_kexinit{_='_'}, receive_msg},
- {send, ssh_msg_kexinit},
+ {send, ssh_msg_kexinit}, % with server unsupported 'ssh-dss' !
{match,
{'or',[#ssh_msg_disconnect{code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, _='_'},
tcp_closed]},
@@ -248,17 +275,16 @@ no_common_alg_client_disconnects(Config) ->
Parent !
{result,self(),
ssh_trpt_test_lib:exec(
- [{set_options, [print_ops, print_messages]},
+ [{set_options, [print_ops, {print_messages,detail}]},
{accept, [{system_dir, system_dir(Config)},
{user_dir, user_dir(Config)}]},
receive_hello,
{send, hello},
-
{match, #ssh_msg_kexinit{_='_'}, receive_msg},
- {send, #ssh_msg_kexinit{
+ {send, #ssh_msg_kexinit{ % with unsupported "SOME-UNSUPPORTED"
cookie = 247381486335508958743193106082599558706,
kex_algorithms = ["diffie-hellman-group1-sha1"],
- server_host_key_algorithms = ["some-unknown"],
+ server_host_key_algorithms = ["SOME-UNSUPPORTED"], % SIC!
encryption_algorithms_client_to_server = ["aes128-ctr"],
encryption_algorithms_server_to_client = ["aes128-ctr"],
mac_algorithms_client_to_server = ["hmac-sha2-256"],
@@ -279,7 +305,8 @@ no_common_alg_client_disconnects(Config) ->
}
end),
- %% and finally connect to it with a regular Erlang SSH client:
+ %% and finally connect to it with a regular Erlang SSH client
+ %% which of course does not support SOME-UNSUPPORTED as pub key algo:
Result = std_connect(HostPort, Config, [{preferred_algorithms,[{public_key,['ssh-dss']}]}]),
ct:log("Result of connect is ~p",[Result]),
@@ -287,12 +314,56 @@ no_common_alg_client_disconnects(Config) ->
{result,Pid,{ok,_}} ->
ok;
{result,Pid,{error,{Op,ExecResult,S}}} ->
- ct:pal("ERROR!~nOp = ~p~nExecResult = ~p~nState =~n~s",
+ ct:log("ERROR!~nOp = ~p~nExecResult = ~p~nState =~n~s",
[Op,ExecResult,ssh_trpt_test_lib:format_msg(S)]),
{fail, ExecResult};
- X -> ct:fail(X)
+ X ->
+ ct:log("¤¤¤¤¤"),
+ ct:fail(X)
end.
+%%%--------------------------------------------------------------------
+gex_client_init_default_noexact(Config) ->
+ do_gex_client_init(Config, {2000, 3000, 4000},
+ %% Warning, app knowledege:
+ ?dh_group15).
+
+
+gex_client_init_default_exact(Config) ->
+ do_gex_client_init(Config, {2000, 2048, 4000},
+ %% Warning, app knowledege:
+ ?dh_group14).
+
+
+gex_client_init_option_groups(Config) ->
+ do_gex_client_init(Config, {2000, 2048, 4000}, {3,41}).
+
+
+gex_client_init_option_groups_file(Config) ->
+ do_gex_client_init(Config, {2000, 2048, 4000}, {5,61}).
+
+do_gex_client_init(Config, {Min,N,Max}, {G,P}) ->
+ {ok,_} =
+ ssh_trpt_test_lib:exec(
+ [{set_options, [print_ops, print_seqnums, print_messages]},
+ {connect,
+ server_host(Config),server_port(Config),
+ [{silently_accept_hosts, true},
+ {user_dir, user_dir(Config)},
+ {user_interaction, false},
+ {preferred_algorithms,[{kex,['diffie-hellman-group-exchange-sha1']}]}
+ ]},
+ receive_hello,
+ {send, hello},
+ {send, ssh_msg_kexinit},
+ {match, #ssh_msg_kexinit{_='_'}, receive_msg},
+ {send, #ssh_msg_kex_dh_gex_request{min = Min,
+ n = N,
+ max = Max}},
+ {match, #ssh_msg_kex_dh_gex_group{p=P, g=G, _='_'}, receive_msg}
+ ]
+ ).
+
%%%================================================================
%%%==== Internal functions ========================================
%%%================================================================
@@ -353,6 +424,7 @@ stop_std_daemon(Config) ->
ct:log("Std server ~p at ~p:~p stopped", [server_pid(Config), server_host(Config), server_port(Config)]),
lists:keydelete(server, 1, Config).
+
check_std_daemon_works(Config, Line) ->
case std_connect(Config) of
{ok,C} ->
@@ -362,13 +434,9 @@ check_std_daemon_works(Config, Line) ->
ok = ssh:close(C),
Config;
Error = {error,_} ->
- {fail,
- lists:flatten(
- io_lib:format("Standard server ~p:~p ~p is ill at line ~p: ~p",
- [server_host(Config), server_port(Config),
- server_pid(Config), Line, Error])
- )
- }
+ ct:fail("Standard server ~p:~p ~p is ill at line ~p: ~p",
+ [server_host(Config), server_port(Config),
+ server_pid(Config), Line, Error])
end.
server_pid(Config) -> element(1,?v(server,Config)).
diff --git a/lib/ssh/test/ssh_protocol_SUITE_data/dh_group_test b/lib/ssh/test/ssh_protocol_SUITE_data/dh_group_test
new file mode 100644
index 0000000000..2887bb4b60
--- /dev/null
+++ b/lib/ssh/test/ssh_protocol_SUITE_data/dh_group_test
@@ -0,0 +1,3 @@
+{2222, 5, 61}.
+{1111, 7, 91}.
+
diff --git a/lib/ssh/test/ssh_sftp_SUITE.erl b/lib/ssh/test/ssh_sftp_SUITE.erl
index 6c631e6f6e..bab5bf9fe9 100644
--- a/lib/ssh/test/ssh_sftp_SUITE.erl
+++ b/lib/ssh/test/ssh_sftp_SUITE.erl
@@ -47,7 +47,7 @@ init_per_suite(Config) ->
catch crypto:stop(),
case (catch crypto:start()) of
ok ->
- ct:pal("file:native_name_encoding() = ~p,~nio:getopts() = ~p",
+ ct:log("file:native_name_encoding() = ~p,~nio:getopts() = ~p",
[file:native_name_encoding(),io:getopts()]),
ssh:start(),
Config;
@@ -64,12 +64,20 @@ end_per_suite(Config) ->
groups() ->
[{not_unicode, [], [{group,erlang_server},
{group,openssh_server},
+ {group,'diffie-hellman-group-exchange-sha1'},
+ {group,'diffie-hellman-group-exchange-sha256'},
sftp_nonexistent_subsystem]},
{unicode, [], [{group,erlang_server},
{group,openssh_server},
sftp_nonexistent_subsystem]},
+ {'diffie-hellman-group-exchange-sha1', [], [{group,erlang_server},
+ {group,openssh_server}]},
+
+ {'diffie-hellman-group-exchange-sha256', [], [{group,erlang_server},
+ {group,openssh_server}]},
+
{erlang_server, [], [{group,write_read_tests},
version_option,
{group,remote_tar}]},
@@ -77,7 +85,12 @@ groups() ->
{openssh_server, [], [{group,write_read_tests},
{group,remote_tar}]},
- {remote_tar, [], [create_empty_tar, files_to_tar, big_file_to_tar, files_chunked_to_tar,
+ {remote_tar, [], [create_empty_tar,
+ ascii_filename_ascii_contents_to_tar,
+ ascii_filename_unicode_contents_to_tar,
+ unicode_filename_ascii_contents_to_tar,
+ files_to_tar,
+ big_file_to_tar, files_chunked_to_tar,
directory_to_tar, binaries_to_tar, null_crypto_tar,
simple_crypto_tar_small, simple_crypto_tar_big,
read_tar, read_null_crypto_tar, read_crypto_tar,
@@ -113,23 +126,35 @@ init_per_group(unicode, Config) ->
ct:comment("Begin ~p",[grps(Config)]),
DataDir = ?config(data_dir, Config),
PrivDir = ?config(priv_dir, Config),
- [{user, "åke高兴"},
- {passwd, "ärlig日本じん"},
- {data, <<"foobar å 一二三四いちにさんち">>},
- {filename, filename:join(PrivDir, "sftp瑞点.txt")},
- {testfile, filename:join(PrivDir, "testハンス.txt")},
- {linktest, filename:join(PrivDir, "link_test語.txt")},
- {tar_filename, filename:join(PrivDir, "sftp_tar_test一二三.tar")},
- {tar_F1_txt, "F一.txt"},
- {datadir_tar, filename:join(DataDir,"sftp_tar_test_data_高兴")}
- | lists:foldl(fun(K,Cf) -> lists:keydelete(K,1,Cf) end,
- Config,
- [user, passwd, data,
- filename, testfile, linktest,
- tar_filename, tar_F1_txt, datadir_tar
- ]
- )
- ];
+ NewConfig =
+ [{user, "åke高兴"},
+ {passwd, "ärlig日本じん"},
+ {data, <<"foobar å 一二三四いちにさんち">>},
+ {filename, filename:join(PrivDir, "sftp瑞点.txt")},
+ {testfile, filename:join(PrivDir, "testハンス.txt")},
+ {linktest, filename:join(PrivDir, "link_test語.txt")},
+ {tar_filename, filename:join(PrivDir, "sftp_tar_test一二三.tar")},
+ {tar_F1_txt, "F一.txt"},
+ {tar_F3_txt, "f3.txt"},
+ {tar_F4_txt, "g四.txt"},
+ {datadir_tar, filename:join(DataDir,"sftp_tar_test_data_高兴")}
+ | lists:foldl(fun(K,Cf) -> lists:keydelete(K,1,Cf) end,
+ Config,
+ [user, passwd, data,
+ filename, testfile, linktest,
+ tar_filename, tar_F1_txt, datadir_tar
+ ]
+ )
+ ],
+ FN = fn(?config(tar_F1_txt,NewConfig), NewConfig),
+ case catch file:read_file(FN) of
+ {ok,FN_contents} ->
+ ct:log("Readable file:read_file(~tp) ->~n~tp",[FN,FN_contents]),
+ NewConfig;
+ Other ->
+ ct:log("Unreadable file:read_file(~tp) ->~n~p",[FN,Other]),
+ {skip, "Not unicode file reading"}
+ end;
_ ->
{skip, "Not unicode file encoding"}
@@ -142,22 +167,26 @@ init_per_group(erlang_server, Config) ->
User = ?config(user, Config),
Passwd = ?config(passwd, Config),
Sftpd = {_, HostX, PortX} =
- ssh_test_lib:daemon([{system_dir, SysDir},
- {user_dir, PrivDir},
- {user_passwords,
- [{User, Passwd}]}]),
+ ssh_test_lib:daemon(extra_opts(Config) ++
+ [{system_dir, SysDir},
+ {user_dir, PrivDir},
+ {user_passwords,
+ [{User, Passwd}]}]),
[{peer, {fmt_host(HostX),PortX}}, {group, erlang_server}, {sftpd, Sftpd} | Config];
init_per_group(openssh_server, Config) ->
ct:comment("Begin ~p",[grps(Config)]),
Host = ssh_test_lib:hostname(),
- case (catch ssh_sftp:start_channel(Host,
- [{user_interaction, false},
- {silently_accept_hosts, true}])) of
+ case (catch ssh_sftp:start_channel(Host,
+ extra_opts(Config) ++
+ [{user_interaction, false},
+ {silently_accept_hosts, true}])) of
{ok, _ChannelPid, Connection} ->
[{peer, {_HostName,{IPx,Portx}}}] = ssh:connection_info(Connection,[peer]),
ssh:close(Connection),
[{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"}
end;
@@ -172,10 +201,11 @@ init_per_group(remote_tar, Config) ->
case ?config(group, Config) of
erlang_server ->
ssh:connect(Host, Port,
- [{user, User},
- {password, Passwd},
- {user_interaction, false},
- {silently_accept_hosts, true}]);
+ extra_opts(Config) ++
+ [{user, User},
+ {password, Passwd},
+ {user_interaction, false},
+ {silently_accept_hosts, true}]);
openssh_server ->
ssh:connect(Host, Port,
[{user_interaction, false},
@@ -184,6 +214,28 @@ init_per_group(remote_tar, Config) ->
[{remote_tar, true},
{connection, Connection} | Config];
+init_per_group('diffie-hellman-group-exchange-sha1', Config) ->
+ case lists:member('diffie-hellman-group-exchange-sha1',
+ ssh_transport:supported_algorithms(kex)) of
+ true ->
+ [{extra_opts, [{preferred_algorithms, [{kex,['diffie-hellman-group-exchange-sha1']}]}]}
+ | Config];
+
+ false ->
+ {skip,"'diffie-hellman-group-exchange-sha1' not supported by this version of erlang ssh"}
+ end;
+
+init_per_group('diffie-hellman-group-exchange-sha256', Config) ->
+ case lists:member('diffie-hellman-group-exchange-sha256',
+ ssh_transport:supported_algorithms(kex)) of
+ true ->
+ [{extra_opts, [{preferred_algorithms, [{kex,['diffie-hellman-group-exchange-sha256']}]}]}
+ | Config];
+
+ false ->
+ {skip,"'diffie-hellman-group-exchange-sha256' not supported by this version of erlang ssh"}
+ end;
+
init_per_group(write_read_tests, Config) ->
ct:comment("Begin ~p",[grps(Config)]),
Config.
@@ -194,7 +246,6 @@ grps(Config) ->
lists:flatten([proplists:get_value(tc_group_properties,Config,[]),
proplists:get_value(tc_group_path,Config,[])])).
-
end_per_group(erlang_server, Config) ->
ct:comment("End ~p",[grps(Config)]),
Config;
@@ -227,11 +278,12 @@ init_per_testcase(version_option, Config) ->
Passwd = ?config(passwd, Config),
{ok, ChannelPid, Connection} =
ssh_sftp:start_channel(Host, Port,
- [{sftp_vsn, 3},
- {user, User},
- {password, Passwd},
- {user_interaction, false},
- {silently_accept_hosts, true}]),
+ extra_opts(Config) ++
+ [{sftp_vsn, 3},
+ {user, User},
+ {password, Passwd},
+ {user_interaction, false},
+ {silently_accept_hosts, true}]),
Sftp = {ChannelPid, Connection},
[{sftp,Sftp}, {watchdog, Dog} | TmpConfig];
@@ -249,10 +301,12 @@ init_per_testcase(Case, Config0) ->
{_,Host, Port} = ?config(sftpd, Config2),
{ok, ChannelPid, Connection} =
ssh_sftp:start_channel(Host, Port,
- [{user, User},
- {password, Passwd},
- {user_interaction, false},
- {silently_accept_hosts, true}]),
+ extra_opts(Config2) ++
+ [{user, User},
+ {password, Passwd},
+ {user_interaction, false},
+ {silently_accept_hosts, true}]
+ ),
Sftp = {ChannelPid, Connection},
[{sftp, Sftp}, {watchdog, Dog} | Config2];
openssh_server when Case == links ->
@@ -261,8 +315,9 @@ init_per_testcase(Case, Config0) ->
Host = ssh_test_lib:hostname(),
{ok, ChannelPid, Connection} =
ssh_sftp:start_channel(Host,
- [{user_interaction, false},
- {silently_accept_hosts, true}]),
+ extra_opts(Config2) ++
+ [{user_interaction, false},
+ {silently_accept_hosts, true}]),
Sftp = {ChannelPid, Connection},
[{sftp, Sftp}, {watchdog, Dog} | Config2]
end,
@@ -342,7 +397,7 @@ read_dir(Config) when is_list(Config) ->
PrivDir = ?config(priv_dir, Config),
{Sftp, _} = ?config(sftp, Config),
{ok, Files} = ssh_sftp:list_dir(Sftp, PrivDir),
- ct:pal("sftp list dir: ~p~n", [Files]).
+ ct:log("sftp list dir: ~p~n", [Files]).
%%--------------------------------------------------------------------
write_file() ->
@@ -423,12 +478,12 @@ rename_file(Config) when is_list(Config) ->
{Sftp, _} = ?config(sftp, Config),
{ok, Files} = ssh_sftp:list_dir(Sftp, PrivDir),
- ct:pal("FileName: ~p, Files: ~p~n", [FileName, Files]),
+ ct:log("FileName: ~p, Files: ~p~n", [FileName, Files]),
true = lists:member(filename:basename(FileName), Files),
false = lists:member(filename:basename(NewFileName), Files),
ok = ssh_sftp:rename(Sftp, FileName, NewFileName),
{ok, NewFiles} = ssh_sftp:list_dir(Sftp, PrivDir),
- ct:pal("FileName: ~p, Files: ~p~n", [FileName, NewFiles]),
+ ct:log("FileName: ~p, Files: ~p~n", [FileName, NewFiles]),
false = lists:member(filename:basename(FileName), NewFiles),
true = lists:member(filename:basename(NewFileName), NewFiles).
@@ -474,7 +529,7 @@ retrieve_attributes(Config) when is_list(Config) ->
{ok, NewFileInfo} = file:read_file_info(FileName),
%% TODO comparison. There are some differences now is that ok?
- ct:pal("SFTP: ~p FILE: ~p~n", [FileInfo, NewFileInfo]).
+ ct:log("SFTP: ~p FILE: ~p~n", [FileInfo, NewFileInfo]).
%%--------------------------------------------------------------------
set_attributes() ->
@@ -503,7 +558,7 @@ async_read(Config) when is_list(Config) ->
receive
{async_reply, Ref, {ok, Data}} ->
- ct:pal("Data: ~p~n", [Data]),
+ ct:log("Data: ~p~n", [Data]),
ok;
Msg ->
ct:fail(Msg)
@@ -648,6 +703,43 @@ files_to_tar(Config) ->
chk_tar([F1, "f2.txt"], Config).
%%--------------------------------------------------------------------
+ascii_filename_ascii_contents_to_tar(Config) ->
+ ChPid2 = ?config(channel_pid2, Config),
+ TarFileName = ?config(tar_filename, Config),
+ {ok,Handle} = ssh_sftp:open_tar(ChPid2, TarFileName, [write]),
+ ok = erl_tar:add(Handle, fn("f2.txt",Config), "f2.txt", [verbose]),
+ ok = erl_tar:close(Handle),
+ chk_tar(["f2.txt"], Config).
+
+%%--------------------------------------------------------------------
+ascii_filename_unicode_contents_to_tar(Config) ->
+ case ?config(tar_F3_txt, Config) of
+ undefined ->
+ {skip, "Unicode test"};
+ Fn ->
+ ChPid2 = ?config(channel_pid2, Config),
+ TarFileName = ?config(tar_filename, Config),
+ {ok,Handle} = ssh_sftp:open_tar(ChPid2, TarFileName, [write]),
+ ok = erl_tar:add(Handle, fn(Fn,Config), Fn, [verbose]),
+ ok = erl_tar:close(Handle),
+ chk_tar([Fn], Config)
+ end.
+
+%%--------------------------------------------------------------------
+unicode_filename_ascii_contents_to_tar(Config) ->
+ case ?config(tar_F4_txt, Config) of
+ undefined ->
+ {skip, "Unicode test"};
+ Fn ->
+ ChPid2 = ?config(channel_pid2, Config),
+ TarFileName = ?config(tar_filename, Config),
+ {ok,Handle} = ssh_sftp:open_tar(ChPid2, TarFileName, [write]),
+ ok = erl_tar:add(Handle, fn(Fn,Config), Fn, [verbose]),
+ ok = erl_tar:close(Handle),
+ chk_tar([Fn], Config)
+ end.
+
+%%--------------------------------------------------------------------
big_file_to_tar(Config) ->
ChPid2 = ?config(channel_pid2, Config),
TarFileName = ?config(tar_filename, Config),
@@ -910,7 +1002,8 @@ prep(Config) ->
ok = file:write_file_info(TestFile,
FileInfo#file_info{mode = Mode}).
-
+extra_opts(Config) ->
+ proplists:get_value(extra_opts, Config, []).
chk_tar(Items, Config) ->
chk_tar(Items, Config, []).
diff --git a/lib/ssh/test/ssh_sftp_SUITE_data/sftp_tar_test_data_高兴/f3.txt b/lib/ssh/test/ssh_sftp_SUITE_data/sftp_tar_test_data_高兴/f3.txt
new file mode 100644
index 0000000000..e6076a05b5
--- /dev/null
+++ b/lib/ssh/test/ssh_sftp_SUITE_data/sftp_tar_test_data_高兴/f3.txt
@@ -0,0 +1 @@
+你好
diff --git a/lib/ssh/test/ssh_sftp_SUITE_data/sftp_tar_test_data_高兴/g四.txt b/lib/ssh/test/ssh_sftp_SUITE_data/sftp_tar_test_data_高兴/g四.txt
new file mode 100644
index 0000000000..d18c6b11fc
--- /dev/null
+++ b/lib/ssh/test/ssh_sftp_SUITE_data/sftp_tar_test_data_高兴/g四.txt
@@ -0,0 +1 @@
+How are you?
diff --git a/lib/ssh/test/ssh_sftpd_SUITE.erl b/lib/ssh/test/ssh_sftpd_SUITE.erl
index f38fcc5521..94a54ec9db 100644
--- a/lib/ssh/test/ssh_sftpd_SUITE.erl
+++ b/lib/ssh/test/ssh_sftpd_SUITE.erl
@@ -152,7 +152,7 @@ init_per_testcase(TestCase, Config) ->
{ok, <<?SSH_FXP_VERSION, ?UINT32(Version), _Ext/binary>>, _}
= reply(Cm, Channel),
- ct:pal("Client: ~p Server ~p~n", [ProtocolVer, Version]),
+ ct:log("Client: ~p Server ~p~n", [ProtocolVer, Version]),
[{sftp, {Cm, Channel}}, {sftpd, Sftpd }| Config].
@@ -418,7 +418,7 @@ real_path(Config) when is_list(Config) ->
RealPath = filename:absname(binary_to_list(Path)),
AbsPrivDir = filename:absname(PrivDir),
- ct:pal("Path: ~p PrivDir: ~p~n", [RealPath, AbsPrivDir]),
+ ct:log("Path: ~p PrivDir: ~p~n", [RealPath, AbsPrivDir]),
true = RealPath == AbsPrivDir
end.
@@ -447,7 +447,7 @@ links(Config) when is_list(Config) ->
true = binary_to_list(Path) == FileName,
- ct:pal("Path: ~p~n", [binary_to_list(Path)])
+ ct:log("Path: ~p~n", [binary_to_list(Path)])
end.
%%--------------------------------------------------------------------
@@ -548,10 +548,10 @@ set_attributes(Config) when is_list(Config) ->
%% Can not test that NewPermissions = Permissions as
%% on Unix platforms, other bits than those listed in the
%% API may be set.
- ct:pal("Org: ~p New: ~p~n", [OrigPermissions, NewPermissions]),
+ ct:log("Org: ~p New: ~p~n", [OrigPermissions, NewPermissions]),
true = OrigPermissions =/= NewPermissions,
- ct:pal("Try to open the file"),
+ ct:log("Try to open the file"),
NewReqId = 2,
{ok, <<?SSH_FXP_HANDLE, ?UINT32(NewReqId), Handle/binary>>, _} =
open_file(FileName, Cm, Channel, NewReqId,
@@ -563,7 +563,7 @@ set_attributes(Config) when is_list(Config) ->
NewReqId1 = 3,
- ct:pal("Set original permissions on the now open file"),
+ ct:log("Set original permissions on the now open file"),
{ok, <<?SSH_FXP_STATUS, ?UINT32(NewReqId1),
?UINT32(?SSH_FX_OK), _/binary>>, _} =
@@ -786,7 +786,7 @@ read_dir(Handle, Cm, Channel, ReqId) ->
case reply(Cm, Channel) of
{ok, <<?SSH_FXP_NAME, ?UINT32(ReqId), ?UINT32(Count),
?UINT32(Len), Listing:Len/binary, _/binary>>, _} ->
- ct:pal("Count: ~p Listing: ~p~n",
+ ct:log("Count: ~p Listing: ~p~n",
[Count, binary_to_list(Listing)]),
read_dir(Handle, Cm, Channel, ReqId);
{ok, <<?SSH_FXP_STATUS, ?UINT32(ReqId),
diff --git a/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl b/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl
index 321e3546cf..7a025a6518 100644
--- a/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl
+++ b/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl
@@ -159,7 +159,7 @@ close_file(Config) when is_list(Config) ->
NumOfPorts = length(erlang:ports()),
- ct:pal("Number of open ports: ~p~n", [NumOfPorts]),
+ ct:log("Number of open ports: ~p~n", [NumOfPorts]),
{ok, <<_/binary>>} = ssh_sftp:read_file(Sftp, FileName),
@@ -255,14 +255,14 @@ root_dir(Config) when is_list(Config) ->
{ok, Bin} = ssh_sftp:read_file(Sftp, FileName),
{ok, Listing} =
ssh_sftp:list_dir(Sftp, "."),
- ct:pal("Listing: ~p~n", [Listing]).
+ ct:log("Listing: ~p~n", [Listing]).
%%--------------------------------------------------------------------
list_dir_limited(Config) when is_list(Config) ->
{Sftp, _} = ?config(sftp, Config),
{ok, Listing} =
ssh_sftp:list_dir(Sftp, "."),
- ct:pal("Listing: ~p~n", [Listing]).
+ ct:log("Listing: ~p~n", [Listing]).
%%--------------------------------------------------------------------
ver6_basic() ->
diff --git a/lib/ssh/test/ssh_test_lib.erl b/lib/ssh/test/ssh_test_lib.erl
index 97c35e549c..988ea47bd8 100644
--- a/lib/ssh/test/ssh_test_lib.erl
+++ b/lib/ssh/test/ssh_test_lib.erl
@@ -97,10 +97,10 @@ loop_io_server(TestCase, Buff0) ->
{input, TestCase, Line} ->
loop_io_server(TestCase, Buff0 ++ [Line]);
{io_request, From, ReplyAs, Request} ->
-%%ct:pal("~p",[{io_request, From, ReplyAs, Request}]),
+%%ct:log("~p",[{io_request, From, ReplyAs, Request}]),
{ok, Reply, Buff} = io_request(Request, TestCase, From,
ReplyAs, Buff0),
-%%ct:pal("io_request(~p)-->~p",[Request,{ok, Reply, Buff}]),
+%%ct:log("io_request(~p)-->~p",[Request,{ok, Reply, Buff}]),
io_reply(From, ReplyAs, Reply),
loop_io_server(TestCase, Buff);
{'EXIT',_, _} ->
@@ -134,26 +134,26 @@ io_request({get_line, _Enc,_}, _, _, _, [Line | Buff]) ->
io_reply(_, _, []) ->
ok;
io_reply(From, ReplyAs, Reply) ->
-%%ct:pal("io_reply ~p sending ~p ! ~p",[self(),From, {io_reply, ReplyAs, Reply}]),
+%%ct:log("io_reply ~p sending ~p ! ~p",[self(),From, {io_reply, ReplyAs, Reply}]),
From ! {io_reply, ReplyAs, Reply}.
reply(_, []) ->
ok;
reply(TestCase, Result) ->
-%%ct:pal("reply ~p sending ~p ! ~p",[self(), TestCase, Result]),
+%%ct:log("reply ~p sending ~p ! ~p",[self(), TestCase, Result]),
TestCase ! Result.
receive_exec_result(Msg) ->
- ct:pal("Expect data! ~p", [Msg]),
+ ct:log("Expect data! ~p", [Msg]),
receive
{ssh_cm,_,{data,_,1, Data}} ->
- ct:pal("StdErr: ~p~n", [Data]),
+ ct:log("StdErr: ~p~n", [Data]),
receive_exec_result(Msg);
Msg ->
- ct:pal("1: Collected data ~p", [Msg]),
+ ct:log("1: Collected data ~p", [Msg]),
expected;
Other ->
- ct:pal("Other ~p", [Other]),
+ ct:log("Other ~p", [Other]),
{unexpected_msg, Other}
end.
@@ -165,15 +165,15 @@ receive_exec_end(ConnectionRef, ChannelId) ->
case receive_exec_result(ExitStatus) of
{unexpected_msg, Eof} -> %% Open ssh seems to not allways send these messages
%% in the same order!
- ct:pal("2: Collected data ~p", [Eof]),
+ ct:log("2: Collected data ~p", [Eof]),
case receive_exec_result(ExitStatus) of
expected ->
expected = receive_exec_result(Closed);
{unexpected_msg, Closed} ->
- ct:pal("3: Collected data ~p", [Closed])
+ ct:log("3: Collected data ~p", [Closed])
end;
expected ->
- ct:pal("4: Collected data ~p", [ExitStatus]),
+ ct:log("4: Collected data ~p", [ExitStatus]),
expected = receive_exec_result(Eof),
expected = receive_exec_result(Closed);
Other ->
diff --git a/lib/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl
index b7283202a3..06bf264033 100644
--- a/lib/ssh/test/ssh_to_openssh_SUITE.erl
+++ b/lib/ssh/test/ssh_to_openssh_SUITE.erl
@@ -51,13 +51,15 @@ groups() ->
erlang_client_openssh_server_publickey_rsa,
erlang_client_openssh_server_publickey_dsa,
erlang_client_openssh_server_password,
+ erlang_client_openssh_server_kexs,
erlang_client_openssh_server_nonexistent_subsystem
]},
{erlang_server, [], [erlang_server_openssh_client_exec,
erlang_server_openssh_client_exec_compressed,
erlang_server_openssh_client_pulic_key_dsa,
erlang_server_openssh_client_cipher_suites,
- erlang_server_openssh_client_macs]}
+ erlang_server_openssh_client_macs,
+ erlang_server_openssh_client_kexs]}
].
init_per_suite(Config) ->
@@ -99,6 +101,12 @@ init_per_testcase(erlang_server_openssh_client_cipher_suites, Config) ->
init_per_testcase(erlang_server_openssh_client_macs, Config) ->
check_ssh_client_support(Config);
+init_per_testcase(erlang_server_openssh_client_kexs, Config) ->
+ check_ssh_client_support(Config);
+
+init_per_testcase(erlang_client_openssh_server_kexs, Config) ->
+ check_ssh_client_support(Config);
+
init_per_testcase(_TestCase, Config) ->
ssh:start(),
Config.
@@ -140,7 +148,7 @@ erlang_client_openssh_server_exec(Config) when is_list(Config) ->
ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId0);
{unexpected_msg,{ssh_cm, ConnectionRef, {exit_status, ChannelId0, 0}}
= ExitStatus0} ->
- ct:pal("0: Collected data ~p", [ExitStatus0]),
+ ct:log("0: Collected data ~p", [ExitStatus0]),
ssh_test_lib:receive_exec_result(Data0,
ConnectionRef, ChannelId0);
Other0 ->
@@ -156,7 +164,7 @@ erlang_client_openssh_server_exec(Config) when is_list(Config) ->
ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId1);
{unexpected_msg,{ssh_cm, ConnectionRef, {exit_status, ChannelId1, 0}}
= ExitStatus1} ->
- ct:pal("0: Collected data ~p", [ExitStatus1]),
+ ct:log("0: Collected data ~p", [ExitStatus1]),
ssh_test_lib:receive_exec_result(Data1,
ConnectionRef, ChannelId1);
Other1 ->
@@ -182,13 +190,55 @@ erlang_client_openssh_server_exec_compressed(Config) when is_list(Config) ->
ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId);
{unexpected_msg,{ssh_cm, ConnectionRef,
{exit_status, ChannelId, 0}} = ExitStatus} ->
- ct:pal("0: Collected data ~p", [ExitStatus]),
+ ct:log("0: Collected data ~p", [ExitStatus]),
ssh_test_lib:receive_exec_result(Data, ConnectionRef, ChannelId);
Other ->
ct:fail(Other)
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) ->
+ 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, ssh_transport:supported_algorithms(kex)),
+ case Success of
+ true ->
+ ok;
+ false ->
+ {fail, "Kex failed for one or more algos"}
+ end.
+
+%%--------------------------------------------------------------------
erlang_server_openssh_client_exec() ->
[{doc, "Test that exec command works."}].
@@ -206,7 +256,7 @@ erlang_server_openssh_client_exec(Config) when is_list(Config) ->
Cmd = "ssh -p " ++ integer_to_list(Port) ++
" -o UserKnownHostsFile=" ++ KnownHosts ++ " " ++ Host ++ " 1+1.",
- ct:pal("Cmd: ~p~n", [Cmd]),
+ ct:log("Cmd: ~p~n", [Cmd]),
SshPort = open_port({spawn, Cmd}, [binary]),
@@ -247,7 +297,7 @@ erlang_server_openssh_client_cipher_suites(Config) when is_list(Config) ->
" -o UserKnownHostsFile=" ++ KnownHosts ++ " " ++ Host ++ " " ++
" -c " ++ Cipher ++ " 1+1.",
- ct:pal("Cmd: ~p~n", [Cmd]),
+ ct:log("Cmd: ~p~n", [Cmd]),
SshPort = open_port({spawn, Cmd}, [binary, stderr_to_stdout]),
@@ -297,7 +347,7 @@ erlang_server_openssh_client_macs(Config) when is_list(Config) ->
" -o UserKnownHostsFile=" ++ KnownHosts ++ " " ++ Host ++ " " ++
" -o MACs=" ++ MAC ++ " 1+1.",
- ct:pal("Cmd: ~p~n", [Cmd]),
+ ct:log("Cmd: ~p~n", [Cmd]),
SshPort = open_port({spawn, Cmd}, [binary, stderr_to_stdout]),
@@ -322,6 +372,70 @@ erlang_server_openssh_client_macs(Config) when is_list(Config) ->
ssh:stop_daemon(Pid).
%%--------------------------------------------------------------------
+erlang_server_openssh_client_kexs() ->
+ [{doc, "Test that we can connect with different KEXs."}].
+
+erlang_server_openssh_client_kexs(Config) when is_list(Config) ->
+ SystemDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ KnownHosts = filename:join(PrivDir, "known_hosts"),
+
+ {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
+ {failfun, fun ssh_test_lib:failfun/2},
+ {preferred_algorithms,
+ [{kex,ssh_transport:supported_algorithms(kex)}]}
+ ]),
+ ct:sleep(500),
+
+ ErlKexs = lists:map(fun erlang:atom_to_list/1,
+ ssh_transport:supported_algorithms(kex)),
+ OpenSshKexs = string:tokens(os:cmd("ssh -Q kex"), "\n"),
+
+ Kexs = [{OpenSshKex,lists:member(OpenSshKex,ErlKexs)}
+ || OpenSshKex <- OpenSshKexs],
+
+ Success =
+ lists:foldl(
+ fun({Kex, Expect}, Acc) ->
+ Cmd = "ssh -p " ++ integer_to_list(Port) ++
+ " -o UserKnownHostsFile=" ++ KnownHosts ++ " " ++ Host ++ " " ++
+ " -o KexAlgorithms=" ++ Kex ++ " 1+1.",
+
+ ct:log("Cmd: ~p~n", [Cmd]),
+
+ SshPort = open_port({spawn, Cmd}, [binary, stderr_to_stdout]),
+
+ case Expect of
+ true ->
+ receive
+ {SshPort,{data, <<"2\n">>}} ->
+ Acc
+ after ?TIMEOUT ->
+ ct:log("Did not receive answer for ~p",[Kex]),
+ false
+ end;
+ false ->
+ receive
+ {SshPort,{data, <<"Unable to negotiate a key exchange method", _/binary>>}} ->
+ Acc
+ after ?TIMEOUT ->
+ ct:log("Did not receive no matching kex message for ~p",[Kex]),
+ false
+ end
+ end
+ end, true, Kexs),
+
+ ssh:stop_daemon(Pid),
+
+ case Success of
+ true ->
+ ok;
+ false ->
+ {fail, "Kex failed for one or more algos"}
+ end.
+
+
+%%--------------------------------------------------------------------
erlang_server_openssh_client_exec_compressed() ->
[{doc, "Test that exec command works."}].
@@ -380,11 +494,11 @@ erlang_client_openssh_server_setenv(Config) when is_list(Config) ->
{data,0,1, UnxpectedData}}} ->
%% Some os may return things as
%% ENV_TEST: Undefined variable.\n"
- ct:pal("UnxpectedData: ~p", [UnxpectedData]),
+ ct:log("UnxpectedData: ~p", [UnxpectedData]),
ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId);
{unexpected_msg,{ssh_cm, ConnectionRef, {exit_status, ChannelId, 0}}
= ExitStatus} ->
- ct:pal("0: Collected data ~p", [ExitStatus]),
+ ct:log("0: Collected data ~p", [ExitStatus]),
ssh_test_lib:receive_exec_result(Data,
ConnectionRef, ChannelId);
Other ->
@@ -487,7 +601,7 @@ erlang_client_openssh_server_password(Config) when is_list(Config) ->
{user_interaction, false},
{user_dir, UserDir}]),
- ct:pal("Test of user foo that does not exist. "
+ ct:log("Test of user foo that does not exist. "
"Error msg: ~p~n", [Reason0]),
User = string:strip(os:cmd("whoami"), right, $\n),
@@ -501,10 +615,10 @@ erlang_client_openssh_server_password(Config) when is_list(Config) ->
{password, "foo"},
{user_interaction, false},
{user_dir, UserDir}]),
- ct:pal("Test of wrong Pasword. "
+ ct:log("Test of wrong Pasword. "
"Error msg: ~p~n", [Reason1]);
_ ->
- ct:pal("Whoami failed reason: ~n", [])
+ ct:log("Whoami failed reason: ~n", [])
end.
%%--------------------------------------------------------------------
@@ -532,19 +646,19 @@ erlang_client_openssh_server_nonexistent_subsystem(Config) when is_list(Config)
receive_hej() ->
receive
<<"Hej", _binary>> = Hej ->
- ct:pal("Expected result: ~p~n", [Hej]);
+ ct:log("Expected result: ~p~n", [Hej]);
<<"Hej\n", _binary>> = Hej ->
- ct:pal("Expected result: ~p~n", [Hej]);
+ ct:log("Expected result: ~p~n", [Hej]);
<<"Hej\r\n", _/binary>> = Hej ->
- ct:pal("Expected result: ~p~n", [Hej]);
+ ct:log("Expected result: ~p~n", [Hej]);
Info ->
Lines = binary:split(Info, [<<"\r\n">>], [global]),
case lists:member(<<"Hej">>, Lines) of
true ->
- ct:pal("Expected result found in lines: ~p~n", [Lines]),
+ ct:log("Expected result found in lines: ~p~n", [Lines]),
ok;
false ->
- ct:pal("Extra info: ~p~n", [Info]),
+ ct:log("Extra info: ~p~n", [Info]),
receive_hej()
end
end.
@@ -558,7 +672,7 @@ receive_logout() ->
ok
end;
Info ->
- ct:pal("Extra info when logging out: ~p~n", [Info]),
+ ct:log("Extra info when logging out: ~p~n", [Info]),
receive_logout()
end.
@@ -601,6 +715,6 @@ check_ssh_client_support2(P) ->
{P, {exit_status, E}} ->
E
after 5000 ->
- ct:pal("Openssh command timed out ~n"),
+ ct:log("Openssh command timed out ~n"),
-1
end.
diff --git a/lib/ssh/test/ssh_trpt_test_lib.erl b/lib/ssh/test/ssh_trpt_test_lib.erl
index 75f495b6d7..38b2789742 100644
--- a/lib/ssh/test/ssh_trpt_test_lib.erl
+++ b/lib/ssh/test/ssh_trpt_test_lib.erl
@@ -42,8 +42,8 @@
seen_hello = false,
enc = <<>>,
ssh = #ssh{}, % #ssh{}
- own_kexinit,
- peer_kexinit,
+ alg_neg = {undefined,undefined}, % {own_kexinit, peer_kexinit}
+ alg, % #alg{}
vars = dict:new(),
reply = [], % Some repy msgs are generated hidden in ssh_transport :[
prints = [],
@@ -140,7 +140,10 @@ op(receive_hello, S0) when S0#s.seen_hello =/= true ->
op(receive_msg, S) when S#s.seen_hello == true ->
try recv(S)
catch
- {tcp,Exc} -> S#s{return_value=Exc}
+ {tcp,Exc} ->
+ S1 = opt(print_messages, S,
+ fun(X) when X==true;X==detail -> {"Recv~n~p~n",[Exc]} end),
+ S1#s{return_value=Exc}
end;
@@ -206,6 +209,9 @@ op_val(E, S0) ->
end.
+fail(Reason, {Fmt,Args}, S) when is_list(Fmt), is_list(Args) ->
+ fail(Reason, save_prints({Fmt,Args}, S)).
+
fail(Reason, S) ->
throw({fail, Reason, S}).
@@ -312,38 +318,51 @@ send(S=#s{ssh=C}, hello) ->
send(S, list_to_binary(Hello));
send(S0, ssh_msg_kexinit) ->
- {Msg, Bytes, C0} = ssh_transport:key_exchange_init_msg(S0#s.ssh),
- S1 = opt(print_messages, S0,
- fun(X) when X==true;X==detail -> {"Send~n~s~n",[format_msg(Msg)]} end),
- S = case ?role(S1) of
- server when is_record(S1#s.peer_kexinit, ssh_msg_kexinit) ->
- {ok, C} =
- ssh_transport:handle_kexinit_msg(S1#s.peer_kexinit, Msg, C0),
- S1#s{peer_kexinit = used,
- own_kexinit = used,
- ssh = C};
- _ ->
- S1#s{ssh = C0,
- own_kexinit = Msg}
- end,
- send_bytes(Bytes, S#s{return_value = Msg});
+ {Msg, _Bytes, _C0} = ssh_transport:key_exchange_init_msg(S0#s.ssh),
+ send(S0, Msg);
-send(S0, ssh_msg_kexdh_init) when ?role(S0) == client,
- is_record(S0#s.peer_kexinit, ssh_msg_kexinit),
- is_record(S0#s.own_kexinit, ssh_msg_kexinit) ->
+send(S0=#s{alg_neg={undefined,PeerMsg}}, Msg=#ssh_msg_kexinit{}) ->
+ S1 = opt(print_messages, S0,
+ fun(X) when X==true;X==detail -> {"Send~n~s~n",[format_msg(Msg)]} end),
+ S2 = case PeerMsg of
+ #ssh_msg_kexinit{} ->
+ try ssh_transport:handle_kexinit_msg(PeerMsg, Msg, S1#s.ssh) of
+ {ok,Cx} when ?role(S1) == server ->
+ S1#s{alg = Cx#ssh.algorithms};
+ {ok,_NextKexMsgBin,Cx} when ?role(S1) == client ->
+ S1#s{alg = Cx#ssh.algorithms}
+ catch
+ Class:Exc ->
+ save_prints({"Algoritm negotiation failed at line ~p:~p~n~p:~s~nPeer: ~s~n Own: ~s~n",
+ [?MODULE,?LINE,Class,format_msg(Exc),format_msg(PeerMsg),format_msg(Msg)]},
+ S1)
+ end;
+ undefined ->
+ S1
+ end,
+ {Bytes, C} = ssh_transport:ssh_packet(Msg, S2#s.ssh),
+ send_bytes(Bytes, S2#s{return_value = Msg,
+ alg_neg = {Msg,PeerMsg},
+ ssh = C});
+
+send(S0, ssh_msg_kexdh_init) when ?role(S0) == client ->
+ {OwnMsg, PeerMsg} = S0#s.alg_neg,
{ok, NextKexMsgBin, C} =
- ssh_transport:handle_kexinit_msg(S0#s.peer_kexinit, S0#s.own_kexinit, S0#s.ssh),
-
+ try ssh_transport:handle_kexinit_msg(PeerMsg, OwnMsg, S0#s.ssh)
+ catch
+ Class:Exc ->
+ fail("Algoritm negotiation failed!",
+ {"Algoritm negotiation failed at line ~p:~p~n~p:~s~nPeer: ~s~n Own: ~s",
+ [?MODULE,?LINE,Class,format_msg(Exc),format_msg(PeerMsg),format_msg(OwnMsg)]},
+ S0)
+ end,
S = opt(print_messages, S0,
fun(X) when X==true;X==detail ->
#ssh{keyex_key = {{_Private, Public}, {_G, _P}}} = C,
Msg = #ssh_msg_kexdh_init{e = Public},
{"Send (reconstructed)~n~s~n",[format_msg(Msg)]}
end),
-
- send_bytes(NextKexMsgBin, S#s{ssh = C,
- peer_kexinit = used,
- own_kexinit = used});
+ send_bytes(NextKexMsgBin, S#s{ssh = C});
send(S0, ssh_msg_kexdh_reply) ->
Bytes = proplists:get_value(ssh_msg_kexdh_reply, S0#s.reply),
@@ -389,26 +408,42 @@ recv(S0 = #s{}) ->
true ->
%% Has seen hello, therefore no more crlf-messages are alowed.
S = receive_binary_msg(S1),
- case M=S#s.return_value of
- #ssh_msg_kexinit{} when ?role(S) == server,
- S#s.own_kexinit =/= undefined ->
- {ok, C} =
- ssh_transport:handle_kexinit_msg(M, S#s.own_kexinit, S#s.ssh),
- S#s{peer_kexinit = used,
- own_kexinit = used,
- ssh = C};
- #ssh_msg_kexinit{} ->
- S#s{peer_kexinit = M};
+ case PeerMsg = S#s.return_value of
+ #ssh_msg_kexinit{} ->
+ case S#s.alg_neg of
+ {undefined,undefined} ->
+ S#s{alg_neg = {undefined,PeerMsg}};
+
+ {undefined,_} ->
+ fail("2 kexint received!!", S);
+
+ {OwnMsg, _} ->
+ try ssh_transport:handle_kexinit_msg(PeerMsg, OwnMsg, S#s.ssh) of
+ {ok,C} when ?role(S) == server ->
+ S#s{alg_neg = {OwnMsg, PeerMsg},
+ alg = C#ssh.algorithms,
+ ssh = C};
+ {ok,_NextKexMsgBin,C} when ?role(S) == client ->
+ S#s{alg_neg = {OwnMsg, PeerMsg},
+ alg = C#ssh.algorithms}
+ catch
+ Class:Exc ->
+ save_prints({"Algoritm negotiation failed at line ~p:~p~n~p:~s~nPeer: ~s~n Own: ~s~n",
+ [?MODULE,?LINE,Class,format_msg(Exc),format_msg(PeerMsg),format_msg(OwnMsg)]},
+ S#s{alg_neg = {OwnMsg, PeerMsg}})
+ end
+ end;
+
#ssh_msg_kexdh_init{} -> % Always the server
- {ok, Reply, C} = ssh_transport:handle_kexdh_init(M, S#s.ssh),
+ {ok, Reply, C} = ssh_transport:handle_kexdh_init(PeerMsg, S#s.ssh),
S#s{ssh = C,
reply = [{ssh_msg_kexdh_reply,Reply} | S#s.reply]
};
#ssh_msg_kexdh_reply{} ->
- {ok, _NewKeys, C} = ssh_transport:handle_kexdh_reply(M, S#s.ssh),
+ {ok, _NewKeys, C} = ssh_transport:handle_kexdh_reply(PeerMsg, S#s.ssh),
S#s{ssh=C#ssh{send_sequence=S#s.ssh#ssh.send_sequence}}; % Back the number
#ssh_msg_newkeys{} ->
- {ok, C} = ssh_transport:handle_new_keys(M, S#s.ssh),
+ {ok, C} = ssh_transport:handle_new_keys(PeerMsg, S#s.ssh),
S#s{ssh=C};
_ ->
S
@@ -682,10 +717,18 @@ seqnum_trace(S) ->
print_traces(S) when S#s.prints == [] -> S;
print_traces(S) ->
+ Len = length(S#s.prints),
ct:log("~s",
- [lists:foldl(fun({Fmt,Args}, Acc) ->
- [io_lib:format(Fmt,Args) | Acc]
- end, "", S#s.prints)]
+ [lists:foldl(
+ fun({Fmt,Args}, Acc) ->
+ [case Len-length(Acc)-1 of
+ 0 ->
+ io_lib:format(Fmt,Args);
+ N ->
+ io_lib:format(lists:concat(['~p --------~n',Fmt]),
+ [Len-length(Acc)-1|Args])
+ end | Acc]
+ end, "", S#s.prints)]
).
opt(Flag, S, Fun) when is_function(Fun,1) ->
diff --git a/lib/ssh/test/ssh_upgrade_SUITE.erl b/lib/ssh/test/ssh_upgrade_SUITE.erl
index eca8b3663d..0d936c118b 100644
--- a/lib/ssh/test/ssh_upgrade_SUITE.erl
+++ b/lib/ssh/test/ssh_upgrade_SUITE.erl
@@ -91,8 +91,8 @@ minor_upgrade(Config) when is_list(Config) ->
%%% Called by ct_release_test:upgrade/4
upgrade_init(CTData, State) ->
{ok, AppUp={_, _, Up, _Down}} = ct_release_test:get_appup(CTData, ssh),
- ct:pal("AppUp: ~p", [AppUp]),
- ct:pal("Up: ~p", [Up]),
+ ct:log("AppUp: ~p", [AppUp]),
+ ct:log("Up: ~p", [Up]),
case Soft = is_soft(Up) of
%% It is symmetrical, if upgrade is soft so is downgrade
true ->
@@ -131,12 +131,12 @@ is_soft(_) ->
test_hard(State0, FileName) ->
- ct:pal("test_hard State0=~p, FileName=~p",[State0, FileName]),
+ ct:log("test_hard State0=~p, FileName=~p",[State0, FileName]),
State = setup_server_client(State0),
test_connection(FileName, random_contents(), State).
test_soft(State0, FileName) ->
- ct:pal("test_soft State0=~p, FileName=~p",[State0, FileName]),
+ ct:log("test_soft State0=~p, FileName=~p",[State0, FileName]),
State = test_connection(FileName, random_contents(), State0),
setup_server_client( close(State) ).
@@ -168,7 +168,7 @@ setup_server_client(#state{config=Config} = State) ->
test_connection(FileName, FileContents,
#state{client = ChannelPid,
root_dir = FtpRootDir} = State) ->
- ct:pal("test_connection Writing with ssh_sftp:write_file",[]),
+ ct:log("test_connection Writing with ssh_sftp:write_file",[]),
case ssh_sftp:write_file(ChannelPid, FileName, FileContents) of
ok ->
case ssh_sftp:read_file(ChannelPid, FileName) of
diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml
index f23b71e28b..6c977bdb74 100644
--- a/lib/ssl/doc/src/ssl.xml
+++ b/lib/ssl/doc/src/ssl.xml
@@ -88,7 +88,8 @@
<item>
<p><c>{verify, verify_type()}</c></p>
<p><c>| {verify_fun, {fun(), term()}}</c></p>
- <p><c>| {fail_if_no_peer_cert, boolean()} {depth, integer()}</c></p>
+ <p><c>| {fail_if_no_peer_cert, boolean()}</c></p>
+ <p><c>| {depth, integer()}</c></p>
<p><c>| {cert, public_key:der_encoded()}</c></p>
<p><c>| {certfile, path()}</c></p>
<p><c>| {key, {'RSAPrivateKey'| 'DSAPrivateKey' | 'ECPrivateKey'
@@ -663,11 +664,6 @@ fun(srp, Username :: string(), UserState :: term()) ->
cipher suite can encipher.
</item>
- <tag><c>{psk_identity, string()}</c></tag>
- <item>Specifies the server identity hint the server presents to the client.
- </item>
- <tag><c>{log_alert, boolean()}</c></tag>
- <item>If false, error reports will not be displayed.</item>
<tag><c>{honor_cipher_order, boolean()}</c></tag>
<item>If true, use the server's preference for cipher selection. If false
(the default), use the client's preference.
diff --git a/lib/stdlib/doc/src/ets.xml b/lib/stdlib/doc/src/ets.xml
index ab1a5900b9..03b995e4de 100644
--- a/lib/stdlib/doc/src/ets.xml
+++ b/lib/stdlib/doc/src/ets.xml
@@ -610,7 +610,7 @@ ets:is_compiled_ms(Broken).</code>
<p>Returns the last key <c><anno>Key</anno></c> according to Erlang term
order in the table <c>Tab</c> of the <c>ordered_set</c> type.
If the table is of any other type, the function is synonymous
- to <c>first/2</c>. If the table is empty,
+ to <c>first/1</c>. If the table is empty,
<c>'$end_of_table'</c> is returned.</p>
<p>Use <c>prev/2</c> to find preceding keys in the table.</p>
</desc>
diff --git a/lib/stdlib/src/qlc_pt.erl b/lib/stdlib/src/qlc_pt.erl
index 4e81e2c2dd..9577d17a85 100644
--- a/lib/stdlib/src/qlc_pt.erl
+++ b/lib/stdlib/src/qlc_pt.erl
@@ -428,7 +428,13 @@ compile_errors(FormsNoShadows) ->
end.
compile_forms(Forms0, Options) ->
- Forms = [F || F <- Forms0, element(1, F) =/= eof] ++ [{eof,anno0()}],
+ Exclude = fun(eof) -> true;
+ (warning) -> true;
+ (error) -> true;
+ (_) -> false
+ end,
+ Forms = ([F || F <- Forms0, not Exclude(element(1, F))]
+ ++ [{eof,anno0()}]),
try
case compile:noenv_forms(Forms, compile_options(Options)) of
{ok, _ModName, Ws0} ->
diff --git a/lib/stdlib/src/slave.erl b/lib/stdlib/src/slave.erl
index 24fc8ce204..4e629a5e56 100644
--- a/lib/stdlib/src/slave.erl
+++ b/lib/stdlib/src/slave.erl
@@ -289,10 +289,7 @@ register_unique_name(Number) ->
%% no need to use rsh.
mk_cmd(Host, Name, Args, Waiter, Prog0) ->
- Prog = case os:type() of
- {ose,_} -> mk_ose_prog(Prog0);
- _ -> quote_progname(Prog0)
- end,
+ Prog = quote_progname(Prog0),
BasicCmd = lists:concat([Prog,
" -detached -noinput -master ", node(),
" ", long_or_short(), Name, "@", Host,
@@ -312,24 +309,6 @@ mk_cmd(Host, Name, Args, Waiter, Prog0) ->
end
end.
-%% On OSE we have to pass the beam arguments directory to the slave
-%% process. To find out what arguments that should be passed on we
-%% make an assumption. All arguments after the last "--" should be
-%% skipped. So given these arguments:
-%% -Muycs256 -A 1 -- -root /mst/ -progname beam.debug.smp -- -home /mst/ -- -kernel inetrc '"/mst/inetrc.conf"' -- -name test@localhost
-%% we send
-%% -Muycs256 -A 1 -- -root /mst/ -progname beam.debug.smp -- -home /mst/ -- -kernel inetrc '"/mst/inetrc.conf"' --
-%% to the slave with whatever other args that are added in mk_cmd.
-mk_ose_prog(Prog) ->
- SkipTail = fun("--",[]) ->
- ["--"];
- (_,[]) ->
- [];
- (Arg,Args) ->
- [Arg," "|Args]
- end,
- [Prog,tl(lists:foldr(SkipTail,[],erlang:system_info(emu_args)))].
-
%% 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.
diff --git a/lib/stdlib/test/filename_SUITE.erl b/lib/stdlib/test/filename_SUITE.erl
index fd47da8150..4372e77df9 100644
--- a/lib/stdlib/test/filename_SUITE.erl
+++ b/lib/stdlib/test/filename_SUITE.erl
@@ -97,20 +97,11 @@ absname(Config) when is_list(Config) ->
?line file:set_cwd(Cwd),
ok;
- Type ->
- case Type of
- {unix, _} ->
- ?line ok = file:set_cwd("/usr"),
- ?line "/usr/foo" = filename:absname(foo),
- ?line "/usr/foo" = filename:absname("foo"),
- ?line "/usr/../ebin" = filename:absname("../ebin");
- {ose, _} ->
- ?line ok = file:set_cwd("/romfs"),
- ?line "/romfs/foo" = filename:absname(foo),
- ?line "/romfs/foo" = filename:absname("foo"),
- ?line "/romfs/../ebin" = filename:absname("../ebin")
- end,
-
+ {unix, _} ->
+ ?line ok = file:set_cwd("/usr"),
+ ?line "/usr/foo" = filename:absname(foo),
+ ?line "/usr/foo" = filename:absname("foo"),
+ ?line "/usr/../ebin" = filename:absname("../ebin"),
?line file:set_cwd("/"),
?line "/foo" = filename:absname(foo),
?line "/foo" = filename:absname("foo"),
@@ -494,18 +485,10 @@ absname_bin(Config) when is_list(Config) ->
?line file:set_cwd(Cwd),
ok;
- Type ->
- case Type of
- {unix,_} ->
- ?line ok = file:set_cwd(<<"/usr">>),
- ?line <<"/usr/foo">> = filename:absname(<<"foo">>),
- ?line <<"/usr/../ebin">> = filename:absname(<<"../ebin">>);
- {ose,_} ->
- ?line ok = file:set_cwd(<<"/romfs">>),
- ?line <<"/romfs/foo">> = filename:absname(<<"foo">>),
- ?line <<"/romfs/../ebin">> = filename:absname(<<"../ebin">>)
- end,
-
+ {unix, _} ->
+ ?line ok = file:set_cwd(<<"/usr">>),
+ ?line <<"/usr/foo">> = filename:absname(<<"foo">>),
+ ?line <<"/usr/../ebin">> = filename:absname(<<"../ebin">>),
?line file:set_cwd(<<"/">>),
?line <<"/foo">> = filename:absname(<<"foo">>),
?line <<"/../ebin">> = filename:absname(<<"../ebin">>),
diff --git a/lib/stdlib/test/qlc_SUITE.erl b/lib/stdlib/test/qlc_SUITE.erl
index 72216bfa0d..52fdb69b73 100644
--- a/lib/stdlib/test/qlc_SUITE.erl
+++ b/lib/stdlib/test/qlc_SUITE.erl
@@ -74,6 +74,7 @@
otp_5644/1, otp_5195/1, otp_6038_bug/1, otp_6359/1, otp_6562/1,
otp_6590/1, otp_6673/1, otp_6964/1, otp_7114/1, otp_7238/1,
otp_7232/1, otp_7552/1, otp_6674/1, otp_7714/1, otp_11758/1,
+ otp_12946/1,
manpage/1,
@@ -143,7 +144,7 @@ groups() ->
{tickets, [],
[otp_5644, otp_5195, otp_6038_bug, otp_6359, otp_6562,
otp_6590, otp_6673, otp_6964, otp_7114, otp_7232,
- otp_7238, otp_7552, otp_6674, otp_7714, otp_11758]},
+ otp_7238, otp_7552, otp_6674, otp_7714, otp_11758, otp_12946]},
{compat, [], [backward, forward]}].
init_per_suite(Config) ->
@@ -7154,6 +7155,18 @@ otp_6674(Config) when is_list(Config) ->
?line run(Config, Ts).
+otp_12946(doc) ->
+ ["Syntax error."];
+otp_12946(suite) -> [];
+otp_12946(Config) when is_list(Config) ->
+ Text =
+ <<"-export([init/0]).
+ init() ->
+ ok.
+ y">>,
+ {errors,[{4,erl_parse,_}],[]} = compile_file(Config, Text, []),
+ ok.
+
manpage(doc) ->
"Examples from qlc(3).";
manpage(suite) -> [];
diff --git a/lib/tools/c_src/Makefile.in b/lib/tools/c_src/Makefile.in
index 66bba229f6..e8bce149b1 100644
--- a/lib/tools/c_src/Makefile.in
+++ b/lib/tools/c_src/Makefile.in
@@ -97,11 +97,8 @@ DRIVERS=
ifneq ($(strip $(ETHR_LIB_NAME)),)
# Need ethread package for emem
-ifneq ($(findstring ose,$(TARGET)),ose)
-# Do not build on OSE
PROGS += $(BIN_DIR)/emem$(TYPEMARKER)@EXEEXT@
endif
-endif
EMEM_OBJ_DIR=$(OBJ_DIR)/emem
CREATE_DIRS += $(EMEM_OBJ_DIR)
@@ -152,12 +149,7 @@ ERTS_LIB = $(ERL_TOP/erts/lib_src/obj/$(TARGET)/$(TYPE)/MADE
_create_dirs := $(shell mkdir -p $(CREATE_DIRS))
-ifneq ($(findstring ose,$(TARGET)),ose)
all: $(PROGS) $(DRIVERS)
-else
-# Do not build dynamic files on OSE
-all:
-endif
$(ERTS_LIB):
$(make_verbose)cd $(ERL_TOP)/erts/lib_src && $(MAKE) $(TYPE)
diff --git a/lib/tools/doc/src/make.xml b/lib/tools/doc/src/make.xml
index e63163d689..5c2e5e5d62 100644
--- a/lib/tools/doc/src/make.xml
+++ b/lib/tools/doc/src/make.xml
@@ -76,7 +76,7 @@
Load mode. Loads all recompiled modules.</item>
<item><c>netload</c> <br></br>
- Net load mode. Loads all recompiled modules an all known nodes.</item>
+ Net load mode. Loads all recompiled modules on all known nodes.</item>
</list>
<p>All items in <c>Options</c> that are not make options are assumed
to be compiler options and are passed as-is to
diff --git a/lib/wx/api_gen/gen_util.erl b/lib/wx/api_gen/gen_util.erl
index 6bdbb4ca96..ff245a6359 100644
--- a/lib/wx/api_gen/gen_util.erl
+++ b/lib/wx/api_gen/gen_util.erl
@@ -230,7 +230,7 @@ erl_copyright() ->
w("%% Copyright Ericsson AB ~p-~p. All Rights Reserved.~n",
[StartYear, CurrentYear]),
w("%%~n",[]),
- w("%% Licensed under the Apache License, Version 2.0 (the \"License\");,~n",[]),
+ w("%% Licensed under the Apache License, Version 2.0 (the \"License\");~n",[]),
w("%% you may not use this file except in compliance with the License.~n",[]),
w("%% You may obtain a copy of the License at~n",[]),
w("%%~n",[]),
@@ -251,7 +251,7 @@ c_copyright() ->
w(" *~n",[]),
w(" * Copyright Ericsson AB 2008-~p. All Rights Reserved.~n",[CurrentYear]),
w(" *~n",[]),
- w(" * Licensed under the Apache License, Version 2.0 (the \"License\");,~n",[]),
+ w(" * Licensed under the Apache License, Version 2.0 (the \"License\");~n",[]),
w(" * you may not use this file except in compliance with the License.~n",[]),
w(" * You may obtain a copy of the License at~n",[]),
w(" *~n",[]),
diff --git a/lib/wx/api_gen/wx_extra/wxEvtHandler.c_src b/lib/wx/api_gen/wx_extra/wxEvtHandler.c_src
index 5d20019d8f..5e02066309 100644
--- a/lib/wx/api_gen/wx_extra/wxEvtHandler.c_src
+++ b/lib/wx/api_gen/wx_extra/wxEvtHandler.c_src
@@ -11,7 +11,7 @@ case 100: { // wxEvtHandler::Connect
int * class_nameLen = (int *) bp; bp += 4;
if(*haveUserData) {
- userData = new wxeErlTerm(Ecmd.bin[0]);
+ userData = new wxeErlTerm(&Ecmd.bin[0]);
}
int eventType = wxeEventTypeFromAtom(bp); bp += *eventTypeLen;
diff --git a/lib/wx/api_gen/wx_extra/wxEvtHandler.erl b/lib/wx/api_gen/wx_extra/wxEvtHandler.erl
index c9726fd475..85ebc093f5 100644
--- a/lib/wx/api_gen/wx_extra/wxEvtHandler.erl
+++ b/lib/wx/api_gen/wx_extra/wxEvtHandler.erl
@@ -70,6 +70,8 @@ connect(This=#wx_ref{type=ThisT}, EventType, Options) ->
parse_opts([{callback,Fun}|R], Opts) when is_function(Fun) ->
%% Check Fun Arity?
parse_opts(R, Opts#evh{cb=Fun});
+parse_opts([{callback,CB={nospawn, Fun}}|R], Opts) when is_function(Fun) ->
+ parse_opts(R, Opts#evh{cb=CB});
parse_opts([callback|R], Opts) ->
parse_opts(R, Opts#evh{cb=self()});
parse_opts([{userData, UserData}|R],Opts) ->
diff --git a/lib/wx/api_gen/wx_gen.erl b/lib/wx/api_gen/wx_gen.erl
index 212574ede3..114b3e561e 100644
--- a/lib/wx/api_gen/wx_gen.erl
+++ b/lib/wx/api_gen/wx_gen.erl
@@ -1196,7 +1196,7 @@ translate_constants(Enums, NotConsts0, Skip0) ->
create_consts([{{enum, Name},Enum = #enum{vals=Vals}}|R], Skip, NotConsts, Acc0) ->
CC = fun(What, Acc) ->
- create_const(What, Skip, NotConsts, Acc)
+ create_const(What, Name, Skip, NotConsts, Acc)
end,
Acc = case Vals of
undefined ->
@@ -1210,17 +1210,17 @@ create_consts([{{enum, Name},Enum = #enum{vals=Vals}}|R], Skip, NotConsts, Acc0)
create_consts(R, Skip, NotConsts, Acc);
create_consts([],_,_,Acc) -> Acc.
-create_const({Name, Val}, Skip, NotConsts, Acc) ->
+create_const({Name, Val}, EnumName, Skip, NotConsts, Acc) ->
case gb_sets:is_member(Name, Skip) of
true -> Acc;
false ->
- case gb_sets:is_member(Name, NotConsts) of
+ case gb_sets:is_member(Name, NotConsts) orelse
+ gb_sets:is_member(EnumName, NotConsts)
+ of
true ->
[#const{name=Name,val=next_id(const),is_const=false}|Acc];
false ->
[#const{name=Name,val=Val,is_const=true}|Acc]
-%% false ->
-%% [#const{name=Name,val=Val}|Acc]
end
end.
diff --git a/lib/wx/api_gen/wx_gen_cpp.erl b/lib/wx/api_gen/wx_gen_cpp.erl
index 3120d491b1..2ce6295078 100644
--- a/lib/wx/api_gen/wx_gen_cpp.erl
+++ b/lib/wx/api_gen/wx_gen_cpp.erl
@@ -206,8 +206,8 @@ gen_funcs(Defs) ->
" rt.addAtom(\"ok\");~n"
" break;~n"
" }~n"),
- w(" case WXE_BIN_INCR:~n driver_binary_inc_refc(Ecmd.bin[0]->bin);~n break;~n",[]),
- w(" case WXE_BIN_DECR:~n driver_binary_dec_refc(Ecmd.bin[0]->bin);~n break;~n",[]),
+ w(" case WXE_BIN_INCR:~n driver_binary_inc_refc(Ecmd.bin[0].bin);~n break;~n",[]),
+ w(" case WXE_BIN_DECR:~n driver_binary_dec_refc(Ecmd.bin[0].bin);~n break;~n",[]),
w(" case WXE_INIT_OPENGL:~n wxe_initOpenGL(&rt, bp);~n break;~n",[]),
Res = [gen_class(Class) || Class <- Defs],
@@ -631,10 +631,10 @@ decode_arg(N,#type{name=Type,base=binary,mod=Mod0},Arg,A0) ->
Mod = mods([M || M <- Mod0]),
case Arg of
arg ->
- w(" ~s~s * ~s = (~s~s*) Ecmd.bin[~p]->base;~n",
+ w(" ~s~s * ~s = (~s~s*) Ecmd.bin[~p].base;~n",
[Mod,Type,N,Mod,Type, next_id(bin_count)]);
opt ->
- w(" ~s = (~s~s*) Ecmd.bin[~p]->base;~n",
+ w(" ~s = (~s~s*) Ecmd.bin[~p].base;~n",
[N,Mod,Type,next_id(bin_count)])
end,
A0;
@@ -644,10 +644,10 @@ decode_arg(N,#type{base={term,"wxTreeItemData"},mod=Mod0},Arg,A0) ->
BinCnt = next_id(bin_count),
case Arg of
arg ->
- w(" ~s~s * ~s = new ~s(Ecmd.bin[~p]->size, Ecmd.bin[~p]->base);~n",
+ w(" ~s~s * ~s = new ~s(Ecmd.bin[~p].size, Ecmd.bin[~p].base);~n",
[Mod,Type,N,Type,BinCnt,BinCnt]);
opt ->
- w(" ~s = new ~s(Ecmd.bin[~p]->size, Ecmd.bin[~p]->base);~n",
+ w(" ~s = new ~s(Ecmd.bin[~p].size, Ecmd.bin[~p].base);~n",
[N,Type,BinCnt,BinCnt])
end,
A0;
@@ -656,10 +656,10 @@ decode_arg(N,#type{name=Type,base={term,_},mod=Mod0},Arg,A0) ->
BinCnt = next_id(bin_count),
case Arg of
arg ->
- w(" ~s~s * ~s = new ~s(Ecmd.bin[~p]);~n",
+ w(" ~s~s * ~s = new ~s(&Ecmd.bin[~p]);~n",
[Mod,Type,N,Type,BinCnt]);
opt ->
- w(" ~s = new ~s(Ecmd.bin[~p]);~n",
+ w(" ~s = new ~s(&Ecmd.bin[~p]);~n",
[N,Type,BinCnt])
end,
A0;
@@ -832,7 +832,7 @@ call_arg(#param{where=c, alt={length,Alt}}) when is_list(Alt) ->
"*" ++ Alt ++ "Len";
call_arg(#param{where=c, alt={size,Id}}) when is_integer(Id) ->
%% It's a binary
- "Ecmd.bin["++ integer_to_list(Id) ++ "]->size";
+ "Ecmd.bin["++ integer_to_list(Id) ++ "].size";
call_arg(#param{name=N,def=Def,type=#type{by_val=true,single=true,base=Base}})
when Base =:= int; Base =:= long; Base =:= float; Base =:= double; Base =:= bool ->
case Def of
diff --git a/lib/wx/api_gen/wxapi.conf b/lib/wx/api_gen/wxapi.conf
index 09877f0f5a..0d1fef6272 100644
--- a/lib/wx/api_gen/wxapi.conf
+++ b/lib/wx/api_gen/wxapi.conf
@@ -36,7 +36,8 @@
wxSL_LABELS,
wxCURSOR_DEFAULT,
wxCURSOR_ARROWWAIT,
- wxCURSOR_MAX
+ wxCURSOR_MAX,
+ wxLanguage
]}.
{gvars,
@@ -556,14 +557,14 @@
{"alpha",[in,{base,binary}]},
{{4,pre_hook},
[{c, "if(!static_data) {"
- "data = (unsigned char *) malloc(Ecmd.bin[0]->size);"
- "memcpy(data,Ecmd.bin[0]->base,Ecmd.bin[0]->size);}"}]},
+ "data = (unsigned char *) malloc(Ecmd.bin[0].size);"
+ "memcpy(data,Ecmd.bin[0].base,Ecmd.bin[0].size);}"}]},
{{5,pre_hook},
[{c, "if(!static_data) {"
- " data = (unsigned char *) malloc(Ecmd.bin[0]->size);"
- " alpha = (unsigned char *) malloc(Ecmd.bin[1]->size);"
- " memcpy(data,Ecmd.bin[0]->base,Ecmd.bin[0]->size);"
- " memcpy(alpha,Ecmd.bin[1]->base,Ecmd.bin[1]->size);}"}]}
+ " data = (unsigned char *) malloc(Ecmd.bin[0].size);"
+ " alpha = (unsigned char *) malloc(Ecmd.bin[1].size);"
+ " memcpy(data,Ecmd.bin[0].base,Ecmd.bin[0].size);"
+ " memcpy(alpha,Ecmd.bin[1].base,Ecmd.bin[1].size);}"}]}
]},
'~wxImage',%'AddHandler',
'Blur','BlurHorizontal','BlurVertical',
@@ -575,14 +576,14 @@
{"alpha",[in,{base,binary}]},
{{4,pre_hook},
[{c, "if(!static_data) {"
- "data = (unsigned char *) malloc(Ecmd.bin[0]->size);"
- "memcpy(data,Ecmd.bin[0]->base,Ecmd.bin[0]->size);}"}]},
+ "data = (unsigned char *) malloc(Ecmd.bin[0].size);"
+ "memcpy(data,Ecmd.bin[0].base,Ecmd.bin[0].size);}"}]},
{{5,pre_hook},
[{c, "if(!static_data) {"
- " data = (unsigned char *) malloc(Ecmd.bin[0]->size);"
- " alpha = (unsigned char *) malloc(Ecmd.bin[1]->size);"
- " memcpy(data,Ecmd.bin[0]->base,Ecmd.bin[0]->size);"
- " memcpy(alpha,Ecmd.bin[1]->base,Ecmd.bin[1]->size);}"}]}
+ " data = (unsigned char *) malloc(Ecmd.bin[0].size);"
+ " alpha = (unsigned char *) malloc(Ecmd.bin[1].size);"
+ " memcpy(data,Ecmd.bin[0].base,Ecmd.bin[0].size);"
+ " memcpy(alpha,Ecmd.bin[1].base,Ecmd.bin[1].size);}"}]}
]},
'Destroy','FindFirstUnusedColour', % 'FindHandler',
'GetImageExtWildcard',
@@ -608,14 +609,14 @@
{'SetAlpha', [{{2,"alpha"},[in,{base,binary}, {def, none}]},
{{2,pre_hook},
[{c, "if(!static_data) {"
- "alpha = (unsigned char *) malloc(Ecmd.bin[0]->size);"
- "memcpy(alpha,Ecmd.bin[0]->base,Ecmd.bin[0]->size);}"}]}
+ "alpha = (unsigned char *) malloc(Ecmd.bin[0].size);"
+ "memcpy(alpha,Ecmd.bin[0].base,Ecmd.bin[0].size);}"}]}
]},
{'SetData', [{"data",[in,{base,binary}]},
{pre_hook,
[{c, "if(!static_data) {"
- "data = (unsigned char *) malloc(Ecmd.bin[0]->size);"
- "memcpy(data,Ecmd.bin[0]->base,Ecmd.bin[0]->size);}"}]}
+ "data = (unsigned char *) malloc(Ecmd.bin[0].size);"
+ "memcpy(data,Ecmd.bin[0].base,Ecmd.bin[0].size);}"}]}
]},
'SetMask','SetMaskColour','SetMaskFromImage','SetOption',
'SetPalette',
@@ -1925,3 +1926,6 @@
{class, wxPopupTransientWindow, wxPopupWindow, [{ifdef, wxUSE_POPUPWIN}],
['wxPopupTransientWindow', '~wxPopupTransientWindow', 'Popup', 'Dismiss']}.
+
+{class, wxMouseCaptureLostEvent, wxEvent,
+ [{event,[wxEVT_MOUSE_CAPTURE_LOST]}],[]}.
diff --git a/lib/wx/c_src/gen/wxe_events.cpp b/lib/wx/c_src/gen/wxe_events.cpp
index 88a147cf90..f6a5868b48 100644
--- a/lib/wx/c_src/gen/wxe_events.cpp
+++ b/lib/wx/c_src/gen/wxe_events.cpp
@@ -302,6 +302,7 @@ void initEventTable()
{wxEVT_ACTIVATE, 231, "activate"},
{wxEVT_ACTIVATE_APP, 231, "activate_app"},
{wxEVT_HIBERNATE, 231, "hibernate"},
+ {wxEVT_MOUSE_CAPTURE_LOST, 234, "mouse_capture_lost"},
{-1, 0, }
};
for(int i=0; event_types[i].ev_type != -1; i++) {
@@ -870,6 +871,13 @@ case 231: {// wxActivateEvent
rt.addTupleCount(3);
break;
}
+case 234: {// wxMouseCaptureLostEvent
+ evClass = (char*)"wxMouseCaptureLostEvent";
+ rt.addAtom((char*)"wxMouseCaptureLost");
+ rt.addAtom(Etype->eName);
+ rt.addTupleCount(2);
+ break;
+}
}
rt.addTupleCount(5);
diff --git a/lib/wx/c_src/gen/wxe_init.cpp b/lib/wx/c_src/gen/wxe_init.cpp
index fd729accc9..1e432e34ce 100644
--- a/lib/wx/c_src/gen/wxe_init.cpp
+++ b/lib/wx/c_src/gen/wxe_init.cpp
@@ -57,6 +57,472 @@ void WxeApp::init_nonconsts(wxeMemEnv *memenv, ErlDrvTermData caller) {
rt.addTupleCount(2);
rt.addAtom("wxMOD_CMD"); rt.addInt(wxMOD_CMD);
rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ABKHAZIAN"); rt.addInt(wxLANGUAGE_ABKHAZIAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_AFAR"); rt.addInt(wxLANGUAGE_AFAR);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_AFRIKAANS"); rt.addInt(wxLANGUAGE_AFRIKAANS);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ALBANIAN"); rt.addInt(wxLANGUAGE_ALBANIAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_AMHARIC"); rt.addInt(wxLANGUAGE_AMHARIC);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ARABIC"); rt.addInt(wxLANGUAGE_ARABIC);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ARABIC_ALGERIA"); rt.addInt(wxLANGUAGE_ARABIC_ALGERIA);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ARABIC_BAHRAIN"); rt.addInt(wxLANGUAGE_ARABIC_BAHRAIN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ARABIC_EGYPT"); rt.addInt(wxLANGUAGE_ARABIC_EGYPT);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ARABIC_IRAQ"); rt.addInt(wxLANGUAGE_ARABIC_IRAQ);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ARABIC_JORDAN"); rt.addInt(wxLANGUAGE_ARABIC_JORDAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ARABIC_KUWAIT"); rt.addInt(wxLANGUAGE_ARABIC_KUWAIT);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ARABIC_LEBANON"); rt.addInt(wxLANGUAGE_ARABIC_LEBANON);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ARABIC_LIBYA"); rt.addInt(wxLANGUAGE_ARABIC_LIBYA);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ARABIC_MOROCCO"); rt.addInt(wxLANGUAGE_ARABIC_MOROCCO);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ARABIC_OMAN"); rt.addInt(wxLANGUAGE_ARABIC_OMAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ARABIC_QATAR"); rt.addInt(wxLANGUAGE_ARABIC_QATAR);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ARABIC_SAUDI_ARABIA"); rt.addInt(wxLANGUAGE_ARABIC_SAUDI_ARABIA);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ARABIC_SUDAN"); rt.addInt(wxLANGUAGE_ARABIC_SUDAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ARABIC_SYRIA"); rt.addInt(wxLANGUAGE_ARABIC_SYRIA);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ARABIC_TUNISIA"); rt.addInt(wxLANGUAGE_ARABIC_TUNISIA);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ARABIC_UAE"); rt.addInt(wxLANGUAGE_ARABIC_UAE);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ARABIC_YEMEN"); rt.addInt(wxLANGUAGE_ARABIC_YEMEN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ARMENIAN"); rt.addInt(wxLANGUAGE_ARMENIAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ASSAMESE"); rt.addInt(wxLANGUAGE_ASSAMESE);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_AYMARA"); rt.addInt(wxLANGUAGE_AYMARA);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_AZERI"); rt.addInt(wxLANGUAGE_AZERI);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_AZERI_CYRILLIC"); rt.addInt(wxLANGUAGE_AZERI_CYRILLIC);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_AZERI_LATIN"); rt.addInt(wxLANGUAGE_AZERI_LATIN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_BASHKIR"); rt.addInt(wxLANGUAGE_BASHKIR);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_BASQUE"); rt.addInt(wxLANGUAGE_BASQUE);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_BELARUSIAN"); rt.addInt(wxLANGUAGE_BELARUSIAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_BENGALI"); rt.addInt(wxLANGUAGE_BENGALI);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_BHUTANI"); rt.addInt(wxLANGUAGE_BHUTANI);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_BIHARI"); rt.addInt(wxLANGUAGE_BIHARI);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_BISLAMA"); rt.addInt(wxLANGUAGE_BISLAMA);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_BRETON"); rt.addInt(wxLANGUAGE_BRETON);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_BULGARIAN"); rt.addInt(wxLANGUAGE_BULGARIAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_BURMESE"); rt.addInt(wxLANGUAGE_BURMESE);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_CAMBODIAN"); rt.addInt(wxLANGUAGE_CAMBODIAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_CATALAN"); rt.addInt(wxLANGUAGE_CATALAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_CHINESE"); rt.addInt(wxLANGUAGE_CHINESE);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_CHINESE_HONGKONG"); rt.addInt(wxLANGUAGE_CHINESE_HONGKONG);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_CHINESE_MACAU"); rt.addInt(wxLANGUAGE_CHINESE_MACAU);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_CHINESE_SIMPLIFIED"); rt.addInt(wxLANGUAGE_CHINESE_SIMPLIFIED);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_CHINESE_SINGAPORE"); rt.addInt(wxLANGUAGE_CHINESE_SINGAPORE);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_CHINESE_TAIWAN"); rt.addInt(wxLANGUAGE_CHINESE_TAIWAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_CHINESE_TRADITIONAL"); rt.addInt(wxLANGUAGE_CHINESE_TRADITIONAL);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_CORSICAN"); rt.addInt(wxLANGUAGE_CORSICAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_CROATIAN"); rt.addInt(wxLANGUAGE_CROATIAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_CZECH"); rt.addInt(wxLANGUAGE_CZECH);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_DANISH"); rt.addInt(wxLANGUAGE_DANISH);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_DEFAULT"); rt.addInt(wxLANGUAGE_DEFAULT);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_DUTCH"); rt.addInt(wxLANGUAGE_DUTCH);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_DUTCH_BELGIAN"); rt.addInt(wxLANGUAGE_DUTCH_BELGIAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ENGLISH"); rt.addInt(wxLANGUAGE_ENGLISH);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ENGLISH_AUSTRALIA"); rt.addInt(wxLANGUAGE_ENGLISH_AUSTRALIA);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ENGLISH_BELIZE"); rt.addInt(wxLANGUAGE_ENGLISH_BELIZE);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ENGLISH_BOTSWANA"); rt.addInt(wxLANGUAGE_ENGLISH_BOTSWANA);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ENGLISH_CANADA"); rt.addInt(wxLANGUAGE_ENGLISH_CANADA);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ENGLISH_CARIBBEAN"); rt.addInt(wxLANGUAGE_ENGLISH_CARIBBEAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ENGLISH_DENMARK"); rt.addInt(wxLANGUAGE_ENGLISH_DENMARK);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ENGLISH_EIRE"); rt.addInt(wxLANGUAGE_ENGLISH_EIRE);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ENGLISH_JAMAICA"); rt.addInt(wxLANGUAGE_ENGLISH_JAMAICA);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ENGLISH_NEW_ZEALAND"); rt.addInt(wxLANGUAGE_ENGLISH_NEW_ZEALAND);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ENGLISH_PHILIPPINES"); rt.addInt(wxLANGUAGE_ENGLISH_PHILIPPINES);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ENGLISH_SOUTH_AFRICA"); rt.addInt(wxLANGUAGE_ENGLISH_SOUTH_AFRICA);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ENGLISH_TRINIDAD"); rt.addInt(wxLANGUAGE_ENGLISH_TRINIDAD);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ENGLISH_UK"); rt.addInt(wxLANGUAGE_ENGLISH_UK);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ENGLISH_US"); rt.addInt(wxLANGUAGE_ENGLISH_US);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ENGLISH_ZIMBABWE"); rt.addInt(wxLANGUAGE_ENGLISH_ZIMBABWE);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ESPERANTO"); rt.addInt(wxLANGUAGE_ESPERANTO);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ESTONIAN"); rt.addInt(wxLANGUAGE_ESTONIAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_FAEROESE"); rt.addInt(wxLANGUAGE_FAEROESE);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_FARSI"); rt.addInt(wxLANGUAGE_FARSI);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_FIJI"); rt.addInt(wxLANGUAGE_FIJI);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_FINNISH"); rt.addInt(wxLANGUAGE_FINNISH);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_FRENCH"); rt.addInt(wxLANGUAGE_FRENCH);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_FRENCH_BELGIAN"); rt.addInt(wxLANGUAGE_FRENCH_BELGIAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_FRENCH_CANADIAN"); rt.addInt(wxLANGUAGE_FRENCH_CANADIAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_FRENCH_LUXEMBOURG"); rt.addInt(wxLANGUAGE_FRENCH_LUXEMBOURG);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_FRENCH_MONACO"); rt.addInt(wxLANGUAGE_FRENCH_MONACO);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_FRENCH_SWISS"); rt.addInt(wxLANGUAGE_FRENCH_SWISS);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_FRISIAN"); rt.addInt(wxLANGUAGE_FRISIAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_GALICIAN"); rt.addInt(wxLANGUAGE_GALICIAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_GEORGIAN"); rt.addInt(wxLANGUAGE_GEORGIAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_GERMAN"); rt.addInt(wxLANGUAGE_GERMAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_GERMAN_AUSTRIAN"); rt.addInt(wxLANGUAGE_GERMAN_AUSTRIAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_GERMAN_BELGIUM"); rt.addInt(wxLANGUAGE_GERMAN_BELGIUM);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_GERMAN_LIECHTENSTEIN"); rt.addInt(wxLANGUAGE_GERMAN_LIECHTENSTEIN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_GERMAN_LUXEMBOURG"); rt.addInt(wxLANGUAGE_GERMAN_LUXEMBOURG);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_GERMAN_SWISS"); rt.addInt(wxLANGUAGE_GERMAN_SWISS);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_GREEK"); rt.addInt(wxLANGUAGE_GREEK);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_GREENLANDIC"); rt.addInt(wxLANGUAGE_GREENLANDIC);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_GUARANI"); rt.addInt(wxLANGUAGE_GUARANI);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_GUJARATI"); rt.addInt(wxLANGUAGE_GUJARATI);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_HAUSA"); rt.addInt(wxLANGUAGE_HAUSA);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_HEBREW"); rt.addInt(wxLANGUAGE_HEBREW);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_HINDI"); rt.addInt(wxLANGUAGE_HINDI);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_HUNGARIAN"); rt.addInt(wxLANGUAGE_HUNGARIAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ICELANDIC"); rt.addInt(wxLANGUAGE_ICELANDIC);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_INDONESIAN"); rt.addInt(wxLANGUAGE_INDONESIAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_INTERLINGUA"); rt.addInt(wxLANGUAGE_INTERLINGUA);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_INTERLINGUE"); rt.addInt(wxLANGUAGE_INTERLINGUE);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_INUKTITUT"); rt.addInt(wxLANGUAGE_INUKTITUT);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_INUPIAK"); rt.addInt(wxLANGUAGE_INUPIAK);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_IRISH"); rt.addInt(wxLANGUAGE_IRISH);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ITALIAN"); rt.addInt(wxLANGUAGE_ITALIAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ITALIAN_SWISS"); rt.addInt(wxLANGUAGE_ITALIAN_SWISS);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_JAPANESE"); rt.addInt(wxLANGUAGE_JAPANESE);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_JAVANESE"); rt.addInt(wxLANGUAGE_JAVANESE);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_KANNADA"); rt.addInt(wxLANGUAGE_KANNADA);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_KASHMIRI"); rt.addInt(wxLANGUAGE_KASHMIRI);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_KASHMIRI_INDIA"); rt.addInt(wxLANGUAGE_KASHMIRI_INDIA);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_KAZAKH"); rt.addInt(wxLANGUAGE_KAZAKH);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_KERNEWEK"); rt.addInt(wxLANGUAGE_KERNEWEK);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_KINYARWANDA"); rt.addInt(wxLANGUAGE_KINYARWANDA);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_KIRGHIZ"); rt.addInt(wxLANGUAGE_KIRGHIZ);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_KIRUNDI"); rt.addInt(wxLANGUAGE_KIRUNDI);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_KONKANI"); rt.addInt(wxLANGUAGE_KONKANI);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_KOREAN"); rt.addInt(wxLANGUAGE_KOREAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_KURDISH"); rt.addInt(wxLANGUAGE_KURDISH);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_LAOTHIAN"); rt.addInt(wxLANGUAGE_LAOTHIAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_LATIN"); rt.addInt(wxLANGUAGE_LATIN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_LATVIAN"); rt.addInt(wxLANGUAGE_LATVIAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_LINGALA"); rt.addInt(wxLANGUAGE_LINGALA);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_LITHUANIAN"); rt.addInt(wxLANGUAGE_LITHUANIAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_MACEDONIAN"); rt.addInt(wxLANGUAGE_MACEDONIAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_MALAGASY"); rt.addInt(wxLANGUAGE_MALAGASY);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_MALAY"); rt.addInt(wxLANGUAGE_MALAY);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_MALAYALAM"); rt.addInt(wxLANGUAGE_MALAYALAM);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_MALAY_BRUNEI_DARUSSALAM"); rt.addInt(wxLANGUAGE_MALAY_BRUNEI_DARUSSALAM);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_MALAY_MALAYSIA"); rt.addInt(wxLANGUAGE_MALAY_MALAYSIA);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_MALTESE"); rt.addInt(wxLANGUAGE_MALTESE);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_MANIPURI"); rt.addInt(wxLANGUAGE_MANIPURI);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_MAORI"); rt.addInt(wxLANGUAGE_MAORI);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_MARATHI"); rt.addInt(wxLANGUAGE_MARATHI);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_MOLDAVIAN"); rt.addInt(wxLANGUAGE_MOLDAVIAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_MONGOLIAN"); rt.addInt(wxLANGUAGE_MONGOLIAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_NAURU"); rt.addInt(wxLANGUAGE_NAURU);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_NEPALI"); rt.addInt(wxLANGUAGE_NEPALI);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_NEPALI_INDIA"); rt.addInt(wxLANGUAGE_NEPALI_INDIA);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_NORWEGIAN_BOKMAL"); rt.addInt(wxLANGUAGE_NORWEGIAN_BOKMAL);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_NORWEGIAN_NYNORSK"); rt.addInt(wxLANGUAGE_NORWEGIAN_NYNORSK);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_OCCITAN"); rt.addInt(wxLANGUAGE_OCCITAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ORIYA"); rt.addInt(wxLANGUAGE_ORIYA);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_OROMO"); rt.addInt(wxLANGUAGE_OROMO);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_PASHTO"); rt.addInt(wxLANGUAGE_PASHTO);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_POLISH"); rt.addInt(wxLANGUAGE_POLISH);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_PORTUGUESE"); rt.addInt(wxLANGUAGE_PORTUGUESE);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_PORTUGUESE_BRAZILIAN"); rt.addInt(wxLANGUAGE_PORTUGUESE_BRAZILIAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_PUNJABI"); rt.addInt(wxLANGUAGE_PUNJABI);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_QUECHUA"); rt.addInt(wxLANGUAGE_QUECHUA);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_RHAETO_ROMANCE"); rt.addInt(wxLANGUAGE_RHAETO_ROMANCE);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ROMANIAN"); rt.addInt(wxLANGUAGE_ROMANIAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_RUSSIAN"); rt.addInt(wxLANGUAGE_RUSSIAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_RUSSIAN_UKRAINE"); rt.addInt(wxLANGUAGE_RUSSIAN_UKRAINE);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SAMI"); rt.addInt(wxLANGUAGE_SAMI);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SAMOAN"); rt.addInt(wxLANGUAGE_SAMOAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SANGHO"); rt.addInt(wxLANGUAGE_SANGHO);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SANSKRIT"); rt.addInt(wxLANGUAGE_SANSKRIT);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SCOTS_GAELIC"); rt.addInt(wxLANGUAGE_SCOTS_GAELIC);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SERBIAN"); rt.addInt(wxLANGUAGE_SERBIAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SERBIAN_CYRILLIC"); rt.addInt(wxLANGUAGE_SERBIAN_CYRILLIC);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SERBIAN_LATIN"); rt.addInt(wxLANGUAGE_SERBIAN_LATIN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SERBO_CROATIAN"); rt.addInt(wxLANGUAGE_SERBO_CROATIAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SESOTHO"); rt.addInt(wxLANGUAGE_SESOTHO);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SETSWANA"); rt.addInt(wxLANGUAGE_SETSWANA);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SHONA"); rt.addInt(wxLANGUAGE_SHONA);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SINDHI"); rt.addInt(wxLANGUAGE_SINDHI);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SINHALESE"); rt.addInt(wxLANGUAGE_SINHALESE);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SISWATI"); rt.addInt(wxLANGUAGE_SISWATI);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SLOVAK"); rt.addInt(wxLANGUAGE_SLOVAK);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SLOVENIAN"); rt.addInt(wxLANGUAGE_SLOVENIAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SOMALI"); rt.addInt(wxLANGUAGE_SOMALI);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SPANISH"); rt.addInt(wxLANGUAGE_SPANISH);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SPANISH_ARGENTINA"); rt.addInt(wxLANGUAGE_SPANISH_ARGENTINA);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SPANISH_BOLIVIA"); rt.addInt(wxLANGUAGE_SPANISH_BOLIVIA);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SPANISH_CHILE"); rt.addInt(wxLANGUAGE_SPANISH_CHILE);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SPANISH_COLOMBIA"); rt.addInt(wxLANGUAGE_SPANISH_COLOMBIA);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SPANISH_COSTA_RICA"); rt.addInt(wxLANGUAGE_SPANISH_COSTA_RICA);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SPANISH_DOMINICAN_REPUBLIC"); rt.addInt(wxLANGUAGE_SPANISH_DOMINICAN_REPUBLIC);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SPANISH_ECUADOR"); rt.addInt(wxLANGUAGE_SPANISH_ECUADOR);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SPANISH_EL_SALVADOR"); rt.addInt(wxLANGUAGE_SPANISH_EL_SALVADOR);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SPANISH_GUATEMALA"); rt.addInt(wxLANGUAGE_SPANISH_GUATEMALA);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SPANISH_HONDURAS"); rt.addInt(wxLANGUAGE_SPANISH_HONDURAS);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SPANISH_MEXICAN"); rt.addInt(wxLANGUAGE_SPANISH_MEXICAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SPANISH_MODERN"); rt.addInt(wxLANGUAGE_SPANISH_MODERN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SPANISH_NICARAGUA"); rt.addInt(wxLANGUAGE_SPANISH_NICARAGUA);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SPANISH_PANAMA"); rt.addInt(wxLANGUAGE_SPANISH_PANAMA);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SPANISH_PARAGUAY"); rt.addInt(wxLANGUAGE_SPANISH_PARAGUAY);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SPANISH_PERU"); rt.addInt(wxLANGUAGE_SPANISH_PERU);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SPANISH_PUERTO_RICO"); rt.addInt(wxLANGUAGE_SPANISH_PUERTO_RICO);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SPANISH_URUGUAY"); rt.addInt(wxLANGUAGE_SPANISH_URUGUAY);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SPANISH_US"); rt.addInt(wxLANGUAGE_SPANISH_US);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SPANISH_VENEZUELA"); rt.addInt(wxLANGUAGE_SPANISH_VENEZUELA);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SUNDANESE"); rt.addInt(wxLANGUAGE_SUNDANESE);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SWAHILI"); rt.addInt(wxLANGUAGE_SWAHILI);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SWEDISH"); rt.addInt(wxLANGUAGE_SWEDISH);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_SWEDISH_FINLAND"); rt.addInt(wxLANGUAGE_SWEDISH_FINLAND);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_TAGALOG"); rt.addInt(wxLANGUAGE_TAGALOG);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_TAJIK"); rt.addInt(wxLANGUAGE_TAJIK);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_TAMIL"); rt.addInt(wxLANGUAGE_TAMIL);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_TATAR"); rt.addInt(wxLANGUAGE_TATAR);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_TELUGU"); rt.addInt(wxLANGUAGE_TELUGU);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_THAI"); rt.addInt(wxLANGUAGE_THAI);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_TIBETAN"); rt.addInt(wxLANGUAGE_TIBETAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_TIGRINYA"); rt.addInt(wxLANGUAGE_TIGRINYA);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_TONGA"); rt.addInt(wxLANGUAGE_TONGA);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_TSONGA"); rt.addInt(wxLANGUAGE_TSONGA);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_TURKISH"); rt.addInt(wxLANGUAGE_TURKISH);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_TURKMEN"); rt.addInt(wxLANGUAGE_TURKMEN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_TWI"); rt.addInt(wxLANGUAGE_TWI);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_UIGHUR"); rt.addInt(wxLANGUAGE_UIGHUR);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_UKRAINIAN"); rt.addInt(wxLANGUAGE_UKRAINIAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_UNKNOWN"); rt.addInt(wxLANGUAGE_UNKNOWN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_URDU"); rt.addInt(wxLANGUAGE_URDU);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_URDU_INDIA"); rt.addInt(wxLANGUAGE_URDU_INDIA);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_URDU_PAKISTAN"); rt.addInt(wxLANGUAGE_URDU_PAKISTAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_USER_DEFINED"); rt.addInt(wxLANGUAGE_USER_DEFINED);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_UZBEK"); rt.addInt(wxLANGUAGE_UZBEK);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_UZBEK_CYRILLIC"); rt.addInt(wxLANGUAGE_UZBEK_CYRILLIC);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_UZBEK_LATIN"); rt.addInt(wxLANGUAGE_UZBEK_LATIN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_VALENCIAN"); rt.addInt(wxLANGUAGE_VALENCIAN);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_VIETNAMESE"); rt.addInt(wxLANGUAGE_VIETNAMESE);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_VOLAPUK"); rt.addInt(wxLANGUAGE_VOLAPUK);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_WELSH"); rt.addInt(wxLANGUAGE_WELSH);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_WOLOF"); rt.addInt(wxLANGUAGE_WOLOF);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_XHOSA"); rt.addInt(wxLANGUAGE_XHOSA);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_YIDDISH"); rt.addInt(wxLANGUAGE_YIDDISH);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_YORUBA"); rt.addInt(wxLANGUAGE_YORUBA);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ZHUANG"); rt.addInt(wxLANGUAGE_ZHUANG);
+ rt.addTupleCount(2);
+ rt.addAtom("wxLANGUAGE_ZULU"); rt.addInt(wxLANGUAGE_ZULU);
+ rt.addTupleCount(2);
rt.addAtom("wxCURSOR_ARROWWAIT"); rt.addInt(wxCURSOR_ARROWWAIT);
rt.addTupleCount(2);
rt.addAtom("wxCURSOR_DEFAULT"); rt.addInt(wxCURSOR_DEFAULT);
@@ -145,7 +611,7 @@ 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(60);
+ rt.endList(293);
rt.addTupleCount(2);
rt.send();
}
diff --git a/lib/wx/c_src/wxe_impl.cpp b/lib/wx/c_src/wxe_impl.cpp
index 6236fb708e..5b34f08704 100644
--- a/lib/wx/c_src/wxe_impl.cpp
+++ b/lib/wx/c_src/wxe_impl.cpp
@@ -60,6 +60,7 @@ wxeFifo * wxe_queue = NULL;
wxeFifo * wxe_queue_cb_saved = NULL;
unsigned int wxe_needs_signal = 0; // inside batch if larger than 0
+unsigned int wxe_cb_invoked = 0;
/* ************************************************************
* Commands from erlang
@@ -181,6 +182,25 @@ void WxeApp::dummy_close(wxEvent& Ev) {
// windows open, and this will kill the erlang, override default handling
}
+void WxeApp::OnAssertFailure(const wxChar *file, int line, const wxChar *cfunc,
+ const wxChar *cond, const wxChar *cmsgUser) {
+ wxString msg;
+ wxString func(cfunc);
+ wxString msgUser(cmsgUser);
+
+ msg.Printf(wxT("wxWidgets Assert failure: %s(%d): \"%s\""),
+ file, line, cond);
+ if ( !func.empty() ) {
+ msg << wxT(" in ") << func << wxT("()");
+ }
+ // and the message itself
+ if ( !msgUser.empty() ) {
+ msg << wxT(" : ") << msgUser;
+ }
+
+ send_msg("error", &msg);
+}
+
// Called by wx thread
void WxeApp::idle(wxIdleEvent& event) {
event.Skip(true);
@@ -214,6 +234,7 @@ void handle_event_callback(ErlDrvPort port, ErlDrvTermData process)
app->recurse_level--;
// fprintf(stderr, "CB EV done %lu \r\n", process);fflush(stderr);
driver_demonitor_process(port, &monitor);
+ wxe_cb_invoked = 1;
}
}
@@ -221,10 +242,16 @@ void WxeApp::dispatch_cmds()
{
if(wxe_status != WXE_INITIATED)
return;
- recurse_level++;
- int level = dispatch(wxe_queue_cb_saved, 0, WXE_STORED);
- dispatch(wxe_queue, level, WXE_NORMAL);
- recurse_level--;
+ do {
+ wxe_cb_invoked = 0;
+ recurse_level++;
+ // fprintf(stderr, "\r\ndispatch_saved 0 \r\n");fflush(stderr);
+ int level = dispatch(wxe_queue_cb_saved, 0, WXE_STORED);
+ // fprintf(stderr, "\r\ndispatch_normal %d\r\n", level);fflush(stderr);
+ dispatch(wxe_queue, level, WXE_NORMAL);
+ // fprintf(stderr, "\r\ndispatch_done \r\n");fflush(stderr);
+ recurse_level--;
+ } while(wxe_cb_invoked);
// Cleanup old memenv's and deleted objects
if(recurse_level == 0) {
@@ -294,7 +321,12 @@ int WxeApp::dispatch(wxeFifo * batch, int blevel, int list_type)
break;
}
event->Delete();
- if(list_type == WXE_NORMAL) erl_drv_mutex_lock(wxe_batch_locker_m);
+ if(list_type == WXE_NORMAL) {
+ if(wxe_cb_invoked)
+ return blevel;
+ else
+ erl_drv_mutex_lock(wxe_batch_locker_m);
+ }
}
if(list_type == WXE_STORED)
return blevel;
diff --git a/lib/wx/c_src/wxe_impl.h b/lib/wx/c_src/wxe_impl.h
index d8241d11a4..d6d3095a0f 100644
--- a/lib/wx/c_src/wxe_impl.h
+++ b/lib/wx/c_src/wxe_impl.h
@@ -57,9 +57,14 @@ class WxeApp : public wxApp
{
public:
virtual bool OnInit();
+
+ virtual void OnAssertFailure(const wxChar *file, int line, const wxChar *func,
+ const wxChar *cond, const wxChar *msg);
+
#ifdef _MACOSX
virtual void MacOpenFile(const wxString &filename);
#endif
+
void shutdown(wxeMetaCommand& event);
int dispatch(wxeFifo *, int, int);
diff --git a/lib/wx/include/wx.hrl b/lib/wx/include/wx.hrl
index 6705e34cb9..69ca13aca1 100644
--- a/lib/wx/include/wx.hrl
+++ b/lib/wx/include/wx.hrl
@@ -133,6 +133,10 @@
-type wxSetCursorEventType() :: set_cursor.
-type wxSetCursor() :: #wxSetCursor{}. %% Callback event: {@link wxSetCursorEvent}
+-record(wxMouseCaptureLost, {type :: wxMouseCaptureLostEventType()}). %% Callback event: {@link wxMouseCaptureLostEvent}
+-type wxMouseCaptureLostEventType() :: mouse_capture_lost.
+-type wxMouseCaptureLost() :: #wxMouseCaptureLost{}. %% Callback event: {@link wxMouseCaptureLostEvent}
+
-record(wxFontPicker,{type :: wxFontPickerEventType(), %% Callback event: {@link wxFontPickerEvent}
font :: wxFont:wxFont()}).
-type wxFontPickerEventType() :: command_fontpicker_changed.
@@ -344,8 +348,8 @@
-type wxTreeEventType() :: command_tree_begin_drag | command_tree_begin_rdrag | command_tree_begin_label_edit | command_tree_end_label_edit | command_tree_delete_item | command_tree_get_info | command_tree_set_info | command_tree_item_expanded | command_tree_item_expanding | command_tree_item_collapsed | command_tree_item_collapsing | command_tree_sel_changed | command_tree_sel_changing | command_tree_key_down | command_tree_item_activated | command_tree_item_right_click | command_tree_item_middle_click | command_tree_end_drag | command_tree_state_image_click | command_tree_item_gettooltip | command_tree_item_menu.
-type wxTree() :: #wxTree{}. %% Callback event: {@link wxTreeEvent}
--type event() :: wxActivate() | wxAuiManager() | wxAuiNotebook() | wxCalendar() | wxChildFocus() | wxClipboardText() | wxClose() | wxColourPicker() | wxCommand() | wxContextMenu() | wxDate() | wxDisplayChanged() | wxErase() | wxFileDirPicker() | wxFocus() | wxFontPicker() | wxGrid() | wxHelp() | wxHtmlLink() | wxIconize() | wxIdle() | wxInitDialog() | wxJoystick() | wxKey() | wxList() | wxMaximize() | wxMenu() | wxMouse() | wxMouseCaptureChanged() | wxMove() | wxNavigationKey() | wxNotebook() | wxPaint() | wxPaletteChanged() | wxQueryNewPalette() | wxSash() | wxScroll() | wxScrollWin() | wxSetCursor() | wxShow() | wxSize() | wxSpin() | wxSplitter() | wxStyledText() | wxSysColourChanged() | wxTaskBarIcon() | wxTree() | wxUpdateUI() | wxWindowCreate() | wxWindowDestroy().
--type wxEventType() :: wxActivateEventType() | wxAuiManagerEventType() | wxAuiNotebookEventType() | wxCalendarEventType() | wxChildFocusEventType() | wxClipboardTextEventType() | wxCloseEventType() | wxColourPickerEventType() | wxCommandEventType() | wxContextMenuEventType() | wxDateEventType() | wxDisplayChangedEventType() | wxEraseEventType() | wxFileDirPickerEventType() | wxFocusEventType() | wxFontPickerEventType() | wxGridEventType() | wxHelpEventType() | wxHtmlLinkEventType() | wxIconizeEventType() | wxIdleEventType() | wxInitDialogEventType() | wxJoystickEventType() | wxKeyEventType() | wxListEventType() | wxMaximizeEventType() | wxMenuEventType() | wxMouseCaptureChangedEventType() | wxMouseEventType() | wxMoveEventType() | wxNavigationKeyEventType() | wxNotebookEventType() | wxPaintEventType() | wxPaletteChangedEventType() | wxQueryNewPaletteEventType() | wxSashEventType() | wxScrollEventType() | wxScrollWinEventType() | wxSetCursorEventType() | wxShowEventType() | wxSizeEventType() | wxSpinEventType() | wxSplitterEventType() | wxStyledTextEventType() | wxSysColourChangedEventType() | wxTaskBarIconEventType() | wxTreeEventType() | wxUpdateUIEventType() | wxWindowCreateEventType() | wxWindowDestroyEventType().
+-type event() :: wxActivate() | wxAuiManager() | wxAuiNotebook() | wxCalendar() | wxChildFocus() | wxClipboardText() | wxClose() | wxColourPicker() | wxCommand() | wxContextMenu() | wxDate() | wxDisplayChanged() | wxErase() | wxFileDirPicker() | wxFocus() | wxFontPicker() | wxGrid() | wxHelp() | wxHtmlLink() | wxIconize() | wxIdle() | wxInitDialog() | wxJoystick() | wxKey() | wxList() | wxMaximize() | wxMenu() | wxMouse() | wxMouseCaptureChanged() | wxMouseCaptureLost() | wxMove() | wxNavigationKey() | wxNotebook() | wxPaint() | wxPaletteChanged() | wxQueryNewPalette() | wxSash() | wxScroll() | wxScrollWin() | wxSetCursor() | wxShow() | wxSize() | wxSpin() | wxSplitter() | wxStyledText() | wxSysColourChanged() | wxTaskBarIcon() | wxTree() | wxUpdateUI() | wxWindowCreate() | wxWindowDestroy().
+-type wxEventType() :: wxActivateEventType() | wxAuiManagerEventType() | wxAuiNotebookEventType() | wxCalendarEventType() | wxChildFocusEventType() | wxClipboardTextEventType() | wxCloseEventType() | wxColourPickerEventType() | wxCommandEventType() | wxContextMenuEventType() | wxDateEventType() | wxDisplayChangedEventType() | wxEraseEventType() | wxFileDirPickerEventType() | wxFocusEventType() | wxFontPickerEventType() | wxGridEventType() | wxHelpEventType() | wxHtmlLinkEventType() | wxIconizeEventType() | wxIdleEventType() | wxInitDialogEventType() | wxJoystickEventType() | wxKeyEventType() | wxListEventType() | wxMaximizeEventType() | wxMenuEventType() | wxMouseCaptureChangedEventType() | wxMouseCaptureLostEventType() | wxMouseEventType() | wxMoveEventType() | wxNavigationKeyEventType() | wxNotebookEventType() | wxPaintEventType() | wxPaletteChangedEventType() | wxQueryNewPaletteEventType() | wxSashEventType() | wxScrollEventType() | wxScrollWinEventType() | wxSetCursorEventType() | wxShowEventType() | wxSizeEventType() | wxSpinEventType() | wxSplitterEventType() | wxStyledTextEventType() | wxSysColourChangedEventType() | wxTaskBarIconEventType() | wxTreeEventType() | wxUpdateUIEventType() | wxWindowCreateEventType() | wxWindowDestroyEventType().
%% Hardcoded Records
-record(wxMouseState, {x :: integer(), y :: integer(),
@@ -2009,239 +2013,239 @@
-define(wxIMAGELIST_DRAW_TRANSPARENT, 2).
-define(wxIMAGELIST_DRAW_NORMAL, 1).
% From "intl.h": wxLanguage
--define(wxLANGUAGE_DEFAULT, 0).
--define(wxLANGUAGE_UNKNOWN, 1).
--define(wxLANGUAGE_ABKHAZIAN, 2).
--define(wxLANGUAGE_AFAR, 3).
--define(wxLANGUAGE_AFRIKAANS, 4).
--define(wxLANGUAGE_ALBANIAN, 5).
--define(wxLANGUAGE_AMHARIC, 6).
--define(wxLANGUAGE_ARABIC, 7).
--define(wxLANGUAGE_ARABIC_ALGERIA, 8).
--define(wxLANGUAGE_ARABIC_BAHRAIN, 9).
--define(wxLANGUAGE_ARABIC_EGYPT, 10).
--define(wxLANGUAGE_ARABIC_IRAQ, 11).
--define(wxLANGUAGE_ARABIC_JORDAN, 12).
--define(wxLANGUAGE_ARABIC_KUWAIT, 13).
--define(wxLANGUAGE_ARABIC_LEBANON, 14).
--define(wxLANGUAGE_ARABIC_LIBYA, 15).
--define(wxLANGUAGE_ARABIC_MOROCCO, 16).
--define(wxLANGUAGE_ARABIC_OMAN, 17).
--define(wxLANGUAGE_ARABIC_QATAR, 18).
--define(wxLANGUAGE_ARABIC_SAUDI_ARABIA, 19).
--define(wxLANGUAGE_ARABIC_SUDAN, 20).
--define(wxLANGUAGE_ARABIC_SYRIA, 21).
--define(wxLANGUAGE_ARABIC_TUNISIA, 22).
--define(wxLANGUAGE_ARABIC_UAE, 23).
--define(wxLANGUAGE_ARABIC_YEMEN, 24).
--define(wxLANGUAGE_ARMENIAN, 25).
--define(wxLANGUAGE_ASSAMESE, 26).
--define(wxLANGUAGE_AYMARA, 27).
--define(wxLANGUAGE_AZERI, 28).
--define(wxLANGUAGE_AZERI_CYRILLIC, 29).
--define(wxLANGUAGE_AZERI_LATIN, 30).
--define(wxLANGUAGE_BASHKIR, 31).
--define(wxLANGUAGE_BASQUE, 32).
--define(wxLANGUAGE_BELARUSIAN, 33).
--define(wxLANGUAGE_BENGALI, 34).
--define(wxLANGUAGE_BHUTANI, 35).
--define(wxLANGUAGE_BIHARI, 36).
--define(wxLANGUAGE_BISLAMA, 37).
--define(wxLANGUAGE_BRETON, 38).
--define(wxLANGUAGE_BULGARIAN, 39).
--define(wxLANGUAGE_BURMESE, 40).
--define(wxLANGUAGE_CAMBODIAN, 41).
--define(wxLANGUAGE_CATALAN, 42).
--define(wxLANGUAGE_CHINESE, 43).
--define(wxLANGUAGE_CHINESE_SIMPLIFIED, 44).
--define(wxLANGUAGE_CHINESE_TRADITIONAL, 45).
--define(wxLANGUAGE_CHINESE_HONGKONG, 46).
--define(wxLANGUAGE_CHINESE_MACAU, 47).
--define(wxLANGUAGE_CHINESE_SINGAPORE, 48).
--define(wxLANGUAGE_CHINESE_TAIWAN, 49).
--define(wxLANGUAGE_CORSICAN, 50).
--define(wxLANGUAGE_CROATIAN, 51).
--define(wxLANGUAGE_CZECH, 52).
--define(wxLANGUAGE_DANISH, 53).
--define(wxLANGUAGE_DUTCH, 54).
--define(wxLANGUAGE_DUTCH_BELGIAN, 55).
--define(wxLANGUAGE_ENGLISH, 56).
--define(wxLANGUAGE_ENGLISH_UK, 57).
--define(wxLANGUAGE_ENGLISH_US, 58).
--define(wxLANGUAGE_ENGLISH_AUSTRALIA, 59).
--define(wxLANGUAGE_ENGLISH_BELIZE, 60).
--define(wxLANGUAGE_ENGLISH_BOTSWANA, 61).
--define(wxLANGUAGE_ENGLISH_CANADA, 62).
--define(wxLANGUAGE_ENGLISH_CARIBBEAN, 63).
--define(wxLANGUAGE_ENGLISH_DENMARK, 64).
--define(wxLANGUAGE_ENGLISH_EIRE, 65).
--define(wxLANGUAGE_ENGLISH_JAMAICA, 66).
--define(wxLANGUAGE_ENGLISH_NEW_ZEALAND, 67).
--define(wxLANGUAGE_ENGLISH_PHILIPPINES, 68).
--define(wxLANGUAGE_ENGLISH_SOUTH_AFRICA, 69).
--define(wxLANGUAGE_ENGLISH_TRINIDAD, 70).
--define(wxLANGUAGE_ENGLISH_ZIMBABWE, 71).
--define(wxLANGUAGE_ESPERANTO, 72).
--define(wxLANGUAGE_ESTONIAN, 73).
--define(wxLANGUAGE_FAEROESE, 74).
--define(wxLANGUAGE_FARSI, 75).
--define(wxLANGUAGE_FIJI, 76).
--define(wxLANGUAGE_FINNISH, 77).
--define(wxLANGUAGE_FRENCH, 78).
--define(wxLANGUAGE_FRENCH_BELGIAN, 79).
--define(wxLANGUAGE_FRENCH_CANADIAN, 80).
--define(wxLANGUAGE_FRENCH_LUXEMBOURG, 81).
--define(wxLANGUAGE_FRENCH_MONACO, 82).
--define(wxLANGUAGE_FRENCH_SWISS, 83).
--define(wxLANGUAGE_FRISIAN, 84).
--define(wxLANGUAGE_GALICIAN, 85).
--define(wxLANGUAGE_GEORGIAN, 86).
--define(wxLANGUAGE_GERMAN, 87).
--define(wxLANGUAGE_GERMAN_AUSTRIAN, 88).
--define(wxLANGUAGE_GERMAN_BELGIUM, 89).
--define(wxLANGUAGE_GERMAN_LIECHTENSTEIN, 90).
--define(wxLANGUAGE_GERMAN_LUXEMBOURG, 91).
--define(wxLANGUAGE_GERMAN_SWISS, 92).
--define(wxLANGUAGE_GREEK, 93).
--define(wxLANGUAGE_GREENLANDIC, 94).
--define(wxLANGUAGE_GUARANI, 95).
--define(wxLANGUAGE_GUJARATI, 96).
--define(wxLANGUAGE_HAUSA, 97).
--define(wxLANGUAGE_HEBREW, 98).
--define(wxLANGUAGE_HINDI, 99).
--define(wxLANGUAGE_HUNGARIAN, 100).
--define(wxLANGUAGE_ICELANDIC, 101).
--define(wxLANGUAGE_INDONESIAN, 102).
--define(wxLANGUAGE_INTERLINGUA, 103).
--define(wxLANGUAGE_INTERLINGUE, 104).
--define(wxLANGUAGE_INUKTITUT, 105).
--define(wxLANGUAGE_INUPIAK, 106).
--define(wxLANGUAGE_IRISH, 107).
--define(wxLANGUAGE_ITALIAN, 108).
--define(wxLANGUAGE_ITALIAN_SWISS, 109).
--define(wxLANGUAGE_JAPANESE, 110).
--define(wxLANGUAGE_JAVANESE, 111).
--define(wxLANGUAGE_KANNADA, 112).
--define(wxLANGUAGE_KASHMIRI, 113).
--define(wxLANGUAGE_KASHMIRI_INDIA, 114).
--define(wxLANGUAGE_KAZAKH, 115).
--define(wxLANGUAGE_KERNEWEK, 116).
--define(wxLANGUAGE_KINYARWANDA, 117).
--define(wxLANGUAGE_KIRGHIZ, 118).
--define(wxLANGUAGE_KIRUNDI, 119).
--define(wxLANGUAGE_KONKANI, 120).
--define(wxLANGUAGE_KOREAN, 121).
--define(wxLANGUAGE_KURDISH, 122).
--define(wxLANGUAGE_LAOTHIAN, 123).
--define(wxLANGUAGE_LATIN, 124).
--define(wxLANGUAGE_LATVIAN, 125).
--define(wxLANGUAGE_LINGALA, 126).
--define(wxLANGUAGE_LITHUANIAN, 127).
--define(wxLANGUAGE_MACEDONIAN, 128).
--define(wxLANGUAGE_MALAGASY, 129).
--define(wxLANGUAGE_MALAY, 130).
--define(wxLANGUAGE_MALAYALAM, 131).
--define(wxLANGUAGE_MALAY_BRUNEI_DARUSSALAM, 132).
--define(wxLANGUAGE_MALAY_MALAYSIA, 133).
--define(wxLANGUAGE_MALTESE, 134).
--define(wxLANGUAGE_MANIPURI, 135).
--define(wxLANGUAGE_MAORI, 136).
--define(wxLANGUAGE_MARATHI, 137).
--define(wxLANGUAGE_MOLDAVIAN, 138).
--define(wxLANGUAGE_MONGOLIAN, 139).
--define(wxLANGUAGE_NAURU, 140).
--define(wxLANGUAGE_NEPALI, 141).
--define(wxLANGUAGE_NEPALI_INDIA, 142).
--define(wxLANGUAGE_NORWEGIAN_BOKMAL, 143).
--define(wxLANGUAGE_NORWEGIAN_NYNORSK, 144).
--define(wxLANGUAGE_OCCITAN, 145).
--define(wxLANGUAGE_ORIYA, 146).
--define(wxLANGUAGE_OROMO, 147).
--define(wxLANGUAGE_PASHTO, 148).
--define(wxLANGUAGE_POLISH, 149).
--define(wxLANGUAGE_PORTUGUESE, 150).
--define(wxLANGUAGE_PORTUGUESE_BRAZILIAN, 151).
--define(wxLANGUAGE_PUNJABI, 152).
--define(wxLANGUAGE_QUECHUA, 153).
--define(wxLANGUAGE_RHAETO_ROMANCE, 154).
--define(wxLANGUAGE_ROMANIAN, 155).
--define(wxLANGUAGE_RUSSIAN, 156).
--define(wxLANGUAGE_RUSSIAN_UKRAINE, 157).
--define(wxLANGUAGE_SAMOAN, 158).
--define(wxLANGUAGE_SANGHO, 159).
--define(wxLANGUAGE_SANSKRIT, 160).
--define(wxLANGUAGE_SCOTS_GAELIC, 161).
--define(wxLANGUAGE_SERBIAN, 162).
--define(wxLANGUAGE_SERBIAN_CYRILLIC, 163).
--define(wxLANGUAGE_SERBIAN_LATIN, 164).
--define(wxLANGUAGE_SERBO_CROATIAN, 165).
--define(wxLANGUAGE_SESOTHO, 166).
--define(wxLANGUAGE_SETSWANA, 167).
--define(wxLANGUAGE_SHONA, 168).
--define(wxLANGUAGE_SINDHI, 169).
--define(wxLANGUAGE_SINHALESE, 170).
--define(wxLANGUAGE_SISWATI, 171).
--define(wxLANGUAGE_SLOVAK, 172).
--define(wxLANGUAGE_SLOVENIAN, 173).
--define(wxLANGUAGE_SOMALI, 174).
--define(wxLANGUAGE_SPANISH, 175).
--define(wxLANGUAGE_SPANISH_ARGENTINA, 176).
--define(wxLANGUAGE_SPANISH_BOLIVIA, 177).
--define(wxLANGUAGE_SPANISH_CHILE, 178).
--define(wxLANGUAGE_SPANISH_COLOMBIA, 179).
--define(wxLANGUAGE_SPANISH_COSTA_RICA, 180).
--define(wxLANGUAGE_SPANISH_DOMINICAN_REPUBLIC, 181).
--define(wxLANGUAGE_SPANISH_ECUADOR, 182).
--define(wxLANGUAGE_SPANISH_EL_SALVADOR, 183).
--define(wxLANGUAGE_SPANISH_GUATEMALA, 184).
--define(wxLANGUAGE_SPANISH_HONDURAS, 185).
--define(wxLANGUAGE_SPANISH_MEXICAN, 186).
--define(wxLANGUAGE_SPANISH_MODERN, 187).
--define(wxLANGUAGE_SPANISH_NICARAGUA, 188).
--define(wxLANGUAGE_SPANISH_PANAMA, 189).
--define(wxLANGUAGE_SPANISH_PARAGUAY, 190).
--define(wxLANGUAGE_SPANISH_PERU, 191).
--define(wxLANGUAGE_SPANISH_PUERTO_RICO, 192).
--define(wxLANGUAGE_SPANISH_URUGUAY, 193).
--define(wxLANGUAGE_SPANISH_US, 194).
--define(wxLANGUAGE_SPANISH_VENEZUELA, 195).
--define(wxLANGUAGE_SUNDANESE, 196).
--define(wxLANGUAGE_SWAHILI, 197).
--define(wxLANGUAGE_SWEDISH, 198).
--define(wxLANGUAGE_SWEDISH_FINLAND, 199).
--define(wxLANGUAGE_TAGALOG, 200).
--define(wxLANGUAGE_TAJIK, 201).
--define(wxLANGUAGE_TAMIL, 202).
--define(wxLANGUAGE_TATAR, 203).
--define(wxLANGUAGE_TELUGU, 204).
--define(wxLANGUAGE_THAI, 205).
--define(wxLANGUAGE_TIBETAN, 206).
--define(wxLANGUAGE_TIGRINYA, 207).
--define(wxLANGUAGE_TONGA, 208).
--define(wxLANGUAGE_TSONGA, 209).
--define(wxLANGUAGE_TURKISH, 210).
--define(wxLANGUAGE_TURKMEN, 211).
--define(wxLANGUAGE_TWI, 212).
--define(wxLANGUAGE_UIGHUR, 213).
--define(wxLANGUAGE_UKRAINIAN, 214).
--define(wxLANGUAGE_URDU, 215).
--define(wxLANGUAGE_URDU_INDIA, 216).
--define(wxLANGUAGE_URDU_PAKISTAN, 217).
--define(wxLANGUAGE_UZBEK, 218).
--define(wxLANGUAGE_UZBEK_CYRILLIC, 219).
--define(wxLANGUAGE_UZBEK_LATIN, 220).
--define(wxLANGUAGE_VIETNAMESE, 221).
--define(wxLANGUAGE_VOLAPUK, 222).
--define(wxLANGUAGE_WELSH, 223).
--define(wxLANGUAGE_WOLOF, 224).
--define(wxLANGUAGE_XHOSA, 225).
--define(wxLANGUAGE_YIDDISH, 226).
--define(wxLANGUAGE_YORUBA, 227).
--define(wxLANGUAGE_ZHUANG, 228).
--define(wxLANGUAGE_ZULU, 229).
--define(wxLANGUAGE_USER_DEFINED, 230).
--define(wxLANGUAGE_VALENCIAN, 536870911).
--define(wxLANGUAGE_SAMI, 536870912).
+-define(wxLANGUAGE_DEFAULT, wxe_util:get_const(wxLANGUAGE_DEFAULT)).
+-define(wxLANGUAGE_UNKNOWN, wxe_util:get_const(wxLANGUAGE_UNKNOWN)).
+-define(wxLANGUAGE_ABKHAZIAN, wxe_util:get_const(wxLANGUAGE_ABKHAZIAN)).
+-define(wxLANGUAGE_AFAR, wxe_util:get_const(wxLANGUAGE_AFAR)).
+-define(wxLANGUAGE_AFRIKAANS, wxe_util:get_const(wxLANGUAGE_AFRIKAANS)).
+-define(wxLANGUAGE_ALBANIAN, wxe_util:get_const(wxLANGUAGE_ALBANIAN)).
+-define(wxLANGUAGE_AMHARIC, wxe_util:get_const(wxLANGUAGE_AMHARIC)).
+-define(wxLANGUAGE_ARABIC, wxe_util:get_const(wxLANGUAGE_ARABIC)).
+-define(wxLANGUAGE_ARABIC_ALGERIA, wxe_util:get_const(wxLANGUAGE_ARABIC_ALGERIA)).
+-define(wxLANGUAGE_ARABIC_BAHRAIN, wxe_util:get_const(wxLANGUAGE_ARABIC_BAHRAIN)).
+-define(wxLANGUAGE_ARABIC_EGYPT, wxe_util:get_const(wxLANGUAGE_ARABIC_EGYPT)).
+-define(wxLANGUAGE_ARABIC_IRAQ, wxe_util:get_const(wxLANGUAGE_ARABIC_IRAQ)).
+-define(wxLANGUAGE_ARABIC_JORDAN, wxe_util:get_const(wxLANGUAGE_ARABIC_JORDAN)).
+-define(wxLANGUAGE_ARABIC_KUWAIT, wxe_util:get_const(wxLANGUAGE_ARABIC_KUWAIT)).
+-define(wxLANGUAGE_ARABIC_LEBANON, wxe_util:get_const(wxLANGUAGE_ARABIC_LEBANON)).
+-define(wxLANGUAGE_ARABIC_LIBYA, wxe_util:get_const(wxLANGUAGE_ARABIC_LIBYA)).
+-define(wxLANGUAGE_ARABIC_MOROCCO, wxe_util:get_const(wxLANGUAGE_ARABIC_MOROCCO)).
+-define(wxLANGUAGE_ARABIC_OMAN, wxe_util:get_const(wxLANGUAGE_ARABIC_OMAN)).
+-define(wxLANGUAGE_ARABIC_QATAR, wxe_util:get_const(wxLANGUAGE_ARABIC_QATAR)).
+-define(wxLANGUAGE_ARABIC_SAUDI_ARABIA, wxe_util:get_const(wxLANGUAGE_ARABIC_SAUDI_ARABIA)).
+-define(wxLANGUAGE_ARABIC_SUDAN, wxe_util:get_const(wxLANGUAGE_ARABIC_SUDAN)).
+-define(wxLANGUAGE_ARABIC_SYRIA, wxe_util:get_const(wxLANGUAGE_ARABIC_SYRIA)).
+-define(wxLANGUAGE_ARABIC_TUNISIA, wxe_util:get_const(wxLANGUAGE_ARABIC_TUNISIA)).
+-define(wxLANGUAGE_ARABIC_UAE, wxe_util:get_const(wxLANGUAGE_ARABIC_UAE)).
+-define(wxLANGUAGE_ARABIC_YEMEN, wxe_util:get_const(wxLANGUAGE_ARABIC_YEMEN)).
+-define(wxLANGUAGE_ARMENIAN, wxe_util:get_const(wxLANGUAGE_ARMENIAN)).
+-define(wxLANGUAGE_ASSAMESE, wxe_util:get_const(wxLANGUAGE_ASSAMESE)).
+-define(wxLANGUAGE_AYMARA, wxe_util:get_const(wxLANGUAGE_AYMARA)).
+-define(wxLANGUAGE_AZERI, wxe_util:get_const(wxLANGUAGE_AZERI)).
+-define(wxLANGUAGE_AZERI_CYRILLIC, wxe_util:get_const(wxLANGUAGE_AZERI_CYRILLIC)).
+-define(wxLANGUAGE_AZERI_LATIN, wxe_util:get_const(wxLANGUAGE_AZERI_LATIN)).
+-define(wxLANGUAGE_BASHKIR, wxe_util:get_const(wxLANGUAGE_BASHKIR)).
+-define(wxLANGUAGE_BASQUE, wxe_util:get_const(wxLANGUAGE_BASQUE)).
+-define(wxLANGUAGE_BELARUSIAN, wxe_util:get_const(wxLANGUAGE_BELARUSIAN)).
+-define(wxLANGUAGE_BENGALI, wxe_util:get_const(wxLANGUAGE_BENGALI)).
+-define(wxLANGUAGE_BHUTANI, wxe_util:get_const(wxLANGUAGE_BHUTANI)).
+-define(wxLANGUAGE_BIHARI, wxe_util:get_const(wxLANGUAGE_BIHARI)).
+-define(wxLANGUAGE_BISLAMA, wxe_util:get_const(wxLANGUAGE_BISLAMA)).
+-define(wxLANGUAGE_BRETON, wxe_util:get_const(wxLANGUAGE_BRETON)).
+-define(wxLANGUAGE_BULGARIAN, wxe_util:get_const(wxLANGUAGE_BULGARIAN)).
+-define(wxLANGUAGE_BURMESE, wxe_util:get_const(wxLANGUAGE_BURMESE)).
+-define(wxLANGUAGE_CAMBODIAN, wxe_util:get_const(wxLANGUAGE_CAMBODIAN)).
+-define(wxLANGUAGE_CATALAN, wxe_util:get_const(wxLANGUAGE_CATALAN)).
+-define(wxLANGUAGE_CHINESE, wxe_util:get_const(wxLANGUAGE_CHINESE)).
+-define(wxLANGUAGE_CHINESE_SIMPLIFIED, wxe_util:get_const(wxLANGUAGE_CHINESE_SIMPLIFIED)).
+-define(wxLANGUAGE_CHINESE_TRADITIONAL, wxe_util:get_const(wxLANGUAGE_CHINESE_TRADITIONAL)).
+-define(wxLANGUAGE_CHINESE_HONGKONG, wxe_util:get_const(wxLANGUAGE_CHINESE_HONGKONG)).
+-define(wxLANGUAGE_CHINESE_MACAU, wxe_util:get_const(wxLANGUAGE_CHINESE_MACAU)).
+-define(wxLANGUAGE_CHINESE_SINGAPORE, wxe_util:get_const(wxLANGUAGE_CHINESE_SINGAPORE)).
+-define(wxLANGUAGE_CHINESE_TAIWAN, wxe_util:get_const(wxLANGUAGE_CHINESE_TAIWAN)).
+-define(wxLANGUAGE_CORSICAN, wxe_util:get_const(wxLANGUAGE_CORSICAN)).
+-define(wxLANGUAGE_CROATIAN, wxe_util:get_const(wxLANGUAGE_CROATIAN)).
+-define(wxLANGUAGE_CZECH, wxe_util:get_const(wxLANGUAGE_CZECH)).
+-define(wxLANGUAGE_DANISH, wxe_util:get_const(wxLANGUAGE_DANISH)).
+-define(wxLANGUAGE_DUTCH, wxe_util:get_const(wxLANGUAGE_DUTCH)).
+-define(wxLANGUAGE_DUTCH_BELGIAN, wxe_util:get_const(wxLANGUAGE_DUTCH_BELGIAN)).
+-define(wxLANGUAGE_ENGLISH, wxe_util:get_const(wxLANGUAGE_ENGLISH)).
+-define(wxLANGUAGE_ENGLISH_UK, wxe_util:get_const(wxLANGUAGE_ENGLISH_UK)).
+-define(wxLANGUAGE_ENGLISH_US, wxe_util:get_const(wxLANGUAGE_ENGLISH_US)).
+-define(wxLANGUAGE_ENGLISH_AUSTRALIA, wxe_util:get_const(wxLANGUAGE_ENGLISH_AUSTRALIA)).
+-define(wxLANGUAGE_ENGLISH_BELIZE, wxe_util:get_const(wxLANGUAGE_ENGLISH_BELIZE)).
+-define(wxLANGUAGE_ENGLISH_BOTSWANA, wxe_util:get_const(wxLANGUAGE_ENGLISH_BOTSWANA)).
+-define(wxLANGUAGE_ENGLISH_CANADA, wxe_util:get_const(wxLANGUAGE_ENGLISH_CANADA)).
+-define(wxLANGUAGE_ENGLISH_CARIBBEAN, wxe_util:get_const(wxLANGUAGE_ENGLISH_CARIBBEAN)).
+-define(wxLANGUAGE_ENGLISH_DENMARK, wxe_util:get_const(wxLANGUAGE_ENGLISH_DENMARK)).
+-define(wxLANGUAGE_ENGLISH_EIRE, wxe_util:get_const(wxLANGUAGE_ENGLISH_EIRE)).
+-define(wxLANGUAGE_ENGLISH_JAMAICA, wxe_util:get_const(wxLANGUAGE_ENGLISH_JAMAICA)).
+-define(wxLANGUAGE_ENGLISH_NEW_ZEALAND, wxe_util:get_const(wxLANGUAGE_ENGLISH_NEW_ZEALAND)).
+-define(wxLANGUAGE_ENGLISH_PHILIPPINES, wxe_util:get_const(wxLANGUAGE_ENGLISH_PHILIPPINES)).
+-define(wxLANGUAGE_ENGLISH_SOUTH_AFRICA, wxe_util:get_const(wxLANGUAGE_ENGLISH_SOUTH_AFRICA)).
+-define(wxLANGUAGE_ENGLISH_TRINIDAD, wxe_util:get_const(wxLANGUAGE_ENGLISH_TRINIDAD)).
+-define(wxLANGUAGE_ENGLISH_ZIMBABWE, wxe_util:get_const(wxLANGUAGE_ENGLISH_ZIMBABWE)).
+-define(wxLANGUAGE_ESPERANTO, wxe_util:get_const(wxLANGUAGE_ESPERANTO)).
+-define(wxLANGUAGE_ESTONIAN, wxe_util:get_const(wxLANGUAGE_ESTONIAN)).
+-define(wxLANGUAGE_FAEROESE, wxe_util:get_const(wxLANGUAGE_FAEROESE)).
+-define(wxLANGUAGE_FARSI, wxe_util:get_const(wxLANGUAGE_FARSI)).
+-define(wxLANGUAGE_FIJI, wxe_util:get_const(wxLANGUAGE_FIJI)).
+-define(wxLANGUAGE_FINNISH, wxe_util:get_const(wxLANGUAGE_FINNISH)).
+-define(wxLANGUAGE_FRENCH, wxe_util:get_const(wxLANGUAGE_FRENCH)).
+-define(wxLANGUAGE_FRENCH_BELGIAN, wxe_util:get_const(wxLANGUAGE_FRENCH_BELGIAN)).
+-define(wxLANGUAGE_FRENCH_CANADIAN, wxe_util:get_const(wxLANGUAGE_FRENCH_CANADIAN)).
+-define(wxLANGUAGE_FRENCH_LUXEMBOURG, wxe_util:get_const(wxLANGUAGE_FRENCH_LUXEMBOURG)).
+-define(wxLANGUAGE_FRENCH_MONACO, wxe_util:get_const(wxLANGUAGE_FRENCH_MONACO)).
+-define(wxLANGUAGE_FRENCH_SWISS, wxe_util:get_const(wxLANGUAGE_FRENCH_SWISS)).
+-define(wxLANGUAGE_FRISIAN, wxe_util:get_const(wxLANGUAGE_FRISIAN)).
+-define(wxLANGUAGE_GALICIAN, wxe_util:get_const(wxLANGUAGE_GALICIAN)).
+-define(wxLANGUAGE_GEORGIAN, wxe_util:get_const(wxLANGUAGE_GEORGIAN)).
+-define(wxLANGUAGE_GERMAN, wxe_util:get_const(wxLANGUAGE_GERMAN)).
+-define(wxLANGUAGE_GERMAN_AUSTRIAN, wxe_util:get_const(wxLANGUAGE_GERMAN_AUSTRIAN)).
+-define(wxLANGUAGE_GERMAN_BELGIUM, wxe_util:get_const(wxLANGUAGE_GERMAN_BELGIUM)).
+-define(wxLANGUAGE_GERMAN_LIECHTENSTEIN, wxe_util:get_const(wxLANGUAGE_GERMAN_LIECHTENSTEIN)).
+-define(wxLANGUAGE_GERMAN_LUXEMBOURG, wxe_util:get_const(wxLANGUAGE_GERMAN_LUXEMBOURG)).
+-define(wxLANGUAGE_GERMAN_SWISS, wxe_util:get_const(wxLANGUAGE_GERMAN_SWISS)).
+-define(wxLANGUAGE_GREEK, wxe_util:get_const(wxLANGUAGE_GREEK)).
+-define(wxLANGUAGE_GREENLANDIC, wxe_util:get_const(wxLANGUAGE_GREENLANDIC)).
+-define(wxLANGUAGE_GUARANI, wxe_util:get_const(wxLANGUAGE_GUARANI)).
+-define(wxLANGUAGE_GUJARATI, wxe_util:get_const(wxLANGUAGE_GUJARATI)).
+-define(wxLANGUAGE_HAUSA, wxe_util:get_const(wxLANGUAGE_HAUSA)).
+-define(wxLANGUAGE_HEBREW, wxe_util:get_const(wxLANGUAGE_HEBREW)).
+-define(wxLANGUAGE_HINDI, wxe_util:get_const(wxLANGUAGE_HINDI)).
+-define(wxLANGUAGE_HUNGARIAN, wxe_util:get_const(wxLANGUAGE_HUNGARIAN)).
+-define(wxLANGUAGE_ICELANDIC, wxe_util:get_const(wxLANGUAGE_ICELANDIC)).
+-define(wxLANGUAGE_INDONESIAN, wxe_util:get_const(wxLANGUAGE_INDONESIAN)).
+-define(wxLANGUAGE_INTERLINGUA, wxe_util:get_const(wxLANGUAGE_INTERLINGUA)).
+-define(wxLANGUAGE_INTERLINGUE, wxe_util:get_const(wxLANGUAGE_INTERLINGUE)).
+-define(wxLANGUAGE_INUKTITUT, wxe_util:get_const(wxLANGUAGE_INUKTITUT)).
+-define(wxLANGUAGE_INUPIAK, wxe_util:get_const(wxLANGUAGE_INUPIAK)).
+-define(wxLANGUAGE_IRISH, wxe_util:get_const(wxLANGUAGE_IRISH)).
+-define(wxLANGUAGE_ITALIAN, wxe_util:get_const(wxLANGUAGE_ITALIAN)).
+-define(wxLANGUAGE_ITALIAN_SWISS, wxe_util:get_const(wxLANGUAGE_ITALIAN_SWISS)).
+-define(wxLANGUAGE_JAPANESE, wxe_util:get_const(wxLANGUAGE_JAPANESE)).
+-define(wxLANGUAGE_JAVANESE, wxe_util:get_const(wxLANGUAGE_JAVANESE)).
+-define(wxLANGUAGE_KANNADA, wxe_util:get_const(wxLANGUAGE_KANNADA)).
+-define(wxLANGUAGE_KASHMIRI, wxe_util:get_const(wxLANGUAGE_KASHMIRI)).
+-define(wxLANGUAGE_KASHMIRI_INDIA, wxe_util:get_const(wxLANGUAGE_KASHMIRI_INDIA)).
+-define(wxLANGUAGE_KAZAKH, wxe_util:get_const(wxLANGUAGE_KAZAKH)).
+-define(wxLANGUAGE_KERNEWEK, wxe_util:get_const(wxLANGUAGE_KERNEWEK)).
+-define(wxLANGUAGE_KINYARWANDA, wxe_util:get_const(wxLANGUAGE_KINYARWANDA)).
+-define(wxLANGUAGE_KIRGHIZ, wxe_util:get_const(wxLANGUAGE_KIRGHIZ)).
+-define(wxLANGUAGE_KIRUNDI, wxe_util:get_const(wxLANGUAGE_KIRUNDI)).
+-define(wxLANGUAGE_KONKANI, wxe_util:get_const(wxLANGUAGE_KONKANI)).
+-define(wxLANGUAGE_KOREAN, wxe_util:get_const(wxLANGUAGE_KOREAN)).
+-define(wxLANGUAGE_KURDISH, wxe_util:get_const(wxLANGUAGE_KURDISH)).
+-define(wxLANGUAGE_LAOTHIAN, wxe_util:get_const(wxLANGUAGE_LAOTHIAN)).
+-define(wxLANGUAGE_LATIN, wxe_util:get_const(wxLANGUAGE_LATIN)).
+-define(wxLANGUAGE_LATVIAN, wxe_util:get_const(wxLANGUAGE_LATVIAN)).
+-define(wxLANGUAGE_LINGALA, wxe_util:get_const(wxLANGUAGE_LINGALA)).
+-define(wxLANGUAGE_LITHUANIAN, wxe_util:get_const(wxLANGUAGE_LITHUANIAN)).
+-define(wxLANGUAGE_MACEDONIAN, wxe_util:get_const(wxLANGUAGE_MACEDONIAN)).
+-define(wxLANGUAGE_MALAGASY, wxe_util:get_const(wxLANGUAGE_MALAGASY)).
+-define(wxLANGUAGE_MALAY, wxe_util:get_const(wxLANGUAGE_MALAY)).
+-define(wxLANGUAGE_MALAYALAM, wxe_util:get_const(wxLANGUAGE_MALAYALAM)).
+-define(wxLANGUAGE_MALAY_BRUNEI_DARUSSALAM, wxe_util:get_const(wxLANGUAGE_MALAY_BRUNEI_DARUSSALAM)).
+-define(wxLANGUAGE_MALAY_MALAYSIA, wxe_util:get_const(wxLANGUAGE_MALAY_MALAYSIA)).
+-define(wxLANGUAGE_MALTESE, wxe_util:get_const(wxLANGUAGE_MALTESE)).
+-define(wxLANGUAGE_MANIPURI, wxe_util:get_const(wxLANGUAGE_MANIPURI)).
+-define(wxLANGUAGE_MAORI, wxe_util:get_const(wxLANGUAGE_MAORI)).
+-define(wxLANGUAGE_MARATHI, wxe_util:get_const(wxLANGUAGE_MARATHI)).
+-define(wxLANGUAGE_MOLDAVIAN, wxe_util:get_const(wxLANGUAGE_MOLDAVIAN)).
+-define(wxLANGUAGE_MONGOLIAN, wxe_util:get_const(wxLANGUAGE_MONGOLIAN)).
+-define(wxLANGUAGE_NAURU, wxe_util:get_const(wxLANGUAGE_NAURU)).
+-define(wxLANGUAGE_NEPALI, wxe_util:get_const(wxLANGUAGE_NEPALI)).
+-define(wxLANGUAGE_NEPALI_INDIA, wxe_util:get_const(wxLANGUAGE_NEPALI_INDIA)).
+-define(wxLANGUAGE_NORWEGIAN_BOKMAL, wxe_util:get_const(wxLANGUAGE_NORWEGIAN_BOKMAL)).
+-define(wxLANGUAGE_NORWEGIAN_NYNORSK, wxe_util:get_const(wxLANGUAGE_NORWEGIAN_NYNORSK)).
+-define(wxLANGUAGE_OCCITAN, wxe_util:get_const(wxLANGUAGE_OCCITAN)).
+-define(wxLANGUAGE_ORIYA, wxe_util:get_const(wxLANGUAGE_ORIYA)).
+-define(wxLANGUAGE_OROMO, wxe_util:get_const(wxLANGUAGE_OROMO)).
+-define(wxLANGUAGE_PASHTO, wxe_util:get_const(wxLANGUAGE_PASHTO)).
+-define(wxLANGUAGE_POLISH, wxe_util:get_const(wxLANGUAGE_POLISH)).
+-define(wxLANGUAGE_PORTUGUESE, wxe_util:get_const(wxLANGUAGE_PORTUGUESE)).
+-define(wxLANGUAGE_PORTUGUESE_BRAZILIAN, wxe_util:get_const(wxLANGUAGE_PORTUGUESE_BRAZILIAN)).
+-define(wxLANGUAGE_PUNJABI, wxe_util:get_const(wxLANGUAGE_PUNJABI)).
+-define(wxLANGUAGE_QUECHUA, wxe_util:get_const(wxLANGUAGE_QUECHUA)).
+-define(wxLANGUAGE_RHAETO_ROMANCE, wxe_util:get_const(wxLANGUAGE_RHAETO_ROMANCE)).
+-define(wxLANGUAGE_ROMANIAN, wxe_util:get_const(wxLANGUAGE_ROMANIAN)).
+-define(wxLANGUAGE_RUSSIAN, wxe_util:get_const(wxLANGUAGE_RUSSIAN)).
+-define(wxLANGUAGE_RUSSIAN_UKRAINE, wxe_util:get_const(wxLANGUAGE_RUSSIAN_UKRAINE)).
+-define(wxLANGUAGE_SAMOAN, wxe_util:get_const(wxLANGUAGE_SAMOAN)).
+-define(wxLANGUAGE_SANGHO, wxe_util:get_const(wxLANGUAGE_SANGHO)).
+-define(wxLANGUAGE_SANSKRIT, wxe_util:get_const(wxLANGUAGE_SANSKRIT)).
+-define(wxLANGUAGE_SCOTS_GAELIC, wxe_util:get_const(wxLANGUAGE_SCOTS_GAELIC)).
+-define(wxLANGUAGE_SERBIAN, wxe_util:get_const(wxLANGUAGE_SERBIAN)).
+-define(wxLANGUAGE_SERBIAN_CYRILLIC, wxe_util:get_const(wxLANGUAGE_SERBIAN_CYRILLIC)).
+-define(wxLANGUAGE_SERBIAN_LATIN, wxe_util:get_const(wxLANGUAGE_SERBIAN_LATIN)).
+-define(wxLANGUAGE_SERBO_CROATIAN, wxe_util:get_const(wxLANGUAGE_SERBO_CROATIAN)).
+-define(wxLANGUAGE_SESOTHO, wxe_util:get_const(wxLANGUAGE_SESOTHO)).
+-define(wxLANGUAGE_SETSWANA, wxe_util:get_const(wxLANGUAGE_SETSWANA)).
+-define(wxLANGUAGE_SHONA, wxe_util:get_const(wxLANGUAGE_SHONA)).
+-define(wxLANGUAGE_SINDHI, wxe_util:get_const(wxLANGUAGE_SINDHI)).
+-define(wxLANGUAGE_SINHALESE, wxe_util:get_const(wxLANGUAGE_SINHALESE)).
+-define(wxLANGUAGE_SISWATI, wxe_util:get_const(wxLANGUAGE_SISWATI)).
+-define(wxLANGUAGE_SLOVAK, wxe_util:get_const(wxLANGUAGE_SLOVAK)).
+-define(wxLANGUAGE_SLOVENIAN, wxe_util:get_const(wxLANGUAGE_SLOVENIAN)).
+-define(wxLANGUAGE_SOMALI, wxe_util:get_const(wxLANGUAGE_SOMALI)).
+-define(wxLANGUAGE_SPANISH, wxe_util:get_const(wxLANGUAGE_SPANISH)).
+-define(wxLANGUAGE_SPANISH_ARGENTINA, wxe_util:get_const(wxLANGUAGE_SPANISH_ARGENTINA)).
+-define(wxLANGUAGE_SPANISH_BOLIVIA, wxe_util:get_const(wxLANGUAGE_SPANISH_BOLIVIA)).
+-define(wxLANGUAGE_SPANISH_CHILE, wxe_util:get_const(wxLANGUAGE_SPANISH_CHILE)).
+-define(wxLANGUAGE_SPANISH_COLOMBIA, wxe_util:get_const(wxLANGUAGE_SPANISH_COLOMBIA)).
+-define(wxLANGUAGE_SPANISH_COSTA_RICA, wxe_util:get_const(wxLANGUAGE_SPANISH_COSTA_RICA)).
+-define(wxLANGUAGE_SPANISH_DOMINICAN_REPUBLIC, wxe_util:get_const(wxLANGUAGE_SPANISH_DOMINICAN_REPUBLIC)).
+-define(wxLANGUAGE_SPANISH_ECUADOR, wxe_util:get_const(wxLANGUAGE_SPANISH_ECUADOR)).
+-define(wxLANGUAGE_SPANISH_EL_SALVADOR, wxe_util:get_const(wxLANGUAGE_SPANISH_EL_SALVADOR)).
+-define(wxLANGUAGE_SPANISH_GUATEMALA, wxe_util:get_const(wxLANGUAGE_SPANISH_GUATEMALA)).
+-define(wxLANGUAGE_SPANISH_HONDURAS, wxe_util:get_const(wxLANGUAGE_SPANISH_HONDURAS)).
+-define(wxLANGUAGE_SPANISH_MEXICAN, wxe_util:get_const(wxLANGUAGE_SPANISH_MEXICAN)).
+-define(wxLANGUAGE_SPANISH_MODERN, wxe_util:get_const(wxLANGUAGE_SPANISH_MODERN)).
+-define(wxLANGUAGE_SPANISH_NICARAGUA, wxe_util:get_const(wxLANGUAGE_SPANISH_NICARAGUA)).
+-define(wxLANGUAGE_SPANISH_PANAMA, wxe_util:get_const(wxLANGUAGE_SPANISH_PANAMA)).
+-define(wxLANGUAGE_SPANISH_PARAGUAY, wxe_util:get_const(wxLANGUAGE_SPANISH_PARAGUAY)).
+-define(wxLANGUAGE_SPANISH_PERU, wxe_util:get_const(wxLANGUAGE_SPANISH_PERU)).
+-define(wxLANGUAGE_SPANISH_PUERTO_RICO, wxe_util:get_const(wxLANGUAGE_SPANISH_PUERTO_RICO)).
+-define(wxLANGUAGE_SPANISH_URUGUAY, wxe_util:get_const(wxLANGUAGE_SPANISH_URUGUAY)).
+-define(wxLANGUAGE_SPANISH_US, wxe_util:get_const(wxLANGUAGE_SPANISH_US)).
+-define(wxLANGUAGE_SPANISH_VENEZUELA, wxe_util:get_const(wxLANGUAGE_SPANISH_VENEZUELA)).
+-define(wxLANGUAGE_SUNDANESE, wxe_util:get_const(wxLANGUAGE_SUNDANESE)).
+-define(wxLANGUAGE_SWAHILI, wxe_util:get_const(wxLANGUAGE_SWAHILI)).
+-define(wxLANGUAGE_SWEDISH, wxe_util:get_const(wxLANGUAGE_SWEDISH)).
+-define(wxLANGUAGE_SWEDISH_FINLAND, wxe_util:get_const(wxLANGUAGE_SWEDISH_FINLAND)).
+-define(wxLANGUAGE_TAGALOG, wxe_util:get_const(wxLANGUAGE_TAGALOG)).
+-define(wxLANGUAGE_TAJIK, wxe_util:get_const(wxLANGUAGE_TAJIK)).
+-define(wxLANGUAGE_TAMIL, wxe_util:get_const(wxLANGUAGE_TAMIL)).
+-define(wxLANGUAGE_TATAR, wxe_util:get_const(wxLANGUAGE_TATAR)).
+-define(wxLANGUAGE_TELUGU, wxe_util:get_const(wxLANGUAGE_TELUGU)).
+-define(wxLANGUAGE_THAI, wxe_util:get_const(wxLANGUAGE_THAI)).
+-define(wxLANGUAGE_TIBETAN, wxe_util:get_const(wxLANGUAGE_TIBETAN)).
+-define(wxLANGUAGE_TIGRINYA, wxe_util:get_const(wxLANGUAGE_TIGRINYA)).
+-define(wxLANGUAGE_TONGA, wxe_util:get_const(wxLANGUAGE_TONGA)).
+-define(wxLANGUAGE_TSONGA, wxe_util:get_const(wxLANGUAGE_TSONGA)).
+-define(wxLANGUAGE_TURKISH, wxe_util:get_const(wxLANGUAGE_TURKISH)).
+-define(wxLANGUAGE_TURKMEN, wxe_util:get_const(wxLANGUAGE_TURKMEN)).
+-define(wxLANGUAGE_TWI, wxe_util:get_const(wxLANGUAGE_TWI)).
+-define(wxLANGUAGE_UIGHUR, wxe_util:get_const(wxLANGUAGE_UIGHUR)).
+-define(wxLANGUAGE_UKRAINIAN, wxe_util:get_const(wxLANGUAGE_UKRAINIAN)).
+-define(wxLANGUAGE_URDU, wxe_util:get_const(wxLANGUAGE_URDU)).
+-define(wxLANGUAGE_URDU_INDIA, wxe_util:get_const(wxLANGUAGE_URDU_INDIA)).
+-define(wxLANGUAGE_URDU_PAKISTAN, wxe_util:get_const(wxLANGUAGE_URDU_PAKISTAN)).
+-define(wxLANGUAGE_UZBEK, wxe_util:get_const(wxLANGUAGE_UZBEK)).
+-define(wxLANGUAGE_UZBEK_CYRILLIC, wxe_util:get_const(wxLANGUAGE_UZBEK_CYRILLIC)).
+-define(wxLANGUAGE_UZBEK_LATIN, wxe_util:get_const(wxLANGUAGE_UZBEK_LATIN)).
+-define(wxLANGUAGE_VIETNAMESE, wxe_util:get_const(wxLANGUAGE_VIETNAMESE)).
+-define(wxLANGUAGE_VOLAPUK, wxe_util:get_const(wxLANGUAGE_VOLAPUK)).
+-define(wxLANGUAGE_WELSH, wxe_util:get_const(wxLANGUAGE_WELSH)).
+-define(wxLANGUAGE_WOLOF, wxe_util:get_const(wxLANGUAGE_WOLOF)).
+-define(wxLANGUAGE_XHOSA, wxe_util:get_const(wxLANGUAGE_XHOSA)).
+-define(wxLANGUAGE_YIDDISH, wxe_util:get_const(wxLANGUAGE_YIDDISH)).
+-define(wxLANGUAGE_YORUBA, wxe_util:get_const(wxLANGUAGE_YORUBA)).
+-define(wxLANGUAGE_ZHUANG, wxe_util:get_const(wxLANGUAGE_ZHUANG)).
+-define(wxLANGUAGE_ZULU, wxe_util:get_const(wxLANGUAGE_ZULU)).
+-define(wxLANGUAGE_USER_DEFINED, wxe_util:get_const(wxLANGUAGE_USER_DEFINED)).
+-define(wxLANGUAGE_VALENCIAN, wxe_util:get_const(wxLANGUAGE_VALENCIAN)).
+-define(wxLANGUAGE_SAMI, wxe_util:get_const(wxLANGUAGE_SAMI)).
% From "intl.h": wxLayoutDirection
-define(wxLayout_Default, 0).
-define(wxLayout_LeftToRight, 1).
diff --git a/lib/wx/src/gen/wxEvtHandler.erl b/lib/wx/src/gen/wxEvtHandler.erl
index 6e9770bbb6..2d0a87f4dd 100644
--- a/lib/wx/src/gen/wxEvtHandler.erl
+++ b/lib/wx/src/gen/wxEvtHandler.erl
@@ -90,6 +90,8 @@ connect(This=#wx_ref{type=ThisT}, EventType, Options) ->
parse_opts([{callback,Fun}|R], Opts) when is_function(Fun) ->
%% Check Fun Arity?
parse_opts(R, Opts#evh{cb=Fun});
+parse_opts([{callback,CB={nospawn, Fun}}|R], Opts) when is_function(Fun) ->
+ parse_opts(R, Opts#evh{cb=CB});
parse_opts([callback|R], Opts) ->
parse_opts(R, Opts#evh{cb=self()});
parse_opts([{userData, UserData}|R],Opts) ->
diff --git a/lib/wx/src/gen/wxMouseCaptureLostEvent.erl b/lib/wx/src/gen/wxMouseCaptureLostEvent.erl
new file mode 100644
index 0000000000..a7e68a2d2f
--- /dev/null
+++ b/lib/wx/src/gen/wxMouseCaptureLostEvent.erl
@@ -0,0 +1,65 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-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%
+%% This file is generated DO NOT EDIT
+
+%% @doc See external documentation: <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxmousecapturelostevent.html">wxMouseCaptureLostEvent</a>.
+%% <dl><dt>Use {@link wxEvtHandler:connect/3.} with EventType:</dt>
+%% <dd><em>mouse_capture_lost</em></dd></dl>
+%% See also the message variant {@link wxEvtHandler:wxMouseCaptureLost(). #wxMouseCaptureLost{}} event record type.
+%%
+%% <p>This class is derived (and can use functions) from:
+%% <br />{@link wxEvent}
+%% </p>
+%% @type wxMouseCaptureLostEvent(). An object reference, The representation is internal
+%% and can be changed without notice. It can't be used for comparsion
+%% stored on disc or distributed for use on other nodes.
+
+-module(wxMouseCaptureLostEvent).
+-include("wxe.hrl").
+-export([]).
+
+%% inherited exports
+-export([getId/1,getSkipped/1,getTimestamp/1,isCommandEvent/1,parent_class/1,
+ resumePropagation/2,shouldPropagate/1,skip/1,skip/2,stopPropagation/1]).
+
+-export_type([wxMouseCaptureLostEvent/0]).
+%% @hidden
+parent_class(wxEvent) -> true;
+parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
+
+-type wxMouseCaptureLostEvent() :: wx:wx_object().
+ %% From wxEvent
+%% @hidden
+stopPropagation(This) -> wxEvent:stopPropagation(This).
+%% @hidden
+skip(This, Options) -> wxEvent:skip(This, Options).
+%% @hidden
+skip(This) -> wxEvent:skip(This).
+%% @hidden
+shouldPropagate(This) -> wxEvent:shouldPropagate(This).
+%% @hidden
+resumePropagation(This,PropagationLevel) -> wxEvent:resumePropagation(This,PropagationLevel).
+%% @hidden
+isCommandEvent(This) -> wxEvent:isCommandEvent(This).
+%% @hidden
+getTimestamp(This) -> wxEvent:getTimestamp(This).
+%% @hidden
+getSkipped(This) -> wxEvent:getSkipped(This).
+%% @hidden
+getId(This) -> wxEvent:getId(This).
diff --git a/lib/wx/src/wxe_server.erl b/lib/wx/src/wxe_server.erl
index 6679fcfbe1..cc253b1143 100644
--- a/lib/wx/src/wxe_server.erl
+++ b/lib/wx/src/wxe_server.erl
@@ -240,6 +240,8 @@ handle_connect(Object, EvData=#evh{handler=Handler},
invoke_cb({{Ev=#wx{}, Ref=#wx_ref{}}, FunId,_}, _S) ->
%% Event callbacks
case get(FunId) of
+ {{nospawn, Fun}, _} when is_function(Fun) ->
+ invoke_callback_fun(fun() -> Fun(Ev, Ref), <<>> end);
{Fun,_} when is_function(Fun) ->
invoke_callback(fun() -> Fun(Ev, Ref), <<>> end);
{Pid,_} when is_pid(Pid) -> %% wx_object sync event
@@ -258,21 +260,10 @@ invoke_cb({FunId, Args, _}, _S) when is_list(Args), is_integer(FunId) ->
invoke_callback(Fun) ->
Env = get(?WXE_IDENTIFIER),
- CB = fun() ->
- wx:set_env(Env),
- wxe_util:cast(?WXE_CB_START, <<>>),
- Res = try
- Return = Fun(),
- true = is_binary(Return),
- Return
- catch _:Reason ->
- ?log("Callback fun crashed with {'EXIT, ~p, ~p}~n",
- [Reason, erlang:get_stacktrace()]),
- <<>>
- end,
- wxe_util:cast(?WXE_CB_RETURN, Res)
- end,
- spawn(CB),
+ spawn(fun() ->
+ wx:set_env(Env),
+ invoke_callback_fun(Fun)
+ end),
ok.
invoke_callback(Pid, Ev, Ref) ->
@@ -302,6 +293,20 @@ invoke_callback(Pid, Ev, Ref) ->
spawn(CB),
ok.
+invoke_callback_fun(Fun) ->
+ wxe_util:cast(?WXE_CB_START, <<>>),
+ Res = try
+ Return = Fun(),
+ true = is_binary(Return),
+ Return
+ catch _:Reason ->
+ ?log("Callback fun crashed with {'EXIT, ~p, ~p}~n",
+ [Reason, erlang:get_stacktrace()]),
+ <<>>
+ end,
+ wxe_util:cast(?WXE_CB_RETURN, Res).
+
+
get_wx_object_state(Pid) ->
case process_info(Pid, dictionary) of
{dictionary, Dict} ->
diff --git a/lib/wx/test/wx_class_SUITE.erl b/lib/wx/test/wx_class_SUITE.erl
index fd6023a820..465299a649 100644
--- a/lib/wx/test/wx_class_SUITE.erl
+++ b/lib/wx/test/wx_class_SUITE.erl
@@ -386,13 +386,17 @@ listCtrlSort(Config) ->
io:format("Sorted ~p ~n",[Time]),
Item = wxListItem:new(),
+
+ %% Force an assert on (and debug compiled) which 3.0 is by default
+ wxListItem:setId(Item, 200),
+ io:format("Got ~p ~n", [wxListCtrl:getItem(LC, Item)]),
+
wxListItem:setMask(Item, ?wxLIST_MASK_TEXT),
_List = wx:map(fun(Int) ->
wxListItem:setId(Item, Int),
?m(true, wxListCtrl:getItem(LC, Item)),
io:format("~p: ~s~n",[Int, wxListItem:getText(Item)])
end, lists:seq(0,10)),
- wxListItem:destroy(Item),
wx_test_lib:wx_destroy(Frame,Config).
@@ -525,7 +529,6 @@ toolbar(Config) ->
wxFrame:show(Frame),
wx_test_lib:wx_destroy(Frame,Config).
-
popup(TestInfo) when is_atom(TestInfo) -> wx_test_lib:tc_info(TestInfo);
popup(Config) ->
Wx = wx:new(),
@@ -575,3 +578,32 @@ popup(Config) ->
wxPopupTransientWindow:dismiss(Pop)
end,
wx_test_lib:wx_destroy(Frame,Config).
+
+locale(TestInfo) when is_atom(TestInfo) -> wx_test_lib:tc_info(TestInfo);
+locale(_Config) ->
+ wx:new(),
+ io:format("SystemEncoding: ~p~n",[wxLocale:getSystemEncoding()]),
+ io:format("SystemEncodingName: ~ts~n",[wxLocale:getSystemEncodingName()]),
+ io:format("SystemLanguage: ~p~n",[wxLocale:getSystemLanguage()]),
+ io:format("SystemLanguageName: ~p~n",[wxLocale:getLanguageName(wxLocale:getSystemLanguage())]),
+ lang_env(),
+ LC = wxLocale:new(),
+ %% wxLocale:addCatalog(LC, "wxstd"),
+ io:format("Swedish: ~p~n",[wxLocale:getLanguageName(?wxLANGUAGE_SWEDISH)]),
+ R0 = wxLocale:init(LC, [{language, ?wxLANGUAGE_SWEDISH}, {flags, 0}]),
+ io:format("initiated ~p~n",[R0]),
+ lang_env(),
+ ok.
+%% wx_test_lib:wx_destroy(Frame,Config).
+
+lang_env() ->
+ Env0 = os:getenv(),
+ Env = [[R,"\n"]||R <- Env0],
+ %%io:format("~p~n",[lists:sort(Env)]),
+ Opts = [global, multiline, {capture, all, list}],
+ format_env(re:run(Env, "LC_ALL.*", Opts)),
+ format_env(re:run(Env, "^LANG.*=.*$", Opts)),
+ ok.
+format_env({match, List}) ->
+ [io:format(" ~ts~n",[L]) || L <- List];
+format_env(nomatch) -> ok.
diff --git a/lib/wx/test/wx_event_SUITE.erl b/lib/wx/test/wx_event_SUITE.erl
index 2d6f7b6aaa..7e71d6ca69 100644
--- a/lib/wx/test/wx_event_SUITE.erl
+++ b/lib/wx/test/wx_event_SUITE.erl
@@ -78,7 +78,6 @@ connect(Config) ->
Tester ! {got_size, UserD}
end,
- ?m(ok, wxFrame:connect(Frame, size)),
?m(ok, wxEvtHandler:connect(Panel, size,[{skip, true},{userData, panel}])),
?m(ok, wxEvtHandler:connect(Panel, size,[{callback,CB},{userData, panel}])),
@@ -91,12 +90,16 @@ connect(Config) ->
?m(ok, wxWindow:connect(Window, size,[{callback,CB},{userData, window}])),
?m(ok, wxWindow:connect(Window, size,[{skip,true},{userData, window}])),
+ %% For trivial side effect free callbacks, can deadlock easily otherwise
+ CB1 = fun(_,_) -> Tester ! {got_size, nospawn_cb} end,
+ ?m(ok, wxWindow:connect(Frame, size, [{callback,{nospawn, CB1}}])),
+ ?m(ok, wxFrame:connect(Frame, size, [{skip, true}])),
?m(true, wxFrame:show(Frame)),
wxWindow:setSize(Panel, {200,100}),
wxWindow:setSize(Window, {200,100}),
- get_size_messages(Frame, [frame, panel_cb, window_cb, window]),
+ get_size_messages(Frame, [frame, panel_cb, window_cb, window, nospawn_cb]),
wx_test_lib:wx_destroy(Frame, Config).
@@ -115,7 +118,9 @@ get_size_messages(Frame, Msgs) ->
?m(false, lists:member(window, Msgs)),
get_size_messages(Frame, lists:delete(window_cb, Msgs));
{got_size,panel} ->
- get_size_messages(Frame, lists:delete(panel_cb, Msgs));
+ get_size_messages(Frame, lists:delete(panel_cb, Msgs));
+ {got_size,nospawn_cb} ->
+ get_size_messages(Frame, lists:delete(nospawn_cb, Msgs));
Other ->
?error("Got unexpected msg ~p ~p~n", [Other,Msgs])
after 1000 ->