sig_coord.c revision 225736
1/* 2 * Copyright (c) 1996-2003 3 * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 * Author: Hartmut Brandt <harti@freebsd.org> 28 * 29 * $Begemot: libunimsg/netnatm/sig/sig_coord.c,v 1.12 2004/08/05 07:11:01 brandt Exp $ 30 * 31 * Coordinator 32 */ 33 34#include <netnatm/unimsg.h> 35#include <netnatm/saal/sscfudef.h> 36#include <netnatm/msg/unistruct.h> 37#include <netnatm/msg/unimsglib.h> 38#include <netnatm/sig/uni.h> 39 40#include <netnatm/sig/unipriv.h> 41#include <netnatm/sig/unimkmsg.h> 42 43#define STR(S) [S] = #S 44static const char *const cunames[] = { 45 STR(CU_STAT0), 46 STR(CU_STAT1), 47 STR(CU_STAT2), 48 STR(CU_STAT3), 49}; 50 51#define DEF_PRIV_SIG(NAME, FROM) [SIG##NAME] = "SIG"#NAME, 52static const char *const coord_sigs[] = { 53 DEF_COORD_SIGS 54}; 55#undef DEF_PRIV_SIG 56 57static void sig_all_calls(struct uni *, u_int sig); 58static void set_custat(struct uni *, enum cu_stat); 59 60static void input_dummy(struct uni *uni, struct uni_msg *m, struct uni_all *u); 61static void input_global(struct uni *uni, struct uni_msg *m, struct uni_all *u); 62static void input_unknown(struct uni *uni, struct uni_msg *m, struct uni_all *u); 63static void input_cobi(struct call *c, struct uni_msg *m, struct uni_all *u); 64static void input_call(struct call *c, struct uni_msg *m, struct uni_all *u); 65 66TIMER_FUNC_UNI(t309, t309_func) 67 68/* 69 * All those 'bogus signal' printouts are not specified in the SDLs. 70 */ 71 72 73/* 74 * SAAL-ESTABLISH.indication 75 * 76 * This means either a resynchronisation or error-recovery or 77 * an incoming SSCOP connection. 78 */ 79static void 80coord_saal_establish_indication(struct uni *uni) 81{ 82 switch (uni->custat) { 83 84 case CU_STAT0: /* Q.2931:Coord-U 4/10 */ 85 case CU_STAT3: /* Q.2931:Coord-U 5/10 */ 86 sig_all_calls(uni, SIGC_LINK_ESTABLISH_indication); 87 set_custat(uni, CU_STAT3); 88 break; 89 90 case CU_STAT1: 91 case CU_STAT2: 92 VERBOSE0(uni, UNI_FAC_COORD, 93 "signal saal_establish.indication in CU%u", uni->custat); 94 break; 95 96 default: 97 ASSERT(0, ("CU_STAT*")); 98 } 99} 100 101/* 102 * SAAL-ESTABLISH.confirm 103 */ 104static void 105coord_saal_establish_confirm(struct uni *uni) 106{ 107 switch (uni->custat) { 108 109 case CU_STAT0: 110 case CU_STAT2: 111 VERBOSE0(uni, UNI_FAC_COORD, 112 "signal saal_establish.confirm in CU%u", uni->custat); 113 break; 114 115 case CU_STAT1: 116 /* 117 * Q.2931:Co-ord-U 4/10 118 */ 119 TIMER_STOP_UNI(uni, t309); 120 sig_all_calls(uni, SIGC_LINK_ESTABLISH_confirm); 121 uni->funcs->uni_output(uni, uni->arg, 122 UNIAPI_LINK_ESTABLISH_confirm, 0, NULL); 123 set_custat(uni, CU_STAT3); 124 break; 125 126 case CU_STAT3: 127 /* 128 * Q.2931:Coord-U 5/10 129 */ 130 sig_all_calls(uni, SIGC_LINK_ESTABLISH_confirm); 131 uni->funcs->uni_output(uni, uni->arg, 132 UNIAPI_LINK_ESTABLISH_confirm, 0, NULL); 133 break; 134 135 default: 136 ASSERT(0, ("CU_STAT*")); 137 } 138} 139 140/* 141 * SAAL-RELEASE.confirm 142 */ 143static void 144coord_saal_release_confirm(struct uni *uni) 145{ 146 switch (uni->custat) { 147 148 case CU_STAT0: 149 case CU_STAT1: 150 case CU_STAT3: 151 VERBOSE0(uni, UNI_FAC_COORD, 152 "signal saal_release.confirm in CU%u", uni->custat); 153 break; 154 155 case CU_STAT2: 156 /* 157 * Q.2931:Coord-U 5/10 158 */ 159 uni->funcs->uni_output(uni, uni->arg, 160 UNIAPI_LINK_RELEASE_confirm, 0, NULL); 161 set_custat(uni, CU_STAT0); 162 break; 163 164 default: 165 ASSERT(0, ("CU_STAT*")); 166 } 167} 168 169/* 170 * SAAL failure. 171 */ 172static void 173coord_saal_release_indication(struct uni *uni) 174{ 175 switch (uni->custat) { 176 177 case CU_STAT0: 178 case CU_STAT2: 179 VERBOSE0(uni, UNI_FAC_COORD, 180 "signal saal_release.indication in CU%u", uni->custat); 181 break; 182 183 case CU_STAT1: 184 case CU_STAT3: 185 /* 186 * Q.2931:Coord-U 4/10 187 * Q.2931:Coord-U 5/10 188 */ 189 sig_all_calls(uni, SIGC_LINK_RELEASE_indication); 190 set_custat(uni, CU_STAT0); 191 break; 192 193 default: 194 ASSERT(0, ("CU_STAT*")); 195 } 196} 197 198/* 199 * Link-establish.request from USER. This can also come from 200 * a call instance. In this case 'cookie' is zero. 201 */ 202static void 203coord_link_establish_request(struct uni *uni, uint32_t cookie) 204{ 205 switch (uni->custat) { 206 207 case CU_STAT0: 208 /* 209 * Q.2931:Coord-U 4/10 210 */ 211 uni->funcs->saal_output(uni, uni->arg, 212 SAAL_ESTABLISH_request, NULL); 213 if (!TIMER_ISACT(uni, t309)) 214 TIMER_START_UNI(uni, t309, uni->timer309); 215 set_custat(uni, CU_STAT1); 216 if (cookie) 217 uniapi_uni_error(uni, UNIAPI_OK, cookie, 0); 218 break; 219 220 case CU_STAT1: 221 /* 222 * Q.2931:Coord-U 4/10 223 * This is probably missing from the delay field. 224 */ 225 uni_delenq_coord(uni, SIGO_LINK_ESTABLISH_request, 226 cookie, NULL); 227 break; 228 229 case CU_STAT2: 230 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALLSTATE, cookie, 0); 231 if (cookie == 0) 232 VERBOSE0(uni, UNI_FAC_COORD, 233 "signal link-establish.request in CU%u", 234 uni->custat); 235 break; 236 237 case CU_STAT3: 238 /* 239 * Q.2931:Coord-U 5/10 240 */ 241 uni->funcs->uni_output(uni, uni->arg, 242 UNIAPI_LINK_ESTABLISH_confirm, 0, NULL); 243 uniapi_uni_error(uni, UNIAPI_OK, cookie, 0); 244 break; 245 246 default: 247 ASSERT(0, ("CU_STAT*")); 248 } 249} 250 251/* 252 * Link-release.request from user 253 */ 254static void 255coord_link_release_request(struct uni *uni, u_int cookie) 256{ 257 switch (uni->custat) { 258 259 case CU_STAT0: 260 case CU_STAT1: 261 case CU_STAT2: 262 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALLSTATE, cookie, 0); 263 break; 264 265 case CU_STAT3: 266 /* 267 * Q.2931:Coord-U 5/10 268 */ 269 uni->funcs->saal_output(uni, uni->arg, 270 SAAL_RELEASE_request, NULL); 271 set_custat(uni, CU_STAT2); 272 uniapi_uni_error(uni, UNIAPI_OK, cookie, 0); 273 break; 274 275 default: 276 ASSERT(0, ("CU_STAT*")); 277 } 278} 279 280/* 281 * T309 timeout signal 282 */ 283static void 284coord_t309(struct uni *uni) 285{ 286 switch (uni->custat) { 287 288 case CU_STAT0: 289 case CU_STAT1: 290 /* 291 * Q.2931:Coord-U 4/10 292 */ 293 sig_all_calls(uni, SIGC_LINK_ESTABLISH_ERROR_indication); 294 set_custat(uni, CU_STAT0); 295 /* this is not in the SDLs, but how will the call control 296 * know, that starting the LINK has failed otherwise? */ 297 uni->funcs->uni_output(uni, uni->arg, 298 UNIAPI_LINK_RELEASE_confirm, 0, NULL); 299 break; 300 301 case CU_STAT2: 302 case CU_STAT3: 303 VERBOSE0(uni, UNI_FAC_COORD, 304 "signal T309 in CU%u", uni->custat); 305 break; 306 307 default: 308 ASSERT(0, ("CU_STAT*")); 309 } 310} 311 312/* 313 * Message from SAAL 314 */ 315static void 316coord_saal_data_indication(struct uni *uni, struct uni_msg *m) 317{ 318 struct uni_all *u; 319 struct call *c; 320 321 memset(&uni->cause, 0, sizeof(uni->cause)); 322 if ((u = UNI_ALLOC()) == NULL) { 323 uni_msg_destroy(m); 324 return; 325 } 326 if (uni_decode_head(m, u, &uni->cx)) { 327 VERBOSE(uni, UNI_FAC_COORD, 2, "bogus message - ignored"); 328 uni_msg_destroy(m); 329 UNI_FREE(u); 330 return; 331 } 332 if (u->u.hdr.cref.cref == CREF_DUMMY) { 333 if (uni->cx.q2932) { 334 input_dummy(uni, m, u); 335 } else { 336 VERBOSE(uni, UNI_FAC_COORD, 2, "dummy cref - ignored"); 337 UNI_FREE(u); 338 uni_msg_destroy(m); 339 } 340 return; 341 } 342 343 if (u->u.hdr.cref.cref == CREF_GLOBAL) 344 input_global(uni, m, u); 345 else if ((c = uni_find_call(uni, &u->u.hdr.cref)) == NULL) 346 input_unknown(uni, m, u); 347 else if (c->type == CALL_COBI) 348 input_cobi(c, m, u); 349 else 350 input_call(c, m, u); 351} 352 353/* 354 * Message with global call reference 355 * 356 * Q.2931:Coord-U (X) 7/10 357 */ 358static void 359input_global(struct uni *uni, struct uni_msg *m, struct uni_all *u) 360{ 361 VERBOSE(uni, UNI_FAC_COORD, 2, "GLOB MTYPE = %x", u->mtype); 362 363 switch (u->mtype) { 364 365 default: 366 /* 367 * Q.2931:Coord-U 7/10 368 * Q.2931: 5.6.3.2e 369 * Amd4: 29e 370 */ 371 uni_respond_status(uni, &u->u.hdr.cref, 372 u->u.hdr.cref.flag ? uni->glob_start : uni->glob_respond, 373 UNI_CAUSE_CREF_INV); 374 break; 375 376 case UNI_RESTART: 377 if (u->u.hdr.cref.flag) { 378 /* 379 * Q.2931:Coord-U 7/10 (5.6.3.2h) 380 */ 381 uni_respond_status(uni, &u->u.hdr.cref, 382 uni->glob_start, UNI_CAUSE_CREF_INV); 383 break; 384 } 385 uni_enq_resp(uni, SIGR_RESTART, 0, m, u); 386 return; 387 388 case UNI_RESTART_ACK: 389 if (!u->u.hdr.cref.flag) { 390 /* 391 * Q.2931:Coord-U 7/10 (5.6.3.2h) 392 * Note, that the SDL diagram contains an error. 393 * The error with the 'YES' label should go to the 394 * box below 'OTHER'. 395 */ 396 uni_respond_status(uni, &u->u.hdr.cref, 397 uni->glob_respond, UNI_CAUSE_CREF_INV); 398 break; 399 } 400 uni_enq_start(uni, SIGS_RESTART_ACK, 0, m, u); 401 return; 402 403 case UNI_STATUS: 404 if (u->u.hdr.cref.flag) 405 uni_enq_start(uni, SIGS_STATUS, 0, m, u); 406 else 407 uni_enq_resp(uni, SIGR_STATUS, 0, m, u); 408 return; 409 } 410 uni_msg_destroy(m); 411 UNI_FREE(u); 412} 413 414/* 415 * Q.2931:Coord-U 8/10 416 * 417 * Message for an unknown call reference 418 */ 419static void 420input_unknown(struct uni *uni, struct uni_msg *m, struct uni_all *u) 421{ 422 struct uni_all *resp; 423 struct call *c; 424 u_int cause = UNI_CAUSE_CREF_INV; 425 426 VERBOSE(uni, UNI_FAC_COORD, 2, "UNKNOWN MTYPE = %x", u->mtype); 427 428 switch (u->mtype) { 429 430 default: 431 /* 432 * This message type is entirly unknown 433 * 434 * 5.6.4 and 5.7.1 are only when the call is not in the 435 * NULL state. This means, 5.6.3.2a takes over. 436 */ 437 break; 438 439 case UNI_SETUP: 440 if (u->u.hdr.cref.flag) 441 /* 442 * 5.6.3.2c 443 */ 444 goto drop; 445 if ((c = uni_create_call(uni, u->u.hdr.cref.cref, 0, 0)) != NULL) { 446 uni_enq_call(c, SIGC_SETUP, 0, m, u); 447 return; 448 } 449 goto drop; 450 451 case UNI_RELEASE_COMPL: 452 /* 453 * 5.6.3.2c 454 */ 455 goto drop; 456 457 case UNI_STATUS: 458 /* 459 * 5.6.12 460 * 461 * The SDLs don't use the verify procedure and don't 462 * handle the case of an invalid callstate - we 463 * ignore the message, if the callstate is not good. 464 */ 465 (void)uni_decode_body(m, u, &uni->cx); 466 if (!IE_ISGOOD(u->u.status.callstate)) 467 goto drop; 468 if (u->u.status.callstate.state == UNI_CALLSTATE_U0) 469 goto drop; 470 cause = UNI_CAUSE_MSG_INCOMP; 471 break; 472 473 case UNI_STATUS_ENQ: 474 if ((resp = UNI_ALLOC()) == NULL) 475 goto drop; 476 477 (void)uni_decode_body(m, u, &uni->cx); 478 MK_MSG_RESP(resp, UNI_STATUS, &u->u.hdr.cref); 479 MK_IE_CALLSTATE(resp->u.status.callstate, UNI_CALLSTATE_U0); 480 MK_IE_CAUSE(resp->u.status.cause, UNI_CAUSE_LOC_USER, 481 UNI_CAUSE_STATUS); 482 483 if (IE_ISGOOD(u->u.status_enq.epref)) { 484 /* reflect epref as required by L3MU_PO */ 485 resp->u.status.epref = u->u.status_enq.epref; 486 MK_IE_EPREF(resp->u.status.epref, 487 u->u.status_enq.epref.epref, 488 !u->u.status_enq.epref.flag); 489 MK_IE_EPSTATE(resp->u.status.epstate, UNI_EPSTATE_NULL); 490 } 491 492 (void)uni_send_output(resp, uni); 493 494 UNI_FREE(resp); 495 goto drop; 496 497 case UNI_COBISETUP: 498 if (u->u.hdr.cref.flag) 499 /* 500 * 5.6.3.2c (probably) 501 */ 502 goto drop; 503 if ((c = uni_create_call(uni, u->u.hdr.cref.cref, 0, 0)) != NULL) { 504 uni_enq_call(c, SIGC_COBISETUP, 0, m, u); 505 return; 506 } 507 goto drop; 508 } 509 510 /* 511 * 5.6.3.2a) 512 * 513 * Respond with a RELEASE COMPLETE 514 */ 515 if ((resp = UNI_ALLOC()) == NULL) 516 goto drop; 517 518 MK_MSG_RESP(resp, UNI_RELEASE_COMPL, &u->u.hdr.cref); 519 MK_IE_CAUSE(resp->u.release_compl.cause[0], UNI_CAUSE_LOC_USER, cause); 520 if (uni_diag(cause, UNI_CODING_ITU) == UNI_DIAG_MTYPE) 521 ADD_CAUSE_MTYPE(resp->u.release_compl.cause[0], u->mtype); 522 523 (void)uni_send_output(resp, uni); 524 525 UNI_FREE(resp); 526 527 drop: 528 UNI_FREE(u); 529 uni_msg_destroy(m); 530} 531 532static void 533input_cobi(struct call *c __unused, struct uni_msg *m, struct uni_all *u) 534{ 535 /* XXX */ 536 UNI_FREE(u); 537 uni_msg_destroy(m); 538} 539 540static void 541input_dummy(struct uni *uni __unused, struct uni_msg *m, struct uni_all *u) 542{ 543 /* XXX */ 544 UNI_FREE(u); 545 uni_msg_destroy(m); 546} 547 548static void 549input_call(struct call *c, struct uni_msg *m, struct uni_all *u) 550{ 551 VERBOSE(c->uni, UNI_FAC_COORD, 2, "CALL MTYPE = %x %d/%s", 552 u->mtype, c->cref, c->mine ? "mine":"his"); 553 554 switch (u->mtype) { 555 556 case UNI_SETUP: 557 /* 558 * Ignored 559 */ 560 break; 561 562 case UNI_CALL_PROC: 563 uni_enq_call(c, SIGC_CALL_PROC, 0, m, u); 564 return; 565 566 case UNI_ALERTING: 567 uni_enq_call(c, SIGC_ALERTING, 0, m, u); 568 return; 569 570 case UNI_RELEASE: 571 uni_enq_call(c, SIGC_RELEASE, 0, m, u); 572 return; 573 574 case UNI_RELEASE_COMPL: 575 uni_enq_call(c, SIGC_RELEASE_COMPL, 0, m, u); 576 return; 577 578 case UNI_CONNECT: 579 uni_enq_call(c, SIGC_CONNECT, 0, m, u); 580 return; 581 582 case UNI_CONNECT_ACK: 583 uni_enq_call(c, SIGC_CONNECT_ACK, 0, m, u); 584 return; 585 586 case UNI_NOTIFY: 587 uni_enq_call(c, SIGC_NOTIFY, 0, m, u); 588 return; 589 590 case UNI_STATUS: 591 uni_enq_call(c, SIGC_STATUS, 0, m, u); 592 return; 593 594 case UNI_STATUS_ENQ: 595 uni_enq_call(c, SIGC_STATUS_ENQ, 0, m, u); 596 return; 597 598 case UNI_ADD_PARTY: 599 uni_enq_call(c, SIGC_ADD_PARTY, 0, m, u); 600 return; 601 602 case UNI_PARTY_ALERTING: 603 uni_enq_call(c, SIGC_PARTY_ALERTING, 0, m, u); 604 return; 605 606 case UNI_ADD_PARTY_ACK: 607 uni_enq_call(c, SIGC_ADD_PARTY_ACK, 0, m, u); 608 return; 609 610 case UNI_ADD_PARTY_REJ: 611 uni_enq_call(c, SIGC_ADD_PARTY_REJ, 0, m, u); 612 return; 613 614 case UNI_DROP_PARTY: 615 uni_enq_call(c, SIGC_DROP_PARTY, 0, m, u); 616 return; 617 618 case UNI_DROP_PARTY_ACK: 619 uni_enq_call(c, SIGC_DROP_PARTY_ACK, 0, m, u); 620 return; 621 622 default: 623 uni_enq_call(c, SIGC_UNKNOWN, 0, m, u); 624 return; 625 } 626 UNI_FREE(u); 627 uni_msg_destroy(m); 628} 629 630 631/* 632 * This macro tries to implement the delaying behaviour for 633 * message from the API when we are in the Awaiting-Establish state. 634 * In this state, the message is delayed. If we drop back to CU 0, 635 * everything gets unqueued and errors are returned for all that stuff. 636 * If we progess to CUSTAT2 we process the requests. 637 */ 638#define COMMON_DELAY(SIG, COOKIE) \ 639 if (uni->custat == CU_STAT0 || uni->custat == CU_STAT2) {\ 640 uniapi_uni_error(uni, UNIAPI_ERROR_BADCU, \ 641 COOKIE, 0); \ 642 break; \ 643 } \ 644 if (uni->custat == CU_STAT1) { \ 645 uni_delenq_coord(uni, SIG, COOKIE, msg); \ 646 break; \ 647 } 648 649/* 650 * Signal handler of the coordinator 651 */ 652void 653uni_sig_coord(struct uni *uni, enum coord_sig sig, uint32_t cookie, 654 struct uni_msg *msg) 655{ 656 struct call *c; 657 658 if (sig >= SIGO_END) { 659 VERBOSE(uni, UNI_FAC_ERR, 1, "Signal %d outside of range to " 660 "Coord", sig); 661 if (msg) 662 uni_msg_destroy(msg); 663 return; 664 } 665 666 VERBOSE(uni, UNI_FAC_COORD, 1, "Signal %s in state %s", 667 coord_sigs[sig], cunames[uni->custat]); 668 669 switch (sig) { 670 671 case SIGO_END: 672 break; 673 674 case SIGO_DATA: /* delayed output */ 675 if (uni->custat == CU_STAT0 || uni->custat == CU_STAT1) 676 break; /* drop */ 677 if (uni->custat == CU_STAT1) 678 uni_delenq_coord(uni, SIGO_DATA, cookie, msg);/* ??? */ 679 else 680 uni->funcs->saal_output(uni, uni->arg, 681 SAAL_DATA_request, msg); 682 msg = NULL; 683 break; 684 685 /* 686 * SAAL signals 687 */ 688 case SIGO_SAAL_ESTABLISH_indication: 689 coord_saal_establish_indication(uni); 690 break; 691 692 case SIGO_SAAL_ESTABLISH_confirm: 693 coord_saal_establish_confirm(uni); 694 break; 695 696 case SIGO_SAAL_RELEASE_confirm: 697 coord_saal_release_confirm(uni); 698 break; 699 700 case SIGO_SAAL_RELEASE_indication: 701 coord_saal_release_indication(uni); 702 break; 703 704 case SIGO_SAAL_DATA_indication: 705 coord_saal_data_indication(uni, msg); 706 msg = NULL; 707 break; 708 709 case SIGO_SAAL_UDATA_indication: 710 VERBOSE0(uni, UNI_FAC_ERR, "SAAL_UDATA_indication"); 711 break; 712 713 /* 714 * Signals from USER 715 */ 716 case SIGO_LINK_ESTABLISH_request: 717 coord_link_establish_request(uni, cookie); 718 break; 719 720 case SIGO_LINK_RELEASE_request: 721 coord_link_release_request(uni, cookie); 722 break; 723 724 case SIGO_RESET_request: 725 uni_enq_start(uni, SIGS_RESET_request, cookie, msg, NULL); 726 msg = NULL; 727 if (uni->custat == CU_STAT0) { 728 uni->funcs->saal_output(uni, uni->arg, 729 SAAL_ESTABLISH_request, NULL); 730 if (!TIMER_ISACT(uni, t309)) 731 TIMER_START_UNI(uni, t309, uni->timer309); 732 set_custat(uni, CU_STAT1); 733 } 734 break; 735 736 case SIGO_RESET_ERROR_response: 737 COMMON_DELAY(SIGO_RESET_ERROR_response, cookie); 738 uni_enq_resp(uni, SIGR_RESET_ERROR_response, cookie, msg, NULL); 739 msg = NULL; 740 break; 741 742 case SIGO_RESET_response: 743 COMMON_DELAY(SIGO_RESET_response, cookie); 744 uni_enq_resp(uni, SIGR_RESET_response, cookie, msg, NULL); 745 msg = NULL; 746 break; 747 748 case SIGO_SETUP_request: 749 if ((c = uni_create_new_call(uni, cookie)) != NULL) { 750 uni_enq_call(c, SIGC_SETUP_request, cookie, msg, NULL); 751 msg = NULL; 752 if (uni->custat == CU_STAT0) { 753 uni->funcs->saal_output(uni, uni->arg, 754 SAAL_ESTABLISH_request, NULL); 755 if (!TIMER_ISACT(uni, t309)) 756 TIMER_START_UNI(uni, t309, uni->timer309); 757 set_custat(uni, CU_STAT1); 758 } 759 } else { 760 uniapi_uni_error(uni, UNIAPI_ERROR_NOMEM, cookie, 761 UNI_CALLSTATE_U0); 762 } 763 break; 764 765 case SIGO_PROCEEDING_request: 766 { 767 struct uniapi_proceeding_request *arg = 768 uni_msg_rptr(msg, struct uniapi_proceeding_request *); 769 770 COMMON_DELAY(SIGO_PROCEEDING_request, cookie); 771 if ((c = uni_find_call(uni, &arg->call_proc.hdr.cref)) != NULL) { 772 uni_enq_call(c, SIGC_PROCEEDING_request, cookie, msg, NULL); 773 msg = NULL; 774 } else { 775 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie, 776 UNI_CALLSTATE_U0); 777 } 778 break; 779 } 780 781 case SIGO_ALERTING_request: 782 { 783 struct uniapi_alerting_request *arg = 784 uni_msg_rptr(msg, struct uniapi_alerting_request *); 785 786 COMMON_DELAY(SIGO_ALERTING_request, cookie); 787 if ((c = uni_find_call(uni, &arg->alerting.hdr.cref)) != NULL) { 788 uni_enq_call(c, SIGC_ALERTING_request, cookie, msg, NULL); 789 msg = NULL; 790 } else { 791 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie, 792 UNI_CALLSTATE_U0); 793 } 794 break; 795 } 796 797 case SIGO_SETUP_response: 798 { 799 struct uniapi_setup_response *arg = 800 uni_msg_rptr(msg, struct uniapi_setup_response *); 801 802 COMMON_DELAY(SIGO_SETUP_response, cookie); 803 if ((c = uni_find_call(uni, &arg->connect.hdr.cref)) != NULL) { 804 uni_enq_call(c, SIGC_SETUP_response, cookie, msg, NULL); 805 msg = NULL; 806 } else { 807 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie, 808 UNI_CALLSTATE_U0); 809 } 810 break; 811 } 812 813 case SIGO_SETUP_COMPLETE_request: 814 { 815 struct uniapi_setup_complete_request *arg = 816 uni_msg_rptr(msg, struct uniapi_setup_complete_request *); 817 818 COMMON_DELAY(SIGO_SETUP_COMPLETE_request, cookie); 819 if ((c = uni_find_call(uni, &arg->connect_ack.hdr.cref)) != NULL) { 820 uni_enq_call(c, SIGC_SETUP_COMPLETE_request, 821 cookie, msg, NULL); 822 msg = NULL; 823 } else { 824 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie, 825 UNI_CALLSTATE_U0); 826 } 827 break; 828 } 829 830 case SIGO_RELEASE_request: 831 { 832 struct uniapi_release_request *arg = 833 uni_msg_rptr(msg, struct uniapi_release_request *); 834 835 COMMON_DELAY(SIGO_RELEASE_request, cookie); 836 if ((c = uni_find_call(uni, &arg->release.hdr.cref)) != NULL) { 837 uni_enq_call(c, SIGC_RELEASE_request, cookie, msg, NULL); 838 msg = NULL; 839 } else { 840 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie, 841 UNI_CALLSTATE_U0); 842 } 843 break; 844 } 845 846 case SIGO_RELEASE_response: 847 { 848 struct uniapi_release_response *arg = 849 uni_msg_rptr(msg, struct uniapi_release_response *); 850 851 COMMON_DELAY(SIGO_RELEASE_response, cookie); 852 if ((c = uni_find_call(uni, &arg->release_compl.hdr.cref)) != NULL) { 853 uni_enq_call(c, SIGC_RELEASE_response, cookie, msg, NULL); 854 msg = NULL; 855 } else { 856 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie, 857 UNI_CALLSTATE_U0); 858 } 859 break; 860 } 861 862 case SIGO_NOTIFY_request: 863 { 864 struct uniapi_notify_request *arg = 865 uni_msg_rptr(msg, struct uniapi_notify_request *); 866 867 COMMON_DELAY(SIGO_NOTIFY_request, cookie); 868 if ((c = uni_find_call(uni, &arg->notify.hdr.cref)) != NULL) { 869 uni_enq_call(c, SIGC_NOTIFY_request, cookie, msg, NULL); 870 msg = NULL; 871 } else { 872 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie, 873 UNI_CALLSTATE_U0); 874 } 875 break; 876 } 877 878 case SIGO_STATUS_ENQUIRY_request: 879 { 880 struct uniapi_status_enquiry_request *arg = 881 uni_msg_rptr(msg, struct uniapi_status_enquiry_request *); 882 883 COMMON_DELAY(SIGO_STATUS_ENQUIRY_request, cookie); 884 if ((c = uni_find_call(uni, &arg->cref)) != NULL) { 885 uni_enq_call(c, SIGC_STATUS_ENQUIRY_request, cookie, msg, NULL); 886 msg = NULL; 887 } else { 888 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie, 889 UNI_CALLSTATE_U0); 890 } 891 break; 892 } 893 894 case SIGO_ADD_PARTY_request: 895 { 896 struct uniapi_add_party_request *arg = 897 uni_msg_rptr(msg, struct uniapi_add_party_request *); 898 899 COMMON_DELAY(SIGO_ADD_PARTY_request, cookie); 900 if ((c = uni_find_call(uni, &arg->add.hdr.cref)) != NULL) { 901 if (c->type != CALL_ROOT) { 902 uniapi_call_error(c, UNIAPI_ERROR_BAD_CTYPE, 903 cookie); 904 break; 905 } 906 uni_enq_call(c, SIGC_ADD_PARTY_request, cookie, msg, NULL); 907 msg = NULL; 908 } else { 909 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie, 910 UNI_CALLSTATE_U0); 911 } 912 break; 913 } 914 915 case SIGO_PARTY_ALERTING_request: 916 { 917 struct uniapi_party_alerting_request *arg = 918 uni_msg_rptr(msg, struct uniapi_party_alerting_request *); 919 920 COMMON_DELAY(SIGO_PARTY_ALERTING_request, cookie); 921 if ((c = uni_find_call(uni, &arg->alert.hdr.cref)) != NULL) { 922 if (c->type != CALL_LEAF) { 923 uniapi_call_error(c, UNIAPI_ERROR_BAD_CTYPE, 924 cookie); 925 break; 926 } 927 uni_enq_call(c, SIGC_PARTY_ALERTING_request, cookie, msg, NULL); 928 msg = NULL; 929 } else { 930 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie, 931 UNI_CALLSTATE_U0); 932 } 933 break; 934 } 935 936 case SIGO_ADD_PARTY_ACK_request: 937 { 938 struct uniapi_add_party_ack_request *arg = 939 uni_msg_rptr(msg, struct uniapi_add_party_ack_request *); 940 941 COMMON_DELAY(SIGO_ADD_PARTY_ACK_request, cookie); 942 if ((c = uni_find_call(uni, &arg->ack.hdr.cref)) != NULL) { 943 if (c->type != CALL_LEAF) { 944 uniapi_call_error(c, UNIAPI_ERROR_BAD_CTYPE, 945 cookie); 946 break; 947 } 948 uni_enq_call(c, SIGC_ADD_PARTY_ACK_request, cookie, msg, NULL); 949 msg = NULL; 950 } else { 951 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie, 952 UNI_CALLSTATE_U0); 953 } 954 break; 955 } 956 957 case SIGO_ADD_PARTY_REJ_request: 958 { 959 struct uniapi_add_party_rej_request *arg = 960 uni_msg_rptr(msg, struct uniapi_add_party_rej_request *); 961 962 COMMON_DELAY(SIGO_ADD_PARTY_REJ_request, cookie); 963 if ((c = uni_find_call(uni, &arg->rej.hdr.cref)) != NULL) { 964 if (c->type != CALL_LEAF) { 965 uniapi_call_error(c, UNIAPI_ERROR_BAD_CTYPE, 966 cookie); 967 break; 968 } 969 uni_enq_call(c, SIGC_ADD_PARTY_REJ_request, cookie, msg, NULL); 970 msg = NULL; 971 } else { 972 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie, 973 UNI_CALLSTATE_U0); 974 } 975 break; 976 } 977 978 case SIGO_DROP_PARTY_request: 979 { 980 struct uniapi_drop_party_request *arg = 981 uni_msg_rptr(msg, struct uniapi_drop_party_request *); 982 983 COMMON_DELAY(SIGO_DROP_PARTY_request, cookie); 984 if ((c = uni_find_call(uni, &arg->drop.hdr.cref)) != NULL) { 985 if (c->type != CALL_ROOT && c->type != CALL_LEAF) { 986 uniapi_call_error(c, UNIAPI_ERROR_BAD_CTYPE, 987 cookie); 988 break; 989 } 990 uni_enq_call(c, SIGC_DROP_PARTY_request, cookie, msg, NULL); 991 msg = NULL; 992 } else { 993 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie, 994 UNI_CALLSTATE_U0); 995 } 996 break; 997 } 998 999 case SIGO_DROP_PARTY_ACK_request: 1000 { 1001 struct uniapi_drop_party_ack_request *arg = 1002 uni_msg_rptr(msg, struct uniapi_drop_party_ack_request *); 1003 1004 COMMON_DELAY(SIGO_DROP_PARTY_ACK_request, cookie); 1005 if ((c = uni_find_call(uni, &arg->ack.hdr.cref)) != NULL) { 1006 if (c->type != CALL_ROOT && c->type != CALL_LEAF) { 1007 uniapi_call_error(c, UNIAPI_ERROR_BAD_CTYPE, 1008 cookie); 1009 break; 1010 } 1011 uni_enq_call(c, SIGC_DROP_PARTY_ACK_request, cookie, msg, NULL); 1012 msg = NULL; 1013 } else { 1014 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie, 1015 UNI_CALLSTATE_U0); 1016 } 1017 break; 1018 } 1019 1020 case SIGO_ABORT_CALL_request: 1021 { 1022 struct uniapi_abort_call_request *arg = 1023 uni_msg_rptr(msg, struct uniapi_abort_call_request *); 1024 1025 if ((c = uni_find_call(uni, &arg->cref)) != NULL) { 1026 uni_enq_call(c, SIGC_ABORT_CALL_request, cookie, NULL, NULL); 1027 } else { 1028 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie, 1029 UNI_CALLSTATE_U0); 1030 } 1031 break; 1032 } 1033 1034 /* 1035 * Call-Control 1036 */ 1037 case SIGO_CALL_DESTROYED: 1038 uni->funcs->uni_output(uni, uni->arg, 1039 UNIAPI_CALL_DESTROYED, 0, msg); 1040 msg = NULL; 1041 break; 1042 1043 /* 1044 * ResetRespond 1045 */ 1046 case SIGO_RESET_indication: 1047 uni->funcs->uni_output(uni, uni->arg, 1048 UNIAPI_RESET_indication, 0, msg); 1049 msg = NULL; 1050 break; 1051 1052 /* 1053 * Timeouts 1054 */ 1055 case SIGO_T309: 1056 coord_t309(uni); 1057 break; 1058 1059 } 1060 if (msg != NULL) 1061 uni_msg_destroy(msg); 1062} 1063 1064/* 1065 * Send a signal to all call instances 1066 */ 1067static void 1068sig_all_calls(struct uni *uni, u_int sig) 1069{ 1070 struct call *call; 1071 1072 TAILQ_FOREACH(call, &uni->calls, link) 1073 uni_enq_call(call, sig, 0, NULL, NULL); 1074} 1075 1076/* 1077 * Set a new coordinator state - this moves all delayed coordinator 1078 * signals from the delayed queue to the signal queue. 1079 */ 1080static int 1081cufilt(struct sig *s, void *arg __unused) 1082{ 1083 return (s->type == SIG_COORD); 1084} 1085 1086static void 1087set_custat(struct uni *uni, enum cu_stat nstate) 1088{ 1089 if (uni->custat != nstate) { 1090 uni->custat = nstate; 1091 uni_undel(uni, cufilt, NULL); 1092 } 1093} 1094 1095/* 1096 * T309 timeout function 1097 */ 1098static void 1099t309_func(struct uni *uni) 1100{ 1101 uni_enq_coord(uni, SIGO_T309, 0, NULL); 1102} 1103 1104/* 1105 * Respond with a status message 1106 */ 1107void 1108uni_respond_status(struct uni *uni, struct uni_cref *cref, 1109 enum uni_callstate cs, enum uni_cause c1) 1110{ 1111 struct uni_all *resp; 1112 1113 if ((resp = UNI_ALLOC()) == NULL) 1114 return; 1115 1116 MK_MSG_RESP(resp, UNI_STATUS, cref); 1117 MK_IE_CALLSTATE(resp->u.status.callstate, cs); 1118 MK_IE_CAUSE(resp->u.status.cause, UNI_CAUSE_LOC_USER, c1); 1119 1120 (void)uni_send_output(resp, uni); 1121 1122 UNI_FREE(resp); 1123} 1124 1125/* 1126 * Respond with a status message 1127 */ 1128void 1129uni_respond_status_mtype(struct uni *uni, struct uni_cref *cref, 1130 enum uni_callstate cs, enum uni_cause c1, u_int mtype) 1131{ 1132 struct uni_all *resp; 1133 1134 if((resp = UNI_ALLOC()) == NULL) 1135 return; 1136 1137 MK_MSG_RESP(resp, UNI_STATUS, cref); 1138 MK_IE_CALLSTATE(resp->u.status.callstate, cs); 1139 MK_IE_CAUSE(resp->u.status.cause, UNI_CAUSE_LOC_USER, c1); 1140 ADD_CAUSE_MTYPE(resp->u.status.cause, mtype); 1141 1142 (void)uni_send_output(resp, uni); 1143 1144 UNI_FREE(resp); 1145} 1146 1147/* 1148 * Send a message. If we are in CUSTAT1, delay the message if we 1149 * are in CUSTAT3 send it, else drop it. 1150 */ 1151int 1152uni_send_output(struct uni_all *u, struct uni *uni) 1153{ 1154 struct uni_msg *m; 1155 int err; 1156 1157 if (uni->custat == CU_STAT0 || uni->custat == CU_STAT2) 1158 return (0); 1159 1160 m = uni_msg_alloc(1024); 1161 if ((err = uni_encode(m, u, &uni->cx)) != 0) { 1162 VERBOSE0(uni, UNI_FAC_ERR, "uni_encode failed: %08x", err); 1163 uni_msg_destroy(m); 1164 return (-1); 1165 } 1166 if (uni->custat == CU_STAT1) 1167 uni_delenq_coord(uni, SIGO_DATA, 0, m); 1168 else 1169 uni->funcs->saal_output(uni, uni->arg, SAAL_DATA_request, m); 1170 return (0); 1171} 1172