1/* 2 * Copyright (c) 2003-2007 3 * Hartmut Brandt 4 * All rights reserved. 5 * 6 * Copyright (c) 2001-2002 7 * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 8 * All rights reserved. 9 * 10 * Author: Harti Brandt <harti@freebsd.org> 11 * 12 * Redistribution of this software and documentation and use in source and 13 * binary forms, with or without modification, are permitted provided that 14 * the following conditions are met: 15 * 16 * 1. Redistributions of source code or documentation must retain the above 17 * copyright notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 22 * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE AUTHOR 23 * AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 24 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 25 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 26 * THE AUTHOR OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 29 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 32 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 * 34 * $Id: cc_conn.c 1291 2007-07-10 10:35:38Z brandt_h $ 35 * 36 * ATM API as defined per af-saa-0108 37 * 38 * Lower half - connection handling 39 */ 40#include <netnatm/unimsg.h> 41#include <netnatm/msg/unistruct.h> 42#include <netnatm/msg/unimsglib.h> 43#include <netnatm/api/unisap.h> 44#include <netnatm/sig/unidef.h> 45#include <netnatm/api/atmapi.h> 46#include <netnatm/api/ccatm.h> 47#include <netnatm/api/ccpriv.h> 48 49static const char *stab[] = { 50#define DEF(N) [N] = #N, 51 CONN_STATES 52#undef DEF 53}; 54 55static const char *ptab[] = { 56#define DEF(N) [PARTY_##N] = #N, 57 PARTY_STATES 58#undef DEF 59}; 60 61const char * 62cc_conn_state2str(u_int s) 63{ 64 if (s >= sizeof(stab) / sizeof(stab[0]) || stab[s] == NULL) 65 return ("?"); 66 return (stab[s]); 67} 68 69void 70cc_conn_set_state(struct ccconn *conn, enum conn_state ns) 71{ 72 if (conn->state != ns) { 73 if (conn->cc->log & CCLOG_CONN_STATE) 74 cc_conn_log(conn, "%s -> %s", 75 stab[conn->state], stab[ns]); 76 conn->state = ns; 77 } 78} 79 80const char * 81cc_party_state2str(u_int s) 82{ 83 if (s >= sizeof(ptab) / sizeof(ptab[0]) || ptab[s] == NULL) 84 return ("?"); 85 return (ptab[s]); 86} 87 88void 89cc_party_set_state(struct ccparty *party, enum party_state ns) 90{ 91 92 if (party->state != ns) { 93 if (party->conn->cc->log & CCLOG_PARTY_STATE) 94 cc_party_log(party, "%s -> %s", 95 ptab[party->state], ptab[ns]); 96 party->state = ns; 97 } 98} 99 100/* 101 * Remove connection from its user's queue 102 */ 103void 104cc_disconnect_from_user(struct ccconn *conn) 105{ 106 107 if (conn->user == NULL) 108 cc_conn_log(conn, "no %s", "user"); 109 else { 110 TAILQ_REMOVE(&conn->user->connq, conn, connq_link); 111 conn->user->queue_act--; 112 conn->user = NULL; 113 } 114} 115 116/* 117 * Put connection on user queue 118 */ 119void 120cc_connect_to_user(struct ccconn *conn, struct ccuser *user) 121{ 122 123 if (conn->user != NULL) 124 cc_conn_log(conn, "still connected to %p", conn->user); 125 conn->user = user; 126 TAILQ_INSERT_TAIL(&user->connq, conn, connq_link); 127 conn->user->queue_act++; 128} 129 130/* 131 * Send a signal to the UNI stack for this connection 132 */ 133static void 134cc_send_uni(struct ccconn *conn, u_int op, struct uni_msg *msg) 135{ 136 struct ccreq *r; 137 138 r = CCZALLOC(sizeof(*r)); 139 if (r == NULL) { 140 if (msg != NULL) 141 uni_msg_destroy(msg); 142 cc_conn_log(conn, "no memory for cookie op=%u", op); 143 return; 144 } 145 146 if ((r->cookie = ++conn->port->cc->cookie) == 0) 147 r->cookie = ++conn->port->cc->cookie; 148 r->req = op; 149 r->conn = conn; 150 151 TAILQ_INSERT_TAIL(&conn->port->cookies, r, link); 152 153 conn->port->cc->funcs->send_uni(conn, conn->port->uarg, op, 154 r->cookie, msg); 155} 156 157/* 158 * Send a RELEASE.request for this connection. 159 */ 160static void 161do_release_request(struct ccconn *conn, const struct uni_ie_cause cause[2]) 162{ 163 struct uni_msg *u; 164 struct uniapi_release_request *req; 165 166 if ((u = uni_msg_alloc(sizeof(*req))) == NULL) 167 return; 168 req = uni_msg_wptr(u, struct uniapi_release_request *); 169 memset(req, 0, sizeof(*req)); 170 u->b_wptr += sizeof(struct uniapi_release_request); 171 172 req->release.hdr.cref = conn->cref; 173 req->release.hdr.act = UNI_MSGACT_DEFAULT; 174 175 if (cause == NULL) { 176 IE_SETPRESENT(req->release.cause[0]); 177 req->release.cause[0].h.act = UNI_IEACT_DEFAULT; 178 req->release.cause[0].loc = UNI_CAUSE_LOC_USER; 179 req->release.cause[0].cause = UNI_CAUSE_UNSPEC; 180 } else { 181 req->release.cause[0] = cause[0]; 182 req->release.cause[1] = cause[1]; 183 } 184 185 cc_send_uni(conn, UNIAPI_RELEASE_request, u); 186} 187 188/* 189 * Make a RELEASE.response for this connection 190 */ 191static void 192do_release_response(struct ccconn *conn, uint8_t cause, struct uni_ie_cause *ie) 193{ 194 struct uni_msg *u; 195 struct uniapi_release_response *resp; 196 197 if ((u = uni_msg_alloc(sizeof(*resp))) == NULL) 198 return; 199 resp = uni_msg_wptr(u, struct uniapi_release_response *); 200 memset(resp, 0, sizeof(*resp)); 201 u->b_wptr += sizeof(struct uniapi_release_response); 202 203 resp->release_compl.hdr.cref = conn->cref; 204 resp->release_compl.hdr.act = UNI_MSGACT_DEFAULT; 205 206 if (ie != NULL) 207 resp->release_compl.cause[0] = *ie; 208 209 if (cause != 0) { 210 IE_SETPRESENT(resp->release_compl.cause[0]); 211 resp->release_compl.cause[0].h.act = UNI_IEACT_DEFAULT; 212 resp->release_compl.cause[0].loc = UNI_CAUSE_LOC_USER; 213 resp->release_compl.cause[0].cause = cause; 214 } 215 216 cc_send_uni(conn, UNIAPI_RELEASE_response, u); 217} 218 219/********************************************************************** 220 * 221 * INSTANCE handling 222 */ 223struct ccconn * 224cc_conn_create(struct ccdata *cc) 225{ 226 struct ccconn *conn; 227 228 conn = CCZALLOC(sizeof(*conn)); 229 if (conn == NULL) 230 return (NULL); 231 232 conn->state = CONN_NULL; 233 conn->port = NULL; 234 conn->cc = cc; 235 LIST_INIT(&conn->parties); 236 237 LIST_INSERT_HEAD(&cc->orphaned_conns, conn, port_link); 238 239 if (conn->cc->log & CCLOG_CONN_INST) 240 cc_conn_log(conn, "created %s", "orphaned"); 241 242 return (conn); 243} 244 245/* 246 * assign to port 247 */ 248void 249cc_conn_ins_port(struct ccconn *conn, struct ccport *port) 250{ 251 252 if (conn->port != NULL) { 253 cc_conn_log(conn, "conn is already on port %u", 254 conn->port->param.port); 255 cc_conn_rem_port(conn); 256 } 257 LIST_REMOVE(conn, port_link); 258 259 conn->port = port; 260 LIST_INSERT_HEAD(&port->conn_list, conn, port_link); 261 262} 263 264/* 265 * remove from port 266 */ 267void 268cc_conn_rem_port(struct ccconn *conn) 269{ 270 271 if (conn->port == NULL) { 272 cc_conn_log(conn, "conn not on any %s", "port"); 273 return; 274 } 275 LIST_REMOVE(conn, port_link); 276 conn->port = NULL; 277 LIST_INSERT_HEAD(&conn->cc->orphaned_conns, conn, port_link); 278} 279 280static void 281cc_conn_flush_cookies(struct ccconn *conn) 282{ 283 struct ccreq *r, *r1; 284 285 if (conn->port == NULL) 286 return; 287 TAILQ_FOREACH_SAFE(r, &conn->port->cookies, link, r1) { 288 if (r->conn == conn) { 289 TAILQ_REMOVE(&conn->port->cookies, r, link); 290 CCFREE(r); 291 } 292 } 293} 294 295void 296cc_conn_reset_acceptor(struct ccconn *conn) 297{ 298 if (conn->acceptor != NULL) { 299 conn->acceptor->accepted = NULL; 300 conn->acceptor = NULL; 301 } 302} 303 304/* 305 * Destroy a connection 306 */ 307void 308cc_conn_destroy(struct ccconn *conn) 309{ 310 struct ccparty *p; 311 312 if (conn->cc->log & CCLOG_CONN_INST) 313 cc_conn_log(conn, "destroy%s", ""); 314 315 if (conn->user != NULL) { 316 cc_conn_log(conn, "still connected to user %p\n", conn->user); 317 conn->user->queue_act--; 318 TAILQ_REMOVE(&conn->user->connq, conn, connq_link); 319 } 320 321 if (conn->acceptor != NULL) 322 conn->acceptor->accepted = NULL; 323 324 cc_conn_flush_cookies(conn); 325 cc_conn_sig_flush(conn); 326 327 LIST_REMOVE(conn, port_link); 328 while ((p = LIST_FIRST(&conn->parties)) != NULL) { 329 LIST_REMOVE(p, link); 330 CCFREE(p); 331 } 332 333 CCFREE(conn); 334} 335 336struct ccparty * 337cc_party_create(struct ccconn *conn, u_int ident, u_int flag) 338{ 339 struct ccparty *party; 340 341 party = CCZALLOC(sizeof(*party)); 342 if (party == NULL) 343 return (NULL); 344 345 party->conn = conn; 346 party->state = PARTY_NULL; 347 IE_SETPRESENT(party->epref); 348 party->epref.flag = flag; 349 party->epref.epref = ident; 350 LIST_INSERT_HEAD(&conn->parties, party, link); 351 352 if (party->conn->cc->log & CCLOG_PARTY_INST) 353 cc_party_log(party, "created %u.%u", flag, ident); 354 355 return (party); 356} 357 358static void 359cc_party_destroy(struct ccparty *party) 360{ 361 362 if (party->conn->cc->log & CCLOG_PARTY_INST) 363 cc_party_log(party, "destroyed %u.%u", party->epref.flag, 364 party->epref.epref); 365 366 LIST_REMOVE(party, link); 367 CCFREE(party); 368} 369 370static struct ccparty * 371cc_party_find(struct ccconn *conn, u_int ident) 372{ 373 struct ccparty *party; 374 375 LIST_FOREACH(party, &conn->parties, link) 376 if (party->epref.epref == ident) 377 return (party); 378 return (NULL); 379} 380/* 381 * Abort connection from down stream (because of the UNI hook beeing 382 * disconnected). This is called from two places: 383 * 1) the shutdown code. 384 * In this case the connections should be already dissociated from 385 * users and be only in states waiting for the UNI stack. 386 * 2) from the disconnect code. 387 */ 388void 389cc_conn_abort(struct ccconn *conn, int shutdown) 390{ 391 struct ccuser *u = conn->user; 392 struct ccparty *p, *p1; 393 394 if (shutdown) { 395 CCASSERT(u == NULL, ("still in use")); 396 CCASSERT(conn->acceptor == NULL, ("still in use")); 397 cc_conn_destroy(conn); 398 return; 399 } 400 401 /* 402 * Look whether any parties are blocked waiting for a response 403 * from the stack. We don't use extra party states to handle 404 * user aborts, so check that there is a user before using it. 405 */ 406 if (u == NULL) { 407 while ((p = LIST_FIRST(&conn->parties)) != NULL) 408 cc_party_destroy(p); 409 } else { 410 LIST_FOREACH_SAFE(p, &conn->parties, link, p1) { 411 switch (p->state) { 412 413 case PARTY_NULL: /* P0 */ 414 /* should not happen */ 415 goto dpty; 416 417 case PARTY_ACTIVE: /* P1 */ 418 /* don't send a drop - user'll get a rel */ 419 goto dpty; 420 421 case PARTY_ADD_WAIT_CREATE: /* P2 */ 422 case PARTY_ADD_WAIT_OK: /* P3 */ 423 /* we're adding - synthesise an error */ 424 cc_user_sig(u, USER_SIG_ADD_PARTY_ERR, 425 NULL, ATMERR_BAD_PORT); 426 goto dpty; 427 428 case PARTY_ADD_WAIT_ACK: /* P4 */ 429 /* don't send a drop - user'll get a rel */ 430 goto dpty; 431 432 case PARTY_DROP_WAIT_OK: /* P5 */ 433 case PARTY_DROP_WAIT_ACK: /* P6 */ 434 case PARTY_ADD_DROP_WAIT_OK: /* P11 */ 435 /* we're dropping - synthesis an ok */ 436 cc_user_sig(u, USER_SIG_DROP_PARTY_OK, 437 NULL, p->epref.epref); 438 goto dpty; 439 440 case PARTY_WAIT_DESTROY: /* P7 */ 441 goto dpty; 442 443 case PARTY_WAIT_SETUP_COMPL: /* P8 */ 444 case PARTY_WAIT_SETUP_CONF: /* P10 */ 445 /* first party - nothing to do */ 446 goto dpty; 447 448 case PARTY_WAIT_DROP_ACK_OK: /* P9 */ 449 case PARTY_ADD_DROPACK_WAIT_OK:/* P12 */ 450 /* we're dropping - nothing to do */ 451 goto dpty; 452 } 453 cc_party_log(p, "bad uabort for party in state %s", 454 ptab[p->state]); 455 dpty: 456 cc_party_destroy(p); 457 } 458 } 459 460 /* 461 * Now do what the connection needs 462 */ 463 switch (conn->state) { 464 465 case CONN_NULL: /* 0 */ 466 case CONN_OUT_PREPARING: /* 1 */ 467 /* may not happen because we're not associated with 468 * aport yet */ 469 break; 470 471 case CONN_OUT_WAIT_CREATE: /* 2 */ 472 case CONN_OUT_WAIT_OK: /* 3 */ 473 case CONN_OUT_WAIT_DESTROY: /* 37 */ 474 /* return an error to the user, go back to C1/U1 475 * reset cref (for C37, C3) and cookie */ 476 conn->cref.flag = 0; 477 conn->cref.cref = 0; 478 cc_conn_flush_cookies(conn); 479 cc_conn_set_state(conn, CONN_OUT_PREPARING); 480 cc_conn_rem_port(conn); 481 cc_user_sig(u, USER_SIG_CONNECT_OUTGOING_ERR, 482 NULL, ATMERR_BAD_PORT); 483 return; 484 485 case CONN_OUT_WAIT_CONF: /* 4 */ 486 case CONN_ACTIVE: /* 5 */ 487 case CONN_IN_WAIT_COMPL: /* 13 */ 488 /* emulate a RELEASE.confirm */ 489 memset(&u->cause, 0, sizeof(u->cause)); 490 cc_user_sig(u, USER_SIG_RELEASE_CONFIRM, NULL, 0); 491 cc_disconnect_from_user(conn); 492 cc_conn_destroy(conn); 493 return; 494 495 case CONN_IN_PREPARING: /* 10 */ 496 case CONN_AB_WAIT_REQ_OK: /* 33 */ 497 case CONN_AB_WAIT_RESP_OK: /* 34 */ 498 case CONN_AB_FLUSH_IND: /* 35 */ 499 /* no user - destroy */ 500 cc_conn_destroy(conn); 501 return; 502 503 case CONN_IN_ARRIVED: /* 11 */ 504 u->aborted = 1; 505 cc_disconnect_from_user(conn); 506 cc_conn_destroy(conn); 507 return; 508 509 case CONN_IN_WAIT_ACCEPT_OK: /* 12 */ 510 /* return ACCEPT error */ 511 cc_disconnect_from_user(conn); 512 cc_conn_reset_acceptor(conn); 513 cc_user_sig(u, USER_SIG_ACCEPT_ERR, 514 u, ATMERR_PREVIOUSLY_ABORTED); 515 cc_conn_destroy(conn); 516 return; 517 518 case CONN_REJ_WAIT_OK: /* 14 */ 519 /* return REJECT ok */ 520 cc_disconnect_from_user(conn); 521 cc_conn_destroy(conn); 522 cc_user_sig(u, USER_SIG_REJECT_OK, NULL, 0); 523 return; 524 525 case CONN_REL_IN_WAIT_OK: /* 15 */ 526 case CONN_REL_WAIT_OK: /* 20 */ 527 /* confirm destroy */ 528 if (u != NULL) { 529 /* connection not aborted */ 530 memset(&u->cause, 0, sizeof(u->cause)); 531 cc_user_sig(u, USER_SIG_RELEASE_CONFIRM, NULL, 0); 532 cc_disconnect_from_user(conn); 533 } 534 cc_conn_destroy(conn); 535 return; 536 537 case CONN_IN_WAITING: /* 21 */ 538 /* user has not seen the connection - destroy */ 539 cc_disconnect_from_user(conn); 540 cc_conn_destroy(conn); 541 return; 542 } 543 cc_conn_log(conn, "bad state %s", stab[conn->state]); 544} 545 546#ifdef DEBUG_MATCH 547static void 548print_sap(const struct uni_sap *sap) 549{ 550 static const char *const tags[] = { 551 [UNISVE_ABSENT] "absent", 552 [UNISVE_PRESENT]"present", 553 [UNISVE_ANY] "any", 554 }; 555 u_int i; 556 557 printf("addr={%s", tags[sap->addr.tag]); 558 if (sap->addr.tag == UNISVE_PRESENT) { 559 printf(",%d-%d", sap->addr.type, sap->addr.plan); 560 for (i = 0; i < sap->addr.len; i++) 561 printf("%c%02x", ",:"[i!=0], sap->addr.addr[i]); 562 } 563 printf("}\n"); 564 565 printf("selector={%s", tags[sap->selector.tag]); 566 if (sap->selector.tag == UNISVE_PRESENT) 567 printf(",%02x", sap->selector.selector); 568 printf("}\n"); 569 570 printf("blli_id2={%s", tags[sap->blli_id2.tag]); 571 if (sap->blli_id2.tag == UNISVE_PRESENT) 572 printf(",%02x,%02x", sap->blli_id2.proto, sap->blli_id2.user); 573 printf("}\n"); 574 575 printf("blli_id3={%s", tags[sap->blli_id3.tag]); 576 if (sap->blli_id3.tag == UNISVE_PRESENT) 577 printf(",%02x,%02x,%02x,%06x,%04x,%d", 578 sap->blli_id3.proto, sap->blli_id3.user, 579 sap->blli_id3.ipi, sap->blli_id3.oui, 580 sap->blli_id3.pid, sap->blli_id3.noipi); 581 printf("}\n"); 582 583 printf("bhli={%s", tags[sap->bhli.tag]); 584 if (sap->bhli.tag == UNISVE_PRESENT) { 585 printf(",%d", sap->bhli.type); 586 for (i = 0; i < sap->bhli.len; i++) 587 printf("%c%02x", ",:"[i!=0], sap->bhli.info[i]); 588 } 589 printf("}\n"); 590} 591#endif 592 593/********************************************************************* 594 * 595 * DISPATCH incoming call 596 */ 597void 598cc_conn_dispatch(struct ccconn *conn) 599{ 600 struct ccdata *priv = conn->port->cc; 601 struct ccuser *user; 602 u_int blli_index; 603 604#ifdef DEBUG_MATCH 605 static char buf[1000]; 606 static struct unicx cx; 607 static int init = 1; 608 609 if (init) { 610 uni_initcx(&cx); 611 init = 0; 612 } 613#endif 614 615 /* 616 * Do call dispatching according to 4.6 617 */ 618#ifdef DEBUG_MATCH 619 printf("+++++ DISPATCH++++++\n"); 620#endif 621 for (blli_index = 0; blli_index < UNI_NUM_IE_BLLI; blli_index++) { 622 if (blli_index > 0 && !IE_ISGOOD(conn->blli[blli_index])) 623 break; 624#ifdef DEBUG_MATCH 625 if (IE_ISPRESENT(conn->called)) { 626 uni_print_ie(buf, sizeof(buf), UNI_IE_CALLED, 627 (union uni_ieall *)&conn->called, &cx); 628 printf("called=%s\n", buf); 629 } 630 if (IE_ISPRESENT(conn->bhli)) { 631 uni_print_ie(buf, sizeof(buf), UNI_IE_BHLI, 632 (union uni_ieall *)&conn->bhli, &cx); 633 printf("bhli=%s\n", buf); 634 } 635 if (IE_ISPRESENT(conn->blli[blli_index])) { 636 uni_print_ie(buf, sizeof(buf), UNI_IE_BLLI, 637 (union uni_ieall *)&conn->blli[blli_index], &cx); 638 printf("%s\n", buf); 639 } 640#endif 641 LIST_FOREACH(user, &priv->user_list, node_link) { 642 if ((user->state == USER_IN_WAITING || 643 user->state == USER_IN_ARRIVED || 644 user->state == USER_IN_WAIT_ACC || 645 user->state == USER_IN_WAIT_REJ) && 646 !unisve_is_catchall(user->sap)) { 647#ifdef DEBUG_MATCH 648 printf("TRYING user=%p\n", user); 649 print_sap(user->sap); 650#endif 651 if (unisve_match(user->sap, &conn->called, 652 &conn->blli[blli_index], &conn->bhli)) 653 goto found; 654 } 655 } 656 } 657#ifdef DEBUG_MATCH 658 printf("TRYING CATCHALL\n"); 659#endif 660 blli_index = 0; 661 LIST_FOREACH(user, &priv->user_list, node_link) { 662 if ((user->state == USER_IN_WAITING || 663 user->state == USER_IN_ARRIVED || 664 user->state == USER_IN_WAIT_ACC || 665 user->state == USER_IN_WAIT_REJ) && 666 unisve_is_catchall(user->sap)) 667 goto found; 668 } 669#ifdef DEBUG_MATCH 670 printf("SORRY\n"); 671#endif 672 673 /* 674 * No application found - reject call. 675 */ 676 do_release_response(conn, UNI_CAUSE_INCOMP, NULL); 677 cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK); 678 return; 679 680 found: 681#ifdef DEBUG_MATCH 682 printf("MATCH\n"); 683#endif 684 if (user->queue_max == user->queue_act) { 685 do_release_response(conn, UNI_CAUSE_BUSY, NULL); 686 cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK); 687 return; 688 } 689 690 if (blli_index == 0 && !IE_ISGOOD(conn->blli[blli_index])) 691 conn->blli_selector = 0; 692 else 693 conn->blli_selector = blli_index + 1; 694 695 cc_conn_set_state(conn, CONN_IN_WAITING); 696 cc_connect_to_user(conn, user); 697 698 cc_user_sig(user, USER_SIG_SETUP_IND, NULL, 0); 699} 700 701static void 702cc_party_setup_conf(struct ccconn *conn) 703{ 704 struct ccparty *party; 705 706 party = cc_party_find(conn, conn->epref.epref); 707 if (party == NULL) { 708 cc_party_log(party, "no party for %s", 709 cc_conn_sigtab[CONN_SIG_SETUP_CONFIRM]); 710 return; 711 } 712 if (party->state != PARTY_WAIT_SETUP_CONF) { 713 cc_party_log(party, "bad state=%s for signal=%s", 714 ptab[party->state], cc_conn_sigtab[CONN_SIG_SETUP_CONFIRM]); 715 return; 716 } 717 cc_party_set_state(party, PARTY_ACTIVE); 718} 719 720static void 721cc_party_add_ack_ind(struct ccconn *conn, const struct uni_ie_epref *epref) 722{ 723 struct ccparty *party; 724 725 party = cc_party_find(conn, epref->epref); 726 if (party == NULL) { 727 cc_party_log(party, "no party for %s", 728 cc_conn_sigtab[CONN_SIG_PARTY_ADD_ACK_IND]); 729 } 730 if (party->state != PARTY_ADD_WAIT_ACK) { 731 cc_party_log(party, "bad state=%s for signal=%s", 732 ptab[party->state], 733 cc_conn_sigtab[CONN_SIG_PARTY_ADD_ACK_IND]); 734 return; 735 } 736 cc_party_set_state(party, PARTY_ACTIVE); 737 cc_user_sig(conn->user, USER_SIG_ADD_PARTY_ACK, 738 NULL, epref->epref); 739} 740 741static void 742cc_party_add_rej_ind(struct ccconn *conn, const struct uni_ie_epref *epref) 743{ 744 struct ccparty *party; 745 746 party = cc_party_find(conn, epref->epref); 747 if (party == NULL) { 748 cc_party_log(party, "no party for %s", 749 cc_conn_sigtab[CONN_SIG_PARTY_ADD_REJ_IND]); 750 return; 751 } 752 if (party->state != PARTY_ADD_WAIT_ACK) { 753 cc_party_log(party, "bad state=%s for signal=%s", 754 ptab[party->state], 755 cc_conn_sigtab[CONN_SIG_PARTY_ADD_REJ_IND]); 756 return; 757 } 758 cc_party_set_state(party, PARTY_WAIT_DESTROY); 759 cc_user_sig(conn->user, USER_SIG_ADD_PARTY_REJ, NULL, epref->epref); 760} 761 762static void 763cc_party_drop_ack_ind(struct ccconn *conn, 764 const struct uni_drop_party *drop) 765{ 766 struct ccparty *party; 767 768 party = cc_party_find(conn, drop->epref.epref); 769 if (party == NULL) { 770 cc_party_log(party, "no party for %s", 771 cc_conn_sigtab[CONN_SIG_DROP_PARTY_ACK_IND]); 772 return; 773 } 774 switch (party->state) { 775 776 case PARTY_ACTIVE: /* P1 */ 777 memset(&conn->user->cause[1], 0, sizeof(conn->user->cause[1])); 778 conn->user->cause[0] = drop->cause; 779 cc_party_set_state(party, PARTY_WAIT_DESTROY); 780 cc_user_sig(conn->user, USER_SIG_DROP_PARTY_IND, 781 NULL, party->epref.epref); 782 break; 783 784 case PARTY_ADD_WAIT_ACK: /* P4 */ 785 memset(&conn->user->cause[1], 0, sizeof(conn->user->cause[1])); 786 conn->user->cause[0] = drop->cause; 787 cc_party_set_state(party, PARTY_WAIT_DESTROY); 788 cc_user_sig(conn->user, USER_SIG_ADD_PARTY_REJ, 789 NULL, party->epref.epref); 790 break; 791 792 case PARTY_DROP_WAIT_ACK: /* P6 */ 793 cc_party_set_state(party, PARTY_WAIT_DESTROY); 794 cc_user_sig(conn->user, USER_SIG_DROP_PARTY_OK, NULL, 0); 795 break; 796 797 case PARTY_WAIT_SETUP_COMPL: /* P8 */ 798 case PARTY_WAIT_SETUP_CONF: /* P10 */ 799 cc_party_set_state(party, PARTY_WAIT_DESTROY); 800 break; 801 802 default: 803 cc_party_log(party, "bad state=%s for signal=%s", 804 ptab[party->state], 805 cc_conn_sigtab[CONN_SIG_DROP_PARTY_ACK_IND]); 806 break; 807 } 808} 809 810/* 811 * Handle a signal to this connection 812 */ 813void 814cc_conn_sig_handle(struct ccconn *conn, enum conn_sig sig, 815 void *arg, u_int iarg) 816{ 817 struct ccparty *party; 818 819 if (conn->cc->log & CCLOG_CONN_SIG) 820 cc_conn_log(conn, "signal %s in state %s", cc_conn_sigtab[sig], 821 stab[conn->state]); 822 823 switch (sig) { 824 825 case CONN_SIG_CONNECT_OUTGOING: 826 /* Do SETUP */ 827 { 828 struct uni_msg *u; 829 struct uniapi_setup_request *setup; 830 831 if (conn->state != CONN_OUT_PREPARING) 832 goto bad_state; 833 834 if (IE_ISGOOD(conn->bearer) && 835 conn->bearer.cfg == UNI_BEARER_MP) { 836 IE_SETPRESENT(conn->epref); 837 conn->epref.flag = 0; 838 conn->epref.epref = 0; 839 } 840 841 /* 842 * Construct message to UNI. 843 */ 844 u = uni_msg_alloc(sizeof(struct uniapi_setup_request)); 845 if (u == NULL) { 846 cc_user_sig(conn->user, USER_SIG_CONNECT_OUTGOING_ERR, 847 NULL, ATMERR_NOMEM); 848 return; 849 } 850 setup = uni_msg_wptr(u, struct uniapi_setup_request *); 851 memset(setup, 0, sizeof(*setup)); 852 u->b_wptr += sizeof(struct uniapi_setup_request); 853 854 setup->setup.hdr.act = UNI_MSGACT_DEFAULT; 855 memcpy(setup->setup.blli, conn->blli, sizeof(conn->blli)); 856 setup->setup.bearer = conn->bearer; 857 setup->setup.traffic = conn->traffic; 858 setup->setup.qos = conn->qos; 859 setup->setup.exqos = conn->exqos; 860 setup->setup.called = conn->called; 861 setup->setup.calledsub[0] = conn->calledsub; 862 setup->setup.aal = conn->aal; 863 setup->setup.epref = conn->epref; 864 setup->setup.eetd = conn->eetd; 865 setup->setup.abrsetup = conn->abrsetup; 866 setup->setup.abradd = conn->abradd; 867 setup->setup.calling = conn->calling; 868 setup->setup.callingsub[0] = conn->callingsub; 869 setup->setup.connid = conn->connid; 870 memcpy(setup->setup.tns, conn->tns, sizeof(conn->tns)); 871 setup->setup.atraffic = conn->atraffic; 872 setup->setup.mintraffic = conn->mintraffic; 873 setup->setup.cscope = conn->cscope; 874 setup->setup.bhli = conn->bhli; 875 setup->setup.mdcr = conn->mdcr; 876 877 cc_conn_set_state(conn, CONN_OUT_WAIT_CREATE); 878 cc_send_uni(conn, UNIAPI_SETUP_request, u); 879 880 break; 881 } 882 883 884 case CONN_SIG_ARRIVAL: 885 /* user informed of arrival of this call */ 886 if (conn->state != CONN_IN_WAITING) 887 goto bad_state; 888 cc_conn_set_state(conn, CONN_IN_ARRIVED); 889 break; 890 891 892 case CONN_SIG_RELEASE: 893 { 894 /* Release this call */ 895 struct uni_msg *u; 896 struct uniapi_release_request *req; 897 898 if (conn->state != CONN_ACTIVE && 899 conn->state != CONN_IN_WAIT_COMPL) 900 goto bad_state; 901 902 if ((u = uni_msg_alloc(sizeof(*req))) == NULL) 903 return; 904 905 req = uni_msg_wptr(u, struct uniapi_release_request *); 906 memset(req, 0, sizeof(*req)); 907 u->b_wptr += sizeof(struct uniapi_release_request); 908 909 req->release.hdr.cref = conn->cref; 910 req->release.hdr.act = UNI_MSGACT_DEFAULT; 911 912 req->release.cause[0] = conn->cause[0]; 913 req->release.cause[1] = conn->cause[1]; 914 915 if (conn->state == CONN_ACTIVE) 916 cc_conn_set_state(conn, CONN_REL_WAIT_OK); 917 else 918 cc_conn_set_state(conn, CONN_REL_IN_WAIT_OK); 919 920 cc_send_uni(conn, UNIAPI_RELEASE_request, u); 921 break; 922 } 923 924 case CONN_SIG_REJECT: 925 { 926 /* reject from user */ 927 struct ccuser *user = conn->user; 928 929 if (conn->state != CONN_IN_ARRIVED) { 930 cc_user_sig(user, USER_SIG_REJECT_ERR, 931 NULL, ATMERR_BAD_STATE); 932 break; 933 } 934 cc_conn_set_state(conn, CONN_REJ_WAIT_OK); 935 do_release_response(conn, 0, conn->cause); 936 break; 937 } 938 939 940 case CONN_SIG_ACCEPT: 941 { 942 /* User accepts. */ 943 struct ccuser *newep = arg; 944 struct uni_msg *u; 945 struct uniapi_setup_response *resp; 946 struct ccuser *user = conn->user; 947 948 if (conn->state != CONN_IN_ARRIVED) { 949 cc_user_sig(user, USER_SIG_ACCEPT_ERR, 950 NULL, ATMERR_PREVIOUSLY_ABORTED); 951 break; 952 } 953 954 u = uni_msg_alloc(sizeof(struct uniapi_setup_response)); 955 if (u == NULL) { 956 cc_user_sig(user, USER_SIG_ACCEPT_ERR, 957 NULL, ATMERR_NOMEM); 958 return; 959 } 960 961 /* 962 * Link to the new endpoint 963 */ 964 conn->acceptor = newep; 965 newep->accepted = conn; 966 967 /* 968 * Construct connect message 969 */ 970 resp = uni_msg_wptr(u, struct uniapi_setup_response *); 971 memset(resp, 0, sizeof(*resp)); 972 u->b_wptr += sizeof(*resp); 973 974 resp->connect.hdr.act = UNI_MSGACT_DEFAULT; 975 resp->connect.hdr.cref = conn->cref; 976 977 /* 978 * attributes 979 */ 980 if (conn->dirty_attr & CCDIRTY_AAL) 981 resp->connect.aal = conn->aal; 982 if (conn->dirty_attr & CCDIRTY_BLLI) 983 resp->connect.blli = 984 conn->blli[conn->blli_selector - 1]; 985 if (conn->dirty_attr & CCDIRTY_CONNID) 986 resp->connect.connid = conn->connid; 987 /* XXX NOTIFY */ 988 if (conn->dirty_attr & CCDIRTY_EETD) 989 resp->connect.eetd = conn->eetd; 990 /* XXX GIT */ 991 /* XXX UU */ 992 if (conn->dirty_attr & CCDIRTY_TRAFFIC) 993 resp->connect.traffic = conn->traffic; 994 if (conn->dirty_attr & CCDIRTY_EXQOS) 995 resp->connect.exqos = conn->exqos; 996 if (conn->dirty_attr & CCDIRTY_ABRSETUP) 997 resp->connect.abrsetup = conn->abrsetup; 998 if (conn->dirty_attr & CCDIRTY_ABRADD) 999 resp->connect.abradd = conn->abradd; 1000 1001 /* 1002 * If the SETUP had an endpoint reference - echo it back 1003 */ 1004 if (IE_ISPRESENT(conn->epref)) { 1005 resp->connect.epref = conn->epref; 1006 resp->connect.epref.flag = !resp->connect.epref.flag; 1007 } 1008 1009 cc_conn_set_state(conn, CONN_IN_WAIT_ACCEPT_OK); 1010 cc_send_uni(conn, UNIAPI_SETUP_response, u); 1011 break; 1012 } 1013 1014 1015 case CONN_SIG_ADD_PARTY: 1016 { 1017 /* request to add party from user */ 1018 struct uni_msg *u; 1019 struct uniapi_add_party_request *req; 1020 1021 if (conn->state != CONN_ACTIVE) 1022 goto bad_state; 1023 1024 /* create the party */ 1025 party = cc_party_create(conn, (u_int)(uintptr_t)arg, 0); 1026 if (party == NULL) { 1027 cc_user_sig(conn->user, USER_SIG_ADD_PARTY_ERR, 1028 NULL, ATMERR_NOMEM); 1029 return; 1030 } 1031 party->called = conn->called; 1032 1033 /* Construct message to UNI. */ 1034 u = uni_msg_alloc(sizeof(struct uniapi_setup_request)); 1035 if (u == NULL) { 1036 cc_party_destroy(party); 1037 cc_user_sig(conn->user, USER_SIG_ADD_PARTY_ERR, 1038 NULL, ATMERR_NOMEM); 1039 return; 1040 } 1041 1042 req = uni_msg_wptr(u, struct uniapi_add_party_request *); 1043 memset(req, 0, sizeof(*req)); 1044 u->b_wptr += sizeof(struct uniapi_add_party_request); 1045 1046 req->add.hdr.act = UNI_MSGACT_DEFAULT; 1047 req->add.hdr.cref = conn->cref; 1048 req->add.epref = party->epref; 1049 req->add.called = party->called; 1050 1051 cc_party_set_state(party, PARTY_ADD_WAIT_CREATE); 1052 cc_send_uni(conn, UNIAPI_ADD_PARTY_request, u); 1053 break; 1054 } 1055 1056 1057 case CONN_SIG_DROP_PARTY: 1058 { 1059 /* user request to drop a party */ 1060 struct uni_msg *u; 1061 struct uniapi_drop_party_request *req; 1062 1063 if (conn->state != CONN_ACTIVE) 1064 goto bad_state; 1065 1066 party = cc_party_find(conn, (u_int)(uintptr_t)arg); 1067 if (party == NULL) { 1068 cc_user_sig(conn->user, USER_SIG_DROP_PARTY_ERR, 1069 NULL, ATMERR_BAD_PARTY); 1070 return; 1071 } 1072 1073 switch (party->state) { 1074 1075 case PARTY_ACTIVE: 1076 case PARTY_ADD_WAIT_ACK: 1077 break; 1078 1079 default: 1080 cc_user_sig(conn->user, USER_SIG_DROP_PARTY_ERR, 1081 NULL, ATMERR_BAD_STATE); 1082 return; 1083 1084 } 1085 /* 1086 * Construct message to UNI. 1087 */ 1088 u = uni_msg_alloc(sizeof(*req)); 1089 if (u == NULL) { 1090 cc_user_sig(conn->user, USER_SIG_DROP_PARTY_ERR, 1091 NULL, ATMERR_NOMEM); 1092 return; 1093 } 1094 1095 req = uni_msg_wptr(u, struct uniapi_drop_party_request *); 1096 memset(req, 0, sizeof(*req)); 1097 u->b_wptr += sizeof(struct uniapi_drop_party_request); 1098 1099 req->drop.hdr.act = UNI_MSGACT_DEFAULT; 1100 req->drop.hdr.cref = conn->cref; 1101 req->drop.epref = party->epref; 1102 req->drop.cause = conn->cause[0]; 1103 1104 if (party->state == PARTY_ACTIVE) 1105 cc_party_set_state(party, PARTY_DROP_WAIT_OK); 1106 else 1107 cc_party_set_state(party, PARTY_ADD_DROP_WAIT_OK); 1108 cc_send_uni(conn, UNIAPI_DROP_PARTY_request, u); 1109 break; 1110 } 1111 1112 case CONN_SIG_DROP_PARTY_ACK_IND: 1113 { 1114 struct uni_msg *msg = arg; 1115 struct uniapi_drop_party_ack_indication *ind = uni_msg_rptr(msg, 1116 struct uniapi_drop_party_ack_indication *); 1117 1118 cc_party_drop_ack_ind(conn, &ind->drop); 1119 break; 1120 } 1121 1122 1123 case CONN_SIG_USER_ABORT: 1124 /* 1125 * Aborting a connection. This is callable in all states. 1126 * The connection is already disconnected from the user. 1127 * The cause is in cause[]. 1128 */ 1129 switch (conn->state) { 1130 1131 case CONN_NULL: /* C0 */ 1132 case CONN_OUT_PREPARING: /* C1 */ 1133 cc_conn_destroy(conn); 1134 break; 1135 1136 case CONN_OUT_WAIT_CONF: /* C4 */ 1137 case CONN_ACTIVE: /* C5 */ 1138 do_release_request(conn, conn->cause); 1139 cc_conn_set_state(conn, CONN_AB_WAIT_REQ_OK); 1140 break; 1141 1142 case CONN_IN_WAITING: /* C21 */ 1143 /* that should not happen */ 1144 goto bad_state; 1145 break; 1146 1147 case CONN_IN_ARRIVED: /* C11 */ 1148 /* 1149 * This is called only for the first connection 1150 * of the user - the others are re-dispatched. 1151 */ 1152 do_release_response(conn, 0, conn->cause); 1153 cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK); 1154 break; 1155 1156 case CONN_IN_WAIT_COMPL: /* C13 */ 1157 do_release_request(conn, conn->cause); 1158 cc_conn_set_state(conn, CONN_AB_WAIT_REQ_OK); 1159 break; 1160 1161 case CONN_OUT_WAIT_DESTROY: /* C20 */ 1162 cc_conn_set_state(conn, CONN_AB_FLUSH_IND); 1163 break; 1164 1165 case CONN_IN_WAIT_ACCEPT_OK: /* C12 */ 1166 case CONN_AB_WAIT_REQ_OK: /* C33 */ 1167 case CONN_AB_WAIT_RESP_OK: /* C34 */ 1168 case CONN_AB_FLUSH_IND: /* C35 */ 1169 /* just ignore */ 1170 break; 1171 1172 /* 1173 * The following states may not happen, because 1174 * we're waiting for a response from the UNI stack. 1175 * As soon as the response comes the ABORT is undefered 1176 * and will hit us (but in another state). 1177 */ 1178 case CONN_OUT_WAIT_CREATE: /* C2 */ 1179 case CONN_OUT_WAIT_OK: /* C3 */ 1180 case CONN_IN_PREPARING: /* C10 */ 1181 case CONN_REJ_WAIT_OK: /* C14 */ 1182 case CONN_REL_IN_WAIT_OK: /* C15 */ 1183 case CONN_REL_WAIT_OK: /* C20 */ 1184 goto bad_state; 1185 } 1186 break; 1187 1188 1189 case CONN_SIG_CREATED: 1190 { 1191 /* 1192 * CALL_CREATED message from UNI. This can happen for either 1193 * incoming or outgoing connections. 1194 */ 1195 struct uni_msg *msg = arg; 1196 struct uniapi_call_created *cr = uni_msg_rptr(msg, 1197 struct uniapi_call_created *); 1198 1199 switch (conn->state) { 1200 1201 case CONN_OUT_WAIT_CREATE: 1202 conn->cref = cr->cref; 1203 cc_conn_set_state(conn, CONN_OUT_WAIT_OK); 1204 break; 1205 1206 case CONN_NULL: 1207 conn->cref = cr->cref; 1208 cc_conn_set_state(conn, CONN_IN_PREPARING); 1209 break; 1210 1211 default: 1212 goto bad_state; 1213 } 1214 break; 1215 } 1216 1217 case CONN_SIG_DESTROYED: 1218 /* 1219 * CALL_DESTROYED message from UNI. 1220 */ 1221 switch (conn->state) { 1222 1223 case CONN_OUT_WAIT_DESTROY: 1224 cc_conn_rem_port(conn); 1225 cc_conn_set_state(conn, CONN_OUT_PREPARING); 1226 if (conn->user != NULL) 1227 cc_user_sig(conn->user, 1228 USER_SIG_CONNECT_OUTGOING_ERR, 1229 NULL, ATM_MKUNIERR(conn->reason)); 1230 break; 1231 1232 case CONN_AB_FLUSH_IND: 1233 cc_conn_destroy(conn); 1234 break; 1235 1236 case CONN_IN_PREPARING: 1237 cc_conn_destroy(conn); 1238 break; 1239 1240 default: 1241 goto bad_state; 1242 } 1243 break; 1244 1245 1246 case CONN_SIG_SETUP_CONFIRM: 1247 /* Setup confirm from the UNI. */ 1248 { 1249 struct uni_msg *msg = arg; 1250 struct uniapi_setup_confirm *conf = uni_msg_rptr(msg, 1251 struct uniapi_setup_confirm *); 1252 1253 switch (conn->state) { 1254 1255 case CONN_OUT_WAIT_CONF: 1256 /* 1257 * Shuffle attributes and inform the user. 1258 * Negotiable attributes are condititionally shuffled, 1259 * because not returning it means accepting it 1260 * (in case of blli the first instance of it). 1261 * All others are shuffled unconditionally. 1262 * Here we should also open the VCI in the driver. (XXX) 1263 */ 1264#define SHUFFLE(ATTR) conn->ATTR = conf->connect.ATTR 1265#define COND_SHUFFLE(ATTR) if (IE_ISPRESENT(conf->connect.ATTR)) SHUFFLE(ATTR) 1266 1267 COND_SHUFFLE(aal); 1268 (void)memset(conn->blli + 1, 0, 1269 sizeof(conn->blli) - sizeof(conn->blli[0])); 1270 if (IE_ISPRESENT(conf->connect.blli)) 1271 conn->blli[0] = conf->connect.blli; 1272 conn->blli_selector = 1; 1273 COND_SHUFFLE(epref); 1274 SHUFFLE(conned); 1275 SHUFFLE(connedsub); 1276 SHUFFLE(eetd); 1277 COND_SHUFFLE(traffic); 1278 COND_SHUFFLE(exqos); 1279 COND_SHUFFLE(abrsetup); 1280 COND_SHUFFLE(abradd); 1281 COND_SHUFFLE(connid); 1282#undef SHUFFLE 1283#undef COND_SHUFFLE 1284 if (IE_ISGOOD(conn->epref)) 1285 cc_party_setup_conf(conn); 1286 1287 cc_conn_set_state(conn, CONN_ACTIVE); 1288 cc_user_sig(conn->user, USER_SIG_SETUP_CONFIRM, 1289 NULL, 0); 1290 break; 1291 1292 case CONN_AB_FLUSH_IND: 1293 case CONN_AB_WAIT_RESP_OK: 1294 break; 1295 1296 default: 1297 goto bad_state; 1298 } 1299 break; 1300 } 1301 1302 case CONN_SIG_SETUP_IND: 1303 { 1304 /* SETUP indication */ 1305 struct uni_msg *msg = arg; 1306 struct uniapi_setup_indication *ind = uni_msg_rptr(msg, 1307 struct uniapi_setup_indication *); 1308 u_int i; 1309 1310 if (conn->state != CONN_IN_PREPARING) 1311 goto bad_state; 1312 1313 /* 1314 * Shuffle information elements. 1315 */ 1316 for (i = 0; i < UNI_NUM_IE_BLLI; i++) 1317 conn->blli[i] = ind->setup.blli[i]; 1318 conn->bearer = ind->setup.bearer; 1319 conn->traffic = ind->setup.traffic; 1320 conn->qos = ind->setup.qos; 1321 conn->exqos = ind->setup.exqos; 1322 conn->called = ind->setup.called; 1323 conn->calledsub = ind->setup.calledsub[0]; 1324 conn->aal = ind->setup.aal; 1325 conn->epref = ind->setup.epref; 1326 conn->eetd = ind->setup.eetd; 1327 conn->abrsetup = ind->setup.abrsetup; 1328 conn->abradd = ind->setup.abradd; 1329 conn->calling = ind->setup.calling; 1330 conn->callingsub = ind->setup.callingsub[0]; 1331 conn->connid = ind->setup.connid; 1332 for (i = 0; i < UNI_NUM_IE_TNS; i++) 1333 conn->tns[i] = ind->setup.tns[i]; 1334 conn->atraffic = ind->setup.atraffic; 1335 conn->mintraffic = ind->setup.mintraffic; 1336 conn->cscope = ind->setup.cscope; 1337 conn->bhli = ind->setup.bhli; 1338 conn->mdcr = ind->setup.mdcr; 1339 1340 cc_conn_dispatch(conn); 1341 break; 1342 } 1343 1344 1345 case CONN_SIG_SETUP_COMPL: 1346 { 1347 struct uni_msg *msg = arg; 1348 struct uniapi_setup_indication *ind __unused = 1349 uni_msg_rptr(msg, struct uniapi_setup_indication *); 1350 1351 /* SETUP_COMPLETE.indication from UNI */ 1352 if (conn->state == CONN_AB_FLUSH_IND || 1353 conn->state == CONN_AB_WAIT_RESP_OK) 1354 break; 1355 1356 if (conn->state != CONN_IN_WAIT_COMPL) 1357 goto bad_state; 1358 1359 cc_conn_set_state(conn, CONN_ACTIVE); 1360 1361 LIST_FOREACH(party, &conn->parties, link) { 1362 if (party->state == PARTY_WAIT_SETUP_COMPL) 1363 cc_party_set_state(party, PARTY_ACTIVE); 1364 else 1365 cc_party_log(party, "bad state=%s for sig=%s", 1366 ptab[party->state], 1367 cc_conn_sigtab[CONN_SIG_SETUP_COMPL]); 1368 } 1369 1370 cc_user_sig(conn->user, USER_SIG_SETUP_COMPL, NULL, 0); 1371 break; 1372 } 1373 1374 1375 case CONN_SIG_PROC_IND: 1376 { 1377 /* 1378 * ALERTING.indication and PROCEEDING.indication are entirly 1379 * ignored by the specification. We need to at least save the 1380 * connid information element. 1381 */ 1382 struct uni_msg *msg = arg; 1383 struct uniapi_proceeding_indication *ind = uni_msg_rptr(msg, 1384 struct uniapi_proceeding_indication *); 1385 1386 switch (conn->state) { 1387 1388 case CONN_OUT_WAIT_CONF: 1389 if (IE_ISGOOD(ind->call_proc.connid)) 1390 conn->connid = ind->call_proc.connid; 1391 break; 1392 1393 case CONN_AB_FLUSH_IND: 1394 case CONN_AB_WAIT_RESP_OK: 1395 break; 1396 1397 default: 1398 goto bad_state; 1399 } 1400 break; 1401 } 1402 1403 case CONN_SIG_ALERTING_IND: 1404 { 1405 struct uni_msg *msg = arg; 1406 struct uniapi_alerting_indication *ind = uni_msg_rptr(msg, 1407 struct uniapi_alerting_indication *); 1408 1409 switch (conn->state) { 1410 1411 case CONN_OUT_WAIT_CONF: 1412 if (IE_ISGOOD(ind->alerting.connid)) 1413 conn->connid = ind->alerting.connid; 1414 break; 1415 1416 case CONN_AB_FLUSH_IND: 1417 case CONN_AB_WAIT_RESP_OK: 1418 break; 1419 1420 default: 1421 goto bad_state; 1422 } 1423 break; 1424 } 1425 1426 case CONN_SIG_REL_CONF: 1427 { 1428 /* RELEASE.confirm from UNI */ 1429 struct uni_msg *msg = arg; 1430 struct uniapi_release_confirm *conf = uni_msg_rptr(msg, 1431 struct uniapi_release_confirm *); 1432 1433 switch (conn->state) { 1434 1435 case CONN_OUT_WAIT_CONF: 1436 case CONN_ACTIVE: 1437 cc_conn_set_state(conn, CONN_AB_FLUSH_IND); 1438 memcpy(conn->user->cause, conf->release.cause, 1439 sizeof(conn->user->cause)); 1440 /* 1441 * If any party is in P6, ok the user 1442 */ 1443 LIST_FOREACH(party, &conn->parties, link) { 1444 if (party->state == PARTY_DROP_WAIT_ACK) { 1445 cc_party_set_state(party, 1446 PARTY_WAIT_DESTROY); 1447 cc_user_sig(conn->user, 1448 USER_SIG_DROP_PARTY_OK, 1449 NULL, party->epref.epref); 1450 } 1451 } 1452 cc_user_sig(conn->user, USER_SIG_RELEASE_CONFIRM, 1453 NULL, 0); 1454 cc_disconnect_from_user(conn); 1455 break; 1456 1457 case CONN_AB_FLUSH_IND: 1458 case CONN_AB_WAIT_RESP_OK: 1459 break; 1460 1461 case CONN_IN_WAITING: 1462 cc_disconnect_from_user(conn); 1463 cc_conn_set_state(conn, CONN_AB_FLUSH_IND); 1464 break; 1465 1466 case CONN_IN_ARRIVED: 1467 conn->user->aborted = 1; 1468 memcpy(conn->user->cause, conf->release.cause, 1469 sizeof(conn->user->cause)); 1470 cc_conn_set_state(conn, CONN_AB_FLUSH_IND); 1471 cc_disconnect_from_user(conn); 1472 break; 1473 1474 case CONN_IN_WAIT_COMPL: 1475 cc_conn_set_state(conn, CONN_AB_FLUSH_IND); 1476 memcpy(conn->user->cause, conf->release.cause, 1477 sizeof(conn->user->cause)); 1478 cc_user_sig(conn->user, USER_SIG_RELEASE_CONFIRM, 1479 NULL, 0); 1480 cc_disconnect_from_user(conn); 1481 break; 1482 1483 default: 1484 goto bad_state; 1485 } 1486 break; 1487 } 1488 1489 case CONN_SIG_REL_IND: 1490 { 1491 /* RELEASE.ind from UNI */ 1492 struct uni_msg *msg = arg; 1493 struct uniapi_release_indication *conf = uni_msg_rptr(msg, 1494 struct uniapi_release_indication *); 1495 1496 switch (conn->state) { 1497 1498 case CONN_OUT_WAIT_CONF: 1499 case CONN_ACTIVE: 1500 do_release_response(conn, 0, NULL); 1501 cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK); 1502 memcpy(conn->user->cause, conf->release.cause, 1503 sizeof(conn->user->cause)); 1504 /* 1505 * If any party is in P6, ok the user 1506 */ 1507 LIST_FOREACH(party, &conn->parties, link) { 1508 if (party->state == PARTY_DROP_WAIT_ACK) { 1509 cc_party_set_state(party, 1510 PARTY_WAIT_DESTROY); 1511 cc_user_sig(conn->user, 1512 USER_SIG_DROP_PARTY_OK, 1513 NULL, party->epref.epref); 1514 } 1515 } 1516 cc_user_sig(conn->user, USER_SIG_RELEASE_CONFIRM, 1517 NULL, 0); 1518 cc_disconnect_from_user(conn); 1519 break; 1520 1521 case CONN_AB_FLUSH_IND: 1522 case CONN_AB_WAIT_RESP_OK: 1523 break; 1524 1525 case CONN_IN_WAITING: 1526 cc_disconnect_from_user(conn); 1527 do_release_response(conn, 0, NULL); 1528 cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK); 1529 break; 1530 1531 case CONN_IN_ARRIVED: 1532 conn->user->aborted = 1; 1533 cc_disconnect_from_user(conn); 1534 do_release_response(conn, 0, NULL); 1535 cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK); 1536 break; 1537 1538 case CONN_IN_WAIT_COMPL: 1539 do_release_response(conn, 0, NULL); 1540 cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK); 1541 memcpy(conn->user->cause, conf->release.cause, 1542 sizeof(conn->user->cause)); 1543 cc_user_sig(conn->user, USER_SIG_RELEASE_CONFIRM, 1544 NULL, 0); 1545 cc_disconnect_from_user(conn); 1546 break; 1547 default: 1548 goto bad_state; 1549 break; 1550 } 1551 break; 1552 } 1553 1554 case CONN_SIG_PARTY_ALERTING_IND: 1555 /* party alerting from UNI */ 1556 if (conn->state == CONN_AB_FLUSH_IND) 1557 break; 1558 if (conn->state != CONN_ACTIVE) 1559 goto bad_state; 1560 /* ignore */ 1561 break; 1562 1563 case CONN_SIG_PARTY_ADD_ACK_IND: 1564 { 1565 /* ADD PARTY ACKNOWLEDGE from UNI */ 1566 struct uni_msg *msg = arg; 1567 struct uniapi_add_party_ack_indication *ind = uni_msg_rptr(msg, 1568 struct uniapi_add_party_ack_indication *); 1569 1570 if (conn->state == CONN_AB_FLUSH_IND) 1571 break; 1572 if (conn->state != CONN_ACTIVE) 1573 goto bad_state; 1574 1575 cc_party_add_ack_ind(conn, &ind->ack.epref); 1576 break; 1577 } 1578 1579 1580 case CONN_SIG_PARTY_ADD_REJ_IND: 1581 { 1582 /* ADD PARTY REJECT indication */ 1583 struct uni_msg *msg = arg; 1584 struct uniapi_add_party_rej_indication *ind = uni_msg_rptr(msg, 1585 struct uniapi_add_party_rej_indication *); 1586 1587 if (conn->state == CONN_AB_FLUSH_IND) 1588 break; 1589 if (conn->state != CONN_ACTIVE) 1590 goto bad_state; 1591 1592 memset(&conn->user->cause[1], 0, sizeof(conn->user->cause[1])); 1593 conn->user->cause[0] = ind->rej.cause; 1594 1595 cc_party_add_rej_ind(conn, &ind->rej.epref); 1596 break; 1597 } 1598 1599 1600 case CONN_SIG_DROP_PARTY_IND: 1601 { 1602 /* DROP_PARTY.indication from UNI */ 1603 struct uni_msg *msg = arg; 1604 struct uniapi_drop_party_indication *ind = uni_msg_rptr(msg, 1605 struct uniapi_drop_party_indication *); 1606 struct uniapi_drop_party_ack_request *req; 1607 struct uni_msg *u; 1608 1609 if (conn->state == CONN_AB_FLUSH_IND) 1610 break; 1611 if (conn->state != CONN_ACTIVE) 1612 goto bad_state; 1613 1614 party = cc_party_find(conn, ind->drop.epref.epref); 1615 if (party == NULL) { 1616 cc_party_log(party, "no party for %s", 1617 cc_conn_sigtab[sig]); 1618 break; 1619 } 1620 1621 u = uni_msg_alloc(sizeof(*req)); 1622 if (u == NULL) 1623 return; 1624 1625 memset(&conn->user->cause[1], 0, sizeof(conn->user->cause[1])); 1626 conn->user->cause[0] = ind->drop.cause; 1627 1628 switch (party->state) { 1629 1630 default: 1631 cc_party_log(party, "bad state %s for DROP.ind", 1632 ptab[party->state]); 1633 /* FALLTHRU */ 1634 1635 case PARTY_ACTIVE: /* P1 -> P9 */ 1636 cc_party_set_state(party, PARTY_WAIT_DROP_ACK_OK); 1637 break; 1638 1639 case PARTY_ADD_WAIT_ACK: /* P4 -> P12 */ 1640 cc_party_set_state(party, PARTY_ADD_DROPACK_WAIT_OK); 1641 break; 1642 } 1643 1644 /* 1645 * Construct message to UNI. 1646 */ 1647 req = uni_msg_wptr(u, struct uniapi_drop_party_ack_request *); 1648 memset(req, 0, sizeof(*req)); 1649 u->b_wptr += sizeof(*req); 1650 1651 IE_SETPRESENT(req->ack.epref); 1652 req->ack.hdr.act = UNI_MSGACT_DEFAULT; 1653 req->ack.hdr.cref = conn->cref; 1654 1655 req->ack.epref.flag = 0; 1656 req->ack.epref.epref = ind->drop.epref.epref; 1657 1658 cc_send_uni(conn, UNIAPI_DROP_PARTY_ACK_request, u); 1659 break; 1660 } 1661 1662 case CONN_SIG_OK: 1663 { 1664 /* OK response from UNI */ 1665 struct ccuser *user = conn->user; 1666 1667 switch (conn->state) { 1668 1669 case CONN_OUT_WAIT_OK: /* C3 */ 1670 cc_conn_set_state(conn, CONN_OUT_WAIT_CONF); 1671 if (conn->user != NULL) 1672 cc_user_sig(conn->user, 1673 USER_SIG_CONNECT_OUTGOING_OK, NULL, 0); 1674 break; 1675 1676 case CONN_AB_WAIT_RESP_OK: /* C33 */ 1677 case CONN_AB_WAIT_REQ_OK: /* C34 */ 1678 cc_conn_set_state(conn, CONN_AB_FLUSH_IND); 1679 break; 1680 1681 case CONN_REL_WAIT_OK: /* C20 */ 1682 case CONN_REL_IN_WAIT_OK: /* C15 */ 1683 cc_conn_set_state(conn, CONN_AB_FLUSH_IND); 1684 if (conn->user != NULL) { 1685 /* connection has not been aborted */ 1686 memset(&conn->user->cause, 0, 1687 sizeof(conn->user->cause)); 1688 cc_user_sig(conn->user, 1689 USER_SIG_RELEASE_CONFIRM, NULL, 0); 1690 cc_disconnect_from_user(conn); 1691 } 1692 break; 1693 1694 case CONN_IN_WAIT_ACCEPT_OK: /* C12 */ 1695 if (user == NULL) { 1696 /* has been aborted */ 1697 do_release_request(conn, NULL); 1698 cc_conn_set_state(conn, CONN_AB_WAIT_REQ_OK); 1699 break; 1700 } 1701 cc_conn_set_state(conn, CONN_IN_WAIT_COMPL); 1702 cc_disconnect_from_user(conn); 1703 cc_user_sig(user, USER_SIG_ACCEPT_OK, NULL, 0); 1704 if (conn->acceptor == NULL) { 1705 do_release_request(conn, NULL); 1706 cc_conn_set_state(conn, CONN_AB_WAIT_REQ_OK); 1707 break; 1708 } 1709 cc_connect_to_user(conn, conn->acceptor); 1710 cc_conn_reset_acceptor(conn); 1711 cc_user_sig(conn->user, USER_SIG_ACCEPTING, NULL, 0); 1712 break; 1713 1714 case CONN_REJ_WAIT_OK: /* C14 */ 1715 cc_conn_set_state(conn, CONN_AB_FLUSH_IND); 1716 if (user != NULL) { 1717 cc_disconnect_from_user(conn); 1718 cc_user_sig(user, USER_SIG_REJECT_OK, NULL, 0); 1719 } 1720 break; 1721 1722 default: 1723 /* maybe it's for a party */ 1724 LIST_FOREACH(party, &conn->parties, link) { 1725 switch (party->state) { 1726 1727 case PARTY_ADD_WAIT_OK: /* P3 */ 1728 if (user != NULL) 1729 cc_user_sig(user, 1730 USER_SIG_ADD_PARTY_OK, 1731 NULL, 0); 1732 cc_party_set_state(party, 1733 PARTY_ADD_WAIT_ACK); 1734 goto ex_party_ok; 1735 1736 case PARTY_DROP_WAIT_OK: /* P5 */ 1737 cc_party_set_state(party, 1738 PARTY_DROP_WAIT_ACK); 1739 goto ex_party_ok; 1740 1741 case PARTY_WAIT_DROP_ACK_OK: /* P9 */ 1742 case PARTY_ADD_DROPACK_WAIT_OK:/* P12 */ 1743 { 1744 struct ccparty *p1; 1745 1746 cc_party_set_state(party, 1747 PARTY_WAIT_DESTROY); 1748 /* signal to user only if there are any other parties */ 1749 LIST_FOREACH(p1, &conn->parties, link) 1750 if (p1 != party) 1751 break; 1752 if (p1 != NULL && user != NULL) 1753 cc_user_sig(user, 1754 USER_SIG_DROP_PARTY_IND, 1755 NULL, 1756 party->epref.epref); 1757 1758 goto ex_party_ok; 1759 } 1760 1761 case PARTY_ADD_DROP_WAIT_OK: /* P11 */ 1762 cc_party_set_state(party, 1763 PARTY_DROP_WAIT_ACK); 1764 goto ex_party_ok; 1765 1766 default: 1767 break; 1768 } 1769 } 1770 goto bad_state; 1771 ex_party_ok: 1772 break; 1773 } 1774 break; 1775 } 1776 1777 case CONN_SIG_ERROR: 1778 { 1779 /* error response from UNI */ 1780 u_int reason = (iarg >> 16) & 0xffff; 1781 u_int state = iarg & 0xffff; 1782 struct ccuser *user = conn->user; 1783 1784 switch (conn->state) { 1785 1786 case CONN_OUT_WAIT_CREATE: /* C2 */ 1787 cc_conn_rem_port(conn); 1788 cc_conn_set_state(conn, CONN_OUT_PREPARING); 1789 if (conn->user != NULL) 1790 cc_user_sig(conn->user, 1791 USER_SIG_CONNECT_OUTGOING_ERR, 1792 NULL, ATM_MKUNIERR(reason)); 1793 break; 1794 1795 case CONN_OUT_WAIT_OK: /* C3 */ 1796 cc_conn_set_state(conn, CONN_OUT_WAIT_DESTROY); 1797 conn->reason = reason; 1798 break; 1799 1800 case CONN_AB_WAIT_REQ_OK: /* C33 */ 1801 if (state == UNI_CALLSTATE_U12) { 1802 do_release_response(conn, 0, conn->cause); 1803 cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK); 1804 break; 1805 } 1806 cc_conn_set_state(conn, CONN_AB_FLUSH_IND); 1807 break; 1808 1809 case CONN_AB_WAIT_RESP_OK: /* C34 */ 1810 cc_conn_set_state(conn, CONN_AB_FLUSH_IND); 1811 break; 1812 1813 case CONN_REL_WAIT_OK: /* C20 */ 1814 if (user == NULL) { 1815 /* connection has been aborted. */ 1816 if (state == UNI_CALLSTATE_U10) { 1817 /* do what we can */ 1818 do_release_request(conn, conn->cause); 1819 cc_conn_set_state(conn, 1820 CONN_AB_WAIT_REQ_OK); 1821 } else if (state == UNI_CALLSTATE_U12) { 1822 do_release_response(conn, 0, NULL); 1823 cc_conn_set_state(conn, 1824 CONN_AB_WAIT_RESP_OK); 1825 } else { 1826 cc_conn_set_state(conn, 1827 CONN_AB_FLUSH_IND); 1828 } 1829 break; 1830 } 1831 if (state == UNI_CALLSTATE_U10) { 1832 cc_conn_set_state(conn, CONN_ACTIVE); 1833 cc_user_sig(conn->user, USER_SIG_RELEASE_ERR, 1834 NULL, reason); 1835 } else if (state == UNI_CALLSTATE_U12) { 1836 do_release_response(conn, 0, NULL); 1837 cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK); 1838 memset(&conn->user->cause, 0, 1839 sizeof(conn->user->cause)); 1840 cc_user_sig(conn->user, 1841 USER_SIG_RELEASE_CONFIRM, NULL, 0); 1842 cc_disconnect_from_user(conn); 1843 } else { 1844 cc_conn_set_state(conn, CONN_AB_FLUSH_IND); 1845 memset(&conn->user->cause, 0, 1846 sizeof(conn->user->cause)); 1847 cc_user_sig(conn->user, 1848 USER_SIG_RELEASE_CONFIRM, NULL, 0); 1849 cc_disconnect_from_user(conn); 1850 } 1851 break; 1852 1853 case CONN_IN_WAIT_ACCEPT_OK: /* C12 */ 1854 if (user == NULL) { 1855 /* connection was aborted */ 1856 if (state == UNI_CALLSTATE_U6 || 1857 state == UNI_CALLSTATE_U7 || 1858 state == UNI_CALLSTATE_U9 || 1859 state == UNI_CALLSTATE_U12) { 1860 do_release_response(conn, 0, NULL); 1861 cc_conn_set_state(conn, 1862 CONN_AB_WAIT_RESP_OK); 1863 } else { 1864 cc_conn_set_state(conn, 1865 CONN_AB_FLUSH_IND); 1866 } 1867 break; 1868 } 1869 cc_conn_reset_acceptor(conn); 1870 if (state == UNI_CALLSTATE_U6 || 1871 state == UNI_CALLSTATE_U9 || 1872 state == UNI_CALLSTATE_U7) { 1873 cc_user_sig(user, USER_SIG_ACCEPT_ERR, 1874 NULL, ATM_MKUNIERR(reason)); 1875 cc_conn_set_state(conn, CONN_IN_ARRIVED); 1876 } else if (state == UNI_CALLSTATE_U12) { 1877 do_release_response(conn, 0, NULL); 1878 cc_disconnect_from_user(conn); 1879 cc_user_sig(user, USER_SIG_ACCEPT_ERR, 1880 user, ATMERR_PREVIOUSLY_ABORTED); 1881 cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK); 1882 } else { 1883 cc_disconnect_from_user(conn); 1884 cc_user_sig(user, USER_SIG_ACCEPT_ERR, 1885 user, ATMERR_PREVIOUSLY_ABORTED); 1886 cc_conn_set_state(conn, CONN_AB_FLUSH_IND); 1887 } 1888 break; 1889 1890 case CONN_REJ_WAIT_OK: /* C14 */ 1891 if (user == NULL) { 1892 /* connection has been aborted. */ 1893 if (state == UNI_CALLSTATE_U6 || 1894 state == UNI_CALLSTATE_U7 || 1895 state == UNI_CALLSTATE_U9 || 1896 state == UNI_CALLSTATE_U12) { 1897 /* do what we can */ 1898 do_release_response(conn, 0, NULL); 1899 cc_conn_set_state(conn, 1900 CONN_AB_WAIT_RESP_OK); 1901 } else { 1902 cc_conn_set_state(conn, 1903 CONN_AB_FLUSH_IND); 1904 } 1905 break; 1906 } 1907 if (state == UNI_CALLSTATE_U6 || 1908 state == UNI_CALLSTATE_U9 || 1909 state == UNI_CALLSTATE_U7) { 1910 cc_user_sig(user, USER_SIG_REJECT_ERR, 1911 NULL, ATM_MKUNIERR(reason)); 1912 cc_conn_set_state(conn, CONN_IN_ARRIVED); 1913 } else { 1914 cc_disconnect_from_user(conn); 1915 cc_user_sig(user, USER_SIG_REJECT_OK, NULL, 0); 1916 cc_conn_set_state(conn, CONN_AB_FLUSH_IND); 1917 } 1918 break; 1919 1920 case CONN_REL_IN_WAIT_OK: /* C15 */ 1921 if (user == NULL) { 1922 /* connection has been aborted. */ 1923 if (state == UNI_CALLSTATE_U8) { 1924 /* do what we can */ 1925 do_release_request(conn, conn->cause); 1926 cc_conn_set_state(conn, 1927 CONN_AB_WAIT_REQ_OK); 1928 } else if (state == UNI_CALLSTATE_U12) { 1929 do_release_response(conn, 0, NULL); 1930 cc_conn_set_state(conn, 1931 CONN_AB_WAIT_RESP_OK); 1932 } else { 1933 cc_conn_set_state(conn, 1934 CONN_AB_FLUSH_IND); 1935 } 1936 break; 1937 } 1938 if (state == UNI_CALLSTATE_U8) { 1939 cc_conn_set_state(conn, CONN_IN_WAIT_COMPL); 1940 cc_user_sig(conn->user, USER_SIG_RELEASE_ERR, 1941 NULL, reason); 1942 } else if (state == UNI_CALLSTATE_U12) { 1943 do_release_response(conn, 0, NULL); 1944 cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK); 1945 memset(&conn->user->cause, 0, 1946 sizeof(conn->user->cause)); 1947 cc_user_sig(conn->user, 1948 USER_SIG_RELEASE_CONFIRM, NULL, 0); 1949 cc_disconnect_from_user(conn); 1950 } else { 1951 cc_conn_set_state(conn, CONN_AB_FLUSH_IND); 1952 memset(&conn->user->cause, 0, 1953 sizeof(conn->user->cause)); 1954 cc_user_sig(conn->user, 1955 USER_SIG_RELEASE_CONFIRM, NULL, 0); 1956 cc_disconnect_from_user(conn); 1957 } 1958 break; 1959 1960 default: 1961 /* maybe it's for a party */ 1962 LIST_FOREACH(party, &conn->parties, link) { 1963 switch (party->state) { 1964 1965 case PARTY_ADD_WAIT_CREATE: /* P2 */ 1966 cc_party_destroy(party); 1967 if (user != NULL) 1968 cc_user_sig(user, 1969 USER_SIG_ADD_PARTY_ERR, 1970 NULL, ATM_MKUNIERR(reason)); 1971 goto ex_party_err; 1972 1973 case PARTY_ADD_WAIT_OK: /* P3 */ 1974 cc_party_set_state(party, 1975 PARTY_WAIT_DESTROY); 1976 if (user != NULL) 1977 cc_user_sig(user, 1978 USER_SIG_ADD_PARTY_ERR, 1979 NULL, ATM_MKUNIERR(reason)); 1980 goto ex_party_err; 1981 1982 case PARTY_DROP_WAIT_OK: /* P5 */ 1983 cc_party_set_state(party, 1984 PARTY_ACTIVE); 1985 if (user != NULL) 1986 cc_user_sig(user, 1987 USER_SIG_DROP_PARTY_ERR, 1988 NULL, ATM_MKUNIERR(reason)); 1989 goto ex_party_err; 1990 1991 case PARTY_WAIT_DROP_ACK_OK: /* P9 */ 1992 cc_party_set_state(party, 1993 PARTY_ACTIVE); 1994 goto ex_party_err; 1995 1996 case PARTY_ADD_DROP_WAIT_OK: /* P11 */ 1997 cc_party_set_state(party, 1998 PARTY_ADD_WAIT_ACK); 1999 if (user != NULL) 2000 cc_user_sig(user, 2001 USER_SIG_DROP_PARTY_ERR, 2002 NULL, ATM_MKUNIERR(reason)); 2003 goto ex_party_err; 2004 2005 case PARTY_ADD_DROPACK_WAIT_OK:/* P12 */ 2006 cc_party_set_state(party, 2007 PARTY_ADD_WAIT_ACK); 2008 goto ex_party_err; 2009 2010 default: 2011 break; 2012 } 2013 } 2014 cc_conn_log(conn, "unexpected reason=%u ustate=%u " 2015 "state=%s\n", reason, state, stab[conn->state]); 2016 ex_party_err: 2017 break; 2018 } 2019 break; 2020 } 2021 2022 case CONN_SIG_PARTY_CREATED: 2023 { 2024 struct uni_msg *msg = arg; 2025 struct uniapi_party_created *pcr = uni_msg_rptr(msg, 2026 struct uniapi_party_created *); 2027 2028 party = cc_party_find(conn, pcr->epref.epref); 2029 if (party == NULL) { 2030 /* for incoming connections we see the party-created 2031 * immediately after the call-create so that we 2032 * must be in C10 */ 2033 switch (conn->state) { 2034 2035 case CONN_IN_PREPARING: 2036 party = cc_party_create(conn, 2037 pcr->epref.epref, 1); 2038 if (party == NULL) 2039 break; 2040 cc_party_set_state(party, 2041 PARTY_WAIT_SETUP_COMPL); 2042 break; 2043 2044 case CONN_OUT_WAIT_OK: 2045 party = cc_party_create(conn, 2046 pcr->epref.epref, 0); 2047 if (party == NULL) 2048 break; 2049 cc_party_set_state(party, 2050 PARTY_WAIT_SETUP_CONF); 2051 break; 2052 2053 default: 2054 goto bad_state; 2055 } 2056 break; 2057 } 2058 /* this is for an ADD-PARTY */ 2059 if (conn->state != CONN_ACTIVE) 2060 goto bad_state; 2061 if (party->state != PARTY_ADD_WAIT_CREATE) 2062 goto bad_party_state; 2063 cc_party_set_state(party, PARTY_ADD_WAIT_OK); 2064 break; 2065 } 2066 2067 case CONN_SIG_PARTY_DESTROYED: 2068 { 2069 struct uni_msg *msg = arg; 2070 struct uniapi_party_destroyed *pcr = uni_msg_rptr(msg, 2071 struct uniapi_party_destroyed *); 2072 2073 party = cc_party_find(conn, pcr->epref.epref); 2074 if (party == NULL) { 2075 cc_conn_log(conn, "no party to destroy %u/%u", 2076 pcr->epref.flag, pcr->epref.epref); 2077 break; 2078 } 2079 cc_party_destroy(party); 2080 break; 2081 } 2082 2083 } 2084 2085 return; 2086 2087 bad_state: 2088 cc_conn_log(conn, "bad state=%s for signal=%s", 2089 stab[conn->state], cc_conn_sigtab[sig]); 2090 return; 2091 2092 bad_party_state: 2093 cc_conn_log(conn, "bad party state=%s for signal=%s", 2094 ptab[party->state], cc_conn_sigtab[sig]); 2095 return; 2096} 2097