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 ap‐
15 plication-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, handle_an‐
24 swer/4 and handle_error/4 are (or may be) called as a consequence
25 of a call to diameter:call/4 to send an outgoing Diameter request
26 message.
27
28 * handle_request/3 is called in response to an incoming Diameter re‐
29 quest 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 di‐
35 ameter: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 ex‐
42 change. Each field of the record is a 2-tuple consisting of values
43 for the (local) host and (remote) peer. Optional or possibly multi‐
44 ple values are encoded as lists of values, mandatory values as the
45 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 ma‐
110 chine 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) -> Se‐
114 lection | 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 in‐
126 dicates 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 op‐
131 tion in the call to diameter:call/4 and whose watchdog state ma‐
132 chine is in the OKAY state. The order of the elements is unspec‐
133 ified except that any peers whose Origin-Host and Origin-Realm
134 matches that of the outgoing request (in the sense of a {filter,
135 {all, [host, realm]}} option to diameter:call/4) will be placed
136 at the head of the list. LocalCandidates contains peers whose
137 transport process resides on the local Erlang node while Remote‐
138 Candidates contains peers that have been communicated from other
139 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 handle_er‐
144 ror/4 depending on whether or not an answer message is received
145 from the peer. If the transport becomes unavailable after pre‐
146 pare_request/3 then a new pick_peer/4 callback may take place to
147 failover to an alternate peer, after which prepare_retransmit/3
148 takes the place of prepare_request/3 in resending the request.
149 There is no guarantee that a pick_peer/4 callback to select an
150 alternate peer will be followed by any additional callbacks
151 since a retransmission to an alternate peer is abandoned if an
152 answer is received from a previously selected peer.
153
154 The return values false and {false, State} (that is, NewState =
155 State) are equivalent, as are {ok, Peer} and {Peer, State}.
156
157 Note:
158 The diameter:service_opt() use_shared_peers determines whether
159 or not a service uses peers shared from other nodes. If not then
160 RemoteCandidates is the empty list.
161
162
163 Warning:
164 The return value {Peer, NewState} is only allowed if the Diame‐
165 ter application in question was configured with the diameter:ap‐
166 plication_opt() {call_mutates_state, true}. Otherwise, the State
167 argument is always the initial value as configured on the appli‐
168 cation, not any subsequent value returned by a peer_up/3 or
169 peer_down/3 callback.
170
171
172 Mod:prepare_request(Packet, SvcName, Peer) -> Action
173
174 Types:
175
176 Packet = packet()
177 SvcName = diameter:service_name()
178 Peer = peer()
179 Action = Send | Discard | {eval_packet, Action, PostF}
180 Send = {send, packet() | message()}
181 Discard = {discard, Reason} | discard
182 PostF = diameter:eval()}
183
184 Invoked to return a request for encoding and transport. Allows
185 the sender to use the selected peer's capabilities to modify the
186 outgoing request. Many implementations may simply want to return
187 {send, Packet}
188
189 A returned packet() should set the request to be encoded in its
190 msg field and can set the transport_data field in order to pass
191 information to the transport process. Extra arguments passed to
192 diameter:call/4 can be used to communicate transport (or any
193 other) data to the callback.
194
195 A returned packet() can set the header field to a #diame‐
196 ter_header{} to specify values that should be preserved in the
197 outgoing request, values otherwise being those in the header
198 record contained in Packet. A returned length, cmd_code or ap‐
199 plication_id is ignored.
200
201 A returned PostF will be evaluated on any encoded #diame‐
202 ter_packet{} prior to transmission, the bin field containing the
203 encoded binary. The return value is ignored.
204
205 Returning {discard, Reason} causes the request to be aborted and
206 the diameter:call/4 for which the callback has taken place to
207 return {error, Reason}. Returning discard is equivalent to re‐
208 turning {discard, discarded}.
209
210 Mod:prepare_retransmit(Packet, SvcName, Peer) -> Action
211
212 Types:
213
214 Packet = packet()
215 SvcName = diameter:service_name()
216 Peer = peer()
217 Action = Send | Discard | {eval_packet, Action, PostF}
218 Send = {send, packet() | message()}
219 Discard = {discard, Reason} | discard
220 PostF = diameter:eval()}
221
222 Invoked to return a request for encoding and retransmission. Has
223 the same role as prepare_request/3 in the case that a peer con‐
224 nection is lost an an alternate peer selected but the argument
225 packet() is as returned by the initial prepare_request/3.
226
227 Returning {discard, Reason} causes the request to be aborted and
228 a handle_error/4 callback to take place with Reason as initial
229 argument. Returning discard is equivalent to returning {discard,
230 discarded}.
231
232 Mod:handle_answer(Packet, Request, SvcName, Peer) -> Result
233
234 Types:
235
236 Packet = packet()
237 Request = message()
238 SvcName = diameter:service_name()
239 Peer = peer()
240 Result = term()
241
242 Invoked when an answer message is received from a peer. The re‐
243 turn value is returned from diameter:call/4 unless the detach
244 option was specified.
245
246 The decoded answer record and undecoded binary are in the msg
247 and bin fields of the argument packet() respectively. Request is
248 the outgoing request message as was returned from prepare_re‐
249 quest/3 or prepare_retransmit/3.
250
251 For any given call to diameter:call/4 there is at most one han‐
252 dle_answer/4 callback: any duplicate answer (due to retransmis‐
253 sion or otherwise) is discarded. Similarly, only one of han‐
254 dle_answer/4 or handle_error/4 is called.
255
256 By default, an incoming answer message that cannot be success‐
257 fully decoded causes the request process to fail, causing diame‐
258 ter:call/4 to return {error, failure} unless the detach option
259 was specified. In particular, there is no handle_error/4 call‐
260 back in this case. The diameter:application_opt() answer_errors
261 can be set to change this behaviour.
262
263 Mod:handle_error(Reason, Request, SvcName, Peer) -> Result
264
265 Types:
266
267 Reason = timeout | failover | term()
268 Request = message()
269 SvcName = diameter:service_name()
270 Peer = peer()
271 Result = term()
272
273 Invoked when an error occurs before an answer message is re‐
274 ceived in response to an outgoing request. The return value is
275 returned from diameter:call/4 unless the detach option was spec‐
276 ified.
277
278 Reason timeout indicates that an answer message has not been re‐
279 ceived within the time specified with the corresponding diame‐
280 ter:call_opt(). Reason failover indicates that the transport
281 connection to the peer to which the request has been sent has
282 become unavailable and that not alternate peer was not selected.
283
284 Mod:handle_request(Packet, SvcName, Peer) -> Action
285
286 Types:
287
288 Packet = packet()
289 SvcName = term()
290 Peer = peer()
291 Action = Reply | {relay, [Opt]} | discard |
292 {eval|eval_packet, Action, PostF}
293 Reply = {reply, packet() | message()} | {answer_message,
294 3000..3999|5000..5999} | {protocol_error, 3000..3999}
295 Opt = diameter:call_opt()
296 PostF = diameter:eval()
297
298 Invoked when a request message is received from a peer. The ap‐
299 plication in which the callback takes place (that is, the call‐
300 back module as configured with diameter:start_service/2) is de‐
301 termined by the Application Identifier in the header of the in‐
302 coming request message, the selected module being the one whose
303 corresponding dictionary declares itself as defining either the
304 application in question or the Relay application.
305
306 The argument packet() has the following signature.
307
308 #diameter_packet{header = #diameter_header{},
309 avps = [#diameter_avp{}],
310 msg = record() | undefined,
311 errors = [Unsigned32() | {Unsigned32(), #diameter_avp{}}],
312 bin = binary(),
313 transport_data = term()}
314
315
316 The msg field will be undefined in case the request has been re‐
317 ceived in the relay application. Otherwise it contains the
318 record representing the request as outlined in diameter_dict(4).
319
320 The errors field specifies any results codes identifying errors
321 found while decoding the request. This is used to set Result-
322 Code and/or Failed-AVP in a returned answer unless the callback
323 returns a #diameter_packet{} whose errors field is set to either
324 a non-empty list of its own, in which case this list is used in‐
325 stead, or the atom false to disable any setting of Result-Code
326 and Failed-AVP. Note that the errors detected by diameter are of
327 the 3xxx and 5xxx series, Protocol Errors and Permanent Failures
328 respectively. The errors list is empty if the request has been
329 received in the relay application.
330
331 The transport_data field contains an arbitrary term passed into
332 diameter from the transport module in question, or the atom un‐
333 defined if the transport specified no data. The term is pre‐
334 served if a message() is returned but must be set explicitly in
335 a returned packet().
336
337 The semantics of each of the possible return values are as fol‐
338 lows.
339
340 {reply, packet() | message()}:
341 Send the specified answer message to the peer. In the case
342 of a packet(), the message to be sent must be set in the msg
343 field and the header field can be set to a #diame‐
344 ter_header{} to specify values that should be preserved in
345 the outgoing answer, appropriate values otherwise being set
346 by diameter.
347
348 {answer_message, 3000..3999|5000..5999}:
349 Send an answer message to the peer containing the specified
350 Result-Code. Equivalent to
351
352 {reply, ['answer-message' | Avps]
353
354
355 where Avps sets the Origin-Host, Origin-Realm, the specified
356 Result-Code and (if the request contained one) Session-Id
357 AVPs, and possibly Failed-AVP as described below.
358
359 Returning a value other than 3xxx or 5xxx will cause the re‐
360 quest process in question to fail, as will returning a 5xxx
361 value if the peer connection in question has been configured
362 with the RFC 3588 common dictionary diame‐
363 ter_gen_base_rfc3588. (Since RFC 3588 only allows 3xxx val‐
364 ues in an answer-message.)
365
366 When returning 5xxx, Failed-AVP will be populated with the
367 AVP of the first matching Result-Code/AVP pair in the errors
368 field of the argument packet(), if found. If this is not ap‐
369 propriate then an answer-message should be constructed ex‐
370 plicitly and returned in a reply tuple instead.
371
372 {relay, Opts}:
373 Relay a request to another peer in the role of a Diameter
374 relay agent. If a routing loop is detected then the request
375 is answered with 3005 (DIAMETER_LOOP_DETECTED). Otherwise a
376 Route-Record AVP (containing the sending peer's Origin-Host)
377 is added to the request and pick_peer/4 and subsequent call‐
378 backs take place just as if diameter:call/4 had been called
379 explicitly. The End-to-End Identifier of the incoming re‐
380 quest is preserved in the header of the relayed request.
381
382 The returned Opts should not specify detach. A subsequent
383 handle_answer/4 callback for the relayed request must return
384 its first argument, the packet() containing the answer mes‐
385 sage. Note that the extra option can be specified to supply
386 arguments that can distinguish the relay case from others if
387 so desired. Any other return value (for example, from a han‐
388 dle_error/4 callback) causes the request to be answered with
389 3002 (DIAMETER_UNABLE_TO_DELIVER).
390
391 discard:
392 Discard the request. No answer message is sent to the peer.
393
394 {eval, Action, PostF}:
395 Handle the request as if Action has been returned and then
396 evaluate PostF in the request process. The return value is
397 ignored.
398
399 {eval_packet, Action, PostF}:
400 Like eval but evaluate PostF on any encoded #diame‐
401 ter_packet{} prior to transmission, the bin field containing
402 the encoded binary. The return value is ignored.
403
404 {protocol_error, 3000..3999}:
405 Equivalent to {answer_message, 3000..3999}.
406
407 Note:
408 Requests containing errors may be answered by diameter, without
409 a callback taking place, depending on the value of the diame‐
410 ter:application_opt() request_errors.
411
412
413
414
415Ericsson AB diameter 2.2.7 diameter_app(3)