1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2010-2019. All Rights Reserved. 5%% 6%% Licensed under the Apache License, Version 2.0 (the "License"); 7%% you may not use this file except in compliance with the License. 8%% You may obtain a copy of the License at 9%% 10%% http://www.apache.org/licenses/LICENSE-2.0 11%% 12%% Unless required by applicable law or agreed to in writing, software 13%% distributed under the License is distributed on an "AS IS" BASIS, 14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15%% See the License for the specific language governing permissions and 16%% limitations under the License. 17%% 18%% %CopyrightEnd% 19%% 20 21-module(diameter). 22 23%% Configuration. 24-export([start_service/2, 25 stop_service/1, 26 add_transport/2, 27 remove_transport/2, 28 subscribe/1, 29 unsubscribe/1]). 30 31%% Traffic. 32-export([session_id/1, 33 origin_state_id/0, 34 call/3, 35 call/4]). 36 37%% Information. 38-export([services/0, 39 peer_info/1, 40 peer_find/1, 41 service_info/2]). 42 43%% Start/stop the application. In a "real" application this should 44%% typically be a consequence of a release file rather than by calling 45%% start/stop explicitly. 46-export([start/0, 47 stop/0]). 48 49-export_type([eval/0, 50 evaluable/0, %% deprecated 51 decode_format/0, 52 strict_arities/0, 53 restriction/0, 54 message_length/0, 55 remotes/0, 56 sequence/0, 57 app_alias/0, 58 service_name/0, 59 capability/0, 60 peer_filter/0, 61 peer_ref/0, 62 service_opt/0, 63 application_opt/0, 64 app_module/0, 65 transport_ref/0, 66 transport_opt/0, 67 transport_pred/0, 68 call_opt/0]). 69 70-export_type(['OctetString'/0, 71 'Integer32'/0, 72 'Integer64'/0, 73 'Unsigned32'/0, 74 'Unsigned64'/0, 75 'Float32'/0, 76 'Float64'/0, 77 'Grouped'/0, 78 'Address'/0, 79 'Time'/0, 80 'UTF8String'/0, 81 'DiameterIdentity'/0, 82 'DiameterURI'/0, 83 'Enumerated'/0, 84 'IPFilterRule'/0, 85 'QoSFilterRule'/0]). 86 87-include_lib("diameter/include/diameter.hrl"). 88-include("diameter_internal.hrl"). 89 90%% --------------------------------------------------------------------------- 91%% start/0 92%% --------------------------------------------------------------------------- 93 94-spec start() 95 -> ok 96 | {error, term()}. 97 98start() -> 99 application:start(?APPLICATION). 100 101%% --------------------------------------------------------------------------- 102%% stop/0 103%% --------------------------------------------------------------------------- 104 105-spec stop() 106 -> ok 107 | {error, term()}. 108 109stop() -> 110 application:stop(?APPLICATION). 111 112%% --------------------------------------------------------------------------- 113%% start_service/2 114%% --------------------------------------------------------------------------- 115 116-spec start_service(service_name(), [service_opt()]) 117 -> ok 118 | {error, term()}. 119 120start_service(SvcName, Opts) 121 when is_list(Opts) -> 122 diameter_config:start_service(SvcName, Opts). 123 124%% --------------------------------------------------------------------------- 125%% stop_service/1 126%% --------------------------------------------------------------------------- 127 128-spec stop_service(service_name()) 129 -> ok 130 | {error, term()}. 131 132stop_service(SvcName) -> 133 diameter_config:stop_service(SvcName). 134 135%% --------------------------------------------------------------------------- 136%% services/0 137%% --------------------------------------------------------------------------- 138 139-spec services() 140 -> [service_name()]. 141 142services() -> 143 [Name || {Name, _} <- diameter_service:services()]. 144 145%% --------------------------------------------------------------------------- 146%% service_info/2 147%% --------------------------------------------------------------------------- 148 149-spec service_info(service_name(), atom() | [atom()]) 150 -> any(). 151 152service_info(SvcName, Option) -> 153 diameter_service:info(SvcName, Option). 154 155%% --------------------------------------------------------------------------- 156%% peer_info/2 157%% --------------------------------------------------------------------------- 158 159-spec peer_info(peer_ref()) 160 -> [tuple()]. 161 162peer_info(PeerRef) -> 163 diameter_service:peer_info(PeerRef). 164 165%% --------------------------------------------------------------------------- 166%% peer_find/1 167%% --------------------------------------------------------------------------- 168 169-spec peer_find(peer_ref() | pid()) 170 -> {peer_ref(), pid()} 171 | false. 172 173peer_find(Pid) -> 174 diameter_peer_fsm:find(Pid). 175 176%% --------------------------------------------------------------------------- 177%% add_transport/3 178%% --------------------------------------------------------------------------- 179 180-spec add_transport(service_name(), {listen|connect, [transport_opt()]}) 181 -> {ok, transport_ref()} 182 | {error, term()}. 183 184add_transport(SvcName, {T, Opts} = Cfg) 185 when is_list(Opts), (T == connect orelse T == listen) -> 186 diameter_config:add_transport(SvcName, Cfg). 187 188%% --------------------------------------------------------------------------- 189%% remove_transport/2 190%% --------------------------------------------------------------------------- 191 192-spec remove_transport(service_name(), transport_pred()) 193 -> ok | {error, term()}. 194 195remove_transport(SvcName, Pred) -> 196 diameter_config:remove_transport(SvcName, Pred). 197 198%% --------------------------------------------------------------------------- 199%% subscribe/1 200%% --------------------------------------------------------------------------- 201 202-spec subscribe(service_name()) 203 -> true. 204 205subscribe(SvcName) -> 206 diameter_service:subscribe(SvcName). 207 208%% --------------------------------------------------------------------------- 209%% unsubscribe/1 210%% --------------------------------------------------------------------------- 211 212-spec unsubscribe(service_name()) 213 -> true. 214 215unsubscribe(SvcName) -> 216 diameter_service:unsubscribe(SvcName). 217 218%% --------------------------------------------------------------------------- 219%% session_id/1 220%% --------------------------------------------------------------------------- 221 222-spec session_id('DiameterIdentity'()) 223 -> 'OctetString'(). 224 225session_id(Ident) -> 226 diameter_session:session_id(Ident). 227 228%% --------------------------------------------------------------------------- 229%% origin_state_id/0 230%% --------------------------------------------------------------------------- 231 232-spec origin_state_id() 233 -> 'Unsigned32'(). 234 235origin_state_id() -> 236 diameter_session:origin_state_id(). 237 238%% --------------------------------------------------------------------------- 239%% call/3,4 240%% --------------------------------------------------------------------------- 241 242-spec call(service_name(), app_alias(), any(), [call_opt()]) 243 -> any(). 244 245call(SvcName, App, Message, Options) -> 246 diameter_traffic:send_request(SvcName, {alias, App}, Message, Options). 247 248call(SvcName, App, Message) -> 249 call(SvcName, App, Message, []). 250 251%% =========================================================================== 252 253%% Diameter basic types 254 255-type 'OctetString'() :: iolist(). 256-type 'Integer32'() :: -2147483647..2147483647. 257-type 'Integer64'() :: -9223372036854775807..9223372036854775807. 258-type 'Unsigned32'() :: 0..4294967295. 259-type 'Unsigned64'() :: 0..18446744073709551615. 260-type 'Float32'() :: '-infinity' | float() | infinity. 261-type 'Float64'() :: '-infinity' | float() | infinity. 262-type 'Grouped'() :: list() | tuple(). 263 264%% Diameter derived types 265 266-type 'Address'() 267 :: inet:ip_address() 268 | string(). 269 270-type 'Time'() :: {{integer(), 1..12, 1..31}, 271 {0..23, 0..59, 0..59}}. 272-type 'UTF8String'() :: iolist(). 273-type 'DiameterIdentity'() :: 'OctetString'(). 274-type 'DiameterURI'() :: 'OctetString'(). 275-type 'Enumerated'() :: 'Integer32'(). 276-type 'IPFilterRule'() :: 'OctetString'(). 277-type 'QoSFilterRule'() :: 'OctetString'(). 278 279%% The handle to a service. 280 281-type service_name() 282 :: any(). 283 284%% Capabilities options/avps on start_service/2 and/or add_transport/2 285 286-type capability() 287 :: {'Origin-Host', 'DiameterIdentity'()} 288 | {'Origin-Realm', 'DiameterIdentity'()} 289 | {'Host-IP-Address', ['Address'()]} 290 | {'Vendor-Id', 'Unsigned32'()} 291 | {'Product-Name', 'UTF8String'()} 292 | {'Supported-Vendor-Id', ['Unsigned32'()]} 293 | {'Auth-Application-Id', ['Unsigned32'()]} 294 | {'Vendor-Specific-Application-Id', ['Grouped'()]} 295 | {'Firmware-Revision', 'Unsigned32'()}. 296 297%% Filters for call/4 298 299-type peer_filter() 300 :: none 301 | host 302 | realm 303 | {host, any|'DiameterIdentity'()} 304 | {realm, any|'DiameterIdentity'()} 305 | {eval, eval()} 306 | {neg, peer_filter()} 307 | {all, [peer_filter()]} 308 | {any, [peer_filter()]}. 309 310-opaque peer_ref() 311 :: pid(). 312 313-type eval() 314 :: {module(), atom(), list()} 315 | fun() 316 | maybe_improper_list(eval(), list()). 317 318-type evaluable() 319 :: eval(). 320 321-type sequence() 322 :: {'Unsigned32'(), 0..32}. 323 324-type restriction() 325 :: false 326 | node 327 | nodes 328 | [node()] 329 | eval(). 330 331-type remotes() 332 :: boolean() 333 | [node()] 334 | eval(). 335 336-type message_length() 337 :: 0..16#FFFFFF. 338 339-type decode_format() 340 :: record 341 | list 342 | map 343 | none 344 | record_from_map. 345 346-type strict_arities() 347 :: false 348 | encode 349 | decode. 350 351%% Options common to both start_service/2 and add_transport/2. 352 353-type common_opt() 354 :: {pool_size, pos_integer()} 355 | {capabilities_cb, eval()} 356 | {capx_timeout, 'Unsigned32'()} 357 | {strict_capx, boolean()} 358 | {strict_mbit, boolean()} 359 | {avp_dictionaries, [module()]} 360 | {disconnect_cb, eval()} 361 | {dpr_timeout, 'Unsigned32'()} 362 | {dpa_timeout, 'Unsigned32'()} 363 | {incoming_maxlen, message_length()} 364 | {length_errors, exit | handle | discard} 365 | {connect_timer, 'Unsigned32'()} 366 | {watchdog_timer, 'Unsigned32'() | {module(), atom(), list()}} 367 | {watchdog_config, [{okay|suspect, non_neg_integer()}]} 368 | {spawn_opt, list() | mfa()}. 369 370%% Options passed to start_service/2 371 372-type service_opt() 373 :: capability() 374 | {application, [application_opt()]} 375 | {restrict_connections, restriction()} 376 | {sequence, sequence() | eval()} 377 | {share_peers, remotes()} 378 | {decode_format, decode_format()} 379 | {traffic_counters, boolean()} 380 | {string_decode, boolean()} 381 | {strict_arities, true | strict_arities()} 382 | {use_shared_peers, remotes()} 383 | common_opt(). 384 385-type application_opt() 386 :: {alias, app_alias()} 387 | {dictionary, module()} 388 | {module, app_module()} 389 | {state, any()} 390 | {call_mutates_state, boolean()} 391 | {answer_errors, callback|report|discard} 392 | {request_errors, answer_3xxx|answer|callback}. 393 394-type app_alias() 395 :: any(). 396 397-type app_module() 398 :: module() 399 | maybe_improper_list(module(), list()) 400 | #diameter_callback{}. 401 402%% Identifier returned by add_transport/2 403 404-type transport_ref() 405 :: reference(). 406 407%% Options passed to add_transport/2 408 409-type transport_opt() 410 :: {transport_module, atom()} 411 | {transport_config, any()} 412 | {transport_config, any(), 'Unsigned32'() | infinity} 413 | {applications, [app_alias()]} 414 | {capabilities, [capability()]} 415 | common_opt() 416 | {private, any()}. 417 418%% Predicate passed to remove_transport/2 419 420-type transport_pred() 421 :: fun((transport_ref(), connect|listen, list()) -> boolean()) 422 | fun((transport_ref(), list()) -> boolean()) 423 | fun((list()) -> boolean()) 424 | transport_ref() 425 | boolean() 426 | list() 427 | {connect|listen, transport_pred()} 428 | {atom(), atom(), list()}. 429 430%% Options passed to call/4 431 432-type call_opt() 433 :: {extra, list()} 434 | {filter, peer_filter()} 435 | {timeout, 'Unsigned32'()} 436 | {peer, peer_ref()} 437 | detach. 438