diff options
Diffstat (limited to 'lib')
25 files changed, 267 insertions, 212 deletions
diff --git a/lib/common_test/src/ct_netconfc.erl b/lib/common_test/src/ct_netconfc.erl index e094ee877a..7f10e1db09 100644 --- a/lib/common_test/src/ct_netconfc.erl +++ b/lib/common_test/src/ct_netconfc.erl @@ -247,7 +247,11 @@ -define(is_timeout(T), (is_integer(T) orelse T==infinity)). -define(is_filter(F), - (is_atom(F) orelse (is_tuple(F) andalso is_atom(element(1,F))))). + (?is_simple_xml(F) + orelse (F==[]) + orelse (is_list(F) andalso ?is_simple_xml(hd(F))))). +-define(is_simple_xml(Xml), + (is_atom(Xml) orelse (is_tuple(Xml) andalso is_atom(element(1,Xml))))). -define(is_string(S), (is_list(S) andalso is_integer(hd(S)))). %%---------------------------------------------------------------------- @@ -540,22 +544,51 @@ get_capabilities(Client) -> get_capabilities(Client, Timeout) -> call(Client, get_capabilities, Timeout). -%% @private +%%---------------------------------------------------------------------- +%% @spec send(Client, SimpleXml) -> Result +%% @equiv send(Client, SimpleXml, infinity) send(Client, SimpleXml) -> send(Client, SimpleXml, ?DEFAULT_TIMEOUT). -%% @private + +%%---------------------------------------------------------------------- +-spec send(Client, SimpleXml, Timeout) -> Result when + Client :: client(), + SimpleXml :: simple_xml(), + Timeout :: timeout(), + Result :: ok | {error,error_reason()}. +%% @doc Send an XML document to the server. +%% +%% The given XML document is sent as is to the server. This function +%% can be used for sending XML documents that can not be expressed by +%% other interface functions in this module. send(Client, SimpleXml, Timeout) -> call(Client,{send, Timeout, SimpleXml}). -%% @private +%%---------------------------------------------------------------------- +%% @spec send_rpc(Client, SimpleXml) -> Result +%% @equiv send_rpc(Client, SimpleXml, infinity) send_rpc(Client, SimpleXml) -> send_rpc(Client, SimpleXml, ?DEFAULT_TIMEOUT). -%% @private + +%%---------------------------------------------------------------------- +-spec send_rpc(Client, SimpleXml, Timeout) -> Result when + Client :: client(), + SimpleXml :: simple_xml(), + Timeout :: timeout(), + Result :: ok | {error,error_reason()}. +%% @doc Send a Netconf <code>rpc</code> request to the server. +%% +%% The given XML document is wrapped in a valid Netconf +%% <code>rpc</code> request and sent to the server. The +%% <code>message-id</code> and namespace attributes are added to the +%% <code>rpc</code> element. +%% +%% This function can be used for sending <code>rpc</code> requests +%% that can not be expressed by other interface functions in this +%% module. send_rpc(Client, SimpleXml, Timeout) -> call(Client,{send_rpc, SimpleXml, Timeout}). - - %%---------------------------------------------------------------------- %% @spec lock(Client, Target) -> Result %% @equiv lock(Client, Target, infinity) @@ -761,7 +794,7 @@ create_subscription(Client,Timeout) when ?is_timeout(Timeout) -> create_subscription(Client,?DEFAULT_STREAM,Timeout); create_subscription(Client,Stream) - when is_list(Stream) -> + when ?is_string(Stream) -> create_subscription(Client,Stream,?DEFAULT_TIMEOUT); create_subscription(Client,Filter) when ?is_filter(Filter) -> @@ -769,14 +802,14 @@ create_subscription(Client,Filter) ?DEFAULT_TIMEOUT). create_subscription(Client,Stream,Timeout) - when is_list(Stream) andalso + when ?is_string(Stream) andalso ?is_timeout(Timeout) -> call(Client,{send_rpc_op,{create_subscription,self()}, [Stream,undefined,undefined,undefined], Timeout}); create_subscription(Client,StartTime,StopTime) - when is_list(StartTime) andalso - is_list(StopTime) -> + when ?is_string(StartTime) andalso + ?is_string(StopTime) -> create_subscription(Client,?DEFAULT_STREAM,StartTime,StopTime, ?DEFAULT_TIMEOUT); create_subscription(Client,Filter,Timeout) @@ -784,28 +817,28 @@ create_subscription(Client,Filter,Timeout) ?is_timeout(Timeout) -> create_subscription(Client,?DEFAULT_STREAM,Filter,Timeout); create_subscription(Client,Stream,Filter) - when is_list(Stream) andalso + when ?is_string(Stream) andalso ?is_filter(Filter) -> create_subscription(Client,Stream,Filter,?DEFAULT_TIMEOUT). create_subscription(Client,StartTime,StopTime,Timeout) - when is_list(StartTime) andalso - is_list(StopTime) andalso + when ?is_string(StartTime) andalso + ?is_string(StopTime) andalso ?is_timeout(Timeout) -> create_subscription(Client,?DEFAULT_STREAM,StartTime,StopTime,Timeout); create_subscription(Client,Stream,StartTime,StopTime) - when is_list(Stream) andalso - is_list(StartTime) andalso - is_list(StopTime) -> + when ?is_string(Stream) andalso + ?is_string(StartTime) andalso + ?is_string(StopTime) -> create_subscription(Client,Stream,StartTime,StopTime,?DEFAULT_TIMEOUT); create_subscription(Client,Filter,StartTime,StopTime) when ?is_filter(Filter) andalso - is_list(StartTime) andalso - is_list(StopTime) -> + ?is_string(StartTime) andalso + ?is_string(StopTime) -> create_subscription(Client,?DEFAULT_STREAM,Filter, StartTime,StopTime,?DEFAULT_TIMEOUT); create_subscription(Client,Stream,Filter,Timeout) - when is_list(Stream) andalso + when ?is_string(Stream) andalso ?is_filter(Filter) andalso ?is_timeout(Timeout) -> call(Client,{send_rpc_op,{create_subscription,self()}, @@ -813,18 +846,18 @@ create_subscription(Client,Stream,Filter,Timeout) Timeout}). create_subscription(Client,Stream,StartTime,StopTime,Timeout) - when is_list(Stream) andalso - is_list(StartTime) andalso - is_list(StopTime) andalso + when ?is_string(Stream) andalso + ?is_string(StartTime) andalso + ?is_string(StopTime) andalso ?is_timeout(Timeout) -> call(Client,{send_rpc_op,{create_subscription,self()}, [Stream,undefined,StartTime,StopTime], Timeout}); create_subscription(Client,Stream,Filter,StartTime,StopTime) - when is_list(Stream) andalso + when ?is_string(Stream) andalso ?is_filter(Filter) andalso - is_list(StartTime) andalso - is_list(StopTime) -> + ?is_string(StartTime) andalso + ?is_string(StopTime) -> create_subscription(Client,Stream,Filter,StartTime,StopTime,?DEFAULT_TIMEOUT). %%---------------------------------------------------------------------- @@ -832,7 +865,7 @@ create_subscription(Client,Stream,Filter,StartTime,StopTime) Result when Client :: client(), Stream :: stream_name(), - Filter :: simple_xml(), + Filter :: simple_xml() | [simple_xml()], StartTime :: xs_datetime(), StopTime :: xs_datetime(), Timeout :: timeout(), @@ -855,8 +888,7 @@ create_subscription(Client,Stream,Filter,StartTime,StopTime) %% possible events is of interest. The format of this parameter is %% the same as that of the filter parameter in the NETCONF protocol %% operations. If not present, all events not precluded by other -%% parameters will be sent. See section 3.6 for more information on -%% filters.</dd> +%% parameters will be sent.</dd> %% %% <dt>StartTime:</dt> %% <dd>An optional parameter used to trigger the replay feature and @@ -1241,8 +1273,10 @@ filter(undefined) -> []; filter({xpath,Filter}) when ?is_string(Filter) -> [{filter,[{type,"xpath"},{select, Filter}],[]}]; +filter(Filter) when is_list(Filter) -> + [{filter,[{type,"subtree"}],Filter}]; filter(Filter) -> - [{filter,[{type,"subtree"}],[Filter]}]. + filter([Filter]). maybe_element(_,undefined) -> []; diff --git a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl index 0535eb924b..6ee7fdd6f6 100644 --- a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl +++ b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl @@ -886,6 +886,19 @@ create_subscription(Config) -> ?NS:expect_do_reply('close-session',close,ok), ?ok = ct_netconfc:close_session(Client8), + %% Multiple filters + {ok,Client9} = open_success(DataDir), + ?NS:expect_reply({'create-subscription',[stream,filter]},ok), + MultiFilters = [{event,[{xmlns,"http://my.namespaces.com/event"}], + [{eventClass,["fault"]}, + {severity,["critical"]}]}, + {event,[{xmlns,"http://my.namespaces.com/event"}], + [{eventClass,["fault"]}, + {severity,["major"]}]}], + ?ok = ct_netconfc:create_subscription(Client9,MultiFilters), + ?NS:expect_do_reply('close-session',close,ok), + ?ok = ct_netconfc:close_session(Client9), + ok. receive_event(Config) -> diff --git a/lib/compiler/test/bs_construct_SUITE.erl b/lib/compiler/test/bs_construct_SUITE.erl index 4ea5235bb6..ce39de2a82 100644 --- a/lib/compiler/test/bs_construct_SUITE.erl +++ b/lib/compiler/test/bs_construct_SUITE.erl @@ -319,6 +319,8 @@ in_guard(Config) when is_list(Config) -> ?line 1 = in_guard_1(<<16#74ad:16>>, 16#e95, 5), ?line 2 = in_guard_1(<<16#3A,16#F7,"hello">>, 16#3AF7, <<"hello">>), ?line 3 = in_guard_1(<<16#FBCD:14,3.1415/float,3:2>>, 16#FBCD, 3.1415), + ?line 3 = in_guard_1(<<16#FBCD:14,3/float,3:2>>, 16#FBCD, 3), + ?line 3 = in_guard_1(<<16#FBCD:14,(2 bsl 226)/float,3:2>>, 16#FBCD, 2 bsl 226), ?line nope = in_guard_1(<<1>>, 42, b), ?line nope = in_guard_1(<<1>>, a, b), ?line nope = in_guard_1(<<1,2>>, 1, 1), diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index 35de3dbf0c..c28ff8136c 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -242,8 +242,6 @@ static ERL_NIF_TERM bf_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar static ERL_NIF_TERM bf_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM blowfish_ofb64_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM ec_key_to_term_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM term_to_ec_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM ecdsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM ecdsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); @@ -372,12 +370,10 @@ static ErlNifFunc nif_funcs[] = { {"bf_ecb_crypt", 3, bf_ecb_crypt}, {"blowfish_ofb64_encrypt", 3, blowfish_ofb64_encrypt}, - {"ec_key_to_term_nif", 1, ec_key_to_term_nif}, - {"term_to_ec_key_nif", 3, term_to_ec_key_nif}, {"ec_key_generate", 1, ec_key_generate}, - {"ecdsa_sign_nif", 3, ecdsa_sign_nif}, - {"ecdsa_verify_nif", 4, ecdsa_verify_nif}, - {"ecdh_compute_key_nif", 2, ecdh_compute_key_nif} + {"ecdsa_sign_nif", 4, ecdsa_sign_nif}, + {"ecdsa_verify_nif", 5, ecdsa_verify_nif}, + {"ecdh_compute_key_nif", 3, ecdh_compute_key_nif} }; #if defined(HAVE_EC) @@ -472,10 +468,7 @@ static struct nid_map ec_curves[] = { #define EC_CURVES_CNT (sizeof(ec_curves)/sizeof(struct nid_map)) -struct nif_ec_key { - EC_KEY *key; -}; -#endif +#endif /* HAVE_EC */ ERL_NIF_INIT(crypto,nif_funcs,load,NULL,upgrade,unload) @@ -528,17 +521,13 @@ static ERL_NIF_TERM atom_none; static ERL_NIF_TERM atom_notsup; static ERL_NIF_TERM atom_digest; -static ERL_NIF_TERM atom_ec; - #if defined(HAVE_EC) +static ERL_NIF_TERM atom_ec; static ERL_NIF_TERM atom_prime_field; static ERL_NIF_TERM atom_characteristic_two_field; static ERL_NIF_TERM atom_tpbasis; static ERL_NIF_TERM atom_ppbasis; static ERL_NIF_TERM atom_onbasis; - -static ErlNifResourceType* res_type_ec_key; -static void ec_key_dtor(ErlNifEnv* env, void* obj); #endif /* @@ -570,7 +559,6 @@ static void error_handler(void* null, const char* errstr) static int init(ErlNifEnv* env, ERL_NIF_TERM load_info) { - int i; ErlNifSysInfo sys_info; get_crypto_callbacks_t* funcp; struct crypto_callbacks* ccb; @@ -591,13 +579,6 @@ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info) return 0; } -#if defined(HAVE_EC) - res_type_ec_key = enif_open_resource_type(env,NULL,"crypto.EC_KEY", - ec_key_dtor, - ERL_NIF_RT_CREATE|ERL_NIF_RT_TAKEOVER, - NULL); -#endif - if (library_refc > 0) { /* Repeated loading of this library (module upgrade). * Atoms and callbacks are already set, we are done. @@ -639,8 +620,11 @@ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info) atom_ppbasis = enif_make_atom(env,"ppbasis"); atom_onbasis = enif_make_atom(env,"onbasis"); - for (i = 0; i < EC_CURVES_CNT; i++) + { + int i; + for (i = 0; i < EC_CURVES_CNT; i++) ec_curves[i].atom = enif_make_atom(env,ec_curves[i].name); + } #endif init_digest_types(env); @@ -1440,7 +1424,7 @@ static ERL_NIF_TERM hmac_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv HMAC_CTX_cleanup(&ctx); if (argc == 2 && req_len < mac_len) { - // Only truncate to req_len bytes if asked. + /* Only truncate to req_len bytes if asked. */ mac_len = req_len; } mac_bin = enif_make_new_binary(env, mac_len, &ret); @@ -2939,7 +2923,7 @@ static EC_KEY* ec_key_new(ErlNifEnv* env, ERL_NIF_TERM curve_arg) && c_arity == 5 && get_bn_from_bin(env, curve[3], &bn_order) && (curve[4] != atom_none && get_bn_from_bin(env, curve[4], &cofactor))) { - //* {Field, Prime, Point, Order, CoFactor} = Curve */ + /* {Field, Prime, Point, Order, CoFactor} = Curve */ int f_arity = -1; const ERL_NIF_TERM* field; @@ -3093,7 +3077,7 @@ static ERL_NIF_TERM bn2term(ErlNifEnv* env, const BIGNUM *bn) dlen = BN_num_bytes(bn); ptr = enif_make_new_binary(env, dlen, &ret); BN_bn2bin(bn, ptr); - + ERL_VALGRIND_MAKE_MEM_DEFINED(ptr, dlen); return ret; } @@ -3116,39 +3100,10 @@ static ERL_NIF_TERM point2term(ErlNifEnv* env, enif_release_binary(&bin); return enif_make_badarg(env); } - + ERL_VALGRIND_MAKE_MEM_DEFINED(bin.data, bin.size); return enif_make_binary(env, &bin); } -#endif - -static ERL_NIF_TERM ec_key_to_term_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{ -#if defined(HAVE_EC) - struct nif_ec_key *obj; - const EC_GROUP *group; - const EC_POINT *public_key; - const BIGNUM *priv_key = NULL; - ERL_NIF_TERM pub_key = atom_undefined; - - if (!enif_get_resource(env, argv[0], res_type_ec_key, (void **)&obj)) - return enif_make_badarg(env); - - group = EC_KEY_get0_group(obj->key); - public_key = EC_KEY_get0_public_key(obj->key); - priv_key = EC_KEY_get0_private_key(obj->key); - - if (group) { - if (public_key) - pub_key = point2term(env, group, public_key, EC_KEY_get_conv_form(obj->key)); - } - - return enif_make_tuple2(env, pub_key, bn2term(env, priv_key)); -#else - return atom_notsup; -#endif -} -#if defined(HAVE_EC) static int term2point(ErlNifEnv* env, ERL_NIF_TERM term, EC_GROUP *group, EC_POINT **pptr) { @@ -3176,24 +3131,22 @@ static int term2point(ErlNifEnv* env, ERL_NIF_TERM term, return ret; } -#endif -static ERL_NIF_TERM term_to_ec_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +static int get_ec_key(ErlNifEnv* env, + ERL_NIF_TERM curve, ERL_NIF_TERM priv, ERL_NIF_TERM pub, + EC_KEY** res) { -#if defined(HAVE_EC) - ERL_NIF_TERM ret; EC_KEY *key = NULL; BIGNUM *priv_key = NULL; EC_POINT *pub_key = NULL; - struct nif_ec_key *obj; EC_GROUP *group = NULL; - if (!(argv[1] == atom_undefined || get_bn_from_bin(env, argv[1], &priv_key)) - || !(argv[2] == atom_undefined || enif_is_binary(env, argv[2]))) { + if (!(priv == atom_undefined || get_bn_from_bin(env, priv, &priv_key)) + || !(pub == atom_undefined || enif_is_binary(env, pub))) { goto out_err; } - key = ec_key_new(env, argv[0]); + key = ec_key_new(env, curve); if (!key) { goto out_err; @@ -3202,12 +3155,12 @@ static ERL_NIF_TERM term_to_ec_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_T if (!group) group = EC_GROUP_dup(EC_KEY_get0_group(key)); - if (term2point(env, argv[2], group, &pub_key)) { + if (term2point(env, pub, group, &pub_key)) { if (!EC_KEY_set_public_key(key, pub_key)) { goto out_err; } } - if (argv[1] != atom_undefined + if (priv != atom_undefined && !BN_is_zero(priv_key)) { if (!EC_KEY_set_private_key(key, priv_key)) goto out_err; @@ -3226,19 +3179,11 @@ static ERL_NIF_TERM term_to_ec_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_T } } - obj = enif_alloc_resource(res_type_ec_key, sizeof(struct nif_ec_key)); - if (!obj) - goto out_err; - - obj->key = key; - ret = enif_make_resource(env, obj); - enif_release_resource(obj); - goto out; out_err: if (key) EC_KEY_free(key); - ret = enif_make_badarg(env); + key = NULL; out: /* some OpenSSL structures are mem-dup'ed into the key, @@ -3246,11 +3191,12 @@ out: if (priv_key) BN_clear_free(priv_key); if (pub_key) EC_POINT_free(pub_key); if (group) EC_GROUP_free(group); - return ret; -#else - return atom_notsup; -#endif + if (!key) + return 0; + *res = key; + return 1; } +#endif /* HAVE_EC */ static ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { @@ -3258,14 +3204,21 @@ static ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM EC_KEY *key = ec_key_new(env, argv[0]); if (key && EC_KEY_generate_key(key)) { - ERL_NIF_TERM term; - struct nif_ec_key *obj = enif_alloc_resource(res_type_ec_key, sizeof(struct nif_ec_key)); - if (!obj) - return atom_error; - obj->key = key; - term = enif_make_resource(env, obj); - enif_release_resource(obj); - return term; + const EC_GROUP *group; + const EC_POINT *public_key; + ERL_NIF_TERM priv_key; + ERL_NIF_TERM pub_key = atom_undefined; + + group = EC_KEY_get0_group(key); + public_key = EC_KEY_get0_public_key(key); + + if (group && public_key) { + pub_key = point2term(env, group, public_key, + EC_KEY_get_conv_form(key)); + } + priv_key = bn2term(env, EC_KEY_get0_private_key(key)); + EC_KEY_free(key); + return enif_make_tuple2(env, pub_key, priv_key); } else return enif_make_badarg(env); @@ -3274,21 +3227,13 @@ static ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM #endif } -#if defined(HAVE_EC) -static void ec_key_dtor(ErlNifEnv* env, void* obj) -{ - struct nif_ec_key *key = (struct nif_ec_key*) obj; - EC_KEY_free(key->key); -} -#endif - static ERL_NIF_TERM ecdsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Type, Data|{digest,Digest}, Key) */ +{/* (Type, Data|{digest,Digest}, Curve, Key) */ #if defined(HAVE_EC) ErlNifBinary data_bin, ret_bin; unsigned char hmacbuf[SHA_DIGEST_LENGTH]; unsigned int dsa_s_len; - struct nif_ec_key *obj; + EC_KEY* key = NULL; int i; const ERL_NIF_TERM* tpl_terms; int tpl_arity; @@ -3303,30 +3248,32 @@ static ERL_NIF_TERM ecdsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM return atom_notsup; } - if (!enif_get_resource(env, argv[2], res_type_ec_key, (void **)&obj)) - return enif_make_badarg(env); + if (!get_ec_key(env, argv[2], argv[3], atom_undefined, &key)) + goto badarg; if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) { if (tpl_arity != 2 || tpl_terms[0] != atom_digest || !enif_inspect_binary(env, tpl_terms[1], &data_bin) || data_bin.size != digp->len) { - return enif_make_badarg(env); + goto badarg; } digest = data_bin.data; } else { if (!enif_inspect_binary(env,argv[1],&data_bin)) { - return enif_make_badarg(env); + goto badarg; } digest = hmacbuf; digp->funcp(data_bin.data, data_bin.size, digest); } - enif_alloc_binary(ECDSA_size(obj->key), &ret_bin); + enif_alloc_binary(ECDSA_size(key), &ret_bin); i = ECDSA_sign(digp->NID_type, digest, digp->len, - ret_bin.data, &dsa_s_len, obj->key); + ret_bin.data, &dsa_s_len, key); + + EC_KEY_free(key); if (i) { if (dsa_s_len != ret_bin.size) { enif_realloc_binary(&ret_bin, dsa_s_len); @@ -3337,18 +3284,23 @@ static ERL_NIF_TERM ecdsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM enif_release_binary(&ret_bin); return atom_error; } + +badarg: + if (key) + EC_KEY_free(key); + return enif_make_badarg(env); #else return atom_notsup; #endif } static ERL_NIF_TERM ecdsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Type, Data|{digest,Digest}, Signature, Key) */ +{/* (Type, Data|{digest,Digest}, Signature, Curve, Key) */ #if defined(HAVE_EC) ErlNifBinary data_bin, sign_bin; unsigned char hmacbuf[SHA512_LEN]; int i; - struct nif_ec_key *obj; + EC_KEY* key = NULL; const ERL_NIF_TERM type = argv[0]; const ERL_NIF_TERM* tpl_terms; int tpl_arity; @@ -3364,15 +3316,15 @@ static ERL_NIF_TERM ecdsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER } if (!enif_inspect_binary(env, argv[2], &sign_bin) - || !enif_get_resource(env, argv[3], res_type_ec_key, (void **)&obj)) - return enif_make_badarg(env); + || !get_ec_key(env, argv[3], atom_undefined, argv[4], &key)) + goto badarg; if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) { if (tpl_arity != 2 || tpl_terms[0] != atom_digest || !enif_inspect_binary(env, tpl_terms[1], &data_bin) || data_bin.size != digp->len) { - return enif_make_badarg(env); + goto badarg; } digest = data_bin.data; } @@ -3381,13 +3333,20 @@ static ERL_NIF_TERM ecdsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER digp->funcp(data_bin.data, data_bin.size, digest); } else { - return enif_make_badarg(env); + goto badarg; } i = ECDSA_verify(digp->NID_type, digest, digp->len, - sign_bin.data, sign_bin.size, obj->key); + sign_bin.data, sign_bin.size, key); + + EC_KEY_free(key); return (i==1 ? atom_true : atom_false); + +badarg: + if (key) + EC_KEY_free(key); + return enif_make_badarg(env); #else return atom_notsup; #endif @@ -3398,24 +3357,24 @@ static ERL_NIF_TERM ecdsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER (_OthersPublicKey, _MyEC_Point) */ static ERL_NIF_TERM ecdh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +/* (OtherPublicKey, Curve, My) */ { #if defined(HAVE_EC) ERL_NIF_TERM ret; unsigned char *p; - struct nif_ec_key *other_key; + EC_KEY* key = NULL; int field_size = 0; int i; - EC_GROUP *group; const BIGNUM *priv_key; EC_POINT *my_ecpoint; EC_KEY *other_ecdh = NULL; - if (!enif_get_resource(env, argv[1], res_type_ec_key, (void **)&other_key)) + if (!get_ec_key(env, argv[1], argv[2], atom_undefined, &key)) return enif_make_badarg(env); - group = EC_GROUP_dup(EC_KEY_get0_group(other_key->key)); - priv_key = EC_KEY_get0_private_key(other_key->key); + group = EC_GROUP_dup(EC_KEY_get0_group(key)); + priv_key = EC_KEY_get0_private_key(key); if (!term2point(env, argv[0], group, &my_ecpoint)) { goto out_err; @@ -3439,6 +3398,7 @@ out: if (group) EC_GROUP_free(group); if (my_ecpoint) EC_POINT_free(my_ecpoint); if (other_ecdh) EC_KEY_free(other_ecdh); + if (key) EC_KEY_free(key); return ret; diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index a093b45410..8e8370f3b0 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -455,7 +455,7 @@ verify(rsa, Type, DataOrDigest, Signature, Key) -> Bool -> Bool end; verify(ecdsa, Type, DataOrDigest, Signature, [Key, Curve]) -> - case ecdsa_verify_nif(Type, DataOrDigest, Signature, term_to_ec_key(Curve, undefined, Key)) of + case ecdsa_verify_nif(Type, DataOrDigest, Signature, nif_curve_params(Curve), ensure_int_as_bin(Key)) of notsup -> erlang:error(notsup); Bool -> Bool end. @@ -474,7 +474,7 @@ sign(dss, Type, DataOrDigest, Key) -> Sign -> Sign end; sign(ecdsa, Type, DataOrDigest, [Key, Curve]) -> - case ecdsa_sign_nif(Type, DataOrDigest, term_to_ec_key(Curve, Key, undefined)) of + case ecdsa_sign_nif(Type, DataOrDigest, nif_curve_params(Curve), ensure_int_as_bin(Key)) of error -> erlang:error(badkey, [Type,DataOrDigest,Key]); Sign -> Sign end. @@ -557,7 +557,7 @@ generate_key(srp, {user, [Generator, Prime, Version]}, PrivateArg) user_srp_gen_key(Private, Generator, Prime); generate_key(ecdh, Curve, undefined) -> - ec_key_to_term_nif(ec_key_generate(Curve)). + ec_key_generate(Curve). compute_key(dh, OthersPublicKey, MyPrivateKey, DHParameters) -> @@ -599,7 +599,8 @@ compute_key(srp, UserPublic, {HostPublic, HostPrivate}, compute_key(ecdh, Others, My, Curve) -> ecdh_compute_key_nif(ensure_int_as_bin(Others), - term_to_ec_key(Curve,My,undefined)). + nif_curve_params(Curve), + ensure_int_as_bin(My)). random_bytes(N) -> @@ -1399,11 +1400,11 @@ srp_value_B_nif(_Multiplier, _Verifier, _Generator, _Exponent, _Prime) -> ?nif_s %% Digital signatures -------------------------------------------------------------------- rsa_sign_nif(_Type,_Data,_Key) -> ?nif_stub. dss_sign_nif(_Type,_Data,_Key) -> ?nif_stub. -ecdsa_sign_nif(_Type, _DataOrDigest, _Key) -> ?nif_stub. +ecdsa_sign_nif(_Type, _DataOrDigest, _Curve, _Key) -> ?nif_stub. dss_verify_nif(_Type, _Data, _Signature, _Key) -> ?nif_stub. rsa_verify_nif(_Type, _Data, _Signature, _Key) -> ?nif_stub. -ecdsa_verify_nif(_Type, _DataOrDigest, _Signature, _Key) -> ?nif_stub. +ecdsa_verify_nif(_Type, _DataOrDigest, _Signature, _Curve, _Key) -> ?nif_stub. %% Public Keys -------------------------------------------------------------------- %% DH Diffie-Hellman functions @@ -1456,12 +1457,11 @@ dh_compute_key_nif(_OthersPublicKey, _MyPrivateKey, _DHParameters) -> ?nif_stub. ec_key_generate(_Key) -> ?nif_stub. -ecdh_compute_key_nif(_Others, _My) -> ?nif_stub. +ecdh_compute_key_nif(_Others, _Curve, _My) -> ?nif_stub. %% %% EC %% -ec_key_to_term_nif(_Key) -> ?nif_stub. term_to_nif_prime({prime_field, Prime}) -> {prime_field, int_to_bin(Prime)}; @@ -1469,19 +1469,12 @@ term_to_nif_prime(PrimeField) -> PrimeField. term_to_nif_curve({A, B, Seed}) -> {ensure_int_as_bin(A), ensure_int_as_bin(B), Seed}. -term_to_nif_curve_parameters({PrimeField, Curve, BasePoint, Order, CoFactor}) -> +nif_curve_params({PrimeField, Curve, BasePoint, Order, CoFactor}) -> {term_to_nif_prime(PrimeField), term_to_nif_curve(Curve), ensure_int_as_bin(BasePoint), int_to_bin(Order), int_to_bin(CoFactor)}; -term_to_nif_curve_parameters(Curve) when is_atom(Curve) -> +nif_curve_params(Curve) when is_atom(Curve) -> %% named curve Curve. -term_to_ec_key(Curve, PrivKey, PubKey) -> - term_to_ec_key_nif(term_to_nif_curve_parameters(Curve), - ensure_int_as_bin(PrivKey), - ensure_int_as_bin(PubKey)). - -term_to_ec_key_nif(_Curve, _PrivKey, _PubKey) -> ?nif_stub. - %% MISC -------------------------------------------------------------------- diff --git a/lib/debugger/test/bs_construct_SUITE.erl b/lib/debugger/test/bs_construct_SUITE.erl index e0bda7eac8..4870c87d74 100644 --- a/lib/debugger/test/bs_construct_SUITE.erl +++ b/lib/debugger/test/bs_construct_SUITE.erl @@ -454,6 +454,8 @@ in_guard(Config) when is_list(Config) -> ?line 1 = in_guard(<<16#74ad:16>>, 16#e95, 5), ?line 2 = in_guard(<<16#3A,16#F7,"hello">>, 16#3AF7, <<"hello">>), ?line 3 = in_guard(<<16#FBCD:14,3.1415/float,3:2>>, 16#FBCD, 3.1415), + ?line 3 = in_guard(<<16#FBCD:14,3/float,3:2>>, 16#FBCD, 3), + ?line 3 = in_guard(<<16#FBCD:14,(2 bsl 226)/float,3:2>>, 16#FBCD, 2 bsl 226), nope = in_guard(<<1>>, 42, b), nope = in_guard(<<1>>, a, b), nope = in_guard(<<1,2>>, 1, 1), diff --git a/lib/debugger/test/bs_match_misc_SUITE.erl b/lib/debugger/test/bs_match_misc_SUITE.erl index 6b66c45448..54fa9a59df 100644 --- a/lib/debugger/test/bs_match_misc_SUITE.erl +++ b/lib/debugger/test/bs_match_misc_SUITE.erl @@ -26,7 +26,7 @@ kenneth/1,encode_binary/1,native/1,happi/1, size_var/1,wiger/1,x0_context/1,huge_float_field/1, writable_binary_matched/1,otp_7198/1, - unordered_bindings/1]). + unordered_bindings/1,float_middle_endian/1]). -include_lib("test_server/include/test_server.hrl"). @@ -36,7 +36,7 @@ all() -> [bound_var, bound_tail, t_float, little_float, sean, kenneth, encode_binary, native, happi, size_var, wiger, x0_context, huge_float_field, writable_binary_matched, - otp_7198, unordered_bindings]. + otp_7198, unordered_bindings, float_middle_endian]. groups() -> []. @@ -106,6 +106,13 @@ t_float(Config) when is_list(Config) -> ok. +float_middle_endian(Config) when is_list(Config) -> + F = 9007199254740990.0, % turns to -NaN when word-swapped + ?line fcmp(F, match_float(<<F:64/float>>, 64, 0)), + ?line fcmp(F, match_float(<<1:1,F:64/float,127:7>>, 64, 1)), + ?line fcmp(F, match_float(<<1:13,F:64/float,127:3>>, 64, 13)), + ok. + fcmp(F1, F2) when (F1 - F2) / F2 < 0.0000001 -> ok. diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml index 72d67ddb4a..d2e7ade5d6 100644 --- a/lib/inets/doc/src/notes.xml +++ b/lib/inets/doc/src/notes.xml @@ -32,7 +32,6 @@ <file>notes.xml</file> </header> - <section><title>Inets 5.9.5</title> <section><title>Fixed Bugs and Malfunctions</title> @@ -93,7 +92,6 @@ </section> <section><title>Inets 5.9.4</title> - <section><title>Improvements and New Features</title> <list> <item> @@ -161,6 +159,19 @@ </section> +<section><title>Inets 5.9.2.1</title> + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Fixed obsolete error report in inets.</p> + <p> + Own Id: OTP-11185 Aux Id: seq12357 </p> + </item> + </list> + </section> +</section> + <section><title>Inets 5.9.2</title> <section><title>Improvements and New Features</title> diff --git a/lib/inets/src/ftp/ftp.erl b/lib/inets/src/ftp/ftp.erl index 132a384a49..5d9887a9a4 100644 --- a/lib/inets/src/ftp/ftp.erl +++ b/lib/inets/src/ftp/ftp.erl @@ -1417,7 +1417,7 @@ handle_info({'DOWN', _Ref, _Type, Process, Reason}, State) -> handle_info({'EXIT', Pid, Reason}, #state{progress = Pid} = State) -> Report = io_lib:format("Progress reporting stopped for reason ~p~n", - Reason), + [Reason]), error_logger:info_report(Report), {noreply, State#state{progress = ignore}}; diff --git a/lib/inets/src/http_client/httpc.erl b/lib/inets/src/http_client/httpc.erl index 41bba7995e..4d7023a8e9 100644 --- a/lib/inets/src/http_client/httpc.erl +++ b/lib/inets/src/http_client/httpc.erl @@ -175,7 +175,7 @@ request(Method, request(Method, {Url, Headers, ContentType, Body}, HTTPOptions, Options, Profile) - when ((Method =:= post) orelse (Method =:= put)) andalso + when ((Method =:= post) orelse (Method =:= put) orelse (Method =:= delete)) andalso (is_atom(Profile) orelse is_pid(Profile)) -> ?hcrt("request", [{method, Method}, {url, Url}, diff --git a/lib/inets/src/http_server/httpd_manager.erl b/lib/inets/src/http_server/httpd_manager.erl index c83d06a158..00384fa108 100644 --- a/lib/inets/src/http_server/httpd_manager.erl +++ b/lib/inets/src/http_server/httpd_manager.erl @@ -507,37 +507,8 @@ code_change(_FromVsn, State, _Extra) -> check_connections(#state{connections = []} = State, _Pid, _Reason) -> State; -check_connections(#state{admin_state = shutting_down, - connections = Connections} = State, Pid, Reason) -> - %% Could be a crashing request handler - case lists:delete(Pid, Connections) of - [] -> % Crashing request handler => block complete - String = - lists:flatten( - io_lib:format("request handler (~p) crashed:" - "~n ~p", [Pid, Reason])), - report_error(State, String), - demonitor_blocker(State#state.blocker_ref), - {Tmr,From,Ref} = State#state.blocking_tmr, - stop_block_tmr(Tmr), - From ! {block_reply,ok,Ref}, - State#state{admin_state = blocked, connections = [], - blocker_ref = undefined}; - Connections1 -> - State#state{connections = Connections1} - end; -check_connections(#state{connections = Connections} = State, Pid, Reason) -> - case lists:delete(Pid, Connections) of - Connections -> % Not a request handler, so ignore - State; - NewConnections -> - String = - lists:flatten( - io_lib:format("request handler (~p) crashed:" - "~n ~p", [Pid, Reason])), - report_error(State, String), - State#state{connections = NewConnections} - end. +check_connections(#state{connections = Connections} = State, Pid, _Reason) -> + State#state{connections = lists:delete(Pid, Connections)}. %% ------------------------------------------------------------------------- diff --git a/lib/inets/test/httpc_proxy_SUITE.erl b/lib/inets/test/httpc_proxy_SUITE.erl index 84db39e76b..ddd23d0c65 100644 --- a/lib/inets/test/httpc_proxy_SUITE.erl +++ b/lib/inets/test/httpc_proxy_SUITE.erl @@ -69,6 +69,7 @@ local_proxy_cases() -> http_post, http_put, http_delete, + http_delete_body, http_headers, http_proxy_auth, http_doesnotexist, @@ -262,6 +263,22 @@ http_delete(Config) when is_list(Config) -> %%-------------------------------------------------------------------- +http_delete_body(doc) -> + ["Perform a DELETE request with a content body. The server will not allow it " + "but we only test sending the request."]; +http_delete_body(Config) when is_list(Config) -> + Method = delete, + URL = url("/delete.html", Config), + Content = "foo=bar", + Request = {URL,[],"application/x-www-form-urlencoded",Content}, + HttpOpts = [], + Opts = [], + {ok,{{_,405,_},[_|_],[_|_]}} = + httpc:request(Method, Request, HttpOpts, Opts), + ok. + +%%-------------------------------------------------------------------- + http_headers(doc) -> ["Use as many request headers as possible"]; http_headers(Config) when is_list(Config) -> diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk index 49404196dd..96c1e3d83d 100644 --- a/lib/kernel/vsn.mk +++ b/lib/kernel/vsn.mk @@ -1 +1 @@ -KERNEL_VSN = 2.16.2 +KERNEL_VSN = 2.16.3 diff --git a/lib/public_key/test/pbe_SUITE.erl b/lib/public_key/test/pbe_SUITE.erl index 254601b107..2c9b17478d 100644 --- a/lib/public_key/test/pbe_SUITE.erl +++ b/lib/public_key/test/pbe_SUITE.erl @@ -42,6 +42,7 @@ groups() -> %%-------------------------------------------------------------------- init_per_suite(Config) -> + application:stop(crypto), try crypto:start() of ok -> Config diff --git a/lib/public_key/test/pkits_SUITE.erl b/lib/public_key/test/pkits_SUITE.erl index 9180fa968b..699481b20f 100644 --- a/lib/public_key/test/pkits_SUITE.erl +++ b/lib/public_key/test/pkits_SUITE.erl @@ -111,6 +111,7 @@ groups() -> %%-------------------------------------------------------------------- init_per_suite(Config) -> + application:stop(crypto), try crypto:start() of ok -> application:start(asn1), diff --git a/lib/public_key/test/public_key_SUITE.erl b/lib/public_key/test/public_key_SUITE.erl index f2596e3d85..c3aa2e2366 100644 --- a/lib/public_key/test/public_key_SUITE.erl +++ b/lib/public_key/test/public_key_SUITE.erl @@ -56,6 +56,7 @@ groups() -> ]. %%------------------------------------------------------------------- init_per_suite(Config) -> + application:stop(crypto), try crypto:start() of ok -> application:start(asn1), diff --git a/lib/sasl/test/systools_SUITE.erl b/lib/sasl/test/systools_SUITE.erl index 367cab1d77..3921b2d3bb 100644 --- a/lib/sasl/test/systools_SUITE.erl +++ b/lib/sasl/test/systools_SUITE.erl @@ -59,6 +59,7 @@ -export([otp_6226_outdir/1]). -export([init_per_suite/1, end_per_suite/1, init_per_testcase/2, end_per_testcase/2]). +-export([delete_tree/1]). -import(lists, [foldl/3]). @@ -299,6 +300,11 @@ unicode_script(Config) when is_list(Config) -> %% 3. path (directory name where unicode_app.tgz is extracted) true = lists:member({path,[P1]},Instr), + %% If all is good, delete the unicode dir to avoid lingering files + %% on windows. + rpc:call(Node,code,add_pathz,[filename:dirname(code:which(?MODULE))]), + rpc:call(Node,?MODULE,delete_tree,[UnicodeLibDir]), + ok. unicode_script(cleanup,Config) -> diff --git a/lib/ssh/doc/src/notes.xml b/lib/ssh/doc/src/notes.xml index 8e112433c1..299dd5058a 100644 --- a/lib/ssh/doc/src/notes.xml +++ b/lib/ssh/doc/src/notes.xml @@ -195,8 +195,6 @@ </item> </list> </section> - - <section><title>Improvements and New Features</title> <list> <item> @@ -251,7 +249,20 @@ </section> </section> +<section><title>Ssh 2.1.2.1</title> +<section><title>Improvements and New Features</title> + <list> + <item> + <p> + Removed error report in ssh_connection_handler triggered + by badmatch failure.</p> + <p> + Own Id: OTP-11188</p> + </item> + </list> + </section> +</section> <section><title>Ssh 2.1.2</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/ssh/src/ssh_cli.erl b/lib/ssh/src/ssh_cli.erl index 69b1ab186f..54911e757c 100644 --- a/lib/ssh/src/ssh_cli.erl +++ b/lib/ssh/src/ssh_cli.erl @@ -68,7 +68,8 @@ init([Shell]) -> handle_ssh_msg({ssh_cm, _ConnectionManager, {data, _ChannelId, _Type, Data}}, #state{group = Group} = State) -> - Group ! {self(), {data, binary_to_list(Data)}}, + List = binary_to_list(Data), + to_group(List, Group), {ok, State}; handle_ssh_msg({ssh_cm, ConnectionManager, @@ -188,6 +189,22 @@ terminate(_Reason, _State) -> %%% Internal functions %%-------------------------------------------------------------------- +to_group([], _Group) -> + ok; +to_group([$\^C | Tail], Group) -> + exit(Group, interrupt), + to_group(Tail, Group); +to_group(Data, Group) -> + Func = fun(C) -> C /= $\^C end, + Tail = case lists:splitwith(Func, Data) of + {[], Right} -> + Right; + {Left, Right} -> + Group ! {self(), {data, Left}}, + Right + end, + to_group(Tail, Group). + exec(Cmd) -> case eval(parse(scan(Cmd))) of {error, _} -> diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl index 1c4477aeb3..df6175e27c 100644 --- a/lib/ssh/src/ssh_connection_handler.erl +++ b/lib/ssh/src/ssh_connection_handler.erl @@ -451,11 +451,12 @@ userauth(#ssh_msg_userauth_failure{authentications = Methodes}, case ssh_auth:userauth_request_msg(Ssh1) of {disconnect, DisconnectMsg, {Msg, Ssh}} -> send_msg(Msg, State), - handle_disconnect(DisconnectMsg, State#state{ssh_params = Ssh}); + handle_disconnect(DisconnectMsg, State#state{ssh_params = Ssh}); {Msg, Ssh} -> send_msg(Msg, State), {next_state, userauth, next_packet(State#state{ssh_params = Ssh})} end; + %% The prefered authentication method failed try next method userauth(#ssh_msg_userauth_failure{}, #state{ssh_params = #ssh{role = client} = Ssh0} = State) -> diff --git a/lib/ssh/src/ssh_file.erl b/lib/ssh/src/ssh_file.erl index f115a32710..21cdedc156 100644 --- a/lib/ssh/src/ssh_file.erl +++ b/lib/ssh/src/ssh_file.erl @@ -315,5 +315,12 @@ default_user_dir()-> {ok,[[Home|_]]} = init:get_argument(home), UserDir = filename:join(Home, ".ssh"), ok = filelib:ensure_dir(filename:join(UserDir, "dummy")), - ok = file:change_mode(UserDir, ?PERM_700), + {ok,Info} = file:read_file_info(UserDir), + #file_info{mode=Mode} = Info, + case (Mode band 8#777) of + ?PERM_700 -> + ok; + _Other -> + ok = file:change_mode(UserDir, ?PERM_700) + end, UserDir. diff --git a/lib/stdlib/doc/src/supervisor.xml b/lib/stdlib/doc/src/supervisor.xml index ed09f6e1f2..e2c9c14e6a 100644 --- a/lib/stdlib/doc/src/supervisor.xml +++ b/lib/stdlib/doc/src/supervisor.xml @@ -371,7 +371,7 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules} children.</p> <p>If the supervisor is <c>simple_one_for_one</c>, <c><anno>Id</anno></c> - must be the child process' <c>pid()</c>. I the specified + must be the child process' <c>pid()</c>. If the specified process is alive, but is not a child of the given supervisor, the function will return <c>{error,not_found}</c>. If the child specification diff --git a/lib/stdlib/src/gen_server.erl b/lib/stdlib/src/gen_server.erl index bc76c9fd10..b18d3dc0c0 100644 --- a/lib/stdlib/src/gen_server.erl +++ b/lib/stdlib/src/gen_server.erl @@ -124,7 +124,7 @@ {noreply, NewState :: term()} | {noreply, NewState :: term(), timeout() | hibernate} | {stop, Reason :: term(), NewState :: term()}. --callback handle_info(Info :: timeout() | term(), State :: term()) -> +-callback handle_info(Info :: timeout | term(), State :: term()) -> {noreply, NewState :: term()} | {noreply, NewState :: term(), timeout() | hibernate} | {stop, Reason :: term(), NewState :: term()}. diff --git a/lib/stdlib/vsn.mk b/lib/stdlib/vsn.mk index fbb838c686..ba6f7cdb8a 100644 --- a/lib/stdlib/vsn.mk +++ b/lib/stdlib/vsn.mk @@ -1 +1 @@ -STDLIB_VSN = 1.19.2 +STDLIB_VSN = 1.19.3 diff --git a/lib/tools/emacs/erlang-skels.el b/lib/tools/emacs/erlang-skels.el index 355b223822..527e812444 100644 --- a/lib/tools/emacs/erlang-skels.el +++ b/lib/tools/emacs/erlang-skels.el @@ -457,7 +457,7 @@ Please see the function `tempo-define-template'.") "handle_info/2," n> "terminate/2, code_change/3])." n n - "-define(SERVER, ?MODULE). " n n + "-define(SERVER, ?MODULE)." n n "-record(state, {})." n n @@ -572,7 +572,7 @@ Please see the function `tempo-define-template'.") "-export([init/1, handle_event/2, handle_call/2, " n> "handle_info/2, terminate/2, code_change/3])." n n - "-define(SERVER, ?MODULE). " n n + "-define(SERVER, ?MODULE)." n n "-record(state, {})." n n |