2 * Copyright (c) 2003-2007
6 * Copyright (c) 2001-2002
7 * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
10 * Author: Harti Brandt <harti@freebsd.org>
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:
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.
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.
34 * $Id: cc_conn.c 1291 2007-07-10 10:35:38Z brandt_h $
36 * ATM API as defined per af-saa-0108
38 * Lower half - connection handling
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>
49 static const char *stab[] = {
50 #define DEF(N) [N] = #N,
55 static const char *ptab[] = {
56 #define DEF(N) [PARTY_##N] = #N,
62 cc_conn_state2str(u_int s)
64 if (s >= sizeof(stab) / sizeof(stab[0]) || stab[s] == NULL)
70 cc_conn_set_state(struct ccconn *conn, enum conn_state ns)
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]);
81 cc_party_state2str(u_int s)
83 if (s >= sizeof(ptab) / sizeof(ptab[0]) || ptab[s] == NULL)
89 cc_party_set_state(struct ccparty *party, enum party_state ns)
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]);
101 * Remove connection from its user's queue
104 cc_disconnect_from_user(struct ccconn *conn)
107 if (conn->user == NULL)
108 cc_conn_log(conn, "no %s", "user");
110 TAILQ_REMOVE(&conn->user->connq, conn, connq_link);
111 conn->user->queue_act--;
117 * Put connection on user queue
120 cc_connect_to_user(struct ccconn *conn, struct ccuser *user)
123 if (conn->user != NULL)
124 cc_conn_log(conn, "still connected to %p", conn->user);
126 TAILQ_INSERT_TAIL(&user->connq, conn, connq_link);
127 conn->user->queue_act++;
131 * Send a signal to the UNI stack for this connection
134 cc_send_uni(struct ccconn *conn, u_int op, struct uni_msg *msg)
138 r = CCZALLOC(sizeof(*r));
141 uni_msg_destroy(msg);
142 cc_conn_log(conn, "no memory for cookie op=%u", op);
146 if ((r->cookie = ++conn->port->cc->cookie) == 0)
147 r->cookie = ++conn->port->cc->cookie;
151 TAILQ_INSERT_TAIL(&conn->port->cookies, r, link);
153 conn->port->cc->funcs->send_uni(conn, conn->port->uarg, op,
158 * Send a RELEASE.request for this connection.
161 do_release_request(struct ccconn *conn, const struct uni_ie_cause cause[2])
164 struct uniapi_release_request *req;
166 if ((u = uni_msg_alloc(sizeof(*req))) == NULL)
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);
172 req->release.hdr.cref = conn->cref;
173 req->release.hdr.act = UNI_MSGACT_DEFAULT;
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;
181 req->release.cause[0] = cause[0];
182 req->release.cause[1] = cause[1];
185 cc_send_uni(conn, UNIAPI_RELEASE_request, u);
189 * Make a RELEASE.response for this connection
192 do_release_response(struct ccconn *conn, uint8_t cause, struct uni_ie_cause *ie)
195 struct uniapi_release_response *resp;
197 if ((u = uni_msg_alloc(sizeof(*resp))) == NULL)
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);
203 resp->release_compl.hdr.cref = conn->cref;
204 resp->release_compl.hdr.act = UNI_MSGACT_DEFAULT;
207 resp->release_compl.cause[0] = *ie;
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;
216 cc_send_uni(conn, UNIAPI_RELEASE_response, u);
219 /**********************************************************************
224 cc_conn_create(struct ccdata *cc)
228 conn = CCZALLOC(sizeof(*conn));
232 conn->state = CONN_NULL;
235 LIST_INIT(&conn->parties);
237 LIST_INSERT_HEAD(&cc->orphaned_conns, conn, port_link);
239 if (conn->cc->log & CCLOG_CONN_INST)
240 cc_conn_log(conn, "created %s", "orphaned");
249 cc_conn_ins_port(struct ccconn *conn, struct ccport *port)
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);
257 LIST_REMOVE(conn, port_link);
260 LIST_INSERT_HEAD(&port->conn_list, conn, port_link);
268 cc_conn_rem_port(struct ccconn *conn)
271 if (conn->port == NULL) {
272 cc_conn_log(conn, "conn not on any %s", "port");
275 LIST_REMOVE(conn, port_link);
277 LIST_INSERT_HEAD(&conn->cc->orphaned_conns, conn, port_link);
281 cc_conn_flush_cookies(struct ccconn *conn)
283 struct ccreq *r, *r1;
285 if (conn->port == NULL)
287 TAILQ_FOREACH_SAFE(r, &conn->port->cookies, link, r1) {
288 if (r->conn == conn) {
289 TAILQ_REMOVE(&conn->port->cookies, r, link);
296 cc_conn_reset_acceptor(struct ccconn *conn)
298 if (conn->acceptor != NULL) {
299 conn->acceptor->accepted = NULL;
300 conn->acceptor = NULL;
305 * Destroy a connection
308 cc_conn_destroy(struct ccconn *conn)
312 if (conn->cc->log & CCLOG_CONN_INST)
313 cc_conn_log(conn, "destroy%s", "");
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);
321 if (conn->acceptor != NULL)
322 conn->acceptor->accepted = NULL;
324 cc_conn_flush_cookies(conn);
325 cc_conn_sig_flush(conn);
327 LIST_REMOVE(conn, port_link);
328 while ((p = LIST_FIRST(&conn->parties)) != NULL) {
329 LIST_REMOVE(p, link);
337 cc_party_create(struct ccconn *conn, u_int ident, u_int flag)
339 struct ccparty *party;
341 party = CCZALLOC(sizeof(*party));
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);
352 if (party->conn->cc->log & CCLOG_PARTY_INST)
353 cc_party_log(party, "created %u.%u", flag, ident);
359 cc_party_destroy(struct ccparty *party)
362 if (party->conn->cc->log & CCLOG_PARTY_INST)
363 cc_party_log(party, "destroyed %u.%u", party->epref.flag,
366 LIST_REMOVE(party, link);
370 static struct ccparty *
371 cc_party_find(struct ccconn *conn, u_int ident)
373 struct ccparty *party;
375 LIST_FOREACH(party, &conn->parties, link)
376 if (party->epref.epref == ident)
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.
389 cc_conn_abort(struct ccconn *conn, int shutdown)
391 struct ccuser *u = conn->user;
392 struct ccparty *p, *p1;
395 CCASSERT(u == NULL, ("still in use"));
396 CCASSERT(conn->acceptor == NULL, ("still in use"));
397 cc_conn_destroy(conn);
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.
407 while ((p = LIST_FIRST(&conn->parties)) != NULL)
410 LIST_FOREACH_SAFE(p, &conn->parties, link, p1) {
413 case PARTY_NULL: /* P0 */
414 /* should not happen */
417 case PARTY_ACTIVE: /* P1 */
418 /* don't send a drop - user'll get a rel */
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);
428 case PARTY_ADD_WAIT_ACK: /* P4 */
429 /* don't send a drop - user'll get a rel */
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);
440 case PARTY_WAIT_DESTROY: /* P7 */
443 case PARTY_WAIT_SETUP_COMPL: /* P8 */
444 case PARTY_WAIT_SETUP_CONF: /* P10 */
445 /* first party - nothing to do */
448 case PARTY_WAIT_DROP_ACK_OK: /* P9 */
449 case PARTY_ADD_DROPACK_WAIT_OK:/* P12 */
450 /* we're dropping - nothing to do */
453 cc_party_log(p, "bad uabort for party in state %s",
461 * Now do what the connection needs
463 switch (conn->state) {
465 case CONN_NULL: /* 0 */
466 case CONN_OUT_PREPARING: /* 1 */
467 /* may not happen because we're not associated with
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 */
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);
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);
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);
503 case CONN_IN_ARRIVED: /* 11 */
505 cc_disconnect_from_user(conn);
506 cc_conn_destroy(conn);
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);
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);
525 case CONN_REL_IN_WAIT_OK: /* 15 */
526 case CONN_REL_WAIT_OK: /* 20 */
527 /* confirm destroy */
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);
534 cc_conn_destroy(conn);
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);
543 cc_conn_log(conn, "bad state %s", stab[conn->state]);
548 print_sap(const struct uni_sap *sap)
550 static const char *const tags[] = {
551 [UNISVE_ABSENT] "absent",
552 [UNISVE_PRESENT]"present",
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]);
565 printf("selector={%s", tags[sap->selector.tag]);
566 if (sap->selector.tag == UNISVE_PRESENT)
567 printf(",%02x", sap->selector.selector);
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);
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);
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]);
593 /*********************************************************************
595 * DISPATCH incoming call
598 cc_conn_dispatch(struct ccconn *conn)
600 struct ccdata *priv = conn->port->cc;
605 static char buf[1000];
606 static struct unicx cx;
616 * Do call dispatching according to 4.6
619 printf("+++++ DISPATCH++++++\n");
621 for (blli_index = 0; blli_index < UNI_NUM_IE_BLLI; blli_index++) {
622 if (blli_index > 0 && !IE_ISGOOD(conn->blli[blli_index]))
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);
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);
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);
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)) {
648 printf("TRYING user=%p\n", user);
649 print_sap(user->sap);
651 if (unisve_match(user->sap, &conn->called,
652 &conn->blli[blli_index], &conn->bhli))
658 printf("TRYING CATCHALL\n");
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))
674 * No application found - reject call.
676 do_release_response(conn, UNI_CAUSE_INCOMP, NULL);
677 cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK);
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);
690 if (blli_index == 0 && !IE_ISGOOD(conn->blli[blli_index]))
691 conn->blli_selector = 0;
693 conn->blli_selector = blli_index + 1;
695 cc_conn_set_state(conn, CONN_IN_WAITING);
696 cc_connect_to_user(conn, user);
698 cc_user_sig(user, USER_SIG_SETUP_IND, NULL, 0);
702 cc_party_setup_conf(struct ccconn *conn)
704 struct ccparty *party;
706 party = cc_party_find(conn, conn->epref.epref);
708 cc_party_log(party, "no party for %s",
709 cc_conn_sigtab[CONN_SIG_SETUP_CONFIRM]);
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]);
717 cc_party_set_state(party, PARTY_ACTIVE);
721 cc_party_add_ack_ind(struct ccconn *conn, const struct uni_ie_epref *epref)
723 struct ccparty *party;
725 party = cc_party_find(conn, epref->epref);
727 cc_party_log(party, "no party for %s",
728 cc_conn_sigtab[CONN_SIG_PARTY_ADD_ACK_IND]);
730 if (party->state != PARTY_ADD_WAIT_ACK) {
731 cc_party_log(party, "bad state=%s for signal=%s",
733 cc_conn_sigtab[CONN_SIG_PARTY_ADD_ACK_IND]);
736 cc_party_set_state(party, PARTY_ACTIVE);
737 cc_user_sig(conn->user, USER_SIG_ADD_PARTY_ACK,
742 cc_party_add_rej_ind(struct ccconn *conn, const struct uni_ie_epref *epref)
744 struct ccparty *party;
746 party = cc_party_find(conn, epref->epref);
748 cc_party_log(party, "no party for %s",
749 cc_conn_sigtab[CONN_SIG_PARTY_ADD_REJ_IND]);
752 if (party->state != PARTY_ADD_WAIT_ACK) {
753 cc_party_log(party, "bad state=%s for signal=%s",
755 cc_conn_sigtab[CONN_SIG_PARTY_ADD_REJ_IND]);
758 cc_party_set_state(party, PARTY_WAIT_DESTROY);
759 cc_user_sig(conn->user, USER_SIG_ADD_PARTY_REJ, NULL, epref->epref);
763 cc_party_drop_ack_ind(struct ccconn *conn,
764 const struct uni_drop_party *drop)
766 struct ccparty *party;
768 party = cc_party_find(conn, drop->epref.epref);
770 cc_party_log(party, "no party for %s",
771 cc_conn_sigtab[CONN_SIG_DROP_PARTY_ACK_IND]);
774 switch (party->state) {
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);
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);
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);
797 case PARTY_WAIT_SETUP_COMPL: /* P8 */
798 case PARTY_WAIT_SETUP_CONF: /* P10 */
799 cc_party_set_state(party, PARTY_WAIT_DESTROY);
803 cc_party_log(party, "bad state=%s for signal=%s",
805 cc_conn_sigtab[CONN_SIG_DROP_PARTY_ACK_IND]);
811 * Handle a signal to this connection
814 cc_conn_sig_handle(struct ccconn *conn, enum conn_sig sig,
815 void *arg, u_int iarg)
817 struct ccparty *party;
819 if (conn->cc->log & CCLOG_CONN_SIG)
820 cc_conn_log(conn, "signal %s in state %s", cc_conn_sigtab[sig],
825 case CONN_SIG_CONNECT_OUTGOING:
829 struct uniapi_setup_request *setup;
831 if (conn->state != CONN_OUT_PREPARING)
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;
842 * Construct message to UNI.
844 u = uni_msg_alloc(sizeof(struct uniapi_setup_request));
846 cc_user_sig(conn->user, USER_SIG_CONNECT_OUTGOING_ERR,
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);
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;
877 cc_conn_set_state(conn, CONN_OUT_WAIT_CREATE);
878 cc_send_uni(conn, UNIAPI_SETUP_request, u);
884 case CONN_SIG_ARRIVAL:
885 /* user informed of arrival of this call */
886 if (conn->state != CONN_IN_WAITING)
888 cc_conn_set_state(conn, CONN_IN_ARRIVED);
892 case CONN_SIG_RELEASE:
894 /* Release this call */
896 struct uniapi_release_request *req;
898 if (conn->state != CONN_ACTIVE &&
899 conn->state != CONN_IN_WAIT_COMPL)
902 if ((u = uni_msg_alloc(sizeof(*req))) == NULL)
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);
909 req->release.hdr.cref = conn->cref;
910 req->release.hdr.act = UNI_MSGACT_DEFAULT;
912 req->release.cause[0] = conn->cause[0];
913 req->release.cause[1] = conn->cause[1];
915 if (conn->state == CONN_ACTIVE)
916 cc_conn_set_state(conn, CONN_REL_WAIT_OK);
918 cc_conn_set_state(conn, CONN_REL_IN_WAIT_OK);
920 cc_send_uni(conn, UNIAPI_RELEASE_request, u);
924 case CONN_SIG_REJECT:
926 /* reject from user */
927 struct ccuser *user = conn->user;
929 if (conn->state != CONN_IN_ARRIVED) {
930 cc_user_sig(user, USER_SIG_REJECT_ERR,
931 NULL, ATMERR_BAD_STATE);
934 cc_conn_set_state(conn, CONN_REJ_WAIT_OK);
935 do_release_response(conn, 0, conn->cause);
940 case CONN_SIG_ACCEPT:
943 struct ccuser *newep = arg;
945 struct uniapi_setup_response *resp;
946 struct ccuser *user = conn->user;
948 if (conn->state != CONN_IN_ARRIVED) {
949 cc_user_sig(user, USER_SIG_ACCEPT_ERR,
950 NULL, ATMERR_PREVIOUSLY_ABORTED);
954 u = uni_msg_alloc(sizeof(struct uniapi_setup_response));
956 cc_user_sig(user, USER_SIG_ACCEPT_ERR,
962 * Link to the new endpoint
964 conn->acceptor = newep;
965 newep->accepted = conn;
968 * Construct connect message
970 resp = uni_msg_wptr(u, struct uniapi_setup_response *);
971 memset(resp, 0, sizeof(*resp));
972 u->b_wptr += sizeof(*resp);
974 resp->connect.hdr.act = UNI_MSGACT_DEFAULT;
975 resp->connect.hdr.cref = conn->cref;
980 if (conn->dirty_attr && CCDIRTY_AAL)
981 resp->connect.aal = conn->aal;
982 if (conn->dirty_attr && CCDIRTY_BLLI)
984 conn->blli[conn->blli_selector - 1];
985 if (conn->dirty_attr && CCDIRTY_CONNID)
986 resp->connect.connid = conn->connid;
988 if (conn->dirty_attr && CCDIRTY_EETD)
989 resp->connect.eetd = conn->eetd;
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;
1002 * If the SETUP had an endpoint reference - echo it back
1004 if (IE_ISPRESENT(conn->epref)) {
1005 resp->connect.epref = conn->epref;
1006 resp->connect.epref.flag = !resp->connect.epref.flag;
1009 cc_conn_set_state(conn, CONN_IN_WAIT_ACCEPT_OK);
1010 cc_send_uni(conn, UNIAPI_SETUP_response, u);
1015 case CONN_SIG_ADD_PARTY:
1017 /* request to add party from user */
1019 struct uniapi_add_party_request *req;
1021 if (conn->state != CONN_ACTIVE)
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);
1031 party->called = conn->called;
1033 /* Construct message to UNI. */
1034 u = uni_msg_alloc(sizeof(struct uniapi_setup_request));
1036 cc_party_destroy(party);
1037 cc_user_sig(conn->user, USER_SIG_ADD_PARTY_ERR,
1038 NULL, ATMERR_NOMEM);
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);
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;
1051 cc_party_set_state(party, PARTY_ADD_WAIT_CREATE);
1052 cc_send_uni(conn, UNIAPI_ADD_PARTY_request, u);
1057 case CONN_SIG_DROP_PARTY:
1059 /* user request to drop a party */
1061 struct uniapi_drop_party_request *req;
1063 if (conn->state != CONN_ACTIVE)
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);
1073 switch (party->state) {
1076 case PARTY_ADD_WAIT_ACK:
1080 cc_user_sig(conn->user, USER_SIG_DROP_PARTY_ERR,
1081 NULL, ATMERR_BAD_STATE);
1086 * Construct message to UNI.
1088 u = uni_msg_alloc(sizeof(*req));
1090 cc_user_sig(conn->user, USER_SIG_DROP_PARTY_ERR,
1091 NULL, ATMERR_NOMEM);
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);
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];
1104 if (party->state == PARTY_ACTIVE)
1105 cc_party_set_state(party, PARTY_DROP_WAIT_OK);
1107 cc_party_set_state(party, PARTY_ADD_DROP_WAIT_OK);
1108 cc_send_uni(conn, UNIAPI_DROP_PARTY_request, u);
1112 case CONN_SIG_DROP_PARTY_ACK_IND:
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 *);
1118 cc_party_drop_ack_ind(conn, &ind->drop);
1123 case CONN_SIG_USER_ABORT:
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[].
1129 switch (conn->state) {
1131 case CONN_NULL: /* C0 */
1132 case CONN_OUT_PREPARING: /* C1 */
1133 cc_conn_destroy(conn);
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);
1142 case CONN_IN_WAITING: /* C21 */
1143 /* that should not happen */
1147 case CONN_IN_ARRIVED: /* C11 */
1149 * This is called only for the first connection
1150 * of the user - the others are re-dispatched.
1152 do_release_response(conn, 0, conn->cause);
1153 cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK);
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);
1161 case CONN_OUT_WAIT_DESTROY: /* C20 */
1162 cc_conn_set_state(conn, CONN_AB_FLUSH_IND);
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 */
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).
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 */
1189 case CONN_SIG_CREATED:
1192 * CALL_CREATED message from UNI. This can happen for either
1193 * incoming or outgoing connections.
1195 struct uni_msg *msg = arg;
1196 struct uniapi_call_created *cr = uni_msg_rptr(msg,
1197 struct uniapi_call_created *);
1199 switch (conn->state) {
1201 case CONN_OUT_WAIT_CREATE:
1202 conn->cref = cr->cref;
1203 cc_conn_set_state(conn, CONN_OUT_WAIT_OK);
1207 conn->cref = cr->cref;
1208 cc_conn_set_state(conn, CONN_IN_PREPARING);
1217 case CONN_SIG_DESTROYED:
1219 * CALL_DESTROYED message from UNI.
1221 switch (conn->state) {
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));
1232 case CONN_AB_FLUSH_IND:
1233 cc_conn_destroy(conn);
1236 case CONN_IN_PREPARING:
1237 cc_conn_destroy(conn);
1246 case CONN_SIG_SETUP_CONFIRM:
1247 /* Setup confirm from the UNI. */
1249 struct uni_msg *msg = arg;
1250 struct uniapi_setup_confirm *conf = uni_msg_rptr(msg,
1251 struct uniapi_setup_confirm *);
1253 switch (conn->state) {
1255 case CONN_OUT_WAIT_CONF:
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)
1264 #define SHUFFLE(ATTR) conn->ATTR = conf->connect.ATTR
1265 #define COND_SHUFFLE(ATTR) if (IE_ISPRESENT(conf->connect.ATTR)) SHUFFLE(ATTR)
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);
1277 COND_SHUFFLE(traffic);
1278 COND_SHUFFLE(exqos);
1279 COND_SHUFFLE(abrsetup);
1280 COND_SHUFFLE(abradd);
1281 COND_SHUFFLE(connid);
1284 if (IE_ISGOOD(conn->epref))
1285 cc_party_setup_conf(conn);
1287 cc_conn_set_state(conn, CONN_ACTIVE);
1288 cc_user_sig(conn->user, USER_SIG_SETUP_CONFIRM,
1292 case CONN_AB_FLUSH_IND:
1293 case CONN_AB_WAIT_RESP_OK:
1302 case CONN_SIG_SETUP_IND:
1304 /* SETUP indication */
1305 struct uni_msg *msg = arg;
1306 struct uniapi_setup_indication *ind = uni_msg_rptr(msg,
1307 struct uniapi_setup_indication *);
1310 if (conn->state != CONN_IN_PREPARING)
1314 * Shuffle information elements.
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;
1340 cc_conn_dispatch(conn);
1345 case CONN_SIG_SETUP_COMPL:
1347 struct uni_msg *msg = arg;
1348 struct uniapi_setup_indication *ind __unused =
1349 uni_msg_rptr(msg, struct uniapi_setup_indication *);
1351 /* SETUP_COMPLETE.indication from UNI */
1352 if (conn->state == CONN_AB_FLUSH_IND ||
1353 conn->state == CONN_AB_WAIT_RESP_OK)
1356 if (conn->state != CONN_IN_WAIT_COMPL)
1359 cc_conn_set_state(conn, CONN_ACTIVE);
1361 LIST_FOREACH(party, &conn->parties, link) {
1362 if (party->state == PARTY_WAIT_SETUP_COMPL)
1363 cc_party_set_state(party, PARTY_ACTIVE);
1365 cc_party_log(party, "bad state=%s for sig=%s",
1367 cc_conn_sigtab[CONN_SIG_SETUP_COMPL]);
1370 cc_user_sig(conn->user, USER_SIG_SETUP_COMPL, NULL, 0);
1375 case CONN_SIG_PROC_IND:
1378 * ALERTING.indication and PROCEEDING.indication are entirly
1379 * ignored by the specification. We need to at least save the
1380 * connid information element.
1382 struct uni_msg *msg = arg;
1383 struct uniapi_proceeding_indication *ind = uni_msg_rptr(msg,
1384 struct uniapi_proceeding_indication *);
1386 switch (conn->state) {
1388 case CONN_OUT_WAIT_CONF:
1389 if (IE_ISGOOD(ind->call_proc.connid))
1390 conn->connid = ind->call_proc.connid;
1393 case CONN_AB_FLUSH_IND:
1394 case CONN_AB_WAIT_RESP_OK:
1403 case CONN_SIG_ALERTING_IND:
1405 struct uni_msg *msg = arg;
1406 struct uniapi_alerting_indication *ind = uni_msg_rptr(msg,
1407 struct uniapi_alerting_indication *);
1409 switch (conn->state) {
1411 case CONN_OUT_WAIT_CONF:
1412 if (IE_ISGOOD(ind->alerting.connid))
1413 conn->connid = ind->alerting.connid;
1416 case CONN_AB_FLUSH_IND:
1417 case CONN_AB_WAIT_RESP_OK:
1426 case CONN_SIG_REL_CONF:
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 *);
1433 switch (conn->state) {
1435 case CONN_OUT_WAIT_CONF:
1437 cc_conn_set_state(conn, CONN_AB_FLUSH_IND);
1438 memcpy(conn->user->cause, conf->release.cause,
1439 sizeof(conn->user->cause));
1441 * If any party is in P6, ok the user
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);
1452 cc_user_sig(conn->user, USER_SIG_RELEASE_CONFIRM,
1454 cc_disconnect_from_user(conn);
1457 case CONN_AB_FLUSH_IND:
1458 case CONN_AB_WAIT_RESP_OK:
1461 case CONN_IN_WAITING:
1462 cc_disconnect_from_user(conn);
1463 cc_conn_set_state(conn, CONN_AB_FLUSH_IND);
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);
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,
1480 cc_disconnect_from_user(conn);
1489 case CONN_SIG_REL_IND:
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 *);
1496 switch (conn->state) {
1498 case CONN_OUT_WAIT_CONF:
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));
1505 * If any party is in P6, ok the user
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);
1516 cc_user_sig(conn->user, USER_SIG_RELEASE_CONFIRM,
1518 cc_disconnect_from_user(conn);
1521 case CONN_AB_FLUSH_IND:
1522 case CONN_AB_WAIT_RESP_OK:
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);
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);
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,
1545 cc_disconnect_from_user(conn);
1554 case CONN_SIG_PARTY_ALERTING_IND:
1555 /* party alerting from UNI */
1556 if (conn->state == CONN_AB_FLUSH_IND)
1558 if (conn->state != CONN_ACTIVE)
1563 case CONN_SIG_PARTY_ADD_ACK_IND:
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 *);
1570 if (conn->state == CONN_AB_FLUSH_IND)
1572 if (conn->state != CONN_ACTIVE)
1575 cc_party_add_ack_ind(conn, &ind->ack.epref);
1580 case CONN_SIG_PARTY_ADD_REJ_IND:
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 *);
1587 if (conn->state == CONN_AB_FLUSH_IND)
1589 if (conn->state != CONN_ACTIVE)
1592 memset(&conn->user->cause[1], 0, sizeof(conn->user->cause[1]));
1593 conn->user->cause[0] = ind->rej.cause;
1595 cc_party_add_rej_ind(conn, &ind->rej.epref);
1600 case CONN_SIG_DROP_PARTY_IND:
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;
1609 if (conn->state == CONN_AB_FLUSH_IND)
1611 if (conn->state != CONN_ACTIVE)
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]);
1621 u = uni_msg_alloc(sizeof(*req));
1625 memset(&conn->user->cause[1], 0, sizeof(conn->user->cause[1]));
1626 conn->user->cause[0] = ind->drop.cause;
1628 switch (party->state) {
1631 cc_party_log(party, "bad state %s for DROP.ind",
1632 ptab[party->state]);
1635 case PARTY_ACTIVE: /* P1 -> P9 */
1636 cc_party_set_state(party, PARTY_WAIT_DROP_ACK_OK);
1639 case PARTY_ADD_WAIT_ACK: /* P4 -> P12 */
1640 cc_party_set_state(party, PARTY_ADD_DROPACK_WAIT_OK);
1645 * Construct message to UNI.
1647 req = uni_msg_wptr(u, struct uniapi_drop_party_ack_request *);
1648 memset(req, 0, sizeof(*req));
1649 u->b_wptr += sizeof(*req);
1651 IE_SETPRESENT(req->ack.epref);
1652 req->ack.hdr.act = UNI_MSGACT_DEFAULT;
1653 req->ack.hdr.cref = conn->cref;
1655 req->ack.epref.flag = 0;
1656 req->ack.epref.epref = ind->drop.epref.epref;
1658 cc_send_uni(conn, UNIAPI_DROP_PARTY_ACK_request, u);
1664 /* OK response from UNI */
1665 struct ccuser *user = conn->user;
1667 switch (conn->state) {
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);
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);
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);
1694 case CONN_IN_WAIT_ACCEPT_OK: /* C12 */
1696 /* has been aborted */
1697 do_release_request(conn, NULL);
1698 cc_conn_set_state(conn, CONN_AB_WAIT_REQ_OK);
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);
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);
1714 case CONN_REJ_WAIT_OK: /* C14 */
1715 cc_conn_set_state(conn, CONN_AB_FLUSH_IND);
1717 cc_disconnect_from_user(conn);
1718 cc_user_sig(user, USER_SIG_REJECT_OK, NULL, 0);
1723 /* maybe it's for a party */
1724 LIST_FOREACH(party, &conn->parties, link) {
1725 switch (party->state) {
1727 case PARTY_ADD_WAIT_OK: /* P3 */
1730 USER_SIG_ADD_PARTY_OK,
1732 cc_party_set_state(party,
1733 PARTY_ADD_WAIT_ACK);
1736 case PARTY_DROP_WAIT_OK: /* P5 */
1737 cc_party_set_state(party,
1738 PARTY_DROP_WAIT_ACK);
1741 case PARTY_WAIT_DROP_ACK_OK: /* P9 */
1742 case PARTY_ADD_DROPACK_WAIT_OK:/* P12 */
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)
1752 if (p1 != NULL && user != NULL)
1754 USER_SIG_DROP_PARTY_IND,
1756 party->epref.epref);
1761 case PARTY_ADD_DROP_WAIT_OK: /* P11 */
1762 cc_party_set_state(party,
1763 PARTY_DROP_WAIT_ACK);
1777 case CONN_SIG_ERROR:
1779 /* error response from UNI */
1780 u_int reason = (iarg >> 16) & 0xffff;
1781 u_int state = iarg & 0xffff;
1782 struct ccuser *user = conn->user;
1784 switch (conn->state) {
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));
1795 case CONN_OUT_WAIT_OK: /* C3 */
1796 cc_conn_set_state(conn, CONN_OUT_WAIT_DESTROY);
1797 conn->reason = reason;
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);
1806 cc_conn_set_state(conn, CONN_AB_FLUSH_IND);
1809 case CONN_AB_WAIT_RESP_OK: /* C34 */
1810 cc_conn_set_state(conn, CONN_AB_FLUSH_IND);
1813 case CONN_REL_WAIT_OK: /* C20 */
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);
1826 cc_conn_set_state(conn,
1831 if (state == UNI_CALLSTATE_U10) {
1832 cc_conn_set_state(conn, CONN_ACTIVE);
1833 cc_user_sig(conn->user, USER_SIG_RELEASE_ERR,
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);
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);
1853 case CONN_IN_WAIT_ACCEPT_OK: /* C12 */
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);
1864 cc_conn_set_state(conn,
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);
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);
1890 case CONN_REJ_WAIT_OK: /* C14 */
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);
1902 cc_conn_set_state(conn,
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);
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);
1920 case CONN_REL_IN_WAIT_OK: /* C15 */
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);
1933 cc_conn_set_state(conn,
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,
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);
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);
1961 /* maybe it's for a party */
1962 LIST_FOREACH(party, &conn->parties, link) {
1963 switch (party->state) {
1965 case PARTY_ADD_WAIT_CREATE: /* P2 */
1966 cc_party_destroy(party);
1969 USER_SIG_ADD_PARTY_ERR,
1970 NULL, ATM_MKUNIERR(reason));
1973 case PARTY_ADD_WAIT_OK: /* P3 */
1974 cc_party_set_state(party,
1975 PARTY_WAIT_DESTROY);
1978 USER_SIG_ADD_PARTY_ERR,
1979 NULL, ATM_MKUNIERR(reason));
1982 case PARTY_DROP_WAIT_OK: /* P5 */
1983 cc_party_set_state(party,
1987 USER_SIG_DROP_PARTY_ERR,
1988 NULL, ATM_MKUNIERR(reason));
1991 case PARTY_WAIT_DROP_ACK_OK: /* P9 */
1992 cc_party_set_state(party,
1996 case PARTY_ADD_DROP_WAIT_OK: /* P11 */
1997 cc_party_set_state(party,
1998 PARTY_ADD_WAIT_ACK);
2001 USER_SIG_DROP_PARTY_ERR,
2002 NULL, ATM_MKUNIERR(reason));
2005 case PARTY_ADD_DROPACK_WAIT_OK:/* P12 */
2006 cc_party_set_state(party,
2007 PARTY_ADD_WAIT_ACK);
2014 cc_conn_log(conn, "unexpected reason=%u ustate=%u "
2015 "state=%s\n", reason, state, stab[conn->state]);
2022 case CONN_SIG_PARTY_CREATED:
2024 struct uni_msg *msg = arg;
2025 struct uniapi_party_created *pcr = uni_msg_rptr(msg,
2026 struct uniapi_party_created *);
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
2033 switch (conn->state) {
2035 case CONN_IN_PREPARING:
2036 party = cc_party_create(conn,
2037 pcr->epref.epref, 1);
2040 cc_party_set_state(party,
2041 PARTY_WAIT_SETUP_COMPL);
2044 case CONN_OUT_WAIT_OK:
2045 party = cc_party_create(conn,
2046 pcr->epref.epref, 0);
2049 cc_party_set_state(party,
2050 PARTY_WAIT_SETUP_CONF);
2058 /* this is for an ADD-PARTY */
2059 if (conn->state != CONN_ACTIVE)
2061 if (party->state != PARTY_ADD_WAIT_CREATE)
2062 goto bad_party_state;
2063 cc_party_set_state(party, PARTY_ADD_WAIT_OK);
2067 case CONN_SIG_PARTY_DESTROYED:
2069 struct uni_msg *msg = arg;
2070 struct uniapi_party_destroyed *pcr = uni_msg_rptr(msg,
2071 struct uniapi_party_destroyed *);
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);
2079 cc_party_destroy(party);
2088 cc_conn_log(conn, "bad state=%s for signal=%s",
2089 stab[conn->state], cc_conn_sigtab[sig]);
2093 cc_conn_log(conn, "bad party state=%s for signal=%s",
2094 ptab[party->state], cc_conn_sigtab[sig]);