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_party.c,v 1.18 2004/08/05 07:11:01 brandt Exp $ 30 * 31 * Party instance handling 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#include <netnatm/sig/unimsgcpy.h> 43 44static void drop_partyE(struct party *p); 45static int epstate_compat(struct party *, enum uni_epstate); 46 47#define DEF_PRIV_SIG(NAME, FROM) [SIG##NAME] = "SIG"#NAME, 48static const char *const party_sigs[] = { 49 DEF_PARTY_SIGS 50}; 51#undef DEF_PRIV_SIG 52 53TIMER_FUNC_PARTY(t397, t397_func) 54TIMER_FUNC_PARTY(t398, t398_func) 55TIMER_FUNC_PARTY(t399, t399_func) 56 57static __inline void 58set_party_state(struct party *p, enum uni_epstate state) 59{ 60 if (p->state != state) { 61 VERBOSE(p->call->uni, UNI_FAC_CALL, 1, 62 "party %u/%u %u/%u PU%u -> PU%u", 63 p->call->cref, p->call->mine, 64 p->epref, p->flags & PARTY_MINE, p->state, state); 65 p->state = state; 66 } 67} 68 69/* 70 * Create a party with a given endpoint reference. 71 * No check is done, that a party with this epref does not alreay exist. 72 */ 73struct party * 74uni_create_partyx(struct call *c, u_int epref, u_int mine, uint32_t cookie) 75{ 76 struct party *p; 77 struct uni_msg *api; 78 struct uniapi_party_created *ind; 79 80 mine = (mine ? PARTY_MINE : 0); 81 82 if ((p = PARTY_ALLOC()) == NULL) 83 return (NULL); 84 85 if ((ind = ALLOC_API(struct uniapi_party_created, api)) == NULL) { 86 PARTY_FREE(p); 87 return (NULL); 88 } 89 90 ind->cref.cref = c->cref; 91 ind->cref.flag = c->mine; 92 MK_IE_EPREF(ind->epref, epref, mine); 93 ind->epref.h.act = UNI_IEACT_DEFAULT; 94 95 p->call = c; 96 p->epref = epref; 97 p->flags = mine; 98 p->state = UNI_EPSTATE_NULL;; 99 100 TIMER_INIT_PARTY(p, t397); 101 TIMER_INIT_PARTY(p, t398); 102 TIMER_INIT_PARTY(p, t399); 103 104 TAILQ_INSERT_HEAD(&c->parties, p, link); 105 106 c->uni->funcs->uni_output(c->uni, c->uni->arg, 107 UNIAPI_PARTY_CREATED, cookie, api); 108 109 VERBOSE(c->uni, UNI_FAC_CALL, 1, "created party %u/%s %u/%s", 110 p->call->cref, p->call->mine ? "mine" : "his", 111 p->epref, (p->flags & PARTY_MINE) ? "mine" : "his"); 112 113 return (p); 114 115} 116 117struct party * 118uni_create_party(struct call *c, struct uni_ie_epref *epref) 119{ 120 return (uni_create_partyx(c, epref->epref, epref->flag, 0)); 121} 122 123struct party * 124uni_find_party(struct call *c, struct uni_ie_epref *epref) 125{ 126 struct party *p; 127 128 TAILQ_FOREACH(p, &c->parties, link) 129 if (p->epref == epref->epref && 130 (!(p->flags & PARTY_MINE) == !epref->flag)) 131 return (p); 132 return (NULL); 133} 134struct party * 135uni_find_partyx(struct call *c, u_int epref, u_int mine) 136{ 137 struct party *p; 138 139 TAILQ_FOREACH(p, &c->parties, link) 140 if (p->epref == epref && (!(p->flags & PARTY_MINE) == !mine)) 141 return (p); 142 return (NULL); 143} 144 145/* 146 * Destroy a party. 147 * This function is assumed to remove the party from the parent's call 148 * party list. 149 */ 150void 151uni_destroy_party(struct party *p, int really) 152{ 153 struct uni_msg *api; 154 struct uniapi_party_destroyed *ind; 155 156 TIMER_DESTROY_PARTY(p, t397); 157 TIMER_DESTROY_PARTY(p, t398); 158 TIMER_DESTROY_PARTY(p, t399); 159 160 TAILQ_REMOVE(&p->call->parties, p, link); 161 162 uni_delsig(p->call->uni, SIG_PARTY, p->call, p); 163 164 if (!really) { 165 ind = ALLOC_API(struct uniapi_party_destroyed, api); 166 if (ind != NULL) { 167 ind->cref.cref = p->call->cref; 168 ind->cref.flag = p->call->mine; 169 ind->epref.epref = p->epref; 170 ind->epref.flag = p->flags & PARTY_MINE; 171 ind->epref.h.act = UNI_IEACT_DEFAULT; 172 IE_SETPRESENT(ind->epref); 173 174 uni_enq_call(p->call, SIGC_PARTY_DESTROYED, 0, api, NULL); 175 } 176 177 uni_enq_party(p, SIGP_PARTY_DELETE, 0, NULL, NULL); 178 return; 179 } 180 PARTY_FREE(p); 181} 182 183/* 184 * Count number of parties in active states. 185 * If the argument is 0 only ACTIVE parties are counter 186 * If the argument is 1 only parties in establishing states are counted 187 * If the argument is 2 both are counted. 188 */ 189u_int 190uni_party_act_count(struct call *c, int kind) 191{ 192 struct party *p; 193 u_int cnt; 194 195 cnt = 0; 196 TAILQ_FOREACH(p, &c->parties, link) { 197 switch (p->state) { 198 199 case UNI_EPSTATE_ACTIVE: 200 if (kind == 0 || kind == 2) 201 cnt++; 202 break; 203 204 case UNI_EPSTATE_ALERT_RCVD: 205 case UNI_EPSTATE_ADD_INIT: 206 case UNI_EPSTATE_ALERT_DLVD: 207 case UNI_EPSTATE_ADD_RCVD: 208 if (kind == 1 || kind == 2) 209 cnt++; 210 break; 211 212 default: 213 break; 214 } 215 } 216 return (cnt); 217} 218 219static void 220stop_all_party_timers(struct party *p) 221{ 222 TIMER_STOP_PARTY(p, t397); 223 TIMER_STOP_PARTY(p, t398); 224 TIMER_STOP_PARTY(p, t399); 225} 226/************************************************************/ 227 228/* 229 * Add-party.request 230 * 231 * Q.2971:Party-control-U 3 (PU0) 232 * Q.2971:Party-control-N 3 (PN0) 233 */ 234static void 235pun0_add_party_request(struct party *p, struct uni_msg *api, uint32_t cookie) 236{ 237 struct uni_all *add; 238 struct uniapi_add_party_request *req = 239 uni_msg_rptr(api, struct uniapi_add_party_request *); 240 241 if ((add = UNI_ALLOC()) == NULL) { 242 uni_msg_destroy(api); 243 uniapi_party_error(p, UNIAPI_ERROR_NOMEM, cookie); 244 return; 245 } 246 247 add->u.add_party = req->add; 248 MK_MSG_ORIG(add, UNI_ADD_PARTY, p->call->cref, !p->call->mine); 249 uni_send_output(add, p->call->uni); 250 UNI_FREE(add); 251 252 TIMER_START_PARTY(p, t399, p->call->uni->timer399); 253 254 set_party_state(p, UNI_EPSTATE_ADD_INIT); 255 256 uni_msg_destroy(api); 257 uniapi_party_error(p, UNIAPI_OK, cookie); 258} 259 260/* 261 * Add-party-ack.request 262 * 263 * Q.2971:Party-Control-U 6 PU2 264 * Q.2971:Party-Control-U 7 PU3 265 * Q.2971:Party-Control-N 6 PN2 266 * Q.2971:Party-Control-N 7 PN3 267 */ 268static void 269punx_add_party_ack_request(struct party *p, struct uni_msg *m, uint32_t cookie) 270{ 271 struct uni_all *ack; 272 struct uniapi_add_party_ack_request *req = 273 uni_msg_rptr(m, struct uniapi_add_party_ack_request *); 274 275 if ((ack = UNI_ALLOC()) == NULL) { 276 uniapi_party_error(p, UNIAPI_ERROR_NOMEM, cookie); 277 uni_msg_destroy(m); 278 return; 279 } 280 ack->u.add_party_ack = req->ack; 281 MK_MSG_ORIG(ack, UNI_ADD_PARTY_ACK, p->call->cref, !p->call->mine); 282 uni_send_output(ack, p->call->uni); 283 UNI_FREE(ack); 284 285 set_party_state(p, UNI_EPSTATE_ACTIVE); 286 287 uni_msg_destroy(m); 288 uniapi_party_error(p, UNIAPI_OK, cookie); 289} 290 291/* 292 * Add-party-rej.request 293 * 294 * Q.2971:Party-Control-U 6 PU2 295 * Q.2971:Party-Control-N 6 PN2 296 */ 297static void 298pun2_add_party_rej_request(struct party *p, struct uni_msg *m, uint32_t cookie) 299{ 300 struct uni_all *rej; 301 struct uniapi_add_party_rej_request *req = 302 uni_msg_rptr(m, struct uniapi_add_party_rej_request *); 303 304 if ((rej = UNI_ALLOC()) == NULL) { 305 uniapi_party_error(p, UNIAPI_ERROR_NOMEM, cookie); 306 uni_msg_destroy(m); 307 return; 308 } 309 310 stop_all_party_timers(p); 311 312 rej->u.add_party_rej = req->rej; 313 MK_MSG_ORIG(rej, UNI_ADD_PARTY_REJ, p->call->cref, !p->call->mine); 314 uni_enq_call(p->call, SIGC_SEND_ADD_PARTY_REJ, cookie, NULL, rej); 315 316 uni_msg_destroy(m); 317 p->state = UNI_EPSTATE_NULL; 318 uniapi_party_error(p, UNIAPI_OK, cookie); 319 320 uni_destroy_party(p, 0); 321} 322 323/* 324 * ADD PARTY in PU0, PN0 325 * 326 * Q.2971:Party-Control-U 3/14 PU0 327 */ 328static void 329pun0_add_party(struct party *p, struct uni_msg *m, struct uni_all *u) 330{ 331 struct uniapi_add_party_indication *ind; 332 struct uni_msg *api; 333 334 ind = ALLOC_API(struct uniapi_add_party_indication, api); 335 if (ind != NULL) { 336 ind->add.hdr = u->u.hdr; 337 copy_msg_add_party(&u->u.add_party, &ind->add); 338 p->call->uni->funcs->uni_output(p->call->uni, p->call->uni->arg, 339 UNIAPI_ADD_PARTY_indication, 0, api); 340 } 341 set_party_state(p, UNI_EPSTATE_ADD_RCVD); 342 343 uni_msg_destroy(m); 344 UNI_FREE(u); 345} 346 347/* 348 * PARTY-ALERTING.request 349 * 350 * Q.2971:Party-Control-U 6 (PU2) 351 * Q.2971:Party-Control-N 6 (PN2) 352 */ 353static void 354pun2_party_alerting_request(struct party *p, struct uni_msg *api, 355 uint32_t cookie) 356{ 357 struct uni_all *alert; 358 struct uniapi_party_alerting_request *req = 359 uni_msg_rptr(api, struct uniapi_party_alerting_request *); 360 361 if ((alert = UNI_ALLOC()) == NULL) { 362 uniapi_party_error(p, UNIAPI_ERROR_NOMEM, cookie); 363 uni_msg_destroy(api); 364 return; 365 } 366 alert->u.party_alerting = req->alert; 367 MK_MSG_ORIG(alert, UNI_PARTY_ALERTING, 368 p->call->cref, !p->call->mine); 369 uni_send_output(alert, p->call->uni); 370 UNI_FREE(alert); 371 372 set_party_state(p, UNI_EPSTATE_ALERT_DLVD); 373 374 uni_msg_destroy(api); 375 uniapi_party_error(p, UNIAPI_OK, cookie); 376} 377 378/* 379 * PARTY-ALERTING in state PU1/PN1 380 * 381 * Q.2971:Party-Control-U 14 382 * Q.2971:Party-Control-N 5 383 */ 384static void 385pun1_party_alerting(struct party *p, struct uni_msg *m, struct uni_all *u) 386{ 387 struct uniapi_party_alerting_indication *ind; 388 struct uni_msg *api; 389 390 ind = ALLOC_API(struct uniapi_party_alerting_indication, api); 391 if (ind == NULL) { 392 uni_msg_destroy(m); 393 UNI_FREE(u); 394 return; 395 } 396 TIMER_STOP_PARTY(p, t399); 397 398 ind->alert.hdr = u->u.hdr; 399 copy_msg_party_alerting(&u->u.party_alerting, &ind->alert); 400 401 p->call->uni->funcs->uni_output(p->call->uni, p->call->uni->arg, 402 UNIAPI_PARTY_ALERTING_indication, 0, api); 403 404 TIMER_START_PARTY(p, t397, p->call->uni->timer397); 405 406 uni_msg_destroy(m); 407 UNI_FREE(u); 408 409 set_party_state(p, UNI_EPSTATE_ALERT_RCVD); 410} 411 412/* 413 * ADD-PARTY-ACK 414 * 415 * Q.2971:Party-Control-U 4 (PU1) 416 * Q.2971:Party-Control-U 7 (PU4) 417 * Q.2971:Party-Control-N 4 (PN1) 418 * Q.2971:Party-Control-N 7 (PN4) 419 */ 420static void 421pun1pun4_add_party_ack(struct party *p, struct uni_msg *m, struct uni_all *u) 422{ 423 struct uniapi_add_party_ack_indication *ind; 424 struct uni_msg *api; 425 426 ind = ALLOC_API(struct uniapi_add_party_ack_indication, api); 427 if (ind == NULL) { 428 uni_msg_destroy(m); 429 UNI_FREE(u); 430 return; 431 } 432 433 if (p->state == UNI_EPSTATE_ADD_INIT) 434 TIMER_STOP_PARTY(p, t399); 435 else 436 TIMER_STOP_PARTY(p, t397); 437 438 ind->ack.hdr = u->u.hdr; 439 copy_msg_add_party_ack(&u->u.add_party_ack, &ind->ack); 440 441 p->call->uni->funcs->uni_output(p->call->uni, p->call->uni->arg, 442 UNIAPI_ADD_PARTY_ACK_indication, 0, api); 443 444 uni_msg_destroy(m); 445 UNI_FREE(u); 446 447 set_party_state(p, UNI_EPSTATE_ACTIVE); 448} 449 450/* 451 * ADD-PARTY-REJECT 452 * 453 * Q.2971:Party-Control-U 4 (PU1) 454 * Q.2971:Party-Control-N 4 (PN1) 455 */ 456static void 457pun1_add_party_rej(struct party *p, struct uni_msg *m, struct uni_all *u) 458{ 459 struct uniapi_add_party_rej_indication *ind; 460 struct uni_msg *api; 461 462 ind = ALLOC_API(struct uniapi_add_party_rej_indication, api); 463 if (ind == NULL) { 464 uni_msg_destroy(m); 465 UNI_FREE(u); 466 return; 467 } 468 469 TIMER_STOP_PARTY(p, t399); 470 471 ind->rej.hdr = u->u.hdr; 472 copy_msg_add_party_rej(&u->u.add_party_rej, &ind->rej); 473 uni_enq_call(p->call, SIGC_ADD_PARTY_REJ_indication, 0, api, NULL); 474 475 uni_destroy_party(p, 0); 476 477 uni_msg_destroy(m); 478 UNI_FREE(u); 479} 480 481/* 482 * ADD-PARTY-REJECT 483 * 484 * Q.2971:Party-Control-U 10 (PU5) 485 * Q.2971:Party-Control-N 10 (PN5) 486 */ 487static void 488pun5_add_party_rej(struct party *p, struct uni_msg *m, struct uni_all *u) 489{ 490 struct uniapi_drop_party_ack_indication *ind; 491 struct uni_msg *api; 492 493 ind = ALLOC_API(struct uniapi_drop_party_ack_indication, api); 494 if (ind == NULL) { 495 uni_msg_destroy(m); 496 UNI_FREE(u); 497 return; 498 } 499 500 ind->drop.hdr = u->u.hdr; 501 COPY_FROM_ADD_REJ(u, &ind->drop); 502 if (IE_ISGOOD(u->u.add_party_rej.crankback)) 503 ind->crankback = u->u.add_party_rej.crankback; 504 uni_enq_call(p->call, SIGC_DROP_PARTY_ACK_indication, 0, api, NULL); 505 506 TIMER_STOP_PARTY(p, t398); 507 508 uni_destroy_party(p, 0); 509 510 uni_msg_destroy(m); 511 UNI_FREE(u); 512} 513 514/* 515 * DROP-PARTY-ACKNOWLEDGE 516 * 517 * Q.2971:Party-Control-U 8 518 * Q.2971:Party-Control-N 8 519 * 520 * Message already verified in Call-Control! 521 */ 522static void 523punx_drop_party_ack(struct party *p, struct uni_msg *m, struct uni_all *u) 524{ 525 struct uniapi_drop_party_ack_indication *ind; 526 struct uni_msg *api; 527 528 stop_all_party_timers(p); 529 530 ind = ALLOC_API(struct uniapi_drop_party_ack_indication, api); 531 if (ind != NULL) { 532 ind->drop.hdr = u->u.hdr; 533 COPY_FROM_DROP_ACK(u, &ind->drop); 534 uni_enq_call(p->call, SIGC_DROP_PARTY_ACK_indication, 535 0, api, NULL); 536 } 537 538 uni_destroy_party(p, 0); 539 540 uni_msg_destroy(m); 541 UNI_FREE(u); 542} 543 544/* 545 * DROP PARTY message in any state except PU5/PN5 546 * 547 * Q.2971:Party-Control-U 9 548 * Q.2971:Party-Control-N 9 549 */ 550static void 551punx_drop_party(struct party *p, struct uni_msg *m, struct uni_all *u) 552{ 553 struct uniapi_drop_party_indication *ind; 554 struct uni_msg *api; 555 556 ind = ALLOC_API(struct uniapi_drop_party_indication, api); 557 if (ind == NULL) { 558 uni_msg_destroy(m); 559 UNI_FREE(u); 560 return; 561 } 562 563 ind->drop.hdr = u->u.hdr; 564 copy_msg_drop_party(&u->u.drop_party, &ind->drop); 565 566 /* need the cause even if it is bad */ 567 if (IE_ISERROR(u->u.drop_party.cause)) 568 ind->drop.cause = u->u.drop_party.cause; 569 570 ind->my_cause = p->call->uni->cause; 571 572 uni_enq_call(p->call, SIGC_DROP_PARTY_indication, 0, api, NULL); 573 574 TIMER_STOP_PARTY(p, t397); 575 TIMER_STOP_PARTY(p, t399); 576 577 uni_msg_destroy(m); 578 UNI_FREE(u); 579 580 set_party_state(p, UNI_EPSTATE_DROP_RCVD); 581} 582 583/* 584 * DROP PARTY message in state PU5/PN5 585 * 586 * Q.2971:Party-Control-U 10 587 * Q.2971:Party-Control-N 10 588 */ 589static void 590pun5_drop_party(struct party *p, struct uni_msg *m, struct uni_all *u) 591{ 592 struct uniapi_drop_party_ack_indication *ind; 593 struct uni_msg *api; 594 595 ind = ALLOC_API(struct uniapi_drop_party_ack_indication, api); 596 if (ind == NULL) { 597 uni_msg_destroy(m); 598 UNI_FREE(u); 599 return; 600 } 601 602 ind->drop.hdr = u->u.hdr; 603 copy_msg_drop_party(&u->u.drop_party, &ind->drop); 604 605 /* need the cause even if it is bad */ 606 if (IE_ISERROR(u->u.drop_party.cause)) 607 ind->drop.cause = u->u.drop_party.cause; 608 609 uni_enq_call(p->call, SIGC_DROP_PARTY_ACK_indication, 0, api, NULL); 610 611 TIMER_STOP_PARTY(p, t398); 612 613 uni_msg_destroy(m); 614 UNI_FREE(u); 615 616 set_party_state(p, UNI_EPSTATE_DROP_RCVD); 617 618 uni_destroy_party(p, 0); 619} 620 621/************************************************************/ 622 623/* 624 * T399 625 * 626 * Q.2971:Party-Control-U 4 (PU1) 627 * Q.2971:Party-Control-N 4 (PN1) 628 */ 629static void 630pun1_t399(struct party *p) 631{ 632 if (p->call->uni->proto == UNIPROTO_UNI40N) { 633 MK_IE_CAUSE(p->call->uni->cause, UNI_CAUSE_LOC_USER, 634 UNI_CAUSE_NO_RESPONSE); 635 } else { 636 MK_IE_CAUSE(p->call->uni->cause, UNI_CAUSE_LOC_USER, 637 UNI_CAUSE_RECOVER); 638 ADD_CAUSE_TIMER(p->call->uni->cause, "399"); 639 } 640 641 drop_partyE(p); 642} 643 644/* 645 * T398 646 * 647 * Q.2971:Party-Control-U 10 (PU5) 648 * Q.2971:Party-Control-N 10 (PN5) 649 */ 650static void 651pun5_t398(struct party *p) 652{ 653 struct uniapi_drop_party_ack_indication *ind; 654 struct uni_all *drop; 655 struct uni_msg *api; 656 657 MK_IE_CAUSE(p->call->uni->cause, 658 UNI_CAUSE_LOC_USER, UNI_CAUSE_RECOVER); 659 ADD_CAUSE_TIMER(p->call->uni->cause, "398"); 660 /* 661 * Send indication to API 662 */ 663 ind = ALLOC_API(struct uniapi_drop_party_ack_indication, api); 664 if (ind != NULL) { 665 ind->drop.hdr.cref.cref = p->call->cref; 666 ind->drop.hdr.cref.flag = p->call->mine; 667 ind->drop.hdr.act = UNI_MSGACT_DEFAULT; 668 MK_IE_EPREF(ind->drop.epref, p->epref, p->flags & PARTY_MINE); 669 ind->drop.cause = p->call->uni->cause; 670 uni_enq_call(p->call, SIGC_DROP_PARTY_ACK_indication, 671 0, api, NULL); 672 } 673 674 /* 675 * Send DROP PARTY ACK 676 */ 677 if ((drop = UNI_ALLOC()) != NULL) { 678 MK_MSG_ORIG(drop, UNI_DROP_PARTY_ACK, 679 p->call->cref, !p->call->mine); 680 MK_IE_EPREF(drop->u.drop_party_ack.epref, 681 p->epref, !(p->flags & PARTY_MINE)); 682 drop->u.drop_party_ack.cause = p->call->uni->cause; 683 uni_enq_call(p->call, SIGC_SEND_DROP_PARTY_ACK, 0, NULL, drop); 684 } 685 686 uni_destroy_party(p, 0); 687} 688 689/* 690 * T397 691 * 692 * Q.2971:Party-Control-U 7 (PU4) 693 * Q.2971:Party-Control-N 7 (PN4) 694 */ 695static void 696pun4_t397(struct party *p) 697{ 698 MK_IE_CAUSE(p->call->uni->cause, UNI_CAUSE_LOC_USER, 699 UNI_CAUSE_RECOVER); 700 ADD_CAUSE_TIMER(p->call->uni->cause, "397"); 701 702 drop_partyE(p); 703} 704 705/************************************************************/ 706 707/* 708 * Drop a party because of an error condition. 709 * This is label E on page Party-Control-U 8/14. 710 * 711 * It is assumed, that the caller has constructed the cause in 712 * p->call->uni->cause. 713 */ 714static void 715drop_partyE(struct party *p) 716{ 717 struct uni_msg *api; 718 struct uniapi_drop_party_indication *ind; 719 struct uni_all *drop; 720 721 /* 722 * Send indication to API 723 */ 724 if ((ind = ALLOC_API(struct uniapi_drop_party_indication, api)) != NULL) { 725 ind->drop.hdr.cref.cref = p->call->cref; 726 ind->drop.hdr.cref.flag = p->call->mine; 727 ind->drop.hdr.act = UNI_MSGACT_DEFAULT; 728 MK_IE_EPREF(ind->drop.epref, p->epref, p->flags & PARTY_MINE); 729 ind->drop.cause = p->call->uni->cause; 730 uni_enq_call(p->call, SIGC_DROP_PARTY_indication, 0, api, NULL); 731 } 732 TIMER_STOP_PARTY(p, t399); 733 TIMER_STOP_PARTY(p, t397); 734 TIMER_START_PARTY(p, t398, p->call->uni->timer398); 735 736 if ((drop = UNI_ALLOC()) != NULL) { 737 drop->u.drop_party.cause = p->call->uni->cause; 738 MK_MSG_ORIG(drop, UNI_DROP_PARTY, p->call->cref, !p->call->mine); 739 MK_IE_EPREF(drop->u.drop_party.epref, p->epref, 740 !(p->flags & PARTY_MINE)); 741 uni_enq_call(p->call, SIGC_SEND_DROP_PARTY, 0, NULL, drop); 742 } 743 744 set_party_state(p, UNI_EPSTATE_DROP_INIT); 745} 746 747/* 748 * Drop party request in Px1, Px3, Px4 or Px7 749 * 750 * Q.2971:Party-Control-U 8 751 * Q.2971:Party-Control-N 8 752 */ 753static void 754punx_drop_party_request(struct party *p, struct uni_msg *api, uint32_t cookie) 755{ 756 struct uniapi_drop_party_request *req = 757 uni_msg_rptr(api, struct uniapi_drop_party_request *); 758 struct uni_all *drop; 759 760 if ((drop = UNI_ALLOC()) == NULL) { 761 uniapi_party_error(p, UNIAPI_ERROR_NOMEM, cookie); 762 uni_msg_destroy(api); 763 return; 764 } 765 766 TIMER_STOP_PARTY(p, t399); 767 TIMER_STOP_PARTY(p, t397); 768 TIMER_START_PARTY(p, t398, p->call->uni->timer398); 769 770 drop->u.drop_party = req->drop; 771 MK_MSG_ORIG(drop, UNI_DROP_PARTY, p->call->cref, !p->call->mine); 772 uni_enq_call(p->call, SIGC_SEND_DROP_PARTY, cookie, NULL, drop); 773 774 set_party_state(p, UNI_EPSTATE_DROP_INIT); 775 776 uni_msg_destroy(api); 777 uniapi_party_error(p, UNIAPI_OK, cookie); 778} 779 780/* 781 * Drop-party-ack.request in Px6 782 * 783 * Q.2971:Party-Control-U 9 784 * Q.2971:Party-Control-N 9 785 */ 786static void 787pun6_drop_party_ack_request(struct party *p, struct uni_msg *api, uint32_t cookie) 788{ 789 struct uniapi_drop_party_ack_request *req = 790 uni_msg_rptr(api, struct uniapi_drop_party_ack_request *); 791 struct uni_all *ack; 792 793 if ((ack = UNI_ALLOC()) == NULL) { 794 uni_msg_destroy(api); 795 uniapi_party_error(p, UNIAPI_ERROR_NOMEM, cookie); 796 return; 797 } 798 ack->u.drop_party_ack = req->ack; 799 MK_MSG_ORIG(ack, UNI_DROP_PARTY_ACK, p->call->cref, !p->call->mine); 800 uni_enq_call(p->call, SIGC_SEND_DROP_PARTY_ACK, cookie, NULL, ack); 801 802 stop_all_party_timers(p); 803 804 uni_msg_destroy(api); 805 uniapi_party_error(p, UNIAPI_OK, cookie); 806 807 uni_destroy_party(p, 0); 808} 809/************************************************************/ 810/* 811 * Party status enquiry request from API or call-control 812 * 813 * Q.2971:Party-Control-U 12 814 * Q.2971:Party-Control-N 12 815 */ 816static void 817punx_status_enquiry_request(struct party *p, uint32_t cookie) 818{ 819 struct uni_all *enq; 820 821 if((enq = UNI_ALLOC()) == NULL) { 822 uniapi_party_error(p, UNIAPI_ERROR_NOMEM, cookie); 823 return; 824 } 825 MK_IE_EPREF(enq->u.status_enq.epref, p->epref, 826 !(p->flags & PARTY_MINE)); 827 MK_MSG_ORIG(enq, UNI_STATUS_ENQ, p->call->cref, !p->call->mine); 828 uni_enq_call(p->call, SIGC_SEND_STATUS_ENQ, cookie, NULL, enq); 829 830 uniapi_party_error(p, UNIAPI_OK, cookie); 831} 832 833/* 834 * STATUS in any state except PU5/PN5 835 * 836 * Q.2971:Party-Control-U 12 837 * Q.2971:Party-Control-N 12 838 */ 839static void 840punx_status(struct party *p, struct uni_msg *m, struct uni_all *u) 841{ 842 struct uniapi_drop_party_ack_indication *ind; 843 struct uni_msg *api; 844 845 if (u->u.status.epstate.state == UNI_EPSTATE_NULL) { 846 /* should not happend */ 847 ind = ALLOC_API(struct uniapi_drop_party_ack_indication, api); 848 if (ind != NULL) { 849 ind->drop.hdr = u->u.hdr; 850 ind->drop.cause = u->u.status.cause; 851 ind->drop.epref = u->u.status.epref; 852 uni_enq_call(p->call, SIGC_DROP_PARTY_ACK_indication, 853 0, api, NULL); 854 } 855 stop_all_party_timers(p); 856 857 uni_destroy_party(p, 0); 858 } else { 859 if (epstate_compat(p, u->u.status.epstate.state)) { 860 if(u->u.status.cause.cause == UNI_CAUSE_MANDAT || 861 u->u.status.cause.cause == UNI_CAUSE_MTYPE_NIMPL || 862 u->u.status.cause.cause == UNI_CAUSE_IE_NIMPL || 863 u->u.status.cause.cause == UNI_CAUSE_IE_INV) { 864 MK_IE_CAUSE(p->call->uni->cause, 865 UNI_CAUSE_LOC_USER, 866 UNI_CAUSE_UNSPEC); 867 drop_partyE(p); 868 } 869 } else { 870 MK_IE_CAUSE(p->call->uni->cause, 871 UNI_CAUSE_LOC_USER, 872 UNI_CAUSE_MSG_INCOMP); 873 drop_partyE(p); 874 } 875 } 876 877 uni_msg_destroy(m); 878 UNI_FREE(u); 879} 880 881/* 882 * STATUS in PU5/PN5 883 * 884 * Q.2971:Party-Control-U 10 885 * Q.2971:Party-Control-N 10 886 */ 887static void 888pun5_status(struct party *p, struct uni_msg *m, struct uni_all *u) 889{ 890 struct uniapi_drop_party_ack_indication *ind; 891 struct uni_msg *api; 892 893 if (u->u.status.epstate.state == UNI_EPSTATE_NULL) { 894 ind = ALLOC_API(struct uniapi_drop_party_ack_indication, api); 895 if (ind != NULL) { 896 ind->drop.hdr = u->u.hdr; 897 ind->drop.cause = u->u.status.cause; 898 ind->drop.epref = u->u.status.epref; 899 uni_enq_call(p->call, SIGC_DROP_PARTY_ACK_indication, 900 0, api, NULL); 901 } 902 TIMER_STOP_PARTY(p, t398); 903 904 uni_destroy_party(p, 0); 905 } 906 907 uni_msg_destroy(m); 908 UNI_FREE(u); 909} 910 911/************************************************************/ 912 913void 914uni_sig_party(struct party *p, enum party_sig sig, uint32_t cookie, 915 struct uni_msg *msg, struct uni_all *u) 916{ 917 if (sig >= SIGP_END) { 918 VERBOSE(p->call->uni, UNI_FAC_ERR, 1, 919 "Signal %d outside of range to Party-Control", sig); 920 if (msg) 921 uni_msg_destroy(msg); 922 if (u) 923 UNI_FREE(u); 924 return; 925 } 926 VERBOSE(p->call->uni, UNI_FAC_CALL, 1, 927 "Signal %s in state %u of party %u/%s (call %u/%s in state %s)" 928 "; cookie %u", party_sigs[sig], p->state, p->epref, 929 (p->flags & PARTY_MINE) ? "mine" : "his", p->call->cref, 930 p->call->mine ? "mine" : "his", callstates[p->call->cstate].name, 931 cookie); 932 933 switch (sig) { 934 935 case SIGP_PARTY_DELETE: 936 PARTY_FREE(p); 937 break; 938 939 /* 940 * Messages 941 */ 942 case SIGP_SETUP: 943 if (p->state == UNI_EPSTATE_NULL) { 944 /* Q.2971:Call-Control-U 3/13 */ 945 /* Q.2971:Call-Control-N 3/13 */ 946 set_party_state(p, UNI_EPSTATE_ADD_RCVD); 947 break; 948 } 949 VERBOSE(p->call->uni, UNI_FAC_ERR, 1, 950 "SETUP in ps=%u", p->state); 951 break; 952 953 case SIGP_ALERTING: 954 if (p->state == UNI_EPSTATE_ADD_INIT) { 955 /* Q.2971:Call-Control-U 14 */ 956 /* Q.2971:Call-Control-N 5 */ 957 TIMER_START_PARTY(p, t397, p->call->uni->timer397); 958 set_party_state(p, UNI_EPSTATE_ALERT_RCVD); 959 break; 960 } 961 VERBOSE(p->call->uni, UNI_FAC_ERR, 1, 962 "ALERTING in ps=%u", p->state); 963 break; 964 965 case SIGP_CONNECT: 966 if (p->state == UNI_EPSTATE_ADD_INIT) { 967 /* Q.2971:Call-Control-U 4/13 */ 968 TIMER_STOP_PARTY(p, t399); 969 set_party_state(p, UNI_EPSTATE_ACTIVE); 970 break; 971 } 972 if (p->state == UNI_EPSTATE_ALERT_RCVD) { 973 /* Q.2971:Call-Control-U 7/13 */ 974 TIMER_STOP_PARTY(p, t397); 975 set_party_state(p, UNI_EPSTATE_ACTIVE); 976 break; 977 } 978 VERBOSE(p->call->uni, UNI_FAC_ERR, 1, 979 "CONNECT in ps=%u", p->state); 980 break; 981 982 case SIGP_CONNECT_ACK: 983 if (p->state == UNI_EPSTATE_ADD_RCVD || 984 p->state == UNI_EPSTATE_ALERT_DLVD) { 985 /* Q.2971:Call-Control-U 6/13 */ 986 /* Q.2971:Call-Control-U 7/13 */ 987 p->flags &= ~PARTY_CONNECT; 988 set_party_state(p, UNI_EPSTATE_ACTIVE); 989 break; 990 } 991 VERBOSE(p->call->uni, UNI_FAC_ERR, 1, 992 "CONNECT in ps=%u", p->state); 993 break; 994 995 case SIGP_RELEASE: 996 if (p->state == UNI_EPSTATE_DROP_INIT) { 997 /* Q.2971:Party-Control-U 10/14 */ 998 /* Q.2971:Party-Control-N 10/14 */ 999 TIMER_STOP_PARTY(p, t398); 1000 uni_destroy_party(p, 0); 1001 break; 1002 } 1003 /* Q.2971:Party-Control-U 11/14 */ 1004 /* Q.2971:Party-Control-N 11/14 */ 1005 TIMER_STOP_PARTY(p, t397); 1006 TIMER_STOP_PARTY(p, t399); 1007 uni_destroy_party(p, 0); 1008 break; 1009 1010 case SIGP_RELEASE_COMPL: 1011 /* Q.2971:Party-Control-U 11/14 */ 1012 /* Q.2971:Party-Control-N 11/14 */ 1013 stop_all_party_timers(p); 1014 uni_destroy_party(p, 0); 1015 break; 1016 1017 case SIGP_RELEASE_confirm: 1018 /* not in the SDLs */ 1019 stop_all_party_timers(p); 1020 uni_destroy_party(p, 0); 1021 break; 1022 1023 case SIGP_RELEASE_request: 1024 if (p->state == UNI_EPSTATE_DROP_INIT) { 1025 /* Q.2971:Party-Control-U 10 */ 1026 /* Q.2971:Party-Control-N 10 */ 1027 uni_destroy_party(p, 0); 1028 break; 1029 } 1030 /* Q.2971:Party-Control-U 11 */ 1031 /* Q.2971:Party-Control-N 11 */ 1032 TIMER_STOP_PARTY(p, t397); 1033 TIMER_STOP_PARTY(p, t399); 1034 uni_destroy_party(p, 0); 1035 break; 1036 1037 case SIGP_RELEASE_response: 1038 /* Q.2971:Party-Control-U 11 */ 1039 /* Q.2971:Party-Control-N 11 */ 1040 stop_all_party_timers(p); 1041 uni_destroy_party(p, 0); 1042 break; 1043 1044 case SIGP_ADD_PARTY: 1045 if (p->state == UNI_EPSTATE_NULL) { 1046 /* Q.2971:Party-Control-U 3 PU0 */ 1047 /* Q.2971:Party-Control-N 3 PN0 */ 1048 pun0_add_party(p, msg, u); 1049 break; 1050 } 1051 if (p->state == UNI_EPSTATE_ADD_RCVD) { 1052 /* Q.2971:Party-Control-U 6 PU2 */ 1053 /* Q.2971:Party-Control-N 6 PN2 */ 1054 uni_msg_destroy(msg); 1055 UNI_FREE(u); 1056 break; 1057 } 1058 uni_bad_message(p->call, u, UNI_CAUSE_MSG_INCOMP, 1059 &u->u.add_party.epref, p->state); 1060 uni_msg_destroy(msg); 1061 UNI_FREE(u); 1062 break; 1063 1064 case SIGP_PARTY_ALERTING: 1065 if (p->state == UNI_EPSTATE_ADD_INIT) { 1066 /* Q.2971:Party-Control-U 14 */ 1067 /* Q.2971:Party-Control-N 5 */ 1068 pun1_party_alerting(p, msg, u); 1069 break; 1070 } 1071 uni_bad_message(p->call, u, UNI_CAUSE_MSG_INCOMP, 1072 &u->u.party_alerting.epref, p->state); 1073 uni_msg_destroy(msg); 1074 UNI_FREE(u); 1075 break; 1076 1077 case SIGP_ADD_PARTY_ACK: 1078 if (p->state == UNI_EPSTATE_ADD_INIT || 1079 p->state == UNI_EPSTATE_ALERT_RCVD) { 1080 /* Q.2971:Party-Control-U 4 (PU1) */ 1081 /* Q.2971:Party-Control-U 7 (PU4) */ 1082 /* Q.2971:Party-Control-N 4 (PN1) */ 1083 /* Q.2971:Party-Control-N 7 (PN4) */ 1084 pun1pun4_add_party_ack(p, msg, u); 1085 break; 1086 } 1087 uni_bad_message(p->call, u, UNI_CAUSE_MSG_INCOMP, 1088 &u->u.add_party_ack.epref, p->state); 1089 uni_msg_destroy(msg); 1090 UNI_FREE(u); 1091 break; 1092 1093 case SIGP_ADD_PARTY_REJ: 1094 if (p->state == UNI_EPSTATE_ADD_INIT) { 1095 /* Q.2971:Party-Control-U 4 (PU1) */ 1096 /* Q.2971:Party-Control-N 4 (PN1) */ 1097 pun1_add_party_rej(p, msg, u); 1098 break; 1099 } 1100 if (p->state == UNI_EPSTATE_DROP_INIT) { 1101 /* Q.2971:Party-Control-U 10 (PU5) */ 1102 /* Q.2971:Party-Control-N 10 (PN5) */ 1103 pun5_add_party_rej(p, msg, u); 1104 break; 1105 } 1106 uni_bad_message(p->call, u, UNI_CAUSE_MSG_INCOMP, 1107 &u->u.add_party_rej.epref, p->state); 1108 uni_msg_destroy(msg); 1109 UNI_FREE(u); 1110 break; 1111 1112 case SIGP_DROP_PARTY_ACK: 1113 /* Q.2971:Party-Control-U 8 */ 1114 /* Q.2971:Party-Control-N 8 */ 1115 punx_drop_party_ack(p, msg, u); 1116 break; 1117 1118 case SIGP_DROP_PARTY: 1119 if (p->state == UNI_EPSTATE_DROP_INIT) 1120 /* Q.2971:Party-Control-U 10 */ 1121 /* Q.2971:Party-Control-N 10 */ 1122 pun5_drop_party(p, msg, u); 1123 else 1124 /* Q.2971:Party-Control-U 9 */ 1125 /* Q.2971:Party-Control-N 9 */ 1126 punx_drop_party(p, msg, u); 1127 break; 1128 1129 case SIGP_STATUS: 1130 if (p->state == UNI_EPSTATE_DROP_INIT) 1131 /* Q.2971:Party-Control-U 10 */ 1132 /* Q.2971:Party-Control-N 10 */ 1133 pun5_status(p, msg, u); 1134 else 1135 /* Q.2971:Party-Control-U 12 */ 1136 /* Q.2971:Party-Control-N 12 */ 1137 punx_status(p, msg, u); 1138 break; 1139 1140 /* 1141 * User 1142 */ 1143 case SIGP_SETUP_request: 1144 if (p->state == UNI_EPSTATE_NULL) { 1145 /* Q.2971:Party-Control-U 3 */ 1146 /* Q.2971:Party-Control-N 3 */ 1147 set_party_state(p, UNI_EPSTATE_ADD_INIT); 1148 break; 1149 } 1150 VERBOSE(p->call->uni, UNI_FAC_ERR, 1, 1151 "SETUP.request in ps=%u", p->state); 1152 uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie); 1153 break; 1154 1155 case SIGP_SETUP_response: 1156 if (p->state == UNI_EPSTATE_ADD_RCVD || 1157 p->state == UNI_EPSTATE_ALERT_DLVD) { 1158 /* Q.2971:Party-Control-N 6 (PN2) */ 1159 /* Q.2971:Party-Control-N 7 (PN3) */ 1160 set_party_state(p, UNI_EPSTATE_ACTIVE); 1161 break; 1162 } 1163 VERBOSE(p->call->uni, UNI_FAC_ERR, 1, 1164 "SETUP.response in ps=%u", p->state); 1165 uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie); 1166 break; 1167 1168 case SIGP_SETUP_COMPL_request: 1169 if (p->state == UNI_EPSTATE_ADD_INIT) { 1170 /* Q.2971:Party-Control-N 4 */ 1171 TIMER_STOP_PARTY(p, t399); 1172 set_party_state(p, UNI_EPSTATE_ACTIVE); 1173 break; 1174 } 1175 if (p->state == UNI_EPSTATE_ALERT_RCVD) { 1176 /* Q.2971:Party-Control-N 7 */ 1177 TIMER_STOP_PARTY(p, t397); 1178 set_party_state(p, UNI_EPSTATE_ACTIVE); 1179 break; 1180 } 1181 VERBOSE(p->call->uni, UNI_FAC_ERR, 1, 1182 "SETUP_COMPL.request in ps=%u", p->state); 1183 uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie); 1184 break; 1185 1186 case SIGP_ADD_PARTY_request: 1187 if (p->state == UNI_EPSTATE_NULL) { 1188 /* Q.2971:Party-control-U 3 (PU0) */ 1189 /* Q.2971:Party-control-N 3 (PN0) */ 1190 pun0_add_party_request(p, msg, cookie); 1191 break; 1192 } 1193 VERBOSE(p->call->uni, UNI_FAC_ERR, 1, 1194 "Add-party.request in ps=%u", p->state); 1195 uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie); 1196 uni_msg_destroy(msg); 1197 break; 1198 1199 case SIGP_ALERTING_request: 1200 /* Q.2971:Party-Control-U 6 (PU2) */ 1201 /* Q.2971:Party-Control-N 6 (PN2) */ 1202 set_party_state(p, UNI_EPSTATE_ALERT_DLVD); 1203 break; 1204 1205 case SIGP_PARTY_ALERTING_request: 1206 if (p->state == UNI_EPSTATE_ADD_RCVD) { 1207 /* Q.2971:Party-Control-U 6 (PU2) */ 1208 /* Q.2971:Party-Control-N 6 (PN2) */ 1209 pun2_party_alerting_request(p, msg, cookie); 1210 break; 1211 } 1212 VERBOSE(p->call->uni, UNI_FAC_ERR, 1, 1213 "Party-alerting.request in ps=%u", p->state); 1214 uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie); 1215 uni_msg_destroy(msg); 1216 break; 1217 1218 case SIGP_ADD_PARTY_ACK_request: 1219 if (p->state == UNI_EPSTATE_ADD_RCVD || 1220 p->state == UNI_EPSTATE_ALERT_DLVD) { 1221 /* Q.2971:Party-Control-U 6 PU2 */ 1222 /* Q.2971:Party-Control-U 7 PU3 */ 1223 /* Q.2971:Party-Control-N 6 PN2 */ 1224 /* Q.2971:Party-Control-N 7 PN3 */ 1225 punx_add_party_ack_request(p, msg, cookie); 1226 break; 1227 } 1228 VERBOSE(p->call->uni, UNI_FAC_ERR, 1, 1229 "Add-party-ack.request in ps=%u", p->state); 1230 uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie); 1231 uni_msg_destroy(msg); 1232 break; 1233 1234 case SIGP_ADD_PARTY_REJ_request: 1235 if (p->state == UNI_EPSTATE_ADD_RCVD) { 1236 /* Q.2971:Party-Control-U 6 PU2 */ 1237 /* Q.2971:Party-Control-N 6 PN2 */ 1238 pun2_add_party_rej_request(p, msg, cookie); 1239 break; 1240 } 1241 VERBOSE(p->call->uni, UNI_FAC_ERR, 1, 1242 "Add-party-rej.request in ps=%u", p->state); 1243 uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie); 1244 uni_msg_destroy(msg); 1245 break; 1246 1247 case SIGP_DROP_PARTY_request: 1248 if (p->state == UNI_EPSTATE_ADD_INIT || 1249 p->state == UNI_EPSTATE_ALERT_DLVD || 1250 p->state == UNI_EPSTATE_ALERT_RCVD || 1251 p->state == UNI_EPSTATE_ACTIVE) { 1252 /* Q.2971:Party-Control-U 8 */ 1253 /* Q.2971:Party-Control-N 8 */ 1254 punx_drop_party_request(p, msg, cookie); 1255 break; 1256 } 1257 VERBOSE(p->call->uni, UNI_FAC_ERR, 1, 1258 "Drop-party.request in ps=%u", p->state); 1259 uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie); 1260 uni_msg_destroy(msg); 1261 break; 1262 1263 case SIGP_DROP_PARTY_ACK_request: 1264 if (p->state == UNI_EPSTATE_DROP_RCVD) { 1265 /* Q.2971:Party-Control-U 9 */ 1266 /* Q.2971:Party-Control-N 9 */ 1267 pun6_drop_party_ack_request(p, msg, cookie); 1268 break; 1269 } 1270 VERBOSE(p->call->uni, UNI_FAC_ERR, 1, 1271 "Drop-party-ack.request in ps=%u", p->state); 1272 uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie); 1273 uni_msg_destroy(msg); 1274 break; 1275 1276 case SIGP_STATUS_ENQUIRY_request: 1277 /* Q.2971:Party-Control-U 12 */ 1278 /* Q.2971:Party-Control-N 12 */ 1279 punx_status_enquiry_request(p, cookie); 1280 break; 1281 1282 /* 1283 * Timers 1284 */ 1285 case SIGP_T397: 1286 if (p->state == UNI_EPSTATE_ALERT_RCVD) { 1287 /* Q.2971:Party-Control-U 7 (PU4) */ 1288 /* Q.2971:Party-Control-N 7 (PN4) */ 1289 pun4_t397(p); 1290 break; 1291 } 1292 VERBOSE(p->call->uni, UNI_FAC_ERR, 1, 1293 "T397 in ps=%u", p->state); 1294 break; 1295 1296 case SIGP_T398: 1297 if (p->state == UNI_EPSTATE_DROP_INIT) { 1298 /* Q.2971:Party-Control-U 10 (PU5) */ 1299 /* Q.2971:Party-Control-N 10 (PN5) */ 1300 pun5_t398(p); 1301 break; 1302 } 1303 VERBOSE(p->call->uni, UNI_FAC_ERR, 1, 1304 "T398 in ps=%u", p->state); 1305 break; 1306 1307 case SIGP_T399: 1308 if (p->state == UNI_EPSTATE_ADD_INIT) { 1309 /* Q.2971:Party-Control-U 4 (PU1) */ 1310 /* Q.2971:Party-Control-N 4 (PN1) */ 1311 pun1_t399(p); 1312 break; 1313 } 1314 VERBOSE(p->call->uni, UNI_FAC_ERR, 1, 1315 "T399 in ps=%u", p->state); 1316 break; 1317 1318 case SIGP_END: 1319 break; 1320 } 1321} 1322 1323static void 1324t397_func(struct party *p) 1325{ 1326 uni_enq_party(p, SIGP_T397, 0, NULL, NULL); 1327} 1328static void 1329t398_func(struct party *p) 1330{ 1331 uni_enq_party(p, SIGP_T398, 0, NULL, NULL); 1332} 1333static void 1334t399_func(struct party *p) 1335{ 1336 uni_enq_party(p, SIGP_T399, 0, NULL, NULL); 1337} 1338 1339static int 1340epstate_compat(struct party *p, enum uni_epstate state) 1341{ 1342 if (p->state == UNI_EPSTATE_ADD_INIT || 1343 p->state == UNI_EPSTATE_ALERT_RCVD) 1344 if (state == UNI_EPSTATE_ADD_INIT || 1345 state == UNI_EPSTATE_ALERT_RCVD) 1346 return (0); 1347 if (p->state == UNI_EPSTATE_ADD_RCVD || 1348 p->state == UNI_EPSTATE_ALERT_DLVD) 1349 if (state == UNI_EPSTATE_ADD_RCVD || 1350 state == UNI_EPSTATE_ALERT_DLVD) 1351 return (0); 1352 return (1); 1353} 1354