1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2013-2016. 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%% 22%% Tests of application_opt() request_errors. There's some overlap 23%% between this suite and the traffic suite but latter exercises more 24%% config. 25%% 26 27-module(diameter_3xxx_SUITE). 28 29-export([suite/0, 30 all/0, 31 groups/0, 32 init_per_suite/1, 33 end_per_suite/1, 34 init_per_group/2, 35 end_per_group/2, 36 init_per_testcase/2, 37 end_per_testcase/2]). 38 39%% testcases 40-export([start/1, 41 send_unknown_application/1, 42 send_unknown_command/1, 43 send_ok/1, 44 send_invalid_hdr_bits/1, 45 send_missing_avp/1, 46 send_ignore_missing_avp/1, 47 send_5xxx_missing_avp/1, 48 send_double_error/1, 49 send_3xxx/1, 50 send_5xxx/1, 51 counters/1, 52 stop/1]). 53 54%% diameter callbacks 55-export([peer_up/3, 56 peer_down/3, 57 pick_peer/5, 58 prepare_request/4, 59 handle_answer/5, 60 handle_error/5, 61 handle_request/3]). 62 63-include("diameter.hrl"). 64-include("diameter_gen_base_rfc6733.hrl"). 65%% Use the fact that STR/STA is identical in RFC's 3588 and 6733. 66 67%% =========================================================================== 68 69-define(util, diameter_util). 70-define(testcase(), proplists:get_value(testcase, get(?MODULE))). 71-define(group(Config), begin 72 put(?MODULE, Config), 73 ?util:name(proplists:get_value(group, Config)) 74 end). 75 76-define(L, atom_to_list). 77-define(A, list_to_atom). 78 79-define(CLIENT, "CLIENT"). 80-define(SERVER, "SERVER"). 81-define(REALM, "erlang.org"). 82-define(HOST(Host, Realm), Host ++ [$.|Realm]). 83 84-define(ERRORS, [answer, answer_3xxx, callback]). 85-define(RFCS, [rfc3588, rfc6733]). 86-define(DICT(RFC), ?A("diameter_gen_base_" ++ ?L(RFC))). 87-define(DICT, ?DICT(rfc6733)). 88 89-define(COMMON, ?DIAMETER_APP_ID_COMMON). 90 91%% Config for diameter:start_service/2. 92-define(SERVICE(Name, Errors, RFC), 93 [{'Origin-Host', Name ++ "." ++ ?REALM}, 94 {'Origin-Realm', ?REALM}, 95 {'Host-IP-Address', [{127,0,0,1}]}, 96 {'Vendor-Id', 12345}, 97 {'Product-Name', "OTP/diameter"}, 98 {'Auth-Application-Id', [?COMMON]}, 99 {application, [{dictionary, ?DICT(RFC)}, 100 {module, ?MODULE}, 101 {answer_errors, callback}, 102 {request_errors, Errors}]}]). 103 104-define(LOGOUT, ?'DIAMETER_BASE_TERMINATION-CAUSE_LOGOUT'). 105 106%% =========================================================================== 107 108suite() -> 109 [{timetrap, {seconds, 60}}]. 110 111all() -> 112 [{group, ?util:name([E,D])} || E <- ?ERRORS, D <- ?RFCS]. 113 114groups() -> 115 Tc = tc(), 116 [{?util:name([E,D]), [], [start] ++ Tc ++ [counters, stop]} 117 || E <- ?ERRORS, D <- ?RFCS]. 118 119init_per_suite(Config) -> 120 ok = diameter:start(), 121 Config. 122 123end_per_suite(_Config) -> 124 ok = diameter:stop(). 125 126init_per_group(Group, Config) -> 127 [{group, Group} | Config]. 128 129end_per_group(_, _) -> 130 ok. 131 132init_per_testcase(Name, Config) -> 133 [{testcase, Name} | Config]. 134 135end_per_testcase(_, _) -> 136 ok. 137 138tc() -> 139 [send_unknown_application, 140 send_unknown_command, 141 send_ok, 142 send_invalid_hdr_bits, 143 send_missing_avp, 144 send_ignore_missing_avp, 145 send_5xxx_missing_avp, 146 send_double_error, 147 send_3xxx, 148 send_5xxx]. 149 150%% =========================================================================== 151 152%% start/1 153 154start(Config) -> 155 Group = proplists:get_value(group, Config), 156 [Errors, RFC] = ?util:name(Group), 157 ok = diameter:start_service(?SERVER, ?SERVICE(?L(Group), 158 Errors, 159 RFC)), 160 ok = diameter:start_service(?CLIENT, ?SERVICE(?CLIENT, 161 callback, 162 rfc6733)), 163 LRef = ?util:listen(?SERVER, tcp), 164 ?util:connect(?CLIENT, tcp, LRef). 165 166%% stop/1 167 168stop(_Config) -> 169 ok = diameter:remove_transport(?CLIENT, true), 170 ok = diameter:remove_transport(?SERVER, true), 171 ok = diameter:stop_service(?SERVER), 172 ok = diameter:stop_service(?CLIENT). 173 174%% counters/1 175%% 176%% Check that counters are as expected. 177 178counters(Config) -> 179 Group = proplists:get_value(group, Config), 180 [_Errors, _Rfc] = G = ?util:name(Group), 181 [] = ?util:run([[fun counters/3, K, S, G] 182 || K <- [statistics, transport, connections], 183 S <- [?CLIENT, ?SERVER]]). 184 185counters(Key, Svc, Group) -> 186 counters(Key, Svc, Group, [_|_] = diameter:service_info(Svc, Key)). 187 188counters(statistics, Svc, [Errors, Rfc], L) -> 189 [{P, Stats}] = L, 190 true = is_pid(P), 191 stats(Svc, Errors, Rfc, lists:sort(Stats)); 192 193counters(_, _, _, _) -> 194 todo. 195 196stats(?CLIENT, E, rfc3588, L) 197 when E == answer; 198 E == answer_3xxx -> 199 [{{{unknown,0},recv},2}, 200 {{{0,257,0},recv},1}, 201 {{{0,257,1},send},1}, 202 {{{0,275,0},recv},6}, 203 {{{0,275,1},send},10}, 204 {{{unknown,0},recv,{'Result-Code',3001}},1}, 205 {{{unknown,0},recv,{'Result-Code',3007}},1}, 206 {{{0,257,0},recv,{'Result-Code',2001}},1}, 207 {{{0,275,0},recv,{'Result-Code',2001}},1}, 208 {{{0,275,0},recv,{'Result-Code',3008}},2}, 209 {{{0,275,0},recv,{'Result-Code',3999}},1}, 210 {{{0,275,0},recv,{'Result-Code',5002}},1}, 211 {{{0,275,0},recv,{'Result-Code',5005}},1}] 212 = L; 213 214stats(?SERVER, E, rfc3588, L) 215 when E == answer; 216 E == answer_3xxx -> 217 [{{{unknown,0},send},2}, 218 {{{unknown,1},recv},1}, 219 {{{0,257,0},send},1}, 220 {{{0,257,1},recv},1}, 221 {{{0,275,0},send},6}, 222 {{{0,275,1},recv},8}, 223 {{{unknown,0},send,{'Result-Code',3001}},1}, 224 {{{unknown,0},send,{'Result-Code',3007}},1}, 225 {{{unknown,1},recv,error},1}, 226 {{{0,257,0},send,{'Result-Code',2001}},1}, 227 {{{0,275,0},send,{'Result-Code',2001}},1}, 228 {{{0,275,0},send,{'Result-Code',3008}},2}, 229 {{{0,275,0},send,{'Result-Code',3999}},1}, 230 {{{0,275,0},send,{'Result-Code',5002}},1}, 231 {{{0,275,0},send,{'Result-Code',5005}},1}, 232 {{{0,275,1},recv,error},5}] 233 = L; 234 235stats(?CLIENT, answer, rfc6733, L) -> 236 [{{{unknown,0},recv},2}, 237 {{{0,257,0},recv},1}, 238 {{{0,257,1},send},1}, 239 {{{0,275,0},recv},8}, 240 {{{0,275,1},send},10}, 241 {{{unknown,0},recv,{'Result-Code',3001}},1}, 242 {{{unknown,0},recv,{'Result-Code',3007}},1}, 243 {{{0,257,0},recv,{'Result-Code',2001}},1}, 244 {{{0,275,0},recv,{'Result-Code',3008}},2}, 245 {{{0,275,0},recv,{'Result-Code',3999}},1}, 246 {{{0,275,0},recv,{'Result-Code',5002}},1}, 247 {{{0,275,0},recv,{'Result-Code',5005}},3}, 248 {{{0,275,0},recv,{'Result-Code',5999}},1}] 249 = L; 250 251stats(?SERVER, answer, rfc6733, L) -> 252 [{{{unknown,0},send},2}, 253 {{{unknown,1},recv},1}, 254 {{{0,257,0},send},1}, 255 {{{0,257,1},recv},1}, 256 {{{0,275,0},send},8}, 257 {{{0,275,1},recv},8}, 258 {{{unknown,0},send,{'Result-Code',3001}},1}, 259 {{{unknown,0},send,{'Result-Code',3007}},1}, 260 {{{unknown,1},recv,error},1}, 261 {{{0,257,0},send,{'Result-Code',2001}},1}, 262 {{{0,275,0},send,{'Result-Code',3008}},2}, 263 {{{0,275,0},send,{'Result-Code',3999}},1}, 264 {{{0,275,0},send,{'Result-Code',5002}},1}, 265 {{{0,275,0},send,{'Result-Code',5005}},3}, 266 {{{0,275,0},send,{'Result-Code',5999}},1}, 267 {{{0,275,1},recv,error},5}] 268 = L; 269 270stats(?CLIENT, answer_3xxx, rfc6733, L) -> 271 [{{{unknown,0},recv},2}, 272 {{{0,257,0},recv},1}, 273 {{{0,257,1},send},1}, 274 {{{0,275,0},recv},8}, 275 {{{0,275,1},send},10}, 276 {{{unknown,0},recv,{'Result-Code',3001}},1}, 277 {{{unknown,0},recv,{'Result-Code',3007}},1}, 278 {{{0,257,0},recv,{'Result-Code',2001}},1}, 279 {{{0,275,0},recv,{'Result-Code',2001}},1}, 280 {{{0,275,0},recv,{'Result-Code',3008}},2}, 281 {{{0,275,0},recv,{'Result-Code',3999}},1}, 282 {{{0,275,0},recv,{'Result-Code',5002}},1}, 283 {{{0,275,0},recv,{'Result-Code',5005}},2}, 284 {{{0,275,0},recv,{'Result-Code',5999}},1}] 285 = L; 286 287stats(?SERVER, answer_3xxx, rfc6733, L) -> 288 [{{{unknown,0},send},2}, 289 {{{unknown,1},recv},1}, 290 {{{0,257,0},send},1}, 291 {{{0,257,1},recv},1}, 292 {{{0,275,0},send},8}, 293 {{{0,275,1},recv},8}, 294 {{{unknown,0},send,{'Result-Code',3001}},1}, 295 {{{unknown,0},send,{'Result-Code',3007}},1}, 296 {{{unknown,1},recv,error},1}, 297 {{{0,257,0},send,{'Result-Code',2001}},1}, 298 {{{0,275,0},send,{'Result-Code',2001}},1}, 299 {{{0,275,0},send,{'Result-Code',3008}},2}, 300 {{{0,275,0},send,{'Result-Code',3999}},1}, 301 {{{0,275,0},send,{'Result-Code',5002}},1}, 302 {{{0,275,0},send,{'Result-Code',5005}},2}, 303 {{{0,275,0},send,{'Result-Code',5999}},1}, 304 {{{0,275,1},recv,error},5}] 305 = L; 306 307stats(?CLIENT, callback, rfc3588, L) -> 308 [{{{unknown,0},recv},1}, 309 {{{0,257,0},recv},1}, 310 {{{0,257,1},send},1}, 311 {{{0,275,0},recv},6}, 312 {{{0,275,1},send},10}, 313 {{{unknown,0},recv,{'Result-Code',3007}},1}, 314 {{{0,257,0},recv,{'Result-Code',2001}},1}, 315 {{{0,275,0},recv,{'Result-Code',2001}},2}, 316 {{{0,275,0},recv,{'Result-Code',3999}},1}, 317 {{{0,275,0},recv,{'Result-Code',5002}},1}, 318 {{{0,275,0},recv,{'Result-Code',5005}},2}] 319 = L; 320 321stats(?SERVER, callback, rfc3588, L) -> 322 [{{{unknown,0},send},1}, 323 {{{unknown,1},recv},1}, 324 {{{0,257,0},send},1}, 325 {{{0,257,1},recv},1}, 326 {{{0,275,0},send},6}, 327 {{{0,275,1},recv},8}, 328 {{{unknown,0},send,{'Result-Code',3007}},1}, 329 {{{unknown,1},recv,error},1}, 330 {{{0,257,0},send,{'Result-Code',2001}},1}, 331 {{{0,275,0},send,{'Result-Code',2001}},2}, 332 {{{0,275,0},send,{'Result-Code',3999}},1}, 333 {{{0,275,0},send,{'Result-Code',5002}},1}, 334 {{{0,275,0},send,{'Result-Code',5005}},2}, 335 {{{0,275,1},recv,error},5}] 336 = L; 337 338stats(?CLIENT, callback, rfc6733, L) -> 339 [{{{unknown,0},recv},1}, 340 {{{0,257,0},recv},1}, 341 {{{0,257,1},send},1}, 342 {{{0,275,0},recv},8}, 343 {{{0,275,1},send},10}, 344 {{{unknown,0},recv,{'Result-Code',3007}},1}, 345 {{{0,257,0},recv,{'Result-Code',2001}},1}, 346 {{{0,275,0},recv,{'Result-Code',2001}},2}, 347 {{{0,275,0},recv,{'Result-Code',3999}},1}, 348 {{{0,275,0},recv,{'Result-Code',5002}},1}, 349 {{{0,275,0},recv,{'Result-Code',5005}},3}, 350 {{{0,275,0},recv,{'Result-Code',5999}},1}] 351 = L; 352 353stats(?SERVER, callback, rfc6733, L) -> 354 [{{{unknown,0},send},1}, 355 {{{unknown,1},recv},1}, 356 {{{0,257,0},send},1}, 357 {{{0,257,1},recv},1}, 358 {{{0,275,0},send},8}, 359 {{{0,275,1},recv},8}, 360 {{{unknown,0},send,{'Result-Code',3007}},1}, 361 {{{unknown,1},recv,error},1}, 362 {{{0,257,0},send,{'Result-Code',2001}},1}, 363 {{{0,275,0},send,{'Result-Code',2001}},2}, 364 {{{0,275,0},send,{'Result-Code',3999}},1}, 365 {{{0,275,0},send,{'Result-Code',5002}},1}, 366 {{{0,275,0},send,{'Result-Code',5005}},3}, 367 {{{0,275,0},send,{'Result-Code',5999}},1}, 368 {{{0,275,1},recv,error},5}] 369 = L. 370 371%% send_unknown_application/1 372%% 373%% Send an unknown application that a callback (which shouldn't take 374%% place) fails on. 375 376%% diameter answers. 377send_unknown_application([_,_]) -> 378 #'diameter_base_answer-message'{'Result-Code' = 3007, 379 %% UNSUPPORTED_APPLICATION 380 'Failed-AVP' = [], 381 'AVP' = []} 382 = call(); 383 384send_unknown_application(Config) -> 385 send_unknown_application(?group(Config)). 386 387%% send_unknown_command/1 388%% 389%% Send a unknown command that a callback discards. 390 391%% handle_request discards the request. 392send_unknown_command([callback, _]) -> 393 {error, timeout} = call(); 394 395%% diameter answers. 396send_unknown_command([_,_]) -> 397 #'diameter_base_answer-message'{'Result-Code' = 3001, 398 %% UNSUPPORTED_COMMAND 399 'Failed-AVP' = [], 400 'AVP' = []} 401 = call(); 402 403send_unknown_command(Config) -> 404 send_unknown_command(?group(Config)). 405 406%% send_ok/1 407%% 408%% Send a correct STR that a callback answers with 5002. 409 410%% Callback answers. 411send_ok([_,_]) -> 412 #diameter_base_STA{'Result-Code' = 5002, %% UNKNOWN_SESSION_ID 413 'Failed-AVP' = [], 414 'AVP' = []} 415 = call(); 416 417send_ok(Config) -> 418 send_ok(?group(Config)). 419 420%% send_invalid_hdr_bits/1 421%% 422%% Send a request with an incorrect E-bit that a callback ignores. 423 424%% Callback answers. 425send_invalid_hdr_bits([callback, _]) -> 426 #diameter_base_STA{'Result-Code' = 2001, %% SUCCESS 427 'Failed-AVP' = [], 428 'AVP' = []} 429 = call(); 430 431%% diameter answers. 432send_invalid_hdr_bits([_,_]) -> 433 #'diameter_base_answer-message'{'Result-Code' = 3008, %% INVALID_HDR_BITS 434 'Failed-AVP' = [], 435 'AVP' = []} 436 = call(); 437 438send_invalid_hdr_bits(Config) -> 439 send_invalid_hdr_bits(?group(Config)). 440 441%% send_missing_avp/1 442%% 443%% Send a request with a missing AVP that a callback answers. 444 445%% diameter answers. 446send_missing_avp([answer, rfc6733]) -> 447 #'diameter_base_answer-message'{'Result-Code' = 5005, %% MISSING_AVP 448 'Failed-AVP' = [_], 449 'AVP' = []} 450 = call(); 451 452%% Callback answers. 453send_missing_avp([_,_]) -> 454 #diameter_base_STA{'Result-Code' = 5005, %% MISSING_AVP 455 'Failed-AVP' = [_], 456 'AVP' = []} 457 = call(); 458 459send_missing_avp(Config) -> 460 send_missing_avp(?group(Config)). 461 462%% send_ignore_missing_avp/1 463%% 464%% Send a request with a missing AVP that a callback ignores. 465 466%% diameter answers. 467send_ignore_missing_avp([answer, rfc6733]) -> 468 #'diameter_base_answer-message'{'Result-Code' = 5005, %% MISSING_AVP 469 'Failed-AVP' = [_], 470 'AVP' = []} 471 = call(); 472 473%% Callback answers, ignores the error 474send_ignore_missing_avp([_,_]) -> 475 #diameter_base_STA{'Result-Code' = 2001, %% SUCCESS 476 'Failed-AVP' = [], 477 'AVP' = []} 478 = call(); 479 480send_ignore_missing_avp(Config) -> 481 send_ignore_missing_avp(?group(Config)). 482 483%% send_5xxx_missing_avp/1 484%% 485%% Send a request with a missing AVP that a callback answers 486%% with {answer_message, 5005}. 487 488%% RFC 6733 allows 5xxx in an answer-message. 489send_5xxx_missing_avp([_, rfc6733]) -> 490 #'diameter_base_answer-message'{'Result-Code' = 5005, %% MISSING_AVP 491 'Failed-AVP' = [_], 492 'AVP' = []} 493 = call(); 494 495%% RFC 3588 doesn't: sending answer fails. 496send_5xxx_missing_avp([_, rfc3588]) -> 497 {error, timeout} = call(); 498 499%% Callback answers, ignores the error 500send_5xxx_missing_avp([_,_]) -> 501 #diameter_base_STA{'Result-Code' = 2001, %% SUCCESS 502 'Failed-AVP' = [], 503 'AVP' = []} 504 = call(); 505 506send_5xxx_missing_avp(Config) -> 507 send_5xxx_missing_avp(?group(Config)). 508 509%% send_double_error/1 510%% 511%% Send a request with both an invalid E-bit and a missing AVP. 512 513%% Callback answers with STA. 514send_double_error([callback, _]) -> 515 #diameter_base_STA{'Result-Code' = 5005, %% MISSING_AVP 516 'Failed-AVP' = [_], 517 'AVP' = []} 518 = call(); 519 520%% diameter answers with answer-message. 521send_double_error([_,_]) -> 522 #'diameter_base_answer-message'{'Result-Code' = 3008, %% INVALID_HDR_BITS 523 'Failed-AVP' = [], 524 'AVP' = []} 525 = call(); 526 527send_double_error(Config) -> 528 send_double_error(?group(Config)). 529 530%% send_3xxx/1 531%% 532%% Send a request that's answered with a 3xxx result code. 533 534%% Callback answers. 535send_3xxx([_,_]) -> 536 #'diameter_base_answer-message'{'Result-Code' = 3999, 537 'Failed-AVP' = [], 538 'AVP' = []} 539 = call(); 540 541send_3xxx(Config) -> 542 send_3xxx(?group(Config)). 543 544%% send_5xxx/1 545%% 546%% Send a request that's answered with a 5xxx result code. 547 548%% Callback answers but fails since 5xxx isn't allowed in an RFC 3588 549%% answer-message. 550send_5xxx([_, rfc3588]) -> 551 {error, timeout} = call(); 552 553%% Callback answers. 554send_5xxx([_,_]) -> 555 #'diameter_base_answer-message'{'Result-Code' = 5999, 556 'Failed-AVP' = [], 557 'AVP' = []} 558 = call(); 559 560send_5xxx(Config) -> 561 send_5xxx(?group(Config)). 562 563%% =========================================================================== 564 565call() -> 566 Name = ?testcase(), 567 diameter:call(?CLIENT, 568 ?DICT, 569 #diameter_base_STR 570 {'Termination-Cause' = ?LOGOUT, 571 'Auth-Application-Id' = ?COMMON, 572 'Class' = [?L(Name)]}, 573 [{extra, [Name]}]). 574 575%% =========================================================================== 576%% diameter callbacks 577 578%% peer_up/3 579 580peer_up(_SvcName, _Peer, State) -> 581 State. 582 583%% peer_down/3 584 585peer_down(_SvcName, _Peer, State) -> 586 State. 587 588%% pick_peer/5 589 590pick_peer([Peer], _, ?CLIENT, _State, _Name) -> 591 {ok, Peer}. 592 593%% prepare_request/4 594 595prepare_request(Pkt, ?CLIENT, {_Ref, Caps}, Name) -> 596 {send, prepare(Pkt, Caps, Name)}. 597 598prepare(Pkt0, Caps, send_unknown_application) -> 599 Req = sta(Pkt0, Caps), 600 #diameter_packet{bin = <<H:8/binary, 0:32, T/binary>>} 601 = Pkt 602 = diameter_codec:encode(?DICT, Pkt0#diameter_packet{msg = Req}), 603 604 Pkt#diameter_packet{bin = <<H/binary, 23:32, T/binary>>}; 605 606prepare(Pkt0, Caps, send_unknown_command) -> 607 Req = sta(Pkt0, Caps), 608 #diameter_packet{bin = <<H:5/binary, 275:24, T/binary>>} 609 = Pkt 610 = diameter_codec:encode(?DICT, Pkt0#diameter_packet{msg = Req}), 611 612 Pkt#diameter_packet{bin = <<H/binary, 572:24, T/binary>>}; 613 614prepare(Pkt, Caps, T) 615 when T == send_ok; 616 T == send_3xxx; 617 T == send_5xxx -> 618 sta(Pkt, Caps); 619 620prepare(Pkt0, Caps, send_invalid_hdr_bits) -> 621 Req = sta(Pkt0, Caps), 622 %% Set the E-bit to force 3008. 623 #diameter_packet{bin = <<H:34, 0:1, T/bitstring>>} 624 = Pkt 625 = diameter_codec:encode(?DICT, Pkt0#diameter_packet{msg = Req}), 626 Pkt#diameter_packet{bin = <<H:34, 1:1, T/bitstring>>}; 627 628prepare(Pkt0, Caps, send_double_error) -> 629 dehost(prepare(Pkt0, Caps, send_invalid_hdr_bits)); 630 631prepare(Pkt, Caps, T) 632 when T == send_missing_avp; 633 T == send_ignore_missing_avp; 634 T == send_5xxx_missing_avp -> 635 Req = sta(Pkt, Caps), 636 dehost(diameter_codec:encode(?DICT, Pkt#diameter_packet{msg = Req})). 637 638sta(Pkt, Caps) -> 639 #diameter_packet{msg = Req} 640 = Pkt, 641 #diameter_caps{origin_host = {OH, _}, 642 origin_realm = {OR, DR}} 643 = Caps, 644 Req#diameter_base_STR{'Session-Id' = diameter:session_id(OH), 645 'Origin-Host' = OH, 646 'Origin-Realm' = OR, 647 'Destination-Realm' = DR}. 648 649%% Strip Origin-Host. 650dehost(#diameter_packet{bin = Bin} = Pkt) -> 651 <<V, Len:24, H:16/binary, T0/binary>> 652 = Bin, 653 {SessionId, T1} = split_avp(T0), 654 {OriginHost, T} = split_avp(T1), 655 Delta = size(OriginHost), 656 Pkt#diameter_packet{bin = <<V, (Len - Delta):24, H/binary, 657 SessionId/binary, 658 T/binary>>}. 659 660%% handle_answer/5 661 662handle_answer(Pkt, _Req, ?CLIENT, _Peer, _Name) -> 663 Pkt#diameter_packet.msg. 664 665%% handle_error/5 666 667handle_error(Reason, _Req, ?CLIENT, _Peer, _Name) -> 668 {error, Reason}. 669 670split_avp(<<_:5/binary, Len:24, _/binary>> = Bin) -> 671 L = pad(Len), 672 <<Avp:L/binary, T/binary>> = Bin, 673 {Avp, T}. 674 675pad(N) 676 when 0 == N rem 4 -> 677 N; 678pad(N) -> 679 N - (N rem 4) + 4. 680 681%% handle_request/3 682 683handle_request(#diameter_packet{header = #diameter_header{application_id = 0}, 684 msg = Msg}, 685 ?SERVER, 686 {_, Caps}) -> 687 request(Msg, Caps). 688 689request(undefined, _) -> %% unknown command 690 discard; 691 692request(#diameter_base_STR{'Class' = [Name]} = Req, Caps) -> 693 request(?A(Name), Req, Caps). 694 695request(send_ok, Req, Caps) -> 696 {reply, #diameter_packet{msg = answer(Req, Caps), 697 errors = [5002]}}; %% UNKNOWN_SESSION_ID 698 699request(send_3xxx, _Req, _Caps) -> 700 {answer_message, 3999}; 701 702request(send_5xxx, _Req, _Caps) -> 703 {answer_message, 5999}; 704 705request(send_invalid_hdr_bits, Req, Caps) -> 706 %% Default errors field but a non-answer-message and only 3xxx 707 %% errors detected means diameter sets neither Result-Code nor 708 %% Failed-AVP. 709 {reply, #diameter_packet{msg = answer(Req, Caps)}}; 710 711request(T, Req, Caps) 712 when T == send_double_error; 713 T == send_missing_avp -> 714 {reply, answer(Req, Caps)}; 715 716request(send_ignore_missing_avp, Req, Caps) -> 717 {reply, #diameter_packet{msg = answer(Req, Caps), 718 errors = false}}; %% ignore errors 719 720request(send_5xxx_missing_avp, _Req, _Caps) -> 721 {answer_message, 5005}. %% MISSING_AVP 722 723answer(Req, Caps) -> 724 #diameter_base_STR{'Session-Id' = SId} 725 = Req, 726 #diameter_caps{origin_host = {OH,_}, 727 origin_realm = {OR,_}} 728 = Caps, 729 #diameter_base_STA{'Session-Id' = SId, 730 'Origin-Host' = OH, 731 'Origin-Realm' = OR, 732 'Result-Code' = 2001}. %% SUCCESS 733