summaryrefslogtreecommitdiff
path: root/lib/diameter/src
diff options
context:
space:
mode:
Diffstat (limited to 'lib/diameter/src')
-rw-r--r--lib/diameter/src/Makefile17
-rw-r--r--lib/diameter/src/base/diameter.erl49
-rw-r--r--lib/diameter/src/base/diameter_codec.erl4
-rw-r--r--lib/diameter/src/base/diameter_config.erl20
-rw-r--r--lib/diameter/src/base/diameter_dist.erl17
-rw-r--r--lib/diameter/src/base/diameter_peer_fsm.erl2
-rw-r--r--lib/diameter/src/base/diameter_service.erl83
-rw-r--r--lib/diameter/src/base/diameter_traffic.erl56
-rw-r--r--lib/diameter/src/diameter.appup.src22
-rw-r--r--lib/diameter/src/modules.mk5
-rw-r--r--lib/diameter/src/transport/diameter_tcp.erl6
11 files changed, 179 insertions, 102 deletions
diff --git a/lib/diameter/src/Makefile b/lib/diameter/src/Makefile
index 4b626db301..36e8fefd4c 100644
--- a/lib/diameter/src/Makefile
+++ b/lib/diameter/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2010-2018. All Rights Reserved.
+# Copyright Ericsson AB 2010-2020. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -216,12 +216,16 @@ realclean: clean
PLT = ./otp.plt
-plt:
+plt: $(PLT)
+
+$(PLT):
dialyzer --build_plt \
--apps erts stdlib kernel \
xmerl ssl public_key crypto \
compiler syntax_tools runtime_tools \
- --output_plt $(PLT) \
+ --output_plt $@ \
+ --get_warnings \
+ --statistics \
--verbose
dialyze: opt $(PLT)
@@ -230,9 +234,12 @@ dialyze: opt $(PLT)
-Wno_improper_lists \
$(EBIN)/diameter_gen_base_rfc3588.$(EMULATOR) \
$(patsubst %, $(EBIN)/%.$(EMULATOR), \
- $(notdir $(RT_MODULES) $(CT_MODULES) $(INFO_MODULES)))
+ $(notdir $(DICT_YRL) \
+ $(RT_MODULES) \
+ $(CT_MODULES) \
+ $(INFO_MODULES)))
# Omit all but the common dictionary module since these
-# (diameter_gen_relay in particular) generate warning depending on how
+# (diameter_gen_relay in particular) generate warnings depending on how
# much of the included diameter_gen.hrl they use.
# ----------------------------------------------------
diff --git a/lib/diameter/src/base/diameter.erl b/lib/diameter/src/base/diameter.erl
index 7f172e1fa1..2982486a10 100644
--- a/lib/diameter/src/base/diameter.erl
+++ b/lib/diameter/src/base/diameter.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2019. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2020. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -146,8 +146,9 @@ services() ->
%% service_info/2
%% ---------------------------------------------------------------------------
--spec service_info(service_name(), atom() | [atom()])
- -> any().
+-spec service_info(service_name(), Item | [Item])
+ -> any()
+ when Item :: atom() | peer_ref().
service_info(SvcName, Option) ->
diameter_service:info(SvcName, Option).
@@ -351,45 +352,45 @@ call(SvcName, App, Message) ->
%% Options common to both start_service/2 and add_transport/2.
-type common_opt()
- :: {pool_size, pos_integer()}
+ :: {avp_dictionaries, [module()]}
| {capabilities_cb, eval()}
| {capx_timeout, 'Unsigned32'()}
- | {strict_capx, boolean()}
- | {strict_mbit, boolean()}
- | {avp_dictionaries, [module()]}
+ | {connect_timer, 'Unsigned32'()}
| {disconnect_cb, eval()}
- | {dpr_timeout, 'Unsigned32'()}
| {dpa_timeout, 'Unsigned32'()}
+ | {dpr_timeout, 'Unsigned32'()}
| {incoming_maxlen, message_length()}
| {length_errors, exit | handle | discard}
- | {connect_timer, 'Unsigned32'()}
- | {watchdog_timer, 'Unsigned32'() | {module(), atom(), list()}}
+ | {pool_size, pos_integer()}
+ | {spawn_opt, list() | mfa()}
+ | {strict_capx, boolean()}
+ | {strict_mbit, boolean()}
| {watchdog_config, [{okay|suspect, non_neg_integer()}]}
- | {spawn_opt, list() | mfa()}.
+ | {watchdog_timer, 'Unsigned32'() | {module(), atom(), list()}}.
%% Options passed to start_service/2
-type service_opt()
:: capability()
| {application, [application_opt()]}
+ | {decode_format, decode_format()}
| {restrict_connections, restriction()}
| {sequence, sequence() | eval()}
| {share_peers, remotes()}
- | {decode_format, decode_format()}
- | {traffic_counters, boolean()}
- | {string_decode, boolean()}
| {strict_arities, true | strict_arities()}
+ | {string_decode, boolean()}
+ | {traffic_counters, boolean()}
| {use_shared_peers, remotes()}
| common_opt().
-type application_opt()
:: {alias, app_alias()}
+ | {answer_errors, callback|report|discard}
+ | {call_mutates_state, boolean()}
| {dictionary, module()}
| {module, app_module()}
- | {state, any()}
- | {call_mutates_state, boolean()}
- | {answer_errors, callback|report|discard}
- | {request_errors, answer_3xxx|answer|callback}.
+ | {request_errors, answer_3xxx|answer|callback}
+ | {state, any()}.
-type app_alias()
:: any().
@@ -407,11 +408,11 @@ call(SvcName, App, Message) ->
%% Options passed to add_transport/2
-type transport_opt()
- :: {transport_module, atom()}
+ :: {applications, [app_alias()]}
+ | {capabilities, [capability()]}
| {transport_config, any()}
| {transport_config, any(), 'Unsigned32'() | infinity}
- | {applications, [app_alias()]}
- | {capabilities, [capability()]}
+ | {transport_module, atom()}
| common_opt()
| {private, any()}.
@@ -430,8 +431,8 @@ call(SvcName, App, Message) ->
%% Options passed to call/4
-type call_opt()
- :: {extra, list()}
+ :: detach
+ | {extra, list()}
| {filter, peer_filter()}
- | {timeout, 'Unsigned32'()}
| {peer, peer_ref()}
- | detach.
+ | {timeout, 'Unsigned32'()}.
diff --git a/lib/diameter/src/base/diameter_codec.erl b/lib/diameter/src/base/diameter_codec.erl
index 493a6ab1e3..7f6baf666a 100644
--- a/lib/diameter/src/base/diameter_codec.erl
+++ b/lib/diameter/src/base/diameter_codec.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2020. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -208,7 +208,7 @@ values(Avps) ->
encode_avps(_, _, [#diameter_avp{} | _] = Avps, Opts) ->
encode_avps(Avps, Opts);
-%% ... or as a tuple list or record.
+%% ... or as a tuple list, map, or record.
encode_avps(Mod, MsgName, Values, Opts) ->
Mod:encode_avps(MsgName, Values, Opts).
diff --git a/lib/diameter/src/base/diameter_config.erl b/lib/diameter/src/base/diameter_config.erl
index 36ae4c2276..495e57e456 100644
--- a/lib/diameter/src/base/diameter_config.erl
+++ b/lib/diameter/src/base/diameter_config.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2020. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -661,6 +661,9 @@ opt(transport, {transport_module, M}) ->
opt(transport, {transport_config, _, Tmo}) ->
?IS_UINT32(Tmo) orelse Tmo == infinity;
+opt(transport, {transport_config, _}) ->
+ true;
+
opt(transport, {applications, As}) ->
is_list(As);
@@ -720,15 +723,16 @@ opt(_, {K, _})
when K == disconnect_cb;
K == capabilities_cb ->
true;
-opt(transport, {K, _})
- when K == transport_config;
- K == private ->
+opt(transport, {private, _}) ->
true;
-%% Anything else, which is ignored in transport config. This makes
-%% options sensitive to spelling mistakes, but arbitrary options are
-%% passed by some users as a way to identify transports so can't just
-%% do away with it.
+%% Anything else is ignored in transport config. This makes options
+%% sensitive to spelling mistakes and unintentionally passing service
+%% options, but arbitrary options are passed by some users as a way to
+%% identify transports (they can be returned by diameter:service_info/2
+%% for example) so can't just do away with it, although silently
+%% swallowing service options is at least debatable. The documentation
+%% says anything, so accept anything.
opt(K, _) ->
K == transport.
diff --git a/lib/diameter/src/base/diameter_dist.erl b/lib/diameter/src/base/diameter_dist.erl
index ed23152b8b..1edca58eb9 100644
--- a/lib/diameter/src/base/diameter_dist.erl
+++ b/lib/diameter/src/base/diameter_dist.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2019. All Rights Reserved.
+%% Copyright Ericsson AB 2019-2020. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -27,6 +27,21 @@
%% transport configuration, to be able to distribute incoming Diameter
%% requests to handler processes (local or remote) in various ways.
%%
+%% The gen_server implemented here must be started on each node on
+%% which {diameter_dist, route_session, _} is configured as a
+%% spawn_opt MFA, as well as each node that wants to receive requests.
+%% This happens as a consequence of diameter application start, but a
+%% minimal solution could start only this server on nodes that should
+%% handle requests but not configure transport. (Although the typical
+%% case is probably that diameter should be started in any case; for
+%% example, to be able to originate requests.)
+%%
+%% Moreover, attach/1 must be called to communicate the list of
+%% services for which the local node is willing to handle requests.
+%% The servers on different nodes communicate so that each server
+%% knows which nodes are prepared to handle requests for which
+%% services.
+%%
%% spawn_opt callbacks
-export([spawn_local/2,
diff --git a/lib/diameter/src/base/diameter_peer_fsm.erl b/lib/diameter/src/base/diameter_peer_fsm.erl
index cf5e7f21d3..b86dcaf923 100644
--- a/lib/diameter/src/base/diameter_peer_fsm.erl
+++ b/lib/diameter/src/base/diameter_peer_fsm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2020. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/diameter/src/base/diameter_service.erl b/lib/diameter/src/base/diameter_service.erl
index 77d184cfc7..520a7233cc 100644
--- a/lib/diameter/src/base/diameter_service.erl
+++ b/lib/diameter/src/base/diameter_service.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2020. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -735,29 +735,31 @@ init_peers() ->
%% Alias,
%% TPid}
+%% Valid service options are all 2-tuples.
service_opts(Opts) ->
- remove([{strict_arities, true},
- {avp_dictionaries, []}],
- maps:merge(maps:from_list([{monitor, false} | def_opts()]),
- maps:from_list(Opts))).
+ remove([{strict_arities, true}, {avp_dictionaries, []}],
+ merge(lists:append([[{monitor, false}] | def_opts()]), Opts)).
+
+merge(List1, List2) ->
+ maps:merge(maps:from_list(List1), maps:from_list(List2)).
remove(List, Map) ->
maps:filter(fun(K,V) -> not lists:member({K,V}, List) end,
Map).
-def_opts() -> %% defaults on the service map
- [{share_peers, false},
- {use_shared_peers, false},
- {sequence, {0,32}},
- {restrict_connections, nodes},
- {incoming_maxlen, 16#FFFFFF},
- {strict_arities, true},
- {strict_mbit, true},
- {decode_format, record},
- {avp_dictionaries, []},
- {traffic_counters, true},
- {string_decode, true},
- {spawn_opt, []}].
+def_opts() -> %% defaults on the options map
+ [[{decode_format, record}, %% service options
+ {restrict_connections, nodes},
+ {sequence, {0,32}},
+ {share_peers, false},
+ {strict_arities, true},
+ {string_decode, true},
+ {traffic_counters, true},
+ {use_shared_peers, false}],
+ [{avp_dictionaries, []}, %% common options
+ {incoming_maxlen, 16#FFFFFF},
+ {spawn_opt, []},
+ {strict_mbit, true}]].
mref(false = No) ->
No;
@@ -875,27 +877,46 @@ start(Ref, Type, Opts, N, #state{watchdogT = WatchdogT,
= Svc1
= merge_service(Opts, Svc0),
Svc = binary_caps(Svc1, SD),
- {SOpts, TOpts} = merge_opts(SvcOpts, Opts),
- RecvData = diameter_traffic:make_recvdata([SvcName, PeerT, Apps, SOpts]),
- T = {TOpts, SOpts, RecvData, Svc},
+ {Map, Rest} = merge_opts(SvcOpts, Opts),
+ RecvData = diameter_traffic:make_recvdata([SvcName, PeerT, Apps, Map]),
+ T = {Rest, Map, RecvData, Svc},
Rec = #watchdog{type = Type,
ref = Ref,
- options = TOpts},
-
+ options = Opts}, %% original options, returned
+ %% by service_info/2
diameter_lib:fold_n(fun(_,A) ->
[wd(Type, Ref, T, WatchdogT, Rec) | A]
end,
[],
N).
-merge_opts(SvcOpts, Opts) ->
- Keys = [K || {K,_} <- def_opts()],
- SO = [T || {K,_} = T <- Opts, lists:member(K, Keys)],
- TO = Opts -- SO,
- {maps:merge(maps:with(Keys, SvcOpts), maps:from_list(SO)),
- TO ++ [T || {K,_} = T <- maps:to_list(SvcOpts),
- not lists:member(K, Keys),
- not lists:keymember(K, 1, Opts)]}.
+%% This is awkward. We have service options that have been passed to
+%% diameter:start_service/2 (minus application and capabilities
+%% options, removed in diameter_config) and transport options passed
+%% to diameter:add_transport/2. The former can include defaults for
+%% the latter, but the latter can also contain arbitrary options that
+%% are just returned by diameter:service_info/2. There's nothing
+%% stopping these arbitrary options from being valid service options,
+%% but these aren't interpreted as such.
+%%
+%% The options are merged (transport defaults have already been merged
+%% into the service options in service_opts/1) and split into a map
+%% for the service options and a few transport options, and a list for
+%% the rest. This is historical convolution. Some options are are
+%% pulled out of the list on the way to starting the transport process
+%% in diameter_peer_fsm, but more work could probably be done here to
+%% simplify things.
+%%
+%% Transport options are not necessarily 2-tuples: the transport_config
+%% 3-tuple means they can't just be turned into a map.
+merge_opts(SOpts, TOpts) ->
+ [SD,TD] = Def = def_opts(),
+ Keys = [K || L <- Def, {K,_} <- L],
+ Opts = [T || {K,_} = T <- TOpts, lists:keymember(K, 1, TD)],
+ {maps:merge(maps:with(Keys, SOpts), maps:from_list(Opts)),%% merge TOpts
+ TOpts ++ [T || {K,_} = T <- maps:to_list(SOpts), %% append SOpts
+ not lists:keymember(K, 1, SD),
+ [] == [A || {A,_} <- TOpts, A == K]]}.
binary_caps(Svc, true) ->
Svc;
diff --git a/lib/diameter/src/base/diameter_traffic.erl b/lib/diameter/src/base/diameter_traffic.erl
index 8423e30269..4667bbc3f2 100644
--- a/lib/diameter/src/base/diameter_traffic.erl
+++ b/lib/diameter/src/base/diameter_traffic.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2019. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2020. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -86,6 +86,7 @@
string_decode := boolean(),
strict_arities => diameter:strict_arities(),
strict_mbit := boolean(),
+ ordered_encode => boolean(),
incoming_maxlen := diameter:message_length()}}).
%% Note that incoming_maxlen is currently handled in diameter_peer_fsm,
%% so that any message exceeding the maximum is discarded. Retain the
@@ -284,12 +285,18 @@ recv(false, false, TPid, Pkt, _, _) ->
spawn_request(false, _, _, _, _, _, _) -> %% no transport
discard;
-%% An MFA should return the pid() of a process in which the argument
-%% fun in applied, or the atom 'discard' if the fun is not applied.
-%% The latter results in an acknowledgment back to the transport
-%% process when appropriate, to ensure that send/recv callbacks can
-%% count outstanding requests. Acknowledgement is implicit if the
-%% handler process dies (in a handle_request callback for example).
+%% An MFA should return the pid() of a process that invokes
+%% diameter_traffic:request(ReqT), or the atom 'discard' if the
+%% function is not called. The latter results in an acknowledgment
+%% back to the transport process when appropriate, to ensure that
+%% send/recv callbacks can count outstanding requests. Acknowledgement
+%% is implicit if the handler process dies (in a handle_request
+%% callback for example).
+%%
+%% There is no requirement that diameter be started on nodes on which
+%% handler processes are spawned, just that diameter and application
+%% callbacks are on the code path. (Although the MFA itself may have
+%% requirements, as in the case of diameter_dist.)
spawn_request(AppT, {M,F,A}, Ack, TPid, Pkt, Dict0, RecvData) ->
%% Term to pass to request/1 in an appropriate process. Module
%% diameter_dist implements callbacks.
@@ -520,7 +527,7 @@ request_cb(noreply, _App, EvalPktFs, EvalFs) ->
%% Relay a request to another peer. This is equivalent to doing an
%% explicit call/4 with the message in question except that (1) a loop
-%% will be detected by examining Route-Record AVP's, (3) a
+%% will be detected by examining Route-Record AVP's, (2) a
%% Route-Record AVP will be added to the outgoing request and (3) the
%% End-to-End Identifier will default to that in the
%% #diameter_header{} without the need for an end_to_end_identifier
@@ -556,14 +563,7 @@ request_cb(T, App, _, _) ->
send_A({reply, Ans}, TPid, App, Dict0, RecvData, Pkt, _Caps, Fs) ->
AppDict = App#diameter_app.dictionary,
MsgDict = msg_dict(AppDict, Dict0, Ans),
- send_answer(Ans,
- TPid,
- MsgDict,
- AppDict,
- Dict0,
- RecvData,
- Pkt,
- Fs);
+ send_answer(Ans, TPid, MsgDict, AppDict, Dict0, RecvData, Pkt, Fs);
send_A({call, Opts}, TPid, App, Dict0, RecvData, Pkt, Caps, Fs) ->
AppDict = App#diameter_app.dictionary,
@@ -667,7 +667,7 @@ is_answer_message(#diameter_packet{msg = Msg}, Dict0) ->
is_answer_message([#diameter_header{is_request = R, is_error = E} | _], _) ->
E andalso not R;
-%% Message sent as a map or tagged avp/value list.
+%% Message sent as a map or avp list.
is_answer_message([Name | _], _) ->
Name == 'answer-message';
@@ -1239,7 +1239,12 @@ is_result(RC, true, _) ->
%% incr/2
incr(TPid, Counter) ->
- diameter_stats:incr(Counter, TPid, 1).
+ Node = node(TPid),
+ if Node == node() ->
+ diameter_stats:incr(Counter, TPid, 1);
+ true ->
+ spawn(Node, diameter_stats, incr, [Counter, TPid, 1])
+ end.
%% rcc/1
@@ -1866,23 +1871,26 @@ z(#diameter_packet{header = H, bin = Bin, transport_data = T}) ->
transport_data = T}.
%% send/1
+%%
+%% Send from a remote node using a peer connection on this one. Pkt is
+%% already stripped.
send({TPid, Pkt, #request{handler = Pid} = Req0, SvcName, Timeout, TRef}) ->
Req = Req0#request{handler = self()},
- recv(TPid, Pid, TRef, zend_requezt(TPid, Pkt, Req, SvcName, Timeout)).
+ Pid ! recv(TPid, TRef, send_request(TPid, Pkt, Req, SvcName, Timeout)).
-%% recv/4
+%% recv/3
%%
%% Relay an answer from a remote node.
-recv(TPid, Pid, TRef, {LocalTRef, MRef}) ->
+recv(TPid, TRef, {LocalTRef, MRef}) ->
receive
{answer, _, _, _, _} = A ->
- Pid ! A;
+ A;
{'DOWN', MRef, process, _, _} ->
- Pid ! {failover, TRef};
+ {failover, TRef};
{failover = T, LocalTRef} ->
- Pid ! {T, TRef};
+ {T, TRef};
T ->
exit({timeout, LocalTRef, TPid} = T)
end.
diff --git a/lib/diameter/src/diameter.appup.src b/lib/diameter/src/diameter.appup.src
index bb2a4a8e92..627213637b 100644
--- a/lib/diameter/src/diameter.appup.src
+++ b/lib/diameter/src/diameter.appup.src
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2019. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2020. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -62,7 +62,15 @@
{"2.1.4.1", [{restart_application, diameter}]}, %% 20.3.8.19
{"2.1.5", [{restart_application, diameter}]}, %% 21.0
{"2.1.6", [{restart_application, diameter}]}, %% 21.1
- {"2.2", [{update, diameter_dist, {advanced, "2.2"}}]} %% 21.3
+ {"2.2", [{restart_application, diameter}]}, %% 21.3
+ {"2.2.1", [{load_module, diameter}, %% 21.3.5
+ {load_module, diameter_codec},
+ {update, diameter_config},
+ {update, diameter_dist},
+ {update, diameter_peer_fsm},
+ {update, diameter_service},
+ {load_module, diameter_traffic},
+ {update, diameter_tcp}]}
],
[
{"0.9", [{restart_application, diameter}]},
@@ -106,6 +114,14 @@
{"2.1.4.1", [{restart_application, diameter}]},
{"2.1.5", [{restart_application, diameter}]},
{"2.1.6", [{restart_application, diameter}]},
- {"2.2", [{restart_application, diameter}]}
+ {"2.2", [{restart_application, diameter}]},
+ {"2.2.1", [{load_module, diameter},
+ {load_module, diameter_codec},
+ {update, diameter_config},
+ {update, diameter_dist},
+ {update, diameter_peer_fsm},
+ {update, diameter_service},
+ {load_module, diameter_traffic},
+ {update, diameter_tcp}]}
]
}.
diff --git a/lib/diameter/src/modules.mk b/lib/diameter/src/modules.mk
index d16292bb88..cf938785e3 100644
--- a/lib/diameter/src/modules.mk
+++ b/lib/diameter/src/modules.mk
@@ -1,7 +1,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2010-2019. All Rights Reserved.
+# Copyright Ericsson AB 2010-2020. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -98,13 +98,14 @@ BINS = \
# Released files relative to ../examples.
EXAMPLES = \
code/GNUmakefile \
- code/node.erl \
code/client.erl \
code/client_cb.erl \
code/server.erl \
code/server_cb.erl \
code/relay.erl \
code/relay_cb.erl \
+ code/redirect.erl \
+ code/redirect_cb.erl \
dict/rfc4004_mip.dia \
dict/rfc4005_nas.dia \
dict/rfc4006_cc.dia \
diff --git a/lib/diameter/src/transport/diameter_tcp.erl b/lib/diameter/src/transport/diameter_tcp.erl
index e5e766d2a0..a051aeb156 100644
--- a/lib/diameter/src/transport/diameter_tcp.erl
+++ b/lib/diameter/src/transport/diameter_tcp.erl
@@ -569,7 +569,11 @@ m({'DOWN', M, process, P, _} = T, #monitor{parent = MRef,
%% l/2
%%
-%% Transition listener state.
+%% Transition listener state. Or not anymore since any message causes
+%% the process to exit.
+
+-spec l(tuple(), #listener{})
+ -> no_return().
%% Service process has died.
l({'DOWN', _, process, Pid, _} = T, #listener{service = Pid,