1diameter_app(3) Erlang Module Definition diameter_app(3)
2
3
4
6 diameter_app - Callback module of a Diameter application.
7
9 A diameter service as started by diameter:start_service/2 configures
10 one of more Diameter applications, each of whose configuration speci‐
11 fies a callback that handles messages specific to the application. The
12 messages and AVPs of the application are defined in a dictionary file
13 whose format is documented in diameter_dict(4) while the callback mod‐
14 ule is documented here. The callback module implements the Diameter
15 application-specific functionality of a service.
16
17 A callback module must export all of the functions documented below.
18 The functions themselves are of three distinct flavours:
19
20 * peer_up/3 and peer_down/3 signal the attainment or loss of connec‐
21 tivity with a Diameter peer.
22
23 * pick_peer/4, prepare_request/3, prepare_retransmit/3, han‐
24 dle_answer/4 and handle_error/4 are (or may be) called as a conse‐
25 quence of a call to diameter:call/4 to send an outgoing Diameter
26 request message.
27
28 * handle_request/3 is called in response to an incoming Diameter
29 request message.
30
31 The arities for the the callback functions here assume no extra argu‐
32 ments. All functions will also be passed any extra arguments configured
33 with the callback module itself when calling diameter:start_service/2
34 and, for the call-specific callbacks, any extra arguments passed to
35 diameter:call/4.
36
38 capabilities() = #diameter_caps{}:
39 A record containing the identities of the local Diameter node and
40 the remote Diameter peer having an established transport connec‐
41 tion, as well as the capabilities as determined by capabilities
42 exchange. Each field of the record is a 2-tuple consisting of val‐
43 ues for the (local) host and (remote) peer. Optional or possibly
44 multiple values are encoded as lists of values, mandatory values as
45 the bare value.
46
47 message() = diameter_codec:message():
48 The representation of a Diameter message as passed to diame‐
49 ter:call/4 or returned from a handle_request/3 callback.
50
51 packet() = diameter_codec:packet():
52 A container for incoming and outgoing Diameter messages that's
53 passed through encode/decode and transport. Fields should not be
54 set in return values except as documented.
55
56 peer_ref() = term():
57 A term identifying a transport connection with a Diameter peer.
58
59 peer() = {peer_ref(), capabilities()}:
60 A tuple representing a Diameter peer connection.
61
62 state() = term():
63 The state maintained by the application callback functions
64 peer_up/3, peer_down/3 and (optionally) pick_peer/4. The initial
65 state is configured in the call to diameter:start_service/2 that
66 configures the application on a service. Callback functions return‐
67 ing a state are evaluated in a common service-specific process
68 while those not returning state are evaluated in a request-specific
69 process.
70
72 Mod:peer_up(SvcName, Peer, State) -> NewState
73
74 Types:
75
76 SvcName = diameter:service_name()
77 Peer = peer()
78 State = NewState = state()
79
80 Invoked to signal the availability of a peer connection on the
81 local Erlang node. In particular, capabilities exchange with the
82 peer has indicated support for the application in question, the
83 RFC 3539 watchdog state machine for the connection has reached
84 state OKAY and Diameter messages can be both sent and received.
85
86 Note:
87 A watchdog state machine can reach state OKAY from state SUSPECT
88 without a new capabilities exchange taking place. A new trans‐
89 port connection (and capabilities exchange) results in a new
90 peer_ref().
91
92
93 Note:
94 There is no requirement that a callback return before incoming
95 requests are received: handle_request/3 callbacks must be han‐
96 dled independently of peer_up/3 and peer_down/3.
97
98
99 Mod:peer_down(SvcName, Peer, State) -> NewState
100
101 Types:
102
103 SvcName = diameter:service_name()
104 Peer = peer()
105 State = NewState = state()
106
107 Invoked to signal that a peer connection on the local Erlang
108 node is no longer available following a previous call to
109 peer_up/3. In particular, that the RFC 3539 watchdog state
110 machine for the connection has left state OKAY and the peer will
111 no longer be a candidate in pick_peer/4 callbacks.
112
113 Mod:pick_peer(LocalCandidates, RemoteCandidates, SvcName, State) ->
114 Selection | false
115
116 Types:
117
118 LocalCandidates = RemoteCandidates = [peer()]
119 SvcName = diameter:service_name()
120 State = NewState = state()
121 Selection = {ok, Peer} | {Peer, NewState}
122 Peer = peer() | false
123
124 Invoked as a consequence of a call to diameter:call/4 to select
125 a destination peer for an outgoing request. The return value
126 indicates the selected peer.
127
128 The candidate lists contain only those peers that have adver‐
129 tised support for the Diameter application in question during
130 capabilities exchange, that have not be excluded by a filter
131 option in the call to diameter:call/4 and whose watchdog state
132 machine is in the OKAY state. The order of the elements is
133 unspecified except that any peers whose Origin-Host and Origin-
134 Realm matches that of the outgoing request (in the sense of a
135 {filter, {all, [host, realm]}} option to diameter:call/4) will
136 be placed at the head of the list. LocalCandidates contains
137 peers whose transport process resides on the local Erlang node
138 while RemoteCandidates contains peers that have been communi‐
139 cated from other nodes by services of the same name.
140
141 A callback that returns a peer() will be followed by a pre‐
142 pare_request/3 callback and, if the latter indicates that the
143 request should be sent, by either handle_answer/4 or han‐
144 dle_error/4 depending on whether or not an answer message is
145 received from the peer. If the transport becomes unavailable
146 after prepare_request/3 then a new pick_peer/4 callback may take
147 place to failover to an alternate peer, after which pre‐
148 pare_retransmit/3 takes the place of prepare_request/3 in
149 resending the request. There is no guarantee that a pick_peer/4
150 callback to select an alternate peer will be followed by any
151 additional callbacks since a retransmission to an alternate peer
152 is abandoned if an answer is received from a previously selected
153 peer.
154
155 The return values false and {false, State} (that is, NewState =
156 State) are equivalent, as are {ok, Peer} and {Peer, State}.
157
158 Note:
159 The diameter:service_opt() use_shared_peers determines whether
160 or not a service uses peers shared from other nodes. If not then
161 RemoteCandidates is the empty list.
162
163
164 Warning:
165 The return value {Peer, NewState} is only allowed if the Diame‐
166 ter application in question was configured with the diame‐
167 ter:application_opt() {call_mutates_state, true}. Otherwise, the
168 State argument is always the initial value as configured on the
169 application, not any subsequent value returned by a peer_up/3 or
170 peer_down/3 callback.
171
172
173 Mod:prepare_request(Packet, SvcName, Peer) -> Action
174
175 Types:
176
177 Packet = packet()
178 SvcName = diameter:service_name()
179 Peer = peer()
180 Action = Send | Discard | {eval_packet, Action, PostF}
181 Send = {send, packet() | message()}
182 Discard = {discard, Reason} | discard
183 PostF = diameter:eval()}
184
185 Invoked to return a request for encoding and transport. Allows
186 the sender to use the selected peer's capabilities to modify the
187 outgoing request. Many implementations may simply want to return
188 {send, Packet}
189
190 A returned packet() should set the request to be encoded in its
191 msg field and can set the transport_data field in order to pass
192 information to the transport process. Extra arguments passed to
193 diameter:call/4 can be used to communicate transport (or any
194 other) data to the callback.
195
196 A returned packet() can set the header field to a #diame‐
197 ter_header{} to specify values that should be preserved in the
198 outgoing request, values otherwise being those in the header
199 record contained in Packet. A returned length, cmd_code or
200 application_id is ignored.
201
202 A returned PostF will be evaluated on any encoded #diame‐
203 ter_packet{} prior to transmission, the bin field containing the
204 encoded binary. The return value is ignored.
205
206 Returning {discard, Reason} causes the request to be aborted and
207 the diameter:call/4 for which the callback has taken place to
208 return {error, Reason}. Returning discard is equivalent to
209 returning {discard, discarded}.
210
211 Mod:prepare_retransmit(Packet, SvcName, Peer) -> Action
212
213 Types:
214
215 Packet = packet()
216 SvcName = diameter:service_name()
217 Peer = peer()
218 Action = Send | Discard | {eval_packet, Action, PostF}
219 Send = {send, packet() | message()}
220 Discard = {discard, Reason} | discard
221 PostF = diameter:eval()}
222
223 Invoked to return a request for encoding and retransmission. Has
224 the same role as prepare_request/3 in the case that a peer con‐
225 nection is lost an an alternate peer selected but the argument
226 packet() is as returned by the initial prepare_request/3.
227
228 Returning {discard, Reason} causes the request to be aborted and
229 a handle_error/4 callback to take place with Reason as initial
230 argument. Returning discard is equivalent to returning {discard,
231 discarded}.
232
233 Mod:handle_answer(Packet, Request, SvcName, Peer) -> Result
234
235 Types:
236
237 Packet = packet()
238 Request = message()
239 SvcName = diameter:service_name()
240 Peer = peer()
241 Result = term()
242
243 Invoked when an answer message is received from a peer. The
244 return value is returned from diameter:call/4 unless the detach
245 option was specified.
246
247 The decoded answer record and undecoded binary are in the msg
248 and bin fields of the argument packet() respectively. Request is
249 the outgoing request message as was returned from pre‐
250 pare_request/3 or prepare_retransmit/3.
251
252 For any given call to diameter:call/4 there is at most one han‐
253 dle_answer/4 callback: any duplicate answer (due to retransmis‐
254 sion or otherwise) is discarded. Similarly, only one of han‐
255 dle_answer/4 or handle_error/4 is called.
256
257 By default, an incoming answer message that cannot be success‐
258 fully decoded causes the request process to fail, causing diame‐
259 ter:call/4 to return {error, failure} unless the detach option
260 was specified. In particular, there is no handle_error/4 call‐
261 back in this case. The diameter:application_opt() answer_errors
262 can be set to change this behaviour.
263
264 Mod:handle_error(Reason, Request, SvcName, Peer) -> Result
265
266 Types:
267
268 Reason = timeout | failover | term()
269 Request = message()
270 SvcName = diameter:service_name()
271 Peer = peer()
272 Result = term()
273
274 Invoked when an error occurs before an answer message is
275 received in response to an outgoing request. The return value is
276 returned from diameter:call/4 unless the detach option was spec‐
277 ified.
278
279 Reason timeout indicates that an answer message has not been
280 received within the time specified with the corresponding diame‐
281 ter:call_opt(). Reason failover indicates that the transport
282 connection to the peer to which the request has been sent has
283 become unavailable and that not alternate peer was not selected.
284
285 Mod:handle_request(Packet, SvcName, Peer) -> Action
286
287 Types:
288
289 Packet = packet()
290 SvcName = term()
291 Peer = peer()
292 Action = Reply | {relay, [Opt]} | discard |
293 {eval|eval_packet, Action, PostF}
294 Reply = {reply, packet() | message()} | {answer_message,
295 3000..3999|5000..5999} | {protocol_error, 3000..3999}
296 Opt = diameter:call_opt()
297 PostF = diameter:eval()
298
299 Invoked when a request message is received from a peer. The
300 application in which the callback takes place (that is, the
301 callback module as configured with diameter:start_service/2) is
302 determined by the Application Identifier in the header of the
303 incoming request message, the selected module being the one
304 whose corresponding dictionary declares itself as defining
305 either the application in question or the Relay application.
306
307 The argument packet() has the following signature.
308
309 #diameter_packet{header = #diameter_header{},
310 avps = [#diameter_avp{}],
311 msg = record() | undefined,
312 errors = [Unsigned32() | {Unsigned32(), #diameter_avp{}}],
313 bin = binary(),
314 transport_data = term()}
315
316
317 The msg field will be undefined in case the request has been
318 received in the relay application. Otherwise it contains the
319 record representing the request as outlined in diameter_dict(4).
320
321 The errors field specifies any results codes identifying errors
322 found while decoding the request. This is used to set Result-
323 Code and/or Failed-AVP in a returned answer unless the callback
324 returns a #diameter_packet{} whose errors field is set to either
325 a non-empty list of its own, in which case this list is used
326 instead, or the atom false to disable any setting of Result-Code
327 and Failed-AVP. Note that the errors detected by diameter are of
328 the 3xxx and 5xxx series, Protocol Errors and Permanent Failures
329 respectively. The errors list is empty if the request has been
330 received in the relay application.
331
332 The transport_data field contains an arbitrary term passed into
333 diameter from the transport module in question, or the atom
334 undefined if the transport specified no data. The term is pre‐
335 served if a message() is returned but must be set explicitly in
336 a returned packet().
337
338 The semantics of each of the possible return values are as fol‐
339 lows.
340
341 {reply, packet() | message()}:
342 Send the specified answer message to the peer. In the case
343 of a packet(), the message to be sent must be set in the msg
344 field and the header field can be set to a #diame‐
345 ter_header{} to specify values that should be preserved in
346 the outgoing answer, appropriate values otherwise being set
347 by diameter.
348
349 {answer_message, 3000..3999|5000..5999}:
350 Send an answer message to the peer containing the specified
351 Result-Code. Equivalent to
352
353 {reply, ['answer-message' | Avps]
354
355
356 where Avps sets the Origin-Host, Origin-Realm, the specified
357 Result-Code and (if the request contained one) Session-Id
358 AVPs, and possibly Failed-AVP as described below.
359
360 Returning a value other than 3xxx or 5xxx will cause the
361 request process in question to fail, as will returning a
362 5xxx value if the peer connection in question has been con‐
363 figured with the RFC 3588 common dictionary diame‐
364 ter_gen_base_rfc3588. (Since RFC 3588 only allows 3xxx val‐
365 ues in an answer-message.)
366
367 When returning 5xxx, Failed-AVP will be populated with the
368 AVP of the first matching Result-Code/AVP pair in the errors
369 field of the argument packet(), if found. If this is not
370 appropriate then an answer-message should be constructed
371 explicitly and returned in a reply tuple instead.
372
373 {relay, Opts}:
374 Relay a request to another peer in the role of a Diameter
375 relay agent. If a routing loop is detected then the request
376 is answered with 3005 (DIAMETER_LOOP_DETECTED). Otherwise a
377 Route-Record AVP (containing the sending peer's Origin-Host)
378 is added to the request and pick_peer/4 and subsequent call‐
379 backs take place just as if diameter:call/4 had been called
380 explicitly. The End-to-End Identifier of the incoming
381 request is preserved in the header of the relayed request.
382
383 The returned Opts should not specify detach. A subsequent
384 handle_answer/4 callback for the relayed request must return
385 its first argument, the packet() containing the answer mes‐
386 sage. Note that the extra option can be specified to supply
387 arguments that can distinguish the relay case from others if
388 so desired. Any other return value (for example, from a han‐
389 dle_error/4 callback) causes the request to be answered with
390 3002 (DIAMETER_UNABLE_TO_DELIVER).
391
392 discard:
393 Discard the request. No answer message is sent to the peer.
394
395 {eval, Action, PostF}:
396 Handle the request as if Action has been returned and then
397 evaluate PostF in the request process. The return value is
398 ignored.
399
400 {eval_packet, Action, PostF}:
401 Like eval but evaluate PostF on any encoded #diame‐
402 ter_packet{} prior to transmission, the bin field containing
403 the encoded binary. The return value is ignored.
404
405 {protocol_error, 3000..3999}:
406 Equivalent to {answer_message, 3000..3999}.
407
408 Note:
409 Requests containing errors may be answered by diameter, without
410 a callback taking place, depending on the value of the diame‐
411 ter:application_opt() request_errors.
412
413
414
415
416Ericsson AB diameter 2.2.1 diameter_app(3)