diff options
Diffstat (limited to 'lib/diameter/src')
-rw-r--r-- | lib/diameter/src/Makefile | 5 | ||||
-rw-r--r-- | lib/diameter/src/app.sed | 40 | ||||
-rw-r--r-- | lib/diameter/src/base/diameter_service.erl | 2 | ||||
-rw-r--r-- | lib/diameter/src/compiler/diameter_codegen.erl | 8 | ||||
-rw-r--r-- | lib/diameter/src/compiler/diameter_dict_util.erl | 37 | ||||
-rw-r--r-- | lib/diameter/src/compiler/diameter_forms.hrl | 6 | ||||
-rw-r--r-- | lib/diameter/src/compiler/diameter_make.erl | 46 | ||||
-rw-r--r-- | lib/diameter/src/diameter.app.src | 19 | ||||
-rw-r--r-- | lib/diameter/src/transport/diameter_sctp.erl | 31 |
9 files changed, 147 insertions, 47 deletions
diff --git a/lib/diameter/src/Makefile b/lib/diameter/src/Makefile index 127406ae23..9afccf298c 100644 --- a/lib/diameter/src/Makefile +++ b/lib/diameter/src/Makefile @@ -148,7 +148,7 @@ gen/$(DICT_YRL).erl: compiler/$(DICT_YRL).yrl $(ERLC) -Werror -o $(@D) $< # Generate the app file. -$(APP_TARGET): $(APP_SRC) ../vsn.mk modules.mk +$(APP_TARGET): $(APP_SRC) ../vsn.mk modules.mk app.sed $(gen_verbose) \ M=`echo $(notdir $(APP_MODULES)) | tr ' ' ,`; \ C=`echo $(COMPILER_MODULES) | tr ' ' ,`; \ @@ -159,7 +159,8 @@ $(APP_TARGET): $(APP_SRC) ../vsn.mk modules.mk -e "s;%COMPILER%;$$C;" \ -e "s;%INFO%;$$I;" \ -e "s;%REGISTERED%;$$R;" \ - $< > $@ + $< \ + | sed -f app.sed > $@ $(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk $(vsn_verbose) \ diff --git a/lib/diameter/src/app.sed b/lib/diameter/src/app.sed new file mode 100644 index 0000000000..7916f65002 --- /dev/null +++ b/lib/diameter/src/app.sed @@ -0,0 +1,40 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2014. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% + +# +# Generate runtime_dependencies from applications to avoid having to +# specify the same application more than once. +# + +/{runtime_dependencies,/b v +/{[-a-z]*, "[0-9.]*"}/!b +/{vsn,/b + +/%%/!H +s/{\([^,]*\)[^}]*}/\1/g +s/%%/%,/ +b + +:v + +p +x +s/\n// +s/%//g +s/\n */ /g +s/{\([^,]*\), "\([^"]*"\)}/"\1-\2/g diff --git a/lib/diameter/src/base/diameter_service.erl b/lib/diameter/src/base/diameter_service.erl index 1274e0fc48..8914992f17 100644 --- a/lib/diameter/src/base/diameter_service.erl +++ b/lib/diameter/src/base/diameter_service.erl @@ -1389,6 +1389,8 @@ pick_peer(Local, Remote, Pid, _SvcName, #diameter_app{mutable = true} = App) case call_service(Pid, {pick_peer, Local, Remote, App}) of {TPid, _} = T when is_pid(TPid) -> T; + false = No -> + No; {error, _} -> false end; diff --git a/lib/diameter/src/compiler/diameter_codegen.erl b/lib/diameter/src/compiler/diameter_codegen.erl index 22422f2ef2..5a068c1a25 100644 --- a/lib/diameter/src/compiler/diameter_codegen.erl +++ b/lib/diameter/src/compiler/diameter_codegen.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2013. All Rights Reserved. +%% Copyright Ericsson AB 2010-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -31,7 +31,8 @@ %% on the beam file of another dictionary. %% --export([from_dict/4]). +-export([from_dict/4, + is_printable_ascii/1]). %% used by ?TERM/1 in diameter_forms.hrl -include("diameter_forms.hrl"). -include("diameter_vsn.hrl"). @@ -121,6 +122,9 @@ eraser(Key) -> %% =========================================================================== %% =========================================================================== +is_printable_ascii(C) -> + 16#20 =< C andalso C =< 16#7F. + get_value(Key, Plist) -> proplists:get_value(Key, Plist, []). diff --git a/lib/diameter/src/compiler/diameter_dict_util.erl b/lib/diameter/src/compiler/diameter_dict_util.erl index 3941f30e03..136bba16cb 100644 --- a/lib/diameter/src/compiler/diameter_dict_util.erl +++ b/lib/diameter/src/compiler/diameter_dict_util.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2013. All Rights Reserved. +%% Copyright Ericsson AB 2010-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -155,6 +155,8 @@ fmt(grouped_avp_has_wrong_type) -> "Grouped AVP ~s at line ~p defined with type ~s at line ~p"; fmt(grouped_avp_not_defined) -> "Grouped AVP ~s on line ~p not defined in @avp_types"; +fmt(grouped_avp_not_grouped) -> + "Grouped AVP ~s on line ~p not defined in @grouped"; fmt(grouped_vendor_id_without_flag) -> "Grouped AVP ~s at line ~p has vendor id " "but definition at line ~p does not specify V flag"; @@ -401,9 +403,9 @@ read(File) -> {ok, iolist_to_binary([File])}. make_dict(Parse, Opts) -> - make_orddict(pass4(pass3(pass2(pass1(reset(make_dict(Parse), - Opts))), - Opts))). + Dict = pass3(pass2(pass1(reset(make_dict(Parse), Opts))), Opts), + ok = examine(Dict), + make_orddict(Dict). %% make_orddict/1 @@ -1168,7 +1170,7 @@ import_avps(Dict, Opts) -> Import = inherit(Dict, Opts), report(imported, Import), - %% pass4/1 tests that all referenced AVP's are either defined + %% examine/1 tests that all referenced AVP's are either defined %% or imported. dict:store(import_avps, @@ -1276,21 +1278,21 @@ dict(Mod) -> end. %% =========================================================================== -%% pass4/1 +%% examine/1 %% %% Sanity checks. -pass4(Dict) -> - dict:fold(fun(K, V, _) -> p4(K, V, Dict) end, ok, Dict), - Dict. +examine(Dict) -> + dict:fold(fun(K, V, _) -> x(K, V, Dict) end, ok, Dict), + ok. %% Ensure enum AVP's have type Enumerated. -p4({enum, Name}, [Line | _], Dict) +x({enum, Name}, [Line | _], Dict) when is_list(Name) -> true = is_enumerated_avp(Name, Dict, Line); %% Ensure all referenced AVP's are either defined locally or imported. -p4({K, {Name, AvpName}}, [Line | _], Dict) +x({K, {Name, AvpName}}, [Line | _], Dict) when (K == grouped orelse K == messages), is_list(Name), is_list(AvpName), @@ -1298,13 +1300,22 @@ p4({K, {Name, AvpName}}, [Line | _], Dict) true = avp_is_defined(AvpName, Dict, Line); %% Ditto. -p4({K, AvpName}, [Line | _], Dict) +x({K, AvpName}, [Line | _], Dict) when K == avp_vendor_id; K == custom_types; K == codecs -> true = avp_is_defined(AvpName, Dict, Line); -p4(_, _, _) -> +%% Ensure that all local AVP's of type Grouped are also present in @grouped. +x({avp_types, Name}, [Line | Toks], Dict) + when 0 < Line, is_list(Name) -> + [{number, _, _Code}, {word, _, Type}, {word, _, _Flags}] = Toks, + "Grouped" == Type + andalso error == dict:find({grouped, Name}, Dict) + andalso ?RETURN(grouped_avp_not_grouped, [Name, Line]), + ok; + +x(_, _, _) -> ok. %% has_enumerated_type/3 diff --git a/lib/diameter/src/compiler/diameter_forms.hrl b/lib/diameter/src/compiler/diameter_forms.hrl index 9b14c1715a..dd03401b9e 100644 --- a/lib/diameter/src/compiler/diameter_forms.hrl +++ b/lib/diameter/src/compiler/diameter_forms.hrl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2013. All Rights Reserved. +%% Copyright Ericsson AB 2010-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -57,4 +57,6 @@ -define(FIELDS(Fs), [{?record_field, ?ATOM(F), V} || {F,V} <- Fs]). %% Literal term. --define(TERM(T), erl_parse:abstract(T, ?LINE)). +-define(TERM(T), erl_parse:abstract(T, [ + {line, ?LINE}, + {encoding, fun diameter_codegen:is_printable_ascii/1}])). diff --git a/lib/diameter/src/compiler/diameter_make.erl b/lib/diameter/src/compiler/diameter_make.erl index 2f314b7e57..72f5d36da4 100644 --- a/lib/diameter/src/compiler/diameter_make.erl +++ b/lib/diameter/src/compiler/diameter_make.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2013. All Rights Reserved. +%% Copyright Ericsson AB 2010-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -33,7 +33,8 @@ -export([codec/2, codec/1, format/1, - flatten/1]). + flatten/1, + format_error/1]). -export_type([opt/0]). @@ -81,8 +82,8 @@ codec(File, Opts) -> case parse(Dict, Opts) of {ok, ParseD} -> make(Path, default(Opts), ParseD); - {error = E, Reason} -> - {E, diameter_dict_util:format_error(Reason)} + {error, _} = E -> + E end. codec(File) -> @@ -115,6 +116,11 @@ flatten([?VERSION = V | Dict]) -> [grouped, import_groups], [enum, import_enums]])]. +%% format_error/1 + +format_error(T) -> + diameter_dict_util:format_error(T). + %% =========================================================================== %% flatten/2 @@ -226,21 +232,29 @@ identify([Vsn | [T|_] = ParseD]) identify({path, File} = T) -> {T, File}; identify(File) -> - Bin = iolist_to_binary([File]), - case is_path(Bin) of + case is_path([File]) of true -> {{path, File}, File}; - false -> {Bin, ?DEFAULT_DICT_FILE} + false -> {File, ?DEFAULT_DICT_FILE} end. -%% Interpret anything containing \n or \r as a literal dictionary, -%% otherwise a path. (Which might be the wrong guess in the worst case.) -is_path(Bin) -> - try - [throw(C) || <<C>> <= Bin, $\n == C orelse $\r == C], - true - catch - throw:_ -> false - end. +%% Interpret anything containing \n or \r as a literal dictionary. + +is_path([<<C,B/binary>> | T]) -> + is_path([C, B | T]); + +is_path([[C|L] | T]) -> + is_path([C, L | T]); + +is_path([C|_]) + when $\n == C; + $\r == C -> + false; + +is_path([_|T]) -> + is_path(T); + +is_path([]) -> + true. make(File, Opts, Dict) -> ok(lists:foldl(fun(M,A) -> [make(File, Opts, Dict, M) | A] end, diff --git a/lib/diameter/src/diameter.app.src b/lib/diameter/src/diameter.app.src index 0eb9e26a44..ac1d847753 100644 --- a/lib/diameter/src/diameter.app.src +++ b/lib/diameter/src/diameter.app.src @@ -27,11 +27,20 @@ ]}, {registered, [%REGISTERED%]}, {applications, [ - stdlib, kernel - %, syntax_tools - %, runtime_tools - %, ssl + {stdlib, "2.0"}, {kernel, "3.0"}%, {erts, "6.0"} + %% {syntax-tools, "1.6.14"} + %% {runtime-tools, "1.8.14"} + %, {ssl, "5.3.4"} ]}, {env, []}, - {mod, {diameter_app, []}} + {mod, {diameter_app, []}}, + {runtime_dependencies, [ + ]} + %% + %% Note that ssl is only required if configured on TCP transports, + %% and syntax-tools and runtime-tools are only required if the + %% dictionary compiler and debug modules (respectively) are + %% needed/wanted at runtime, which they typically aren't. These + %% modules are the two commented lines in the 'modules' tuple. + %% ]}. diff --git a/lib/diameter/src/transport/diameter_sctp.erl b/lib/diameter/src/transport/diameter_sctp.erl index 1a93972b31..d0a01351f3 100644 --- a/lib/diameter/src/transport/diameter_sctp.erl +++ b/lib/diameter/src/transport/diameter_sctp.erl @@ -171,18 +171,33 @@ start_link(T) -> info({gen_sctp, Sock}) -> lists:flatmap(fun(K) -> info(K, Sock) end, - [{socket, sockname}, - {peer, peername}, + [{socket, socknames}, + {peer, peernames}, {statistics, getstat}]). info({K,F}, Sock) -> case inet:F(Sock) of {ok, V} -> - [{K,V}]; + [{K, map(F,V)}]; _ -> [] end. +%% inet:{sock,peer}names/1 returns [{Addr, Port}] but the port number +%% should be the same in each tuple. Map to a {[Addr], Port} tuple if +%% so. +map(K, [{_, Port} | _] = APs) + when K == socknames; + K == peernames -> + try [A || {A,P} <- APs, P == Port orelse throw(?MODULE)] of + As -> {As, Port} + catch + ?MODULE -> APs + end; + +map(_, V) -> + V. + %% --------------------------------------------------------------------------- %% # init/1 %% --------------------------------------------------------------------------- @@ -549,7 +564,7 @@ accept_peer(_, []) -> ok; accept_peer(Sock, Matches) -> - {RAddrs, _} = ok(inet:peername(Sock)), + RAddrs = [A || {A,_} <- ok(inet:peernames(Sock))], diameter_peer:match(RAddrs, Matches) orelse x({accept, RAddrs, Matches}), ok. @@ -594,11 +609,13 @@ accept(_, Pid, #listener{ref = Ref, pending = {N,Q}} = S) -> %% send/2 %% Outbound Diameter message on a specified stream ... -send(#diameter_packet{bin = Bin, transport_data = {stream, SId}}, S) -> - send(SId, Bin, S), +send(#diameter_packet{bin = Bin, transport_data = {outstream, SId}}, + #transport{streams = {_, OS}} + = S) -> + send(SId rem OS, Bin, S), S; -%% ... or not: rotate through all steams. +%% ... or not: rotate through all streams. send(Bin, #transport{streams = {_, OS}, os = N} = S) |