diff options
Diffstat (limited to 'sys/contrib/ngatm/netnatm/sig/sig_call.c')
-rw-r--r-- | sys/contrib/ngatm/netnatm/sig/sig_call.c | 4310 |
1 files changed, 0 insertions, 4310 deletions
diff --git a/sys/contrib/ngatm/netnatm/sig/sig_call.c b/sys/contrib/ngatm/netnatm/sig/sig_call.c deleted file mode 100644 index d2e3b7f9af2e..000000000000 --- a/sys/contrib/ngatm/netnatm/sig/sig_call.c +++ /dev/null @@ -1,4310 +0,0 @@ -/* - * Copyright (c) 1996-2003 - * Fraunhofer Institute for Open Communication Systems (FhG Fokus). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * Author: Hartmut Brandt <harti@freebsd.org> - * - * $Begemot: libunimsg/netnatm/sig/sig_call.c,v 1.65 2004/08/05 07:11:00 brandt Exp $ - * - * Call instance handling - * - * Note: - * In all functions that handle messages from the user or from - * the SAAL, commit memory allocation always at the begin of the - * function. If allocation fails, ignore saal messages and - * respond with an error to user messages. - */ - -#include <netnatm/unimsg.h> -#include <netnatm/saal/sscfudef.h> -#include <netnatm/msg/unistruct.h> -#include <netnatm/msg/unimsglib.h> -#include <netnatm/sig/uni.h> - -#include <netnatm/sig/unipriv.h> -#include <netnatm/sig/unimkmsg.h> -#include <netnatm/sig/unimsgcpy.h> - -static enum call_state state_compat(struct call *, enum uni_callstate); -static void respond_drop_party_ack(struct call *, struct uni_ie_epref *, u_int); - - -#define DEF_PRIV_SIG(NAME, FROM) [SIG##NAME] = "SIG"#NAME, -static const char *const call_sigs[] = { - DEF_CALL_SIGS -}; -#undef DEF_PRIV_SIG - -TIMER_FUNC_CALL(t308, t308_func) -TIMER_FUNC_CALL(t303, t303_func) -TIMER_FUNC_CALL(t301, t301_func) -TIMER_FUNC_CALL(t310, t310_func) -TIMER_FUNC_CALL(t313, t313_func) -TIMER_FUNC_CALL(t322, t322_func) - -const struct callstates callstates[] = { - [CALLST_NULL] = { "NU0", UNI_CALLSTATE_U0 }, - [CALLST_U1] = { "U1", UNI_CALLSTATE_U1 }, - [CALLST_U3] = { "U3", UNI_CALLSTATE_U3 }, - [CALLST_U4] = { "U4", UNI_CALLSTATE_U4 }, - [CALLST_U6] = { "U6", UNI_CALLSTATE_U6 }, - [CALLST_U7] = { "U7", UNI_CALLSTATE_U7 }, - [CALLST_U8] = { "U8", UNI_CALLSTATE_U8 }, - [CALLST_U9] = { "U9", UNI_CALLSTATE_U9 }, - [CALLST_U10] = { "U10", UNI_CALLSTATE_U10 }, - [CALLST_U11] = { "U11", UNI_CALLSTATE_U11 }, - [CALLST_U12] = { "U12", UNI_CALLSTATE_U12 }, - [CALLST_N1] = { "N1", UNI_CALLSTATE_N1 }, - [CALLST_N3] = { "N3", UNI_CALLSTATE_N3 }, - [CALLST_N4] = { "N4", UNI_CALLSTATE_N4 }, - [CALLST_N6] = { "N6", UNI_CALLSTATE_N6 }, - [CALLST_N7] = { "N7", UNI_CALLSTATE_N7 }, - [CALLST_N8] = { "N8", UNI_CALLSTATE_N8 }, - [CALLST_N9] = { "N9", UNI_CALLSTATE_N9 }, - [CALLST_N10] = { "N10", UNI_CALLSTATE_N10 }, - [CALLST_N11] = { "N11", UNI_CALLSTATE_N11 }, - [CALLST_N12] = { "N12", UNI_CALLSTATE_N12 }, -}; - -static void unx_send_add_party_rej(struct call *c, struct uni_all *u); - -static __inline void -set_call_state(struct call *c, enum call_state state) -{ - ASSERT(state == CALLST_NULL || - (c->uni->proto == UNIPROTO_UNI40U && - (state >= CALLST_U1 && state <= CALLST_U12)) || - (c->uni->proto == UNIPROTO_UNI40N && - (state >= CALLST_N1 && state <= CALLST_N12)), - ("setting wrong callstate for proto %u: %u", c->uni->proto, state)); - - if (c->cstate != state) { - VERBOSE(c->uni, UNI_FAC_CALL, 1, "call %d/%d %s -> %s", - c->cref, c->mine, callstates[c->cstate].name, - callstates[state].name); - c->cstate = state; - } -} - -static enum uni_callstate -map_callstate(enum call_state state) -{ - return (callstates[state].ext); -} - -/* - * Find the call. Assume, that the cref is one of a message just received. - * That is, if the call reference flag is 0 it is his call, if it is 1 it - * is my call. - */ -struct call * -uni_find_call(struct uni *uni, struct uni_cref *cref) -{ - struct call *c; - - TAILQ_FOREACH(c, &uni->calls, link) - if (c->cref == cref->cref && (!c->mine == !cref->flag)) - return (c); - return (NULL); -} -struct call * -uni_find_callx(struct uni *uni, u_int cref, u_int mine) -{ - struct call *c; - - TAILQ_FOREACH(c, &uni->calls, link) - if (c->cref == cref && !c->mine == !mine) - return (c); - return (NULL); -} - -/* - * Create a new call instance. The type must be set by the caller. - */ -struct call * -uni_create_call(struct uni *uni, u_int cref, u_int mine, uint32_t cookie) -{ - struct call *c; - struct uniapi_call_created *ind; - struct uni_msg *api; - - if ((c = CALL_ALLOC()) == NULL) - return (NULL); - - if ((ind = ALLOC_API(struct uniapi_call_created, api)) == NULL) { - CALL_FREE(c); - return (NULL); - } - ind->cref.cref = cref; - ind->cref.flag = mine; - - c->uni = uni; - c->type = CALL_NULL; - c->cref = cref; - c->mine = mine; - c->cstate = CALLST_NULL; - TAILQ_INIT(&c->parties); - - TIMER_INIT_CALL(c, t301); - TIMER_INIT_CALL(c, t303); - TIMER_INIT_CALL(c, t308); - TIMER_INIT_CALL(c, t310); - TIMER_INIT_CALL(c, t313); - TIMER_INIT_CALL(c, t322); - - TAILQ_INSERT_HEAD(&uni->calls, c, link); - - uni->funcs->uni_output(uni, uni->arg, UNIAPI_CALL_CREATED, cookie, api); - - VERBOSE(c->uni, UNI_FAC_CALL, 1, "created call %u/%s", - c->cref, c->mine ? "mine" : "his"); - - return (c); -} - -struct call * -uni_create_new_call(struct uni *uni, uint32_t cookie) -{ - struct call *c; - uint32_t old = uni->cref_alloc++; - - again: - if (uni->cref_alloc == (1 << 23)) - uni->cref_alloc = 1; - if (uni->cref_alloc == old) - return (NULL); /* all crefs exhausted!!! */ - TAILQ_FOREACH(c, &uni->calls, link) - if (c->mine && c->cref == uni->cref_alloc) { - uni->cref_alloc++; - goto again; - } - return (uni_create_call(uni, uni->cref_alloc, 1, cookie)); -} - -/* - * Assume timers are all stopped. Memory is not actually freed unless - * the reference count drops to 0. - * This function is assumed to remove the call from the parent UNI's - * call queue. - */ -void -uni_destroy_call(struct call *c, int really) -{ - struct uniapi_call_destroyed *ind; - struct uni_msg *api; - struct party *p; - - VERBOSE(c->uni, UNI_FAC_CALL, 1, "destroying call %u/%s", - c->cref, c->mine ? "mine" : "his"); - - TIMER_DESTROY_CALL(c, t301); - TIMER_DESTROY_CALL(c, t303); - TIMER_DESTROY_CALL(c, t308); - TIMER_DESTROY_CALL(c, t310); - TIMER_DESTROY_CALL(c, t313); - TIMER_DESTROY_CALL(c, t322); - TAILQ_REMOVE(&c->uni->calls, c, link); - - uni_delsig(c->uni, SIG_CALL, c, NULL); - - while ((p = TAILQ_FIRST(&c->parties)) != NULL) { - TAILQ_REMOVE(&c->parties, p, link); - uni_destroy_party(p, really); - } - - if (!really) { - ind = ALLOC_API(struct uniapi_call_destroyed, api); - if (ind != NULL) { - ind->cref.cref = c->cref; - ind->cref.flag = c->mine; - - uni_enq_coord(c->uni, SIGO_CALL_DESTROYED, 0, api); - } - - uni_enq_call(c, SIGC_CALL_DELETE, 0, NULL, NULL); - return; - } - - CALL_FREE(c); -} - -static void -allocate_epref(struct call *c, struct uni_ie_epref *epref) -{ - struct party *p; - uint32_t old = c->epref_alloc++; - - again: - if (c->epref_alloc == (1 << 15)) - c->epref_alloc = 0; - if (c->epref_alloc == old) - return; /* all crefs exhausted!!! */ - TAILQ_FOREACH(p, &c->parties, link) - if (p->epref == c->epref_alloc) { - c->epref_alloc++; - goto again; - } - IE_SETPRESENT(*epref); - epref->flag = 0; - epref->epref = c->epref_alloc; - - epref->h.coding = UNI_CODING_ITU; - epref->h.act = UNI_IEACT_DEFAULT; -} - -static void -reset_all_timers(struct call *c) -{ - TIMER_STOP_CALL(c, t301); - TIMER_STOP_CALL(c, t303); - TIMER_STOP_CALL(c, t308); - TIMER_STOP_CALL(c, t310); - TIMER_STOP_CALL(c, t313); - TIMER_STOP_CALL(c, t322); -} - -/* - * Initiate call clearing because of a problem. This is label D in - * the SDLs and is called from many places. - * The call must have constructed the cause IE in struct call. - * - * Q.2971:Call-Control-U 27/39 - * Q.2971:Call-Control-N 28/39 - * - * Memory problems are handled differently here: we simply ignore them - * by not sending messages or user indications. Because of T308 we - * may be lucky to send the message in a second run. - * - * It is assumed, that the cause for the release is constructed by - * the calling function in uni->cause. - */ -static void -clear_callD(struct call *c) -{ - struct uni_msg *api; - struct uniapi_release_indication *ind; - struct party *p; - struct uni_all *rel; - - /* - * Send indication to API - */ - if ((ind = ALLOC_API(struct uniapi_release_indication, api)) != NULL) { - ind->release.hdr.cref.cref = c->cref; - ind->release.hdr.cref.flag = c->mine; - ind->release.hdr.act = UNI_MSGACT_DEFAULT; - ind->release.cause[0] = c->uni->cause; - - c->uni->funcs->uni_output(c->uni, c->uni->arg, - UNIAPI_RELEASE_indication, 0, api); - } - - reset_all_timers(c); - - if (c->type == CALL_LEAF || c->type == CALL_ROOT) { - TAILQ_FOREACH(p, &c->parties, link) { - uni_enq_party(p, SIGP_RELEASE_request, 0, NULL, NULL); - } - } - - memset(&c->msg_release, 0, sizeof(c->msg_release)); - c->msg_release.cause[0] = c->uni->cause; - - if ((rel = UNI_ALLOC()) != NULL) { - rel->u.release = c->msg_release; - MK_MSG_ORIG(rel, UNI_RELEASE, c->cref, !c->mine); - (void)uni_send_output(rel, c->uni); - UNI_FREE(rel); - } - - TIMER_START_CALL(c, t308, c->uni->timer308); - c->cnt308 = 0; - - if (c->uni->proto == UNIPROTO_UNI40N) - set_call_state(c, CALLST_N12); - else - set_call_state(c, CALLST_U11); -} - - -/**********************************************************************/ -/* - * SETUP message in state NULL - * - * Q.2971:Call-Control-U 4/39 - * Q.2971:Call-Control-N 4/39 - */ -static void -un0_setup(struct call *c, struct uni_msg *m, struct uni_all *u, - enum call_state new_state) -{ - struct uni_all *resp; - struct party *p; - struct uniapi_setup_indication *ind; - struct uni_msg *api; - enum verify v; - - if ((ind = ALLOC_API(struct uniapi_setup_indication, api)) == NULL) { - clear: - uni_destroy_call(c, 0); - uni_msg_destroy(m); - UNI_FREE(u); - return; - } - - /* - * Analyze message - */ - (void)uni_decode_body(m, u, &c->uni->cx); - MANDATE_IE(c->uni, u->u.setup.bearer, UNI_IE_BEARER); - MANDATE_IE(c->uni, u->u.setup.traffic, UNI_IE_TRAFFIC); - MANDATE_IE(c->uni, u->u.setup.called, UNI_IE_CALLED); - - /* - * UNI4.0: 9.1.1.2 Notes 2/3 - */ - if (!IE_ISPRESENT(u->u.setup.qos)) - MANDATE_IE(c->uni, u->u.setup.exqos, UNI_IE_EXQOS); - if (!IE_ISPRESENT(u->u.setup.exqos)) - MANDATE_IE(c->uni, u->u.setup.qos, UNI_IE_QOS); - - /* - * Q.2971 - */ - if (IE_ISGOOD(u->u.setup.bearer) && - u->u.setup.bearer.cfg == UNI_BEARER_MP) { - if (IE_ISGOOD(u->u.setup.epref) && - u->u.setup.epref.flag == 1) { - IE_SETERROR(u->u.setup.epref); - (void)UNI_SAVE_IERR(&c->uni->cx, UNI_IE_EPREF, - u->u.setup.epref.h.act, UNI_IERR_BAD); - } - uni_mandate_epref(c->uni, &u->u.setup.epref); - } - - v = uni_verify(c->uni, u->u.hdr.act); - switch (v) { - - case VFY_RAI: - uni_respond_status_verify(c->uni, &u->u.hdr.cref, - UNI_CALLSTATE_U0, NULL, 0); - /* FALLTHRU */ - case VFY_I: - uni_msg_destroy(api); - goto clear; - - case VFY_RAIM: - case VFY_CLR: - if ((resp = UNI_ALLOC()) != NULL) { - MK_MSG_RESP(resp, UNI_RELEASE_COMPL, &u->u.hdr.cref); - uni_vfy_collect_ies(c->uni); - resp->u.release_compl.cause[0] = c->uni->cause; - uni_send_output(resp, c->uni); - UNI_FREE(resp); - } - uni_msg_destroy(api); - goto clear; - - case VFY_RAP: - case VFY_RAPU: - uni_respond_status_verify(c->uni, &u->u.hdr.cref, - map_callstate(new_state), NULL, 0); - /* FALLTHRU */ - case VFY_OK: - break; - } - - if (u->u.setup.bearer.cfg == UNI_BEARER_P2P) { - c->type = CALL_P2P; - - } else { - c->type = CALL_LEAF; - if ((p = uni_create_party(c, &u->u.setup.epref)) == NULL) { - uni_msg_destroy(api); - goto clear; - } - uni_enq_party(p, SIGP_SETUP, 0, NULL, NULL); - } - - ind->setup.hdr = u->u.hdr; - copy_msg_setup(&u->u.setup, &ind->setup); - c->uni->funcs->uni_output(c->uni, c->uni->arg, - UNIAPI_SETUP_indication, 0, api); - - uni_msg_destroy(m); - UNI_FREE(u); - - set_call_state(c, new_state); -} - -/* - * Setup.request from user - * - * Q.2971:Call-Control-U 4/39 (U0) - * Q.2971:Call-Control-N 4/39 (N0) - */ -static void -un0_setup_request(struct call *c, struct uni_msg *m, uint32_t cookie, - enum call_state new_state) -{ - struct uniapi_setup_request *arg = - uni_msg_rptr(m, struct uniapi_setup_request *); - struct uni_setup *setup = &arg->setup; - struct uni_all *out; - struct party *p; - - if (!IE_ISGOOD(setup->bearer)) { - uni_msg_destroy(m); - uniapi_call_error(c, UNIAPI_ERROR_MISSING_IE, cookie); - uni_destroy_call(c, 0); - return; - } - if ((out = UNI_ALLOC()) == NULL) { - uni_msg_destroy(m); - uniapi_call_error(c, UNIAPI_ERROR_NOMEM, cookie); - uni_destroy_call(c, 0); - return; - } - - c->msg_setup = *setup; - - if (IE_ISGOOD(setup->connid)) - c->connid = setup->connid; - - if (setup->bearer.cfg == UNI_BEARER_P2P) { - c->type = CALL_P2P; - } else { - c->type = CALL_ROOT; - - /* - * If the user didn't specify a endpoint reference, - * use 0. Use IE_IGNORE accoring to Appendix II Q.2971 - */ - if (!IE_ISPRESENT(c->msg_setup.epref)) { - MK_IE_EPREF(c->msg_setup.epref, 0, 0); - if (c->uni->proto == UNIPROTO_UNI40N) - c->msg_setup.epref.h.act = UNI_IEACT_IGNORE; - - } else if (!IE_ISGOOD(c->msg_setup.epref)) { - uni_msg_destroy(m); - uniapi_call_error(c, UNIAPI_ERROR_BAD_IE, cookie); - uni_destroy_call(c, 0); - return; - } - if ((p = uni_create_partyx(c, 0, 1, cookie)) == NULL) { - uni_msg_destroy(m); - uniapi_call_error(c, UNIAPI_ERROR_NOMEM, cookie); - uni_destroy_call(c, 0); - return; - } - uni_enq_party(p, SIGP_SETUP_request, cookie, NULL, NULL); - } - - uni_msg_destroy(m); - - out->u.setup = c->msg_setup; - MK_MSG_ORIG(out, UNI_SETUP, c->cref, !c->mine); - (void)uni_send_output(out, c->uni); - UNI_FREE(out); - - TIMER_START_CALL(c, t303, c->uni->timer303); - c->cnt303 = 0; - - set_call_state(c, new_state); - - uniapi_call_error(c, UNIAPI_OK, cookie); -} - -/* - * CALL PROCEEDING message - * - * Q.2971:Call-Control-U 6/39 (in U1) - * Q.2971:Call-Control-N 11/39 (in N6) - */ -static void -u1n6_call_proc(struct call *c, struct uni_msg *m, struct uni_all *u, - enum call_state new_state) -{ - struct uni_call_proc *cp = &u->u.call_proc; - struct uniapi_proceeding_indication *ind; - struct uni_msg *api; - - ind = ALLOC_API(struct uniapi_proceeding_indication, api); - if (ind == NULL) { - ignore: - uni_msg_destroy(m); - UNI_FREE(u); - return; - } - /* - * Analyze message - */ - (void)uni_decode_body(m, u, &c->uni->cx); - if (!IE_ISPRESENT(c->connid) && !IE_ISGOOD(cp->connid)) - uni_mandate_ie(c->uni, UNI_IE_CONNID); - - /* - * Q.2971: L3MU_01_03 requests us to ignore the message if - * the EPREF is missing. - */ - if (c->msg_setup.bearer.cfg == UNI_BEARER_MP && - IE_ISPRESENT(c->msg_setup.epref)) { - if (!IE_ISPRESENT(cp->epref)) - uni_mandate_ie(c->uni, UNI_IE_EPREF); \ - - else if (IE_ISGOOD(cp->epref) && - (cp->epref.flag != 1 || - cp->epref.epref != c->msg_setup.epref.epref)) { - IE_SETERROR(cp->epref); - (void)UNI_SAVE_IERR(&c->uni->cx, UNI_IE_EPREF, - cp->epref.h.act, UNI_IERR_BAD); - } - } - - switch (uni_verify(c->uni, u->u.hdr.act)) { - - case VFY_CLR: - uni_vfy_collect_ies(c->uni); - clear_callD(c); - /* FALLTHRU */ - case VFY_I: - uni_msg_destroy(api); - goto ignore; - - case VFY_RAIM: - case VFY_RAI: - report: - uni_respond_status_verify(c->uni, &u->u.hdr.cref, - map_callstate(c->cstate), NULL, 0); - uni_msg_destroy(api); - goto ignore; - - case VFY_RAP: - case VFY_RAPU: - if (c->type == CALL_ROOT && !IE_ISGOOD(cp->epref)) - goto report; - uni_respond_status_verify(c->uni, &u->u.hdr.cref, - map_callstate(new_state), NULL, 0); - /* FALLTHRU */ - case VFY_OK: - break; - } - - TIMER_STOP_CALL(c, t303); - - if (IE_ISGOOD(cp->connid)) - c->connid = cp->connid; - - ind->call_proc.hdr = u->u.hdr; - copy_msg_call_proc(cp, &ind->call_proc); - c->uni->funcs->uni_output(c->uni, c->uni->arg, - UNIAPI_PROCEEDING_indication, 0, api); - - TIMER_START_CALL(c, t310, c->uni->timer310); - - uni_msg_destroy(m); - UNI_FREE(u); - - set_call_state(c, new_state); -} - -/* - * T303 tick. - * - * Q.2971:Call-Control-U 6/39 - * Q.2971:Call-Control-N 11/39 - */ -static void -u1n6_t303(struct call *c) -{ - struct uni_all *msg; - struct uniapi_release_confirm *conf; - struct uni_msg *api; - - VERBOSE(c->uni, UNI_FAC_TIMEOUT, 1, "call %u/%s T303 tick %d", - c->cref, c->mine ? "mine" : "his", c->cnt303 + 1); - - if (++c->cnt303 < c->uni->init303) { - if ((msg = UNI_ALLOC()) != NULL) { - msg->u.setup = c->msg_setup; - MK_MSG_ORIG(msg, UNI_SETUP, c->cref, !c->mine); - (void)uni_send_output(msg, c->uni); - UNI_FREE(msg); - } - TIMER_START_CALL(c, t303, c->uni->timer303); - return; - } - - /* - * Send indication to API - */ - if ((conf = ALLOC_API(struct uniapi_release_confirm, api)) != NULL) { - conf->release.hdr.cref.cref = c->cref; - conf->release.hdr.cref.flag = c->mine; - conf->release.hdr.act = UNI_MSGACT_DEFAULT; - MK_IE_CAUSE(conf->release.cause[0], UNI_CAUSE_LOC_USER, - UNI_CAUSE_NO_RESPONSE); - - c->uni->funcs->uni_output(c->uni, c->uni->arg, - UNIAPI_RELEASE_confirm, 0, api); - } - - /* - * send to party (there may be only one) - */ - if (c->type == CALL_ROOT && !TAILQ_EMPTY(&c->parties)) { - uni_enq_party(TAILQ_FIRST(&c->parties), - SIGP_RELEASE_confirm, 0, NULL, NULL); - } - uni_destroy_call(c, 0); -} - -/* - * T310 (Call Proceeding) timer tick. - * - * Q.2971:Call-Control-U 7/39 - * Q.2971:Call-Control-N 17/39 - */ -static void -u3n9_t310(struct call *c) -{ - VERBOSE(c->uni, UNI_FAC_TIMEOUT, 1, "call %u/%s T310 tick", - c->cref, c->mine ? "mine" : "his"); - - MK_IE_CAUSE(c->uni->cause, UNI_CAUSE_LOC_USER, UNI_CAUSE_NO_RESPONSE); - clear_callD(c); -} - -/* - * T301 (Alerting) timer tick. - * - * Q.2971:Call-Control-U Missing - * Q.2971:Call-Control-N 14/39 - */ -static void -u4n7_t301(struct call *c) -{ - VERBOSE(c->uni, UNI_FAC_TIMEOUT, 1, "call %u/%s T301 tick", - c->cref, c->mine ? "mine" : "his"); - - MK_IE_CAUSE(c->uni->cause, UNI_CAUSE_LOC_USER, UNI_CAUSE_NO_RESP_ALERT); - clear_callD(c); -} - -/* - * ALERTING received - * - * Q.2971:Call-Control-U 37/39 (U1) - * Q.2971:Call-Control-U 7/39 (U3) - * Q.2971:Call-Control-N 9/39 (N6) - * Q.2971:Call-Control-N 17/39 (N9) - * - * There are two errors in the user side SDL Annex A: - * - * - the resetted timers are swapped (T310 and T303) - * - * - for U1 we should go to C12, not C3 to start T301. - */ -static void -unx_alerting(struct call *c, struct uni_msg *m, struct uni_all *u, - enum call_state new_state) -{ - struct uni_alerting *al = &u->u.alerting; - struct uniapi_alerting_indication *ind; - struct uni_msg *api; - - ind = ALLOC_API(struct uniapi_alerting_indication, api); - if (ind == NULL) { - ignore: - uni_msg_destroy(m); - UNI_FREE(u); - return; - } - - /* - * Analyze message - */ - (void)uni_decode_body(m, u, &c->uni->cx); - if (!IE_ISPRESENT(c->connid) && !IE_ISGOOD(al->connid)) - uni_mandate_ie(c->uni, UNI_IE_CONNID); - - /* - * Q.2971: L3MU_01_04 requests us to ignore the message if the - * EPREF is missing. - */ - if (c->msg_setup.bearer.cfg == UNI_BEARER_MP && - IE_ISPRESENT(c->msg_setup.epref)) { - if (!IE_ISPRESENT(al->epref)) - uni_mandate_ie(c->uni, UNI_IE_EPREF); \ - - else if (IE_ISGOOD(al->epref) && - (al->epref.flag != 1 || - al->epref.epref != c->msg_setup.epref.epref)) { - IE_SETERROR(al->epref); - (void)UNI_SAVE_IERR(&c->uni->cx, UNI_IE_EPREF, - al->epref.h.act, UNI_IERR_BAD); - } - } - - switch (uni_verify(c->uni, u->u.hdr.act)) { - - case VFY_CLR: - uni_vfy_collect_ies(c->uni); - clear_callD(c); - case VFY_I: - uni_msg_destroy(api); - goto ignore; - - case VFY_RAIM: - case VFY_RAI: - report: - uni_respond_status_verify(c->uni, &u->u.hdr.cref, - map_callstate(c->cstate), NULL, 0); - uni_msg_destroy(api); - goto ignore; - - case VFY_RAP: - case VFY_RAPU: - if (c->type == CALL_ROOT && !IE_ISGOOD(al->epref)) - goto report; - uni_respond_status_verify(c->uni, &u->u.hdr.cref, - map_callstate(c->cstate), NULL, 0); - case VFY_OK: - break; - } - - if (c->cstate == CALLST_U1 || c->cstate == CALLST_N6) - TIMER_STOP_CALL(c, t303); - else if (c->cstate == CALLST_U3 || c->cstate == CALLST_N9) - TIMER_STOP_CALL(c, t310); - - if (IE_ISGOOD(al->connid)) - c->connid = al->connid; - - ind->alerting.hdr = u->u.hdr; - copy_msg_alerting(al, &ind->alerting); - - if (c->type == CALL_LEAF || c->type == CALL_ROOT) { - uni_enq_party(TAILQ_FIRST(&c->parties), SIGP_ALERTING, - 0, NULL, NULL); - c->uni->funcs->uni_output(c->uni, c->uni->arg, - UNIAPI_ALERTING_indication, 0, api); - } else { - c->uni->funcs->uni_output(c->uni, c->uni->arg, - UNIAPI_ALERTING_indication, 0, api); - TIMER_START_CALL(c, t301, c->uni->timer301); - } - UNI_FREE(u); - uni_msg_destroy(m); - - set_call_state(c, new_state); -} - -/* - * Proceeding.request from API - * - * Q.2971:Call-Control-U 12/39 (U6) - * Q.2971:Call-Control-N 6/39 (N1) - */ -static void -u6n1_proceeding_request(struct call *c, struct uni_msg *m, uint32_t cookie, - enum call_state new_state) -{ - struct uni_all *msg; - struct uniapi_proceeding_request *arg = - uni_msg_rptr(m, struct uniapi_proceeding_request *); - - if ((msg = UNI_ALLOC()) == NULL) { - uni_msg_destroy(m); - uniapi_call_error(c, UNIAPI_ERROR_NOMEM, cookie); - return; - } - - if (IE_ISGOOD(arg->call_proc.connid)) - c->connid = arg->call_proc.connid; - - msg->u.call_proc = arg->call_proc; - MK_MSG_ORIG(msg, UNI_CALL_PROC, c->cref, !c->mine); - (void)uni_send_output(msg, c->uni); - UNI_FREE(msg); - - set_call_state(c, new_state); - - uni_msg_destroy(m); - - uniapi_call_error(c, UNIAPI_OK, cookie); -} - -/* - * Alerting.request from API - * - * Q.2971:Call-Control-U 13/39 (U6) - * Q.2971:Call-Control-U 17/39 (U9) - * Q.2971:Call-Control-N 38/39 (N1) - * Q.2971:Call-Control-N 7/39 (N3) - */ -static void -unx_alerting_request(struct call *c, struct uni_msg *m, uint32_t cookie, - enum call_state new_state) -{ - struct uni_all *msg; - struct uniapi_alerting_request *arg = - uni_msg_rptr(m, struct uniapi_alerting_request *); - - if ((msg = UNI_ALLOC()) == NULL) { - uni_msg_destroy(m); - uniapi_call_error(c, UNIAPI_ERROR_NOMEM, cookie); - return; - } - - if (c->type == CALL_ROOT || c->type == CALL_LEAF) { - uni_enq_party(TAILQ_FIRST(&c->parties), - SIGP_ALERTING_request, cookie, NULL, NULL); - } - - /* - * It's not really clear, what happens, if we send another - * connid in CALL_PROC and ALERTING - */ - if (!IE_ISGOOD(c->connid) && IE_ISGOOD(arg->alerting.connid)) - c->connid = arg->alerting.connid; - - msg->u.alerting = arg->alerting; - MK_MSG_ORIG(msg, UNI_ALERTING, c->cref, !c->mine); - (void)uni_send_output(msg, c->uni); - UNI_FREE(msg); - - set_call_state(c, new_state); - - uni_msg_destroy(m); - - uniapi_call_error(c, UNIAPI_OK, cookie); -} - - -/* - * Setup.response from API - * - * Q.2971:Call-Control-U 13/39 (U6) - * Q.2971:Call-Control-U 14/39 (U7) - * Q.2971:Call-Control-U 17/39 (U9) - * Q.2971:Call-Control-N 39/39 (N1) - * Q.2971:Call-Control-N 7/39 (N3) - * Q.2971:Call-Control-N 8/39 (N4) - */ -static void -unx_setup_response(struct call *c, struct uni_msg *m, uint32_t cookie, - enum call_state new_state) -{ - struct uni_all *msg; - struct uniapi_setup_response *arg = - uni_msg_rptr(m, struct uniapi_setup_response *); - struct party *p; - - if ((msg = UNI_ALLOC()) == NULL) { - uni_msg_destroy(m); - uniapi_call_error(c, UNIAPI_ERROR_NOMEM, cookie); - return; - } - - if (!IE_ISGOOD(c->connid) && IE_ISGOOD(arg->connect.connid)) - c->connid = arg->connect.connid; - - if (IE_ISGOOD(arg->connect.epref)) { - p = uni_find_partyx(c, arg->connect.epref.epref, - !arg->connect.epref.flag); - if (p == NULL) { - uniapi_call_error(c, UNIAPI_ERROR_BAD_PARTY, cookie); - UNI_FREE(msg); - uni_msg_destroy(m); - return; - } - /* we need to remember that we have sent the CONNECT from this - * party because the CONNECT ACK must move only this party - * into P7 */ - p->flags |= PARTY_CONNECT; - - } else if (c->type == CALL_LEAF) { - /* XXX don't mandate if only one party */ - uniapi_call_error(c, UNIAPI_ERROR_BAD_PARTY, cookie); - UNI_FREE(msg); - uni_msg_destroy(m); - return; - } - - /* inform the parties on the network side */ - if (c->uni->proto == UNIPROTO_UNI40N && c->type == CALL_LEAF) - TAILQ_FOREACH(p, &c->parties, link) - uni_enq_party(p, SIGP_SETUP_response, 0, NULL, NULL); - - msg->u.connect = arg->connect; - MK_MSG_ORIG(msg, UNI_CONNECT, c->cref, !c->mine); - (void)uni_send_output(msg, c->uni); - UNI_FREE(msg); - - if (c->uni->proto == UNIPROTO_UNI40U) - TIMER_START_CALL(c, t313, c->uni->timer313); - - set_call_state(c, new_state); - - uni_msg_destroy(m); - - uniapi_call_error(c, UNIAPI_OK, cookie); -} - -/* - * Setup_complete.request - * - * Q.2971:Call-Control-N 15/39 (N8) - */ -static void -n8_setup_compl_request(struct call *c, struct uni_msg *m, uint32_t cookie, - enum call_state new_state) -{ - struct uni_all *msg; - struct uniapi_setup_complete_request *arg = - uni_msg_rptr(m, struct uniapi_setup_complete_request *); - struct party *p; - - if ((msg = UNI_ALLOC()) == NULL) { - uni_msg_destroy(m); - uniapi_call_error(c, UNIAPI_ERROR_NOMEM, cookie); - return; - } - - /* inform the parties on the network side */ - if (c->uni->proto == UNIPROTO_UNI40N && - (c->type == CALL_LEAF || c->type == CALL_ROOT)) { - TAILQ_FOREACH(p, &c->parties, link) - uni_enq_party(p, SIGP_SETUP_COMPL_request, - 0, NULL, NULL); - } - - msg->u.connect_ack = arg->connect_ack; - MK_MSG_ORIG(msg, UNI_CONNECT_ACK, c->cref, !c->mine); - (void)uni_send_output(msg, c->uni); - UNI_FREE(msg); - - set_call_state(c, new_state); - - uni_msg_destroy(m); - - uniapi_call_error(c, UNIAPI_OK, cookie); -} - -/* - * CONNECT message - * - * Q.2971:Call-Control-U 7-8/39 (U3) - * Q.2971:Call-Control-U 11/39 (U4) - * Q.2971:Call-Control-U 37/39 (U1) - * Q.2971:Call-Control-N 9-10/39 (N6) - * Q.2971:Call-Control-N 14/39 (N7) - * Q.2971:Call-Control-N 17/39 (N9) - */ -static void -unx_connect(struct call *c, struct uni_msg *m, struct uni_all *u, - enum call_state new_state) -{ - struct uni_connect *co = &u->u.connect; - struct uniapi_setup_confirm *conf; - struct uni_msg *api; - struct uni_all *ack; - struct party *p; - - conf = ALLOC_API(struct uniapi_setup_confirm, api); - if (conf == NULL) { - ignore: - UNI_FREE(u); - uni_msg_destroy(m); - return; - } - if ((ack = UNI_ALLOC()) == NULL) { - uni_msg_destroy(api); - goto ignore; - } - - /* - * Analyze message - */ - (void)uni_decode_body(m, u, &c->uni->cx); - if (!IE_ISPRESENT(c->connid) && !IE_ISGOOD(co->connid)) - uni_mandate_ie(c->uni, UNI_IE_CONNID); - - /* - * Q.2971: L3MU_01_05 requires the epref to be present. - */ - p = NULL; - if (c->msg_setup.bearer.cfg == UNI_BEARER_MP) { - if (IE_ISPRESENT(c->msg_setup.epref)) { - if (!IE_ISPRESENT(co->epref)) - uni_mandate_ie(c->uni, UNI_IE_EPREF); \ - - if (IE_ISGOOD(co->epref) && - co->epref.flag != 1) { - IE_SETERROR(co->epref); - (void)UNI_SAVE_IERR(&c->uni->cx, UNI_IE_EPREF, - co->epref.h.act, UNI_IERR_BAD); - } - } - - if (IE_ISGOOD(co->epref)) { - p = uni_find_party(c, &co->epref); - if (p == NULL) { - respond_drop_party_ack(c, &co->epref, - UNI_CAUSE_ENDP_INV); - uni_msg_destroy(api); - UNI_FREE(ack); - goto ignore; - } - } - } - - switch (uni_verify(c->uni, u->u.hdr.act)) { - - case VFY_CLR: - uni_vfy_collect_ies(c->uni); - clear_callD(c); - /* FALLTHRU */ - case VFY_I: - uni_msg_destroy(api); - UNI_FREE(ack); - goto ignore; - - case VFY_RAIM: - case VFY_RAI: - report: - uni_respond_status_verify(c->uni, &u->u.hdr.cref, - map_callstate(c->cstate), NULL, 0); - uni_msg_destroy(api); - UNI_FREE(ack); - goto ignore; - - case VFY_RAP: - case VFY_RAPU: - if (c->type == CALL_ROOT && !IE_ISGOOD(co->epref)) - goto report; - uni_respond_status_verify(c->uni, &u->u.hdr.cref, - map_callstate(new_state), NULL, 0); - /* FALLTHRU */ - case VFY_OK: - break; - } - - if (IE_ISGOOD(co->connid)) - c->connid = co->connid; - - if (c->cstate == CALLST_U1 || c->cstate == CALLST_N6) - TIMER_STOP_CALL(c, t303); - else if (c->cstate == CALLST_U3 || c->cstate == CALLST_N9) - TIMER_STOP_CALL(c, t310); - else if (c->cstate == CALLST_U4 || c->cstate == CALLST_N7) { - if(c->type == CALL_P2P) - TIMER_STOP_CALL(c, t301); - } - - /* - * This is sent to the party only on the user side and only - * to the one party in the epref (L3MU_05_03). - */ - if (c->uni->proto == UNIPROTO_UNI40U && - (c->type == CALL_LEAF || c->type == CALL_ROOT)) - uni_enq_party(p, SIGP_CONNECT, 0, NULL, NULL); - - conf->connect.hdr = u->u.hdr; - copy_msg_connect(co, &conf->connect); - c->uni->funcs->uni_output(c->uni, c->uni->arg, - UNIAPI_SETUP_confirm, 0, api); - - if (c->uni->proto == UNIPROTO_UNI40U) { - /* this is left to the application on the network side */ - MK_MSG_ORIG(ack, UNI_CONNECT_ACK, c->cref, !c->mine); - (void)uni_send_output(ack, c->uni); - UNI_FREE(ack); - } - - UNI_FREE(u); - uni_msg_destroy(m); - - set_call_state(c, new_state); -} - -/* - * T313 (Connect) timer tick. - * - * Q.2971:Call-Control-U 15/39 - */ -static void -u8_t313(struct call *c) -{ - VERBOSE(c->uni, UNI_FAC_TIMEOUT, 1, "call %u/%s T313 tick", - c->cref, c->mine ? "mine" : "his"); - - MK_IE_CAUSE(c->uni->cause, UNI_CAUSE_LOC_USER, UNI_CAUSE_RECOVER); - ADD_CAUSE_TIMER(c->uni->cause, "313"); - clear_callD(c); -} - -/* - * CONNECT ACKNOWLEDGE message in U8 - * - * Q.2971:Call-Control-U 15-16/39 - */ -static void -u8_connect_ack(struct call *c, struct uni_msg *m, struct uni_all *u, - enum call_state new_state) -{ - struct uniapi_setup_complete_indication *ind; - struct uni_msg *api; - - ind = ALLOC_API(struct uniapi_setup_complete_indication, api); - if (ind == NULL) { - ignore: - uni_msg_destroy(m); - UNI_FREE(u); - return; - } - - /* - * Analyze message - */ - (void)uni_decode_body(m, u, &c->uni->cx); - - switch (uni_verify(c->uni, u->u.hdr.act)) { - - case VFY_CLR: - uni_vfy_collect_ies(c->uni); - clear_callD(c); - /* FALLTHRU */ - case VFY_I: - uni_msg_destroy(api); - goto ignore; - - case VFY_RAIM: - case VFY_RAI: - uni_respond_status_verify(c->uni, &u->u.hdr.cref, - map_callstate(c->cstate), NULL, 0); - uni_msg_destroy(api); - goto ignore; - - case VFY_RAP: - case VFY_RAPU: - uni_respond_status_verify(c->uni, &u->u.hdr.cref, - map_callstate(new_state), NULL, 0); - /* FALLTHRU */ - case VFY_OK: - break; - } - - TIMER_STOP_CALL(c, t313); - - if (c->type == CALL_LEAF) { - struct party *p; - - TAILQ_FOREACH(p, &c->parties, link) { - if (p->flags & PARTY_CONNECT) { - uni_enq_party(p, SIGP_CONNECT_ACK, - 0, NULL, NULL); - break; - } - } - } - - ind->connect_ack.hdr = u->u.hdr; - copy_msg_connect_ack(&u->u.connect_ack, &ind->connect_ack); - c->uni->funcs->uni_output(c->uni, c->uni->arg, - UNIAPI_SETUP_COMPLETE_indication, 0, api); - - UNI_FREE(u); - uni_msg_destroy(m); - - set_call_state(c, new_state); -} - -/* - * CONNECT ACKNOWLEDGE message in N10 - * - * Q.2971:Call-Control-N 18/39 - */ -static void -n10_connect_ack(struct call *c, struct uni_msg *m, struct uni_all *u) -{ - /* - * Analyze message - */ - (void)uni_decode_body(m, u, &c->uni->cx); - - switch (uni_verify(c->uni, u->u.hdr.act)) { - - case VFY_CLR: - uni_vfy_collect_ies(c->uni); - clear_callD(c); - /* FALLTHRU */ - case VFY_I: - uni_msg_destroy(m); - UNI_FREE(u); - return; - - case VFY_RAIM: - case VFY_RAI: - case VFY_RAP: - case VFY_RAPU: - uni_respond_status_verify(c->uni, &u->u.hdr.cref, - map_callstate(c->cstate), NULL, 0); - /* FALLTHRU */ - case VFY_OK: - uni_msg_destroy(m); - UNI_FREE(u); - return; - } -} - -/* - * Release.response in U6 or U12. - * - * Q.2971:Call-Control-U 12/39 (U6) - * Q.2971:Call-Control-U 30/39 (U12) - * Q.2971:Call-Control-N 6/39 (N1) - * Q.2971:Call-Control-N 29/39 (N11) - */ -static void -unx_release_response(struct call *c, struct uni_msg *m, uint32_t cookie) -{ - struct party *p; - struct uni_all *msg; - struct uniapi_release_response *arg = - uni_msg_rptr(m, struct uniapi_release_response *); - - if ((msg = UNI_ALLOC()) == NULL) { - uniapi_call_error(c, UNIAPI_ERROR_NOMEM, cookie); - uni_msg_destroy(m); - return; - } - - if (c->cstate == CALLST_U6 || c->cstate == CALLST_N1) { - if (c->type == CALL_ROOT || c->type == CALL_LEAF) { - TAILQ_FOREACH(p, &c->parties, link) - uni_enq_party(p, SIGP_RELEASE_response, - cookie, NULL, NULL); - } - } - msg->u.release_compl = arg->release_compl; - MK_MSG_ORIG(msg, UNI_RELEASE_COMPL, c->cref, !c->mine); - (void)uni_send_output(msg, c->uni); - UNI_FREE(msg); - - uni_msg_destroy(m); - - uniapi_call_error(c, UNIAPI_OK, cookie); - - uni_destroy_call(c, 0); -} - -/* - * Got a RELEASE COMPLETE in any state expect U0 - * - * Q.2971:Call-Control-U 25/39 - * Q.2971:Call-Control-N 26/39 - * - * This is also called from the restart processes. - */ -void -uni_release_compl(struct call *c, struct uni_all *u) -{ - struct uni_msg *api; - struct uniapi_release_confirm *conf; - struct party *p; - u_int i, j; - - if ((conf = ALLOC_API(struct uniapi_release_confirm, api)) == NULL) - return; - - reset_all_timers(c); - if (c->type == CALL_ROOT || c->type == CALL_LEAF) { - TAILQ_FOREACH(p, &c->parties, link) - uni_enq_party(p, SIGP_RELEASE_COMPL, 0, NULL, NULL); - /* YYY optional call reoffering 10.3.3/10.3.4 */ - } - conf->release.hdr = u->u.hdr; - - for (i = j = 0; i < 2; i++) - if (IE_ISGOOD(u->u.release_compl.cause[i])) - conf->release.cause[j++] = u->u.release_compl.cause[i]; - for (i = j = 0; i < UNI_NUM_IE_GIT; i++) - if (IE_ISGOOD(u->u.release_compl.git[i])) - conf->release.git[j++] = u->u.release_compl.git[i]; - if (IE_ISGOOD(u->u.release_compl.uu)) - conf->release.uu = u->u.release_compl.uu; - if (IE_ISGOOD(u->u.release_compl.crankback)) - conf->release.crankback = u->u.release_compl.crankback; - - c->uni->funcs->uni_output(c->uni, c->uni->arg, - UNIAPI_RELEASE_confirm, 0, api); - - uni_destroy_call(c, 0); -} -static void -unx_release_compl(struct call *c, struct uni_msg *m, struct uni_all *u) -{ - - (void)uni_decode_body(m, u, &c->uni->cx); - (void)uni_verify(c->uni, u->u.hdr.act); /* no point :-) */ - - uni_release_compl(c, u); - - uni_msg_destroy(m); - UNI_FREE(u); -} - -/* - * Got a RELEASE COMPLETE in any state expect U0 and U11 - * - * Q.2971:Call-Control-U 25/39 - * Q.2971:Call-Control-N 26/39 - */ -static void -unx_release(struct call *c, struct uni_msg *m, struct uni_all *u, - enum call_state new_state) -{ - struct uniapi_release_indication *ind; - struct uni_msg *api; - - if ((ind = ALLOC_API(struct uniapi_release_indication, api)) == NULL) { - uni_msg_destroy(m); - UNI_FREE(u); - return; - } - - (void)uni_decode_body(m, u, &c->uni->cx); - (void)uni_verify(c->uni, u->u.hdr.act); /* no point :-) */ - - reset_all_timers(c); - if (c->type == CALL_ROOT || c->type == CALL_LEAF) { - struct party *p; - - TAILQ_FOREACH(p, &c->parties, link) - uni_enq_party(p, SIGP_RELEASE, 0, NULL, NULL); - /* YYY optional call reoffering 10.3.3/10.3.4 */ - } - if (c->cstate != new_state) { - /* - * According to Q.2971 we should send a 2nd - * Release.indication. - * According to Q.2931 the recipte of a RELEASE in U12/N11 - * is illegal. - * According to us make it legal, but don't send a 2nd - * indication. - */ - ind->release.hdr = u->u.hdr; - copy_msg_release(&u->u.release, &ind->release); - - c->uni->funcs->uni_output(c->uni, c->uni->arg, - UNIAPI_RELEASE_indication, 0, api); - } else - uni_msg_destroy(api); - - uni_msg_destroy(m); - UNI_FREE(u); - - set_call_state(c, new_state); -} - -/* - * Got RELEASE in U11 or N12 - * - * Q.2971:Call-Control-U 28/39 - * Q.2971:Call-Control-N 30/39 - */ -static void -u11n12_release(struct call *c, struct uni_msg *m, struct uni_all *u) -{ - struct uniapi_release_confirm *conf; - struct uni_msg *api; - - if ((conf = ALLOC_API(struct uniapi_release_confirm, api)) == NULL) { - uni_msg_destroy(m); - UNI_FREE(u); - return; - } - - (void)uni_decode_body(m, u, &c->uni->cx); - (void)uni_verify(c->uni, u->u.hdr.act); /* no point :-) */ - - TIMER_STOP_CALL(c, t308); - - conf->release.hdr = u->u.hdr; - copy_msg_release(&u->u.release, &conf->release); - - c->uni->funcs->uni_output(c->uni, c->uni->arg, - UNIAPI_RELEASE_confirm, 0, api); - - uni_msg_destroy(m); - UNI_FREE(u); - - uni_destroy_call(c, 0); -} - -/* - * NOTIFY message - * - * Q.2971:Call-Control-U 18/39 - * Q.2971:Call-Control-N 19/39 - */ -static void -unx_notify(struct call *c, struct uni_msg *m, struct uni_all *u) -{ - struct uniapi_notify_indication *ind; - struct uni_msg *api; - struct party *p = NULL; - - if ((ind = ALLOC_API(struct uniapi_notify_indication, api)) == NULL) { - ignore: - uni_msg_destroy(m); - UNI_FREE(u); - return; - } - - /* - * Analyze message - */ - (void)uni_decode_body(m, u, &c->uni->cx); - MANDATE_IE(c->uni, u->u.notify.notify, UNI_IE_NOTIFY); - - if (IE_ISGOOD(u->u.notify.epref)) { - if ((p = uni_find_party(c, &u->u.notify.epref)) == NULL) { - respond_drop_party_ack(c, &u->u.notify.epref, - UNI_CAUSE_ENDP_INV); - uni_msg_destroy(api); - goto ignore; - } - } - - switch (uni_verify(c->uni, u->u.hdr.act)) { - - case VFY_CLR: - uni_msg_destroy(api); - uni_vfy_collect_ies(c->uni); - clear_callD(c); - goto ignore; - - case VFY_RAIM: - case VFY_RAI: - uni_respond_status_verify(c->uni, &u->u.hdr.cref, - map_callstate(c->cstate), &u->u.notify.epref, - p ? p->state : 0); - /* FALLTHRU */ - case VFY_I: - uni_msg_destroy(api); - goto ignore; - - case VFY_RAP: - case VFY_RAPU: - uni_respond_status_verify(c->uni, &u->u.hdr.cref, - map_callstate(c->cstate), &u->u.notify.epref, - p ? p->state : 0); - case VFY_OK: - /* FALLTHRU */ - break; - } - - ind->notify.hdr = u->u.hdr; - copy_msg_notify(&u->u.notify, &ind->notify); - c->uni->funcs->uni_output(c->uni, c->uni->arg, - UNIAPI_NOTIFY_indication, 0, api); - - UNI_FREE(u); - uni_msg_destroy(m); -} - -/* - * Notify.request from user - * - * Q.2971:Call-Control-U 18/39 - * Q.2971:Call-Control-N 19/39 - */ -static void -unx_notify_request(struct call *c, struct uni_msg *m, uint32_t cookie) -{ - struct uni_all *msg; - struct uniapi_notify_request *arg = - uni_msg_rptr(m, struct uniapi_notify_request *); - - if ((msg = UNI_ALLOC()) == NULL) { - uni_msg_destroy(m); - uniapi_call_error(c, UNIAPI_ERROR_NOMEM, cookie); - return; - } - - msg->u.notify = arg->notify; - MK_MSG_ORIG(msg, UNI_NOTIFY, c->cref, !c->mine); - (void)uni_send_output(msg, c->uni); - UNI_FREE(msg); - - uni_msg_destroy(m); - - uniapi_call_error(c, UNIAPI_OK, cookie); -} - -/**********************************************************************/ - -/* - * Release.request from API in any state except U11, U12, N11, N12 - * - * Q.2971:Call-Control-U 27/39 - * Q.2971:Call-Control-N 28/39 - */ -static void -unx_release_request(struct call *c, struct uni_msg *m, uint32_t cookie, - enum call_state new_state) -{ - struct uni_all *msg; - struct uniapi_release_request *arg = - uni_msg_rptr(m, struct uniapi_release_request *); - struct party *p; - - if ((msg = UNI_ALLOC()) == NULL) { - uni_msg_destroy(m); - uniapi_call_error(c, UNIAPI_ERROR_NOMEM, cookie); - return; - } - - reset_all_timers(c); - - if (c->type == CALL_LEAF || c->type == CALL_ROOT) { - TAILQ_FOREACH(p, &c->parties, link) { - uni_enq_party(p, SIGP_RELEASE_request, cookie, - NULL, NULL); - } - } - - c->msg_release = arg->release; - if (!IE_ISPRESENT(c->msg_release.cause[0]) && - !IE_ISPRESENT(c->msg_release.cause[1])) - MK_IE_CAUSE(c->msg_release.cause[0], UNI_CAUSE_LOC_USER, - UNI_CAUSE_UNSPEC); - - msg->u.release = c->msg_release; - MK_MSG_ORIG(msg, UNI_RELEASE, c->cref, !c->mine); - (void)uni_send_output(msg, c->uni); - UNI_FREE(msg); - - TIMER_START_CALL(c, t308, c->uni->timer308); - c->cnt308 = 0; - - set_call_state(c, new_state); - - uni_msg_destroy(m); - - uniapi_call_error(c, UNIAPI_OK, cookie); -} - -/* - * Message with unknown EPREF - send a drop party according to 9.5.3.2.3a) - */ -static void -respond_drop_party_ack(struct call *c, struct uni_ie_epref *epref, - u_int cause) -{ - struct uni_all *msg; - - if ((msg = UNI_ALLOC()) == NULL) - return; - - MK_MSG_ORIG(msg, UNI_DROP_PARTY_ACK, c->cref, !c->mine); - MK_IE_EPREF(msg->u.drop_party_ack.epref, epref->epref, !epref->flag); - MK_IE_CAUSE(msg->u.drop_party_ack.cause, UNI_CAUSE_LOC_USER, cause); - (void)uni_send_output(msg, c->uni); - UNI_FREE(msg); -} - -/* - * T308 (RELEASE) timer - * - * Q.2971:Call-Control-U 28/39 - * Q.2971:Call-Control-N 30/39 - */ -static void -u11n12_t308(struct call *c) -{ - struct uni_all *msg; - struct uni_msg *api; - struct uniapi_release_confirm *conf; - - VERBOSE(c->uni, UNI_FAC_TIMEOUT, 1, "call %u/%s T308 tick %d", - c->cref, c->mine ? "mine" : "his", c->cnt308 + 1); - - if (++c->cnt308 < c->uni->init308) { - if ((msg = UNI_ALLOC()) != NULL) { - msg->u.release = c->msg_release; - MK_MSG_ORIG(msg, UNI_RELEASE, c->cref, !c->mine); - if (!IE_ISPRESENT(msg->u.release.cause[1])) { - MK_IE_CAUSE(msg->u.release.cause[1], - UNI_CAUSE_LOC_USER, UNI_CAUSE_RECOVER); - ADD_CAUSE_TIMER(msg->u.release.cause[1], "308"); - } - (void)uni_send_output(msg, c->uni); - UNI_FREE(msg); - } - TIMER_START_CALL(c, t308, c->uni->timer308); - return; - } - - /* - * Send indication to API - */ - if ((conf = ALLOC_API(struct uniapi_release_confirm, api)) != NULL) { - conf->release.hdr.cref.cref = c->cref; - conf->release.hdr.cref.flag = c->mine; - conf->release.hdr.act = UNI_MSGACT_DEFAULT; - MK_IE_CAUSE(conf->release.cause[0], UNI_CAUSE_LOC_USER, - UNI_CAUSE_RECOVER); - ADD_CAUSE_TIMER(conf->release.cause[0], "308"); - - c->uni->funcs->uni_output(c->uni, c->uni->arg, - UNIAPI_RELEASE_confirm, 0, api); - } - - uni_destroy_call(c, 0); -} -/**********************************************************************/ - -/* - * STATUS in U11/U12 - * - * Q.2971:Call-Control-U 29/39 (U11) - * Q.2971:Call-Control-U 30/39 (U12) - * Q.2971:Call-Control-N 29/39 (N11) - * Q.2971:Call-Control-N 31/39 (N12) - */ -static void -un11un12_status(struct call *c, struct uni_msg *m, struct uni_all *u) -{ - enum call_state ns; - struct uniapi_release_confirm *conf; - struct uni_msg *api; - struct party *p; - struct uniapi_status_indication *stat; - - /* - * Analyze message - */ - (void)uni_decode_body(m, u, &c->uni->cx); - MANDATE_IE(c->uni, u->u.status.callstate, UNI_IE_CALLSTATE); - MANDATE_IE(c->uni, u->u.status.cause, UNI_IE_CAUSE); - - ns = c->cstate; - if (IE_ISGOOD(u->u.status.callstate) && - u->u.status.callstate.state == UNI_CALLSTATE_U0) - ns = CALLST_NULL; - - p = NULL; - if (IE_ISGOOD(u->u.status.epref)) - p = uni_find_party(c, &u->u.status.epref); - - switch (uni_verify(c->uni, u->u.hdr.act)) { - - case VFY_CLR: - uni_vfy_collect_ies(c->uni); - clear_callD(c); - uni_msg_destroy(m); - UNI_FREE(u); - return; - - case VFY_RAIM: - case VFY_RAI: - case VFY_RAP: - case VFY_RAPU: - uni_respond_status_verify(c->uni, &u->u.hdr.cref, - map_callstate(ns), &u->u.status.epref, - p ? p->state : UNI_EPSTATE_NULL); - case VFY_I: - case VFY_OK: - break; - } - - if (ns == c->cstate) { - /* - * Inform API - */ - stat = ALLOC_API(struct uniapi_status_indication, api); - if (stat != NULL) { - stat->cref = u->u.hdr.cref; - stat->my_state = map_callstate(c->cstate); - stat->his_state = u->u.status.callstate; - stat->his_cause = u->u.status.cause; - stat->epref = u->u.status.epref; - stat->epstate = u->u.status.epstate; - stat->my_cause = 0; - c->uni->funcs->uni_output(c->uni, c->uni->arg, - UNIAPI_STATUS_indication, 0, api); - } - - uni_msg_destroy(m); - UNI_FREE(u); - - return; - } - - uni_msg_destroy(m); - UNI_FREE(u); - - /* - * Send indication to API - */ - if ((conf = ALLOC_API(struct uniapi_release_confirm, api)) != NULL) { - conf->release.hdr.cref.cref = c->cref; - conf->release.hdr.cref.flag = c->mine; - conf->release.hdr.act = UNI_MSGACT_DEFAULT; - MK_IE_CAUSE(conf->release.cause[0], UNI_CAUSE_LOC_USER, - UNI_CAUSE_MSG_INCOMP); - ADD_CAUSE_MTYPE(conf->release.cause[0], UNI_STATUS); - - c->uni->funcs->uni_output(c->uni, c->uni->arg, - UNIAPI_RELEASE_confirm, 0, api); - } - - uni_destroy_call(c, 0); -} - -static int -status_enq_filter(struct sig *sig, void *arg) -{ - return (sig->type == SIG_CALL && - (struct call *)arg == sig->call && - sig->sig == SIGC_SEND_STATUS_ENQ); -} - -/* - * STATUS in any state except U0/U11/U12 N0/N11/N12 - * - * Q.2971:Call-Control-U 32/39 - * Q.2971:Call-Control-N 33/39 - */ -static void -unx_status(struct call *c, struct uni_msg *m, struct uni_all *u) -{ - struct uniapi_status_indication *stat; - struct uniapi_release_confirm *conf; - enum call_state ns; - struct uni_msg *api; - struct party *p; - - /* - * Analyze message - */ - (void)uni_decode_body(m, u, &c->uni->cx); - MANDATE_IE(c->uni, u->u.status.callstate, UNI_IE_CALLSTATE); - MANDATE_IE(c->uni, u->u.status.cause, UNI_IE_CAUSE); - - ns = c->cstate; - if (IE_ISGOOD(u->u.status.callstate)) - ns = state_compat(c, u->u.status.callstate.state); - - p = NULL; - if (IE_ISGOOD(u->u.status.epref)) { - p = uni_find_party(c, &u->u.status.epref); - MANDATE_IE(c->uni, u->u.status.epstate, UNI_IE_EPSTATE); - } - - switch (uni_verify(c->uni, u->u.hdr.act)) { - - case VFY_CLR: - uni_vfy_collect_ies(c->uni); - clear_callD(c); - uni_msg_destroy(m); - UNI_FREE(u); - return; - - case VFY_RAIM: - case VFY_RAI: - case VFY_RAP: - case VFY_RAPU: - uni_respond_status_verify(c->uni, &u->u.hdr.cref, - map_callstate(ns), &u->u.notify.epref, - p ? p->state : UNI_EPSTATE_NULL); - /* FALLTHRU */ - case VFY_I: - case VFY_OK: - break; - } - - if (u->u.status.callstate.state == UNI_CALLSTATE_U0) { - /* release_complete */ - uni_msg_destroy(m); - UNI_FREE(u); - - if (c->type == CALL_LEAF || c->type == CALL_ROOT) { - TAILQ_FOREACH(p, &c->parties, link) - uni_enq_party(p, SIGP_RELEASE_COMPL, - 0, NULL, NULL); - } - /* - * Send indication to API - */ - conf = ALLOC_API(struct uniapi_release_confirm, api); - if (conf != NULL) { - conf->release.hdr.cref.cref = c->cref; - conf->release.hdr.cref.flag = c->mine; - conf->release.hdr.act = UNI_MSGACT_DEFAULT; - MK_IE_CAUSE(conf->release.cause[0], UNI_CAUSE_LOC_USER, - UNI_CAUSE_MSG_INCOMP); - ADD_CAUSE_MTYPE(conf->release.cause[0], UNI_STATUS); - - c->uni->funcs->uni_output(c->uni, c->uni->arg, - UNIAPI_RELEASE_confirm, 0, api); - } - uni_destroy_call(c, 0); - return; - } - - if (IE_ISGOOD(u->u.status.cause) && - u->u.status.cause.cause == UNI_CAUSE_STATUS) { - c->se_active = 0; - TIMER_STOP_CALL(c, t322); - uni_undel(c->uni, status_enq_filter, c); - } - - /* - * Inform API - */ - if ((stat = ALLOC_API(struct uniapi_status_indication, api)) != NULL) { - stat->cref = u->u.hdr.cref; - stat->my_state = map_callstate(c->cstate); - stat->his_state = u->u.status.callstate; - stat->his_cause = u->u.status.cause; - stat->epref = u->u.status.epref; - stat->epstate = u->u.status.epstate; - } - - if (ns == c->cstate) { - /* compatible or recovered */ - if (p != NULL) - uni_enq_party(p, SIGP_STATUS, 0, m, u); - else { - if (IE_ISGOOD(u->u.status.epref) && - (!IE_ISGOOD(u->u.status.epstate) || - u->u.status.epstate.state != UNI_EPSTATE_NULL)) - respond_drop_party_ack(c, &u->u.status.epref, - UNI_CAUSE_MSG_INCOMP); - - uni_msg_destroy(m); - UNI_FREE(u); - } - if (stat != NULL) { - stat->my_cause = 0; - c->uni->funcs->uni_output(c->uni, c->uni->arg, - UNIAPI_STATUS_indication, 0, api); - } - - return; - } - - /* incompatible */ - if (stat != NULL) { - stat->my_cause = UNI_CAUSE_MSG_INCOMP; - c->uni->funcs->uni_output(c->uni, c->uni->arg, - UNIAPI_STATUS_indication, 0, api); - } - - MK_IE_CAUSE(c->uni->cause, UNI_CAUSE_LOC_USER, UNI_CAUSE_MSG_INCOMP); - - uni_msg_destroy(m); - UNI_FREE(u); - - clear_callD(c); -} - -/* - * Enquiry peer status - * - * Q.2971:Call-Control-U 31/39 - * Q.2971:Call-Control-N 32/39 - */ -static void -unx_status_enquiry_request(struct call *c, struct uni_msg *msg, uint32_t cookie) -{ - struct uniapi_status_enquiry_request *arg = - uni_msg_rptr(msg, struct uniapi_status_enquiry_request *); - struct party *p; - struct uni_all *stat; - - if (c->se_active) { - /* This case is not handled in the SDLs */ - uniapi_call_error(c, UNIAPI_ERROR_BUSY, cookie); - uni_msg_destroy(msg); - return; - } - if ((c->type == CALL_ROOT || c->type == CALL_LEAF) && - IE_ISGOOD(arg->epref)) { - if ((p = uni_find_partyx(c, arg->epref.epref, !arg->epref.flag)) - == NULL) { - uniapi_call_error(c, UNIAPI_ERROR_BAD_PARTY, cookie); - uni_msg_destroy(msg); - return; - } - uni_msg_destroy(msg); - uni_enq_party(p, SIGP_STATUS_ENQUIRY_request, cookie, - NULL, NULL); - return; - } - if ((stat = UNI_ALLOC()) == NULL) { - uniapi_call_error(c, UNIAPI_ERROR_NOMEM, cookie); - uni_msg_destroy(msg); - return; - } - memset(&c->stat_epref, 0, sizeof(c->stat_epref)); - MK_MSG_ORIG(stat, UNI_STATUS_ENQ, c->cref, !c->mine); - (void)uni_send_output(stat, c->uni); - UNI_FREE(stat); - - TIMER_START_CALL(c, t322, c->uni->timer322); - c->cnt322 = 0; - c->se_active = 1; - - uniapi_call_error(c, UNIAPI_OK, cookie); -} - -/* - * T322 tick - * - * Q.2971:Call-Control-U 34/39 - * Q.2971:Call-Control-N 35/39 - */ -static void -unx_t322(struct call *c) -{ - struct uni_all *stat; - - VERBOSE(c->uni, UNI_FAC_TIMEOUT, 1, "call %u/%s T322 tick %d", - c->cref, c->mine ? "mine" : "his", c->cnt322 + 1); - - if (++c->cnt322 < c->uni->init322) { - if ((stat = UNI_ALLOC()) != NULL) { - MK_MSG_ORIG(stat, UNI_STATUS_ENQ, c->cref, !c->mine); - stat->u.status_enq.epref = c->stat_epref; - (void)uni_send_output(stat, c->uni); - UNI_FREE(stat); - } - TIMER_START_CALL(c, t322, c->uni->timer322); - return; - } - c->se_active = 0; - - MK_IE_CAUSE(c->uni->cause, UNI_CAUSE_LOC_USER, UNI_CAUSE_RECOVER); - ADD_CAUSE_TIMER(c->uni->cause, "322"); - - clear_callD(c); -} - -/* - * STATUS ENQUIRY message - * - * Q.2971:Call-Control-U 31/39 - * Q.2971:Call-Control-N 32/39 - */ -static void -unx_status_enq(struct call *c, struct uni_msg *m, struct uni_all *u) -{ - struct party *p = NULL; - u_int epref, flag; - - /* - * Analyze message - */ - (void)uni_decode_body(m, u, &c->uni->cx); - - switch (uni_verify(c->uni, u->u.hdr.act)) { - - case VFY_CLR: - uni_vfy_collect_ies(c->uni); - clear_callD(c); - uni_msg_destroy(m); - UNI_FREE(u); - return; - - case VFY_RAIM: - case VFY_RAI: - case VFY_RAP: - case VFY_RAPU: - case VFY_I: - case VFY_OK: - break; - } - - uni_msg_destroy(m); - - if ((c->type == CALL_ROOT || c->type == CALL_LEAF) && - IE_ISGOOD(u->u.status_enq.epref)) { - p = uni_find_party(c, &u->u.status_enq.epref); - - epref = u->u.status_enq.epref.epref; - flag = u->u.status_enq.epref.flag; - memset(u, 0, sizeof(*u)); - MK_IE_EPREF(u->u.status.epref, epref, !flag); - - if (p != NULL) - MK_IE_EPSTATE(u->u.status.epstate, p->state); - else - MK_IE_EPSTATE(u->u.status.epstate, UNI_EPSTATE_NULL); - } else - memset(u, 0, sizeof(*u)); - - - MK_MSG_ORIG(u, UNI_STATUS, c->cref, !c->mine); - MK_IE_CALLSTATE(u->u.status.callstate, map_callstate(c->cstate)); - MK_IE_CAUSE(u->u.status.cause, UNI_CAUSE_LOC_USER, UNI_CAUSE_STATUS); - (void)uni_send_output(u, c->uni); - UNI_FREE(u); -} - -/**********************************************************************/ - -/* - * Link-release.indication from SAAL in state U10 or N10. - * - * Q.2971:Call-Control-U 19/39 - * Q.2971:Call-Control-N 20/39 - */ -static void -un10_link_release_indication(struct call *c) -{ - struct party *p; - - if (c->type == CALL_LEAF || c->type == CALL_ROOT) - TAILQ_FOREACH(p, &c->parties, link) { - if (p->state != UNI_EPSTATE_ACTIVE) - uni_enq_party(p, SIGP_RELEASE_COMPL, - 0, NULL, NULL); - } - - uni_enq_coord(c->uni, SIGO_LINK_ESTABLISH_request, 0, NULL); -} - -/* - * Link-release.indication from SAAL in all state except U10 and N10. - * - * Q.2971:Call-Control-U 36/39 - * Q.2971:Call-Control-N 37/39 - */ -static void -unx_link_release_indication(struct call *c) -{ - struct uniapi_release_confirm *conf; - struct uni_msg *api; - struct party *p; - - if (c->type == CALL_LEAF || c->type == CALL_ROOT) - TAILQ_FOREACH(p, &c->parties, link) - uni_enq_party(p, SIGP_RELEASE_COMPL, 0, NULL, NULL); - - if ((conf = ALLOC_API(struct uniapi_release_confirm, api)) != NULL) { - conf->release.hdr.cref.cref = c->cref; - conf->release.hdr.cref.flag = c->mine; - conf->release.hdr.act = UNI_MSGACT_DEFAULT; - MK_IE_CAUSE(conf->release.cause[0], UNI_CAUSE_LOC_USER, - UNI_CAUSE_DST_OOO); - - c->uni->funcs->uni_output(c->uni, c->uni->arg, - UNIAPI_RELEASE_confirm, 0, api); - } - - uni_destroy_call(c, 0); -} - -/* - * Failed to establish SAAL link. Can happen only in U10 or N10. - * - * Q.2971:Call-Control-U 19/39 - * Q.2971:Call-Control-N 20/39 - */ -static void -un10_link_establish_error_indication(struct call *c) -{ - struct party *p; - struct uni_msg *api; - struct uniapi_release_confirm *conf; - - if (c->type == CALL_LEAF || c->type == CALL_ROOT) - TAILQ_FOREACH(p, &c->parties, link) - uni_enq_party(p, SIGP_RELEASE_COMPL, 0, NULL, NULL); - - if ((conf = ALLOC_API(struct uniapi_release_confirm, api)) != NULL) { - conf->release.hdr.cref.cref = c->cref; - conf->release.hdr.cref.flag = c->mine; - conf->release.hdr.act = UNI_MSGACT_DEFAULT; - MK_IE_CAUSE(conf->release.cause[0], UNI_CAUSE_LOC_USER, - UNI_CAUSE_DST_OOO); - - c->uni->funcs->uni_output(c->uni, c->uni->arg, - UNIAPI_RELEASE_confirm, 0, api); - } - - uni_destroy_call(c, 0); -} - -/* - * Issue a STATUS ENQUIRY of we are not busy - * - * Q.2971: Call-Control-U: 34/39 - * Q.2971: Call-Control-N: 34/39 - */ -static void -call_se(struct call *c) -{ - struct uni_all *stat; - - c->cnt322 = 0; - if (c->se_active) - return; - - memset(&c->stat_epref, 0, sizeof(c->stat_epref)); - if ((stat = UNI_ALLOC()) != NULL) { - MK_MSG_ORIG(stat, UNI_STATUS_ENQ, c->cref, !c->mine); - (void)uni_send_output(stat, c->uni); - UNI_FREE(stat); - } - - TIMER_START_CALL(c, t322, c->uni->timer322); - c->se_active = 1; -} - -/* - * Link-establish.indication in U10 - * - * Q.2971:Call-Control-U 19-20/39 - * Q.2971:Call-Control-N 20-22/39 - */ -static void -un10_link_establish_indication(struct call *c) -{ - int act = 0; - struct party *p; - - if (c->type == CALL_ROOT || c->type == CALL_LEAF) { - TAILQ_FOREACH(p, &c->parties, link) - if (p->state == UNI_EPSTATE_ACTIVE) { - act = 1; - uni_enq_party(p, SIGP_STATUS_ENQUIRY_request, - 0, NULL, NULL); - } - if (act) - return; - } - call_se(c); -} - -/* - * Link-establish.indication in NOT U10/U11/U12 N10/N11/N12 - * - * Q.2971:Call-Control-U 36/39 - * Q.2971:Call-Control-N 37/39 - */ -static void -unx_link_establish_indication(struct call *c) -{ - call_se(c); -} - -/* - * Link-establish.confirm in U10 or N10 - * - * Q.2971:Call-Control-U 19/39 - * Q.2971:Call-Control-N 20/39 - */ -static void -un10_link_establish_confirm(struct call *c) -{ - struct party *p; - - if (c->type == CALL_ROOT || c->type == CALL_LEAF) { - TAILQ_FOREACH(p, &c->parties, link) - uni_enq_party(p, SIGP_STATUS_ENQUIRY_request, - 0, NULL, NULL); - return; - } - - call_se(c); -} - -/* - * STATUS ENQ from party - * - * Q.2971:Call-Control-U 21/39 - * Q.2971:Call-Control-U 25/39 - */ -static void -unx_send_party_status_enq(struct call *c, struct uni_all *u) -{ - if (c->se_active) { - uni_delenq_sig(c->uni, SIG_CALL, c, NULL, - SIGC_SEND_STATUS_ENQ, 0, NULL, u); - return; - } - - c->stat_epref = u->u.status_enq.epref; - (void)uni_send_output(u, c->uni); - UNI_FREE(u); - - TIMER_START_CALL(c, t322, c->uni->timer322); - c->se_active = 1; -} - -/**********************************************************************/ - -static void -make_drop_cause(struct call *c, struct uni_ie_cause *cause) -{ - - if (!IE_ISGOOD(*cause)) { - /* 9.5.7.1 paragraph 2 */ - if (IE_ISPRESENT(*cause)) - MK_IE_CAUSE(c->uni->cause, UNI_CAUSE_LOC_USER, - UNI_CAUSE_IE_INV); - else - MK_IE_CAUSE(c->uni->cause, UNI_CAUSE_LOC_USER, - UNI_CAUSE_MANDAT); - c->uni->cause.u.ie.len = 1; - c->uni->cause.u.ie.ie[0] = UNI_IE_CAUSE; - c->uni->cause.h.present |= UNI_CAUSE_IE_P; - - } else if (!IE_ISGOOD(c->uni->cause)) - c->uni->cause = *cause; -} - -/* - * Drop-party.indication from Party-Control in any state. - * - * Q.2971:Call-Control-U 23/39 - */ -static void -ux_drop_party_indication(struct call *c, struct uni_msg *api) -{ - struct uniapi_drop_party_indication *drop = - uni_msg_rptr(api, struct uniapi_drop_party_indication *); - - if (uni_party_act_count(c, 2) == 0) { - if (c->cstate != CALLST_U11) { - make_drop_cause(c, &drop->drop.cause); - clear_callD(c); - } - uni_msg_destroy(api); - return; - } - c->uni->funcs->uni_output(c->uni, c->uni->arg, - UNIAPI_DROP_PARTY_indication, 0, api); -} - -/* - * Drop-party.indication from Party-Control in any state. - * - * Q.2971:Call-Control-N 23/39 - */ -static void -nx_drop_party_indication(struct call *c, struct uni_msg *api) -{ - struct uniapi_drop_party_indication *drop = - uni_msg_rptr(api, struct uniapi_drop_party_indication *); - - if (uni_party_act_count(c, 0) == 0) { - if (uni_party_act_count(c, 1) == 0) { - if (c->cstate != CALLST_U11) { - make_drop_cause(c, &drop->drop.cause); - clear_callD(c); - } - uni_msg_destroy(api); - } else { - c->uni->funcs->uni_output(c->uni, c->uni->arg, - UNIAPI_DROP_PARTY_indication, 0, api); - set_call_state(c, CALLST_N7); - } - } else { - c->uni->funcs->uni_output(c->uni, c->uni->arg, - UNIAPI_DROP_PARTY_indication, 0, api); - } -} - -/* - * Drop-party-ack.indication from Party-Control in any state. - * - * Q.2971:Call-Control-U 23/39 - */ -static void -ux_drop_party_ack_indication(struct call *c, struct uni_msg *api) -{ - struct uniapi_drop_party_ack_indication *drop = - uni_msg_rptr(api, struct uniapi_drop_party_ack_indication *); - - if (uni_party_act_count(c, 2) == 0) { - if (c->cstate != CALLST_U11) { - make_drop_cause(c, &drop->drop.cause); - clear_callD(c); - } - uni_msg_destroy(api); - return; - } - c->uni->funcs->uni_output(c->uni, c->uni->arg, - UNIAPI_DROP_PARTY_ACK_indication, 0, api); -} - -/* - * Drop-party-ack.indication from Party-Control in any state. - * - * Q.2971:Call-Control-N 23/39 - */ -static void -nx_drop_party_ack_indication(struct call *c, struct uni_msg *api) -{ - struct uniapi_drop_party_ack_indication *drop = - uni_msg_rptr(api, struct uniapi_drop_party_ack_indication *); - - if (uni_party_act_count(c, 0) == 0) { - if (uni_party_act_count(c, 1) == 0) { - if (c->cstate != CALLST_U11) { - make_drop_cause(c, &drop->drop.cause); - clear_callD(c); - } - uni_msg_destroy(api); - } else { - c->uni->funcs->uni_output(c->uni, c->uni->arg, - UNIAPI_DROP_PARTY_ACK_indication, 0, api); - set_call_state(c, CALLST_N7); - } - } else { - c->uni->funcs->uni_output(c->uni, c->uni->arg, - UNIAPI_DROP_PARTY_ACK_indication, 0, api); - } -} - -/* - * Add-party-rej.indication from Party-Control in any state. - * - * Q.2971:Call-Control-U 23/39 - */ -static void -ux_add_party_rej_indication(struct call *c, struct uni_msg *api) -{ - struct uniapi_add_party_rej_indication *rej = - uni_msg_rptr(api, struct uniapi_add_party_rej_indication *); - - if (uni_party_act_count(c, 2) == 0) { - if (c->cstate != CALLST_U11) { - make_drop_cause(c, &rej->rej.cause); - clear_callD(c); - } - uni_msg_destroy(api); - return; - } - c->uni->funcs->uni_output(c->uni, c->uni->arg, - UNIAPI_ADD_PARTY_REJ_indication, 0, api); -} - -/* - * Add-party-rej.indication from Party-Control in any state. - * - * Q.2971:Call-Control-N 23/39 - */ -static void -nx_add_party_rej_indication(struct call *c, struct uni_msg *api) -{ - struct uniapi_add_party_rej_indication *rej = - uni_msg_rptr(api, struct uniapi_add_party_rej_indication *); - - if (uni_party_act_count(c, 0) == 0) { - if (uni_party_act_count(c, 1) == 0) { - if (c->cstate != CALLST_U11) { - make_drop_cause(c, &rej->rej.cause); - clear_callD(c); - } - uni_msg_destroy(api); - } else { - c->uni->funcs->uni_output(c->uni, c->uni->arg, - UNIAPI_ADD_PARTY_REJ_indication, 0, api); - set_call_state(c, CALLST_N7); - } - } else { - c->uni->funcs->uni_output(c->uni, c->uni->arg, - UNIAPI_ADD_PARTY_REJ_indication, 0, api); - } -} - -/* - * Add-party.request from API in U4 or U10 - * - * Q.2971:Call-Control-U 9-10/39 (U4) - * Q.2971:Call-Control-U 21/39 (U10) - * Q.2971:Call-Control-N 12/39 (N7) - * Q.2971:Call-Control-N 22/39 (N10) - */ -static void -unx_add_party_request(struct call *c, struct uni_msg *msg, uint32_t cookie) -{ - struct uniapi_add_party_request *add = - uni_msg_rptr(msg, struct uniapi_add_party_request *); - struct party *p; - - if (IE_ISGOOD(add->add.epref)) { - if (add->add.epref.flag != 0) { - uni_msg_destroy(msg); - uniapi_call_error(c, UNIAPI_ERROR_BAD_IE, cookie); - return; - } - p = uni_find_partyx(c, add->add.epref.epref, 1); - if (p != NULL) { - uni_msg_destroy(msg); - uniapi_call_error(c, UNIAPI_ERROR_EPREF_INUSE, cookie); - return; - } - } else if (!IE_ISPRESENT(add->add.epref)) { - allocate_epref(c, &add->add.epref); - if (!IE_ISPRESENT(add->add.epref)) { - uni_msg_destroy(msg); - uniapi_call_error(c, UNIAPI_ERROR_EPREF_INUSE, cookie); - return; - } - } else { - uni_msg_destroy(msg); - uniapi_call_error(c, UNIAPI_ERROR_BAD_IE, cookie); - return; - } - - if ((p = uni_create_partyx(c, add->add.epref.epref, 1, cookie)) == NULL) { - uni_msg_destroy(msg); - uniapi_call_error(c, UNIAPI_ERROR_NOMEM, cookie); - return; - } - uni_enq_party(p, SIGP_ADD_PARTY_request, cookie, msg, NULL); -} - -/* - * Add-party-ack.request from API in U10/N10 - * - * Q.2971:Call-Control-U 21/39 - * Q.2971:Call-Control-N 22/39 - */ -static void -un10_add_party_ack_request(struct call *c, struct uni_msg *msg, uint32_t cookie) -{ - struct uniapi_add_party_ack_request *ack = - uni_msg_rptr(msg, struct uniapi_add_party_ack_request *); - struct party *p; - - if (!IE_ISGOOD(ack->ack.epref)) { - uni_msg_destroy(msg); - uniapi_call_error(c, UNIAPI_ERROR_BAD_IE, cookie); - return; - } - if (ack->ack.epref.flag != 1) { - uni_msg_destroy(msg); - uniapi_call_error(c, UNIAPI_ERROR_BAD_IE, cookie); - return; - } - if ((p = uni_find_partyx(c, ack->ack.epref.epref, 0)) == NULL) { - uni_msg_destroy(msg); - uniapi_call_error(c, UNIAPI_ERROR_BAD_PARTY, cookie); - return; - } - - uni_enq_party(p, SIGP_ADD_PARTY_ACK_request, cookie, msg, NULL); -} - -/* - * Party-alerting.request from API in U7/U8/U10 - * - * Q.2971:Call-Control-U 14/39 U7 - * Q.2971:Call-Control-U 15/39 U8 - * Q.2971:Call-Control-U 21/39 U10 - * Q.2971:Call-Control-N 8/39 N4 - * Q.2971:Call-Control-N 22/39 N10 - */ -static void -unx_party_alerting_request(struct call *c, struct uni_msg *msg, uint32_t cookie) -{ - struct uniapi_party_alerting_request *alert = - uni_msg_rptr(msg, struct uniapi_party_alerting_request *); - struct party *p; - - if (!IE_ISGOOD(alert->alert.epref)) { - uni_msg_destroy(msg); - uniapi_call_error(c, UNIAPI_ERROR_BAD_IE, cookie); - return; - } - if (alert->alert.epref.flag != 1) { - uni_msg_destroy(msg); - uniapi_call_error(c, UNIAPI_ERROR_BAD_IE, cookie); - return; - } - if ((p = uni_find_partyx(c, alert->alert.epref.epref, 0)) == NULL) { - uni_msg_destroy(msg); - uniapi_call_error(c, UNIAPI_ERROR_BAD_PARTY, cookie); - return; - } - - uni_enq_party(p, SIGP_PARTY_ALERTING_request, cookie, msg, NULL); -} - -/* - * Add-party-rej.request from API in U7/U8/U10/N4/N10 - * - * Q.2971:Call-Control-U 14/39 U7 - * Q.2971:Call-Control-U 15/39 U8 - * Q.2971:Call-Control-U 21/39 U10 - * Q.2971:Call-Control-N 8/39 N4 - * Q.2971:Call-Control-N 22/39 N10 - */ -static void -unx_add_party_rej_request(struct call *c, struct uni_msg *msg, uint32_t cookie) -{ - struct uniapi_add_party_rej_request *rej = - uni_msg_rptr(msg, struct uniapi_add_party_rej_request *); - struct party *p; - - if (!IE_ISGOOD(rej->rej.epref)) { - uni_msg_destroy(msg); - uniapi_call_error(c, UNIAPI_ERROR_BAD_IE, cookie); - return; - } - if (rej->rej.epref.flag != 1) { - uni_msg_destroy(msg); - uniapi_call_error(c, UNIAPI_ERROR_BAD_IE, cookie); - return; - } - if ((p = uni_find_partyx(c, rej->rej.epref.epref, 0)) == NULL) { - uni_msg_destroy(msg); - uniapi_call_error(c, UNIAPI_ERROR_BAD_PARTY, cookie); - return; - } - - uni_enq_party(p, SIGP_ADD_PARTY_REJ_request, cookie, msg, NULL); -} - -/* - * Drop-party.request from API in U1-U10 - * - * Q.2971:Call-Control-U 21/39 U10 - * Q.2971:Call-Control-U 26/39 U1-U9 - * Q.2971:Call-Control-N 22/39 N10 - * Q.2971:Call-Control-N 27/39 N1-N9 - */ -static void -unx_drop_party_request(struct call *c, struct uni_msg *msg, uint32_t cookie) -{ - struct uniapi_drop_party_request *drop = - uni_msg_rptr(msg, struct uniapi_drop_party_request *); - struct party *p; - - if (!IE_ISGOOD(drop->drop.epref)) { - uni_msg_destroy(msg); - uniapi_call_error(c, UNIAPI_ERROR_BAD_IE, cookie); - return; - } - if ((p = uni_find_partyx(c, drop->drop.epref.epref, !drop->drop.epref.flag)) == NULL) { - uni_msg_destroy(msg); - uniapi_call_error(c, UNIAPI_ERROR_BAD_PARTY, cookie); - return; - } - - uni_enq_party(p, SIGP_DROP_PARTY_request, cookie, msg, NULL); -} - -/* - * Drop-party-ack.request from API in U1-U10 - * - * Q.2971:Call-Control-U 21/39 U10 - * Q.2971:Call-Control-U 26/39 U1-U9 - * Q.2971:Call-Control-N 22/39 N10 - * Q.2971:Call-Control-N 27/39 N1-N9 - */ -static void -unx_drop_party_ack_request(struct call *c, struct uni_msg *msg, - uint32_t cookie) -{ - struct uniapi_drop_party_ack_request *ack = - uni_msg_rptr(msg, struct uniapi_drop_party_ack_request *); - struct party *p; - - if (!IE_ISGOOD(ack->ack.epref)) { - uni_msg_destroy(msg); - uniapi_call_error(c, UNIAPI_ERROR_BAD_IE, cookie); - return; - } - if ((p = uni_find_partyx(c, ack->ack.epref.epref, !ack->ack.epref.flag)) == NULL) { - uni_msg_destroy(msg); - uniapi_call_error(c, UNIAPI_ERROR_BAD_PARTY, cookie); - return; - } - - uni_enq_party(p, SIGP_DROP_PARTY_ACK_request, cookie, msg, NULL); -} - -/* - * ADD PARTY in U7/U8/U10 - * - * Q.2971:Call-Control-U 14/39 U7 - * Q.2971:Call-Control-U 15/39 U8 - * Q.2971:Call-Control-U 21/39 U10 - * Q.2971:Call-Control-N 8/39 N4 - * Q.2971:Call-Control-N 21/39 N10 - * - * Body already decoded - * XXX check EPREF flag - */ -static void -unx_add_party(struct call *c, struct uni_msg *m, struct uni_all *u, - int legal) -{ - struct uni_all *resp; - struct uni_ierr *e1; - struct party *p = NULL; - enum verify vfy; - - uni_mandate_epref(c->uni, &u->u.add_party.epref); - MANDATE_IE(c->uni, u->u.add_party.called, UNI_IE_CALLED); - - /* - * Do part of the verify handish: according to 9.5.7.2 we must send - * an ADD_PARTY_REJ if mandatory IEs are bad or missing instead of - * clearing the call. But we must send a STATUS, if it is the EPREF! - */ - if (IE_ISGOOD(u->u.add_party.epref)) { - c->uni->cause.u.ie.len = 0; - FOREACH_ERR(e1, c->uni) { - if (e1->err == UNI_IERR_MIS) { - MK_IE_CAUSE(c->uni->cause, UNI_CAUSE_LOC_USER, - UNI_CAUSE_MANDAT); - goto rej; - } - } - FOREACH_ERR(e1, c->uni) { - if (e1->man && e1->ie != UNI_IE_EPREF && - e1->act == UNI_IEACT_DEFAULT) { - MK_IE_CAUSE(c->uni->cause, UNI_CAUSE_LOC_USER, - UNI_CAUSE_IE_INV); - rej: - uni_vfy_collect_ies(c->uni); - if ((resp = UNI_ALLOC()) != NULL) { - MK_MSG_RESP(resp, UNI_ADD_PARTY_REJ, - &u->u.hdr.cref); - MK_IE_EPREF(resp->u.add_party_rej.epref, - u->u.add_party.epref.epref, - !u->u.add_party.epref.flag); - resp->u.add_party_rej.cause = - c->uni->cause; - - unx_send_add_party_rej(c, resp); - } - goto ignore; - } - } - p = uni_find_partyx(c, u->u.add_party.epref.epref, - u->u.add_party.epref.flag); - } - - vfy = uni_verify(c->uni, u->u.hdr.act); - - switch (vfy) { - - case VFY_CLR: - uni_vfy_collect_ies(c->uni); - clear_callD(c); - goto ignore; - - case VFY_RAIM: - case VFY_RAI: - uni_respond_status_verify(c->uni, &u->u.hdr.cref, - map_callstate(c->cstate), &u->u.add_party.epref, - p ? p->state : UNI_EPSTATE_NULL); - /* FALLTHRU */ - case VFY_I: - goto ignore; - - case VFY_RAP: - case VFY_RAPU: - uni_respond_status_verify(c->uni, &u->u.hdr.cref, - map_callstate(c->cstate), &u->u.add_party.epref, - UNI_EPSTATE_ADD_RCVD); - case VFY_OK: - /* FALLTHRU */ - break; - } - if (!legal) { - uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, - &u->u.add_party.epref, -1); - return; - } - - if (IE_ISGOOD(u->u.add_party.epref) && p == NULL && - u->u.add_party.epref.flag) { - IE_SETERROR(u->u.add_party.epref); - (void)UNI_SAVE_IERR(&c->uni->cx, UNI_IE_EPREF, - u->u.add_party.epref.h.act, UNI_IERR_BAD); - } - - if (!IE_ISGOOD(u->u.add_party.epref)) { - /* 9.5.3.2.2 */ - if (vfy == VFY_OK) { - MK_IE_CAUSE(c->uni->cause, UNI_CAUSE_LOC_USER, - UNI_CAUSE_IE_INV); - - uni_respond_status_verify(c->uni, &u->u.hdr.cref, - map_callstate(c->cstate), NULL, 0); - } - goto ignore; - } - - - if (p == NULL && (p = uni_create_party(c, &u->u.add_party.epref)) - == NULL) - goto ignore; - - uni_enq_party(p, SIGP_ADD_PARTY, 0, m, u); - return; - - ignore: - uni_msg_destroy(m); - UNI_FREE(u); -} - -/* - * ADD PARTY ACKNOWLEDGE - * - * Q.2971:Call-Control-U 21/39 U10 - * Q.2971:Call-Control-N 15/39 N8 - * Q.2971:Call-Control-N 22/39 N10 - */ -static void -un10n8_add_party_ack(struct call *c, struct uni_msg *m, struct uni_all *u, - int legal) -{ - struct party *p = NULL; - - if (IE_ISGOOD(u->u.add_party_ack.epref)) { - if (u->u.add_party_ack.epref.flag == 0) { - IE_SETERROR(u->u.add_party_ack.epref); - (void)UNI_SAVE_IERR(&c->uni->cx, UNI_IE_EPREF, - u->u.add_party_ack.epref.h.act, UNI_IERR_BAD); - } else { - p = uni_find_partyx(c, u->u.add_party_ack.epref.epref, 1); - if (p == NULL) { - respond_drop_party_ack(c, - &u->u.add_party_ack.epref, - UNI_CAUSE_ENDP_INV); - goto ignore; - } - } - } - uni_mandate_epref(c->uni, &u->u.add_party_ack.epref); - - switch (uni_verify(c->uni, u->u.hdr.act)) { - - case VFY_CLR: - uni_vfy_collect_ies(c->uni); - clear_callD(c); - goto ignore; - - case VFY_RAIM: - case VFY_RAI: - report: - uni_respond_status_verify(c->uni, &u->u.hdr.cref, - map_callstate(c->cstate), &u->u.add_party_ack.epref, - p ? p->state : UNI_EPSTATE_NULL); - case VFY_I: - goto ignore; - - case VFY_RAP: - case VFY_RAPU: - uni_respond_status_verify(c->uni, &u->u.hdr.cref, - map_callstate(c->cstate), &u->u.add_party_ack.epref, - p ? UNI_EPSTATE_ACTIVE : UNI_EPSTATE_NULL); - if (!IE_ISGOOD(u->u.party_alerting.epref)) - /* See below */ - goto ignore; - break; - case VFY_OK: - if (!IE_ISGOOD(u->u.party_alerting.epref)) - /* this happens when the EPREF has bad format. - * The rules require us the message to be ignored - * (9.5.3.2.2e) and to report status. - */ - goto report; - break; - } - if (legal) { - /* p is != NULL here */ - uni_enq_party(p, SIGP_ADD_PARTY_ACK, 0, m, u); - return; - } - if (p == NULL) - /* Q.2971 9.5.3.2.3a) */ - respond_drop_party_ack(c, &u->u.add_party_ack.epref, - UNI_CAUSE_ENDP_INV); - else - uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, - &u->u.add_party_ack.epref, p->state); - - ignore: - uni_msg_destroy(m); - UNI_FREE(u); -} - -/* - * Make the EPREF action default - */ -static void -default_act_epref(struct uni *uni, struct uni_ie_epref *epref) -{ - struct uni_ierr *e; - - FOREACH_ERR(e, uni) - if (e->ie == UNI_IE_EPREF) { - e->act = UNI_IEACT_DEFAULT; - break; - } - epref->h.act = UNI_IEACT_DEFAULT; -} - -/* - * PARTY ALERTING message - * - * Q.2971:Call-Control-U 9/39 U4 - * Q.2971:Call-Control-U 21/39 U10 - * Q.2971:Call-Control-N 12/39 N7 - * Q.2971:Call-Control-N 15/39 N8 - * Q.2971:Call-Control-N 22/39 N10 - */ -static void -unx_party_alerting(struct call *c, struct uni_msg *m, struct uni_all *u, - int legal) -{ - struct party *p = NULL; - - if (IE_ISGOOD(u->u.party_alerting.epref)) { - if (u->u.party_alerting.epref.flag == 0) { - IE_SETERROR(u->u.party_alerting.epref); - (void)UNI_SAVE_IERR(&c->uni->cx, UNI_IE_EPREF, - u->u.party_alerting.epref.h.act, UNI_IERR_BAD); - } else { - p = uni_find_partyx(c, u->u.party_alerting.epref.epref, 1); - if (p == NULL) { - respond_drop_party_ack(c, - &u->u.party_alerting.epref, - UNI_CAUSE_ENDP_INV); - goto ignore; - } - } - } - uni_mandate_epref(c->uni, &u->u.party_alerting.epref); - - switch (uni_verify(c->uni, u->u.hdr.act)) { - - case VFY_CLR: - uni_vfy_collect_ies(c->uni); - clear_callD(c); - goto ignore; - - case VFY_RAIM: - case VFY_RAI: - report: - uni_respond_status_verify(c->uni, &u->u.hdr.cref, - map_callstate(c->cstate), &u->u.party_alerting.epref, - p ? p->state : UNI_EPSTATE_NULL); - case VFY_I: - goto ignore; - - case VFY_RAP: - case VFY_RAPU: - uni_respond_status_verify(c->uni, &u->u.hdr.cref, - map_callstate(c->cstate), &u->u.party_alerting.epref, - p ? UNI_EPSTATE_ALERT_RCVD : UNI_EPSTATE_NULL); - if (!IE_ISGOOD(u->u.party_alerting.epref)) - /* See below */ - goto ignore; - break; - - case VFY_OK: - if (!IE_ISGOOD(u->u.party_alerting.epref)) - /* The rules require us the message to be ignored - * (9.5.3.2.2e) and to report status. - */ - goto report; - break; - } - if (legal) { - /* p is != NULL here */ - uni_enq_party(p, SIGP_PARTY_ALERTING, 0, m, u); - return; - } - if (p == NULL) - /* Q.2971 9.5.3.2.3a) */ - respond_drop_party_ack(c, &u->u.party_alerting.epref, - UNI_CAUSE_ENDP_INV); - else - uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, - &u->u.party_alerting.epref, p->state); - - ignore: - uni_msg_destroy(m); - UNI_FREE(u); -} - -/* - * Handle a bad/missing cause in a DROP_PARTY_ACK or ADD_PARTY_REJ - * - * If the IE is missing or bad and the action is defaulted handle as - * cause #1 according to 9.5.7.1/2. - * Otherwise keep the IE. - */ -static void -handle_bad_drop_cause(struct call *c, struct uni_ie_cause *cause, int mkcause) -{ - - if (IE_ISGOOD(*cause)) - return; - - if (!IE_ISPRESENT(*cause)) { - /* 9.5.7.1 */ - /* cannot make cause here because we need the 96 error */ - uni_vfy_remove_cause(c->uni); - return; - } - if (cause->h.act != UNI_IEACT_DEFAULT) - return; - - /* 9.5.7.2 */ - uni_vfy_remove_cause(c->uni); - if (mkcause) - MK_IE_CAUSE(*cause, UNI_CAUSE_LOC_USER, UNI_CAUSE_UNSPEC); -} - -/* - * ADD PARTY REJ from party control - * Q.2971:Call-Control-U 21/39 - * Q.2971:Call-Control-U 24/39 - */ -static void -unx_send_add_party_rej(struct call *c, struct uni_all *u) -{ - - if (uni_party_act_count(c, 2) == 0) { - if (c->cstate != CALLST_U11 && c->cstate != CALLST_N12) { - c->uni->cause = u->u.add_party_rej.cause; - clear_callD(c); - } - } else - (void)uni_send_output(u, c->uni); - UNI_FREE(u); -} - -/* - * ADD_PARTY_REJECT in U4/U10 - * - * Q.2971:Call-Control-U 9/39 U4 - * Q.2971:Call-Control-U 21/39 U10 - * Q.2971:Call-Control-N 12/39 N7 - * Q.2971:Call-Control-N 15/39 N8 - * Q.2971:Call-Control-N 22/39 N10 - */ -static void -unx_add_party_rej(struct call *c, struct uni_msg *m, struct uni_all *u, - int legal) -{ - struct uni_add_party_rej *ar = &u->u.add_party_rej; - struct party *p; - - if (IE_ISGOOD(ar->epref)) { - p = uni_find_partyx(c, ar->epref.epref, ar->epref.flag); - if (p == NULL) - goto ignore; - - if (legal) { - handle_bad_drop_cause(c, &ar->cause, 0); - uni_vfy_remove_unknown(c->uni); - switch (uni_verify(c->uni, u->u.hdr.act)) { - - case VFY_CLR: - goto clear; - - case VFY_RAIM: - case VFY_RAI: - uni_respond_status_verify(c->uni, - &u->u.hdr.cref, map_callstate(c->cstate), - &ar->epref, p->state); - case VFY_I: - goto ignore; - - case VFY_RAPU: - uni_vfy_collect_ies(c->uni); - break; - - case VFY_RAP: - uni_respond_status_verify(c->uni, - &u->u.hdr.cref, map_callstate(c->cstate), - &ar->epref, p->state); - case VFY_OK: - break; - } - uni_enq_party(p, SIGP_ADD_PARTY_REJ, 0, m, u); - return; - } - uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, - &ar->epref, -1); - return; - } - - /* Q.2971: 9.5.3.2.1 last paragraph - * 9.5.3.2.2 second to last paragraph - * Make the action indicator default. - */ - default_act_epref(c->uni, &ar->epref); - if (!IE_ISPRESENT(ar->epref)) - uni_mandate_ie(c->uni, UNI_IE_EPREF); - (void)uni_verify(c->uni, u->u.hdr.act); - - clear: - uni_vfy_collect_ies(c->uni); - clear_callD(c); - - ignore: - uni_msg_destroy(m); - UNI_FREE(u); -} - -/* - * DROP_PARTY - * - * Q.2971:Call-Control-U 26/39 Ux - * Q.2971:Call-Control-U 21/39 U10 - * Q.2971:Call-Control-N 27/39 Nx - * Q.2971:Call-Control-N 22/39 N10 - */ -static void -unx_drop_party(struct call *c, struct uni_msg *m, struct uni_all *u, int legal) -{ - struct uni_drop_party *dp = &u->u.drop_party; - struct party *p; - struct uni_ierr *e; - - if (IE_ISGOOD(dp->epref)) { - p = uni_find_partyx(c, dp->epref.epref, dp->epref.flag); - if (p == NULL) { - respond_drop_party_ack(c, &dp->epref, - UNI_CAUSE_ENDP_INV); - goto ignore; - } - handle_bad_drop_cause(c, &dp->cause, 0); - uni_vfy_remove_unknown(c->uni); - switch (uni_verify(c->uni, u->u.hdr.act)) { - - case VFY_CLR: - goto clear; - - case VFY_RAIM: - case VFY_RAI: - uni_respond_status_verify(c->uni, &u->u.hdr.cref, - map_callstate(c->cstate), - &u->u.drop_party.epref, p->state); - case VFY_I: - goto ignore; - - case VFY_RAPU: - uni_vfy_collect_ies(c->uni); - break; - - case VFY_RAP: - uni_respond_status_verify(c->uni, &u->u.hdr.cref, - map_callstate(c->cstate), - &dp->epref, UNI_EPSTATE_DROP_RCVD); - case VFY_OK: - break; - } - if (legal) { - uni_enq_party(p, SIGP_DROP_PARTY, 0, m, u); - return; - } - uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, &dp->epref, -1); - goto ignore; - } - - /* Q.2971: 9.5.3.2.1 last paragraph - * 9.5.3.2.2 second to last paragraph - * Make the action indicator default. - */ - FOREACH_ERR(e, c->uni) - if (e->ie == UNI_IE_EPREF) { - e->act = UNI_IEACT_DEFAULT; - break; - } - dp->epref.h.act = UNI_IEACT_DEFAULT; - - if (!IE_ISPRESENT(dp->epref)) - uni_mandate_ie(c->uni, UNI_IE_EPREF); - (void)uni_verify(c->uni, u->u.hdr.act); - - clear: - uni_vfy_collect_ies(c->uni); - clear_callD(c); - uni_msg_destroy(m); - UNI_FREE(u); - return; - - ignore: - uni_msg_destroy(m); - UNI_FREE(u); -} - -/* - * DROP_PARTY_ACK - * - * Q.2971:Call-Control-U 26/39 Ux - * Q.2971:Call-Control-U 21/39 U10 - * Q.2971:Call-Control-N 27/39 Nx - * Q.2971:Call-Control-N 22/39 N10 - */ -static void -unx_drop_party_ack(struct call *c, struct uni_msg *m, struct uni_all *u, - int legal) -{ - struct party *p; - struct uni_drop_party_ack *ack = &u->u.drop_party_ack; - - if (IE_ISGOOD(u->u.drop_party_ack.epref)) { - p = uni_find_partyx(c, ack->epref.epref, ack->epref.flag); - if (p != NULL) { - handle_bad_drop_cause(c, &ack->cause, 1); - uni_vfy_remove_unknown(c->uni); - switch (uni_verify(c->uni, u->u.hdr.act)) { - - case VFY_CLR: - goto clear; - - case VFY_RAIM: - case VFY_RAI: - uni_respond_status_verify(c->uni, - &u->u.hdr.cref, map_callstate(c->cstate), - &ack->epref, p->state); - case VFY_I: - goto ignore; - - case VFY_RAP: - uni_respond_status_verify(c->uni, - &u->u.hdr.cref, map_callstate(c->cstate), - &ack->epref, UNI_EPSTATE_NULL); - case VFY_RAPU: - case VFY_OK: - break; - } - if (legal) { - uni_enq_party(p, SIGP_DROP_PARTY_ACK, 0, m, u); - return; - } - uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, - &ack->epref, -1); - } - goto ignore; - } - - /* Q.2971: 9.5.3.2.1 last paragraph - * 9.5.3.2.2 second to last paragraph - */ - (void)uni_verify(c->uni, u->u.hdr.act); - MK_IE_CAUSE(c->uni->cause, UNI_CAUSE_LOC_USER, UNI_CAUSE_IE_INV); - - clear: - uni_vfy_collect_ies(c->uni); - clear_callD(c); - uni_msg_destroy(m); - UNI_FREE(u); - return; - - ignore: - uni_msg_destroy(m); - UNI_FREE(u); -} - -/**********************************************************************/ - -/* - * Bad or unrecognized message. - * - * Q.2971:Call-Control-U 35/39 - */ -void -uni_bad_message(struct call *c, struct uni_all *u, u_int cause, - struct uni_ie_epref *epref, int ps) -{ - struct uni_all *resp; - struct party *p; - - if ((u->u.hdr.act == UNI_MSGACT_CLEAR && - (c->cstate == CALLST_U11 || - c->cstate == CALLST_U12 || - c->cstate == CALLST_N11 || - c->cstate == CALLST_N12)) || - u->u.hdr.act == UNI_MSGACT_IGNORE) - return; - - MK_IE_CAUSE(c->uni->cause, UNI_CAUSE_LOC_USER, cause); - ADD_CAUSE_MTYPE(c->uni->cause, u->mtype); - - if (u->u.hdr.act == UNI_MSGACT_CLEAR) { - clear_callD(c); - return; - } - - /* - * Send STATUS - */ - if ((resp = UNI_ALLOC()) != NULL) { - MK_MSG_RESP(resp, UNI_STATUS, &u->u.hdr.cref); - MK_IE_CALLSTATE(resp->u.status.callstate, - map_callstate(c->cstate)); - resp->u.status.cause = c->uni->cause; - - if (epref != NULL && IE_ISGOOD(*epref)) { - MK_IE_EPREF(resp->u.status.epref, epref->epref, !epref->flag); - if (ps == -1) { - p = uni_find_party(c, epref); - if (p == NULL) - ps = UNI_EPSTATE_NULL; - else - ps = p->state; - } - MK_IE_EPSTATE(resp->u.status.epstate, ps); - } - (void)uni_send_output(resp, c->uni); - - UNI_FREE(resp); - } -} - -/**********************************************************************/ - -/* - * Unknown message in any state. - * - * Q.2971:Call-Control 35/39 - * Q.2971:Call-Control 36/39 - */ -static void -unx_unknown(struct call *c, struct uni_msg *m, struct uni_all *u) -{ - /* - * Unrecognized message. Cannot call verify here, because - * it doesn't know about unrecognized messages. - */ - if (u->u.hdr.act == UNI_MSGACT_CLEAR) { - MK_IE_CAUSE(c->uni->cause, UNI_CAUSE_LOC_USER, - UNI_CAUSE_MTYPE_NIMPL); - ADD_CAUSE_MTYPE(c->uni->cause, u->mtype); - clear_callD(c); - } else if(u->u.hdr.act == UNI_MSGACT_IGNORE) { - ; - } else { - (void)uni_decode_body(m, u, &c->uni->cx); - uni_bad_message(c, u, UNI_CAUSE_MTYPE_NIMPL, - &u->u.unknown.epref, -1); - } - uni_msg_destroy(m); - UNI_FREE(u); -} -/**********************************************************************/ - -void -uni_sig_call(struct call *c, enum call_sig sig, uint32_t cookie, - struct uni_msg *msg, struct uni_all *u) -{ - if (sig >= SIGC_END) { - VERBOSE(c->uni, UNI_FAC_ERR, 1, - "Signal %d outside of range to Call-Control", sig); - if (msg) - uni_msg_destroy(msg); - if (u) - UNI_FREE(u); - return; - } - - VERBOSE(c->uni, UNI_FAC_CALL, 1, "Signal %s in state %s of call %u/%s" - "; cookie %u", call_sigs[sig], callstates[c->cstate].name, c->cref, - c->mine ? "mine" : "his", cookie); - - switch (sig) { - - case SIGC_LINK_RELEASE_indication: - if (c->cstate == CALLST_U10 || c->cstate == CALLST_N10) - /* Q.2971:Call-Control-U 36/39 */ - /* Q.2971:Call-Control-N 20/39 */ - un10_link_release_indication(c); - else - /* Q.2971:Call-Control-U 36/39 */ - /* Q.2971:Call-Control-N 37/39 */ - unx_link_release_indication(c); - break; - - case SIGC_LINK_ESTABLISH_ERROR_indication: - if (c->cstate != CALLST_U10 && c->cstate != CALLST_N10) { - VERBOSE(c->uni, UNI_FAC_ERR, 1, - "link-establish-error.indication in cs=%s", - callstates[c->cstate].name); - break; - } - /* Q.2971:Call-Control-U 19/39 */ - /* Q.2971:Call-Control-N 20/39 */ - un10_link_establish_error_indication(c); - break; - - case SIGC_LINK_ESTABLISH_indication: - switch (c->cstate) { - - case CALLST_U1: case CALLST_N1: - case CALLST_U3: case CALLST_N3: - case CALLST_U4: case CALLST_N4: - case CALLST_U6: case CALLST_N6: - case CALLST_U7: case CALLST_N7: - case CALLST_U8: case CALLST_N8: - case CALLST_U9: case CALLST_N9: - /* Q.2971:Call-Control-U 36/39 */ - /* Q.2971:Call-Control-N 37/39 */ - unx_link_establish_indication(c); - break; - - case CALLST_U10: case CALLST_N10: - /* Q.2971:Call-Control-U 19/39 */ - /* Q.2971:Call-Control-N 20/39 */ - un10_link_establish_indication(c); - break; - - case CALLST_U11: case CALLST_N11: - case CALLST_U12: case CALLST_N12: - /* Q.2971:Call-Control-U 36/39 */ - /* Q.2971:Call-Control-N 37/39 */ - break; - - default: - VERBOSE(c->uni, UNI_FAC_ERR, 1, - "link-establish.indication in cs=%s", - callstates[c->cstate].name); - } - break; - - case SIGC_LINK_ESTABLISH_confirm: - if (c->cstate != CALLST_U10 && c->cstate != CALLST_N10) { - VERBOSE(c->uni, UNI_FAC_ERR, 1, - "link-establish.confirm in cs=%s", - callstates[c->cstate].name); - break; - } - /* Q.2971:Call-Control-U 19/39 */ - /* Q.2971:Call-Control-N 20/39 */ - un10_link_establish_confirm(c); - break; - - case SIGC_UNKNOWN: - /* Q.2971:Call-Control 35/39 */ - /* Q.2971:Call-Control 36/39 */ - unx_unknown(c, msg, u); - break; - - case SIGC_SETUP: - if (c->cstate != CALLST_NULL) { - (void)uni_decode_body(msg, u, &c->uni->cx); - uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, - &u->u.setup.epref, -1); - goto drop; - } - if (c->uni->proto == UNIPROTO_UNI40N) - /* Q.2971:Call-Control-N 4/39 */ - un0_setup(c, msg, u, CALLST_N1); - else - /* Q.2971:Call-Control-U 4/39 */ - un0_setup(c, msg, u, CALLST_U6); - break; - - case SIGC_CALL_PROC: - if (c->cstate == CALLST_U1) { - /* Q.2971:Call-Control-U 6/39 */ - u1n6_call_proc(c, msg, u, CALLST_U3); - break; - } - if (c->cstate == CALLST_N6) { - /* Q.2971:Call-Control-N 11/39 */ - u1n6_call_proc(c, msg, u, CALLST_N9); - break; - } - (void)uni_decode_body(msg, u, &c->uni->cx); - uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, - &u->u.call_proc.epref, -1); - goto drop; - - case SIGC_ALERTING: - if (c->cstate == CALLST_U1 || c->cstate == CALLST_U3) { - /* Q.2971:Call-Control-U 37/39 (U1) */ - /* Q.2971:Call-Control-U 7/39 (U3) */ - unx_alerting(c, msg, u, CALLST_U4); - break; - } - if (c->cstate == CALLST_N6) { - /* Q.2971:Call-Control-N 9/39 (N6) */ - /* Q.2971:Call-Control-N 17/39 (N9) */ - unx_alerting(c, msg, u, CALLST_N7); - break; - } - (void)uni_decode_body(msg, u, &c->uni->cx); - uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, - &u->u.alerting.epref, -1); - goto drop; - - case SIGC_CONNECT: - if (c->cstate == CALLST_U1 || c->cstate == CALLST_U3 || - c->cstate == CALLST_U4) { - /* Q.2971:Call-Control-U 7-8/39 (U3) */ - /* Q.2971:Call-Control-U 11/39 (U4) */ - /* Q.2971:Call-Control-U 37/39 (U1) */ - unx_connect(c, msg, u, CALLST_U10); - break; - } - if (c->cstate == CALLST_N6 || c->cstate == CALLST_N7 || - c->cstate == CALLST_N9) { - /* Q.2971:Call-Control-N 9-10/39 (N6) */ - /* Q.2971:Call-Control-N 14/39 (N7) */ - /* Q.2971:Call-Control-N 17/39 (N9) */ - unx_connect(c, msg, u, CALLST_N8); - break; - } - (void)uni_decode_body(msg, u, &c->uni->cx); - uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, - &u->u.connect.epref, -1); - goto drop; - - case SIGC_CONNECT_ACK: - if (c->cstate == CALLST_U8) { - /* Q.2971:Call-Control-U 15-16/39 */ - u8_connect_ack(c, msg, u, CALLST_U10); - break; - } - if (c->cstate == CALLST_N10) { - /* Q.2971:Call-Control-N 18/39 */ - n10_connect_ack(c, msg, u); - break; - } - uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, NULL, 0); - goto drop; - - case SIGC_RELEASE: - switch (c->cstate) { - - default: - uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, NULL, 0); - goto drop; - - case CALLST_U11: - case CALLST_N12: - /* Q.2971:Call-Control-U 28/39 */ - /* Q.2971:Call-Control-N 30/39 */ - u11n12_release(c, msg, u); - break; - - case CALLST_U1: - case CALLST_U3: - case CALLST_U4: - case CALLST_U6: - case CALLST_U7: - case CALLST_U8: - case CALLST_U9: - case CALLST_U10: - case CALLST_U12: - /* Q.2971:Call-Control-U 25/39 */ - unx_release(c, msg, u, CALLST_U12); - break; - - case CALLST_N1: - case CALLST_N3: - case CALLST_N4: - case CALLST_N6: - case CALLST_N7: - case CALLST_N8: - case CALLST_N9: - case CALLST_N10: - case CALLST_N11: - /* Q.2971:Call-Control-N 26/39 */ - unx_release(c, msg, u, CALLST_N11); - break; - } - break; - - case SIGC_RELEASE_COMPL: - /* Q.2971:Call-Control-U 25/39 */ - /* Q.2971:Call-Control-N 26/39 */ - unx_release_compl(c, msg, u); - break; - - case SIGC_NOTIFY: - /* Q.2971:Call-Control-U 18/39 */ - /* Q.2971:Call-Control-N 19/39 */ - unx_notify(c, msg, u); - break; - - case SIGC_STATUS: - if (c->cstate == CALLST_U11 || c->cstate == CALLST_U12 || - c->cstate == CALLST_N11 || c->cstate == CALLST_N12) { - /* Q.2971:Call-Control-U 29/39 (U11) */ - /* Q.2971:Call-Control-U 30/39 (U12) */ - /* Q.2971:Call-Control-N 29/39 (N11) */ - /* Q.2971:Call-Control-N 31/39 (N12) */ - un11un12_status(c, msg, u); - break; - } - /* Q.2971:Call-Control-U 32/39 */ - /* Q.2971:Call-Control-N 33/39 */ - unx_status(c, msg, u); - break; - - case SIGC_STATUS_ENQ: - /* Q.2971:Call-Control-U 31/39 */ - /* Q.2971:Call-Control-N 32/39 */ - unx_status_enq(c, msg, u); - break; - - case SIGC_ADD_PARTY: - (void)uni_decode_body(msg, u, &c->uni->cx); - - if (c->type != CALL_LEAF && c->type != CALL_ROOT) { - uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, - &u->u.add_party.epref, UNI_EPSTATE_NULL); - goto drop; - } - switch (c->cstate) { - case CALLST_U7: - case CALLST_U8: - case CALLST_U10: - case CALLST_N4: - case CALLST_N10: - /* Q.2971:Call-Control-U 14/39 U7 */ - /* Q.2971:Call-Control-U 15/39 U8 */ - /* Q.2971:Call-Control-U 21/39 U10 */ - /* Q.2971:Call-Control-N 8/39 N4 */ - /* Q.2971:Call-Control-N 21/39 N10 */ - unx_add_party(c, msg, u, 1); - break; - - default: - unx_add_party(c, msg, u, 0); - goto drop; - } - break; - - case SIGC_PARTY_ALERTING: - (void)uni_decode_body(msg, u, &c->uni->cx); - - if (c->type != CALL_ROOT) { - uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, - &u->u.party_alerting.epref, -1); - goto drop; - } - switch (c->cstate) { - - default: - /* Q.2971 9.5.3.2.3a) */ - unx_party_alerting(c, msg, u, 0); - break; - - case CALLST_U4: - case CALLST_U10: - /* Q.2971:Call-Control-U 9/39 U4 */ - /* Q.2971:Call-Control-U 21/39 U10 */ - /* Q.2971:Call-Control-N 12/39 N7 */ - /* Q.2971:Call-Control-N 15/39 N8 */ - /* Q.2971:Call-Control-N 22/39 N10 */ - unx_party_alerting(c, msg, u, 1); - break; - } - break; - - case SIGC_ADD_PARTY_ACK: - (void)uni_decode_body(msg, u, &c->uni->cx); - - if (c->type != CALL_ROOT) { - uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, - &u->u.add_party_rej.epref, -1); - goto drop; - } - switch (c->cstate) { - - case CALLST_U10: - /* Q.2971:Call-Control-U 21/39 U10 */ - /* Q.2971:Call-Control-N 15/39 N8 */ - /* Q.2971:Call-Control-N 22/39 N10 */ - un10n8_add_party_ack(c, msg, u, 1); - break; - - default: - /* Q.2971 9.5.3.2.3a) */ - un10n8_add_party_ack(c, msg, u, 0); - break; - } - break; - - case SIGC_ADD_PARTY_REJ: - (void)uni_decode_body(msg, u, &c->uni->cx); - - if (c->type != CALL_ROOT) { - uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, - &u->u.add_party_rej.epref, -1); - goto drop; - } - switch (c->cstate) { - - case CALLST_U4: - case CALLST_U10: - case CALLST_N7: - case CALLST_N8: - case CALLST_N10: - /* Q.2971:Call-Control-U 9/39 U4 */ - /* Q.2971:Call-Control-U 21/39 U10 */ - /* Q.2971:Call-Control-N 12/39 N7 */ - /* Q.2971:Call-Control-N 15/39 N8 */ - /* Q.2971:Call-Control-N 22/39 N10 */ - unx_add_party_rej(c, msg, u, 1); - break; - - default: - /* Q.2971: 9.5.3.2.3b */ - unx_add_party_rej(c, msg, u, 0); - break; - } - break; - - case SIGC_DROP_PARTY: - (void)uni_decode_body(msg, u, &c->uni->cx); - - if (c->type != CALL_ROOT && c->type != CALL_LEAF) { - uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, - &u->u.drop_party.epref, -1); - goto drop; - } - switch (c->cstate) { - case CALLST_U11: - case CALLST_U12: - case CALLST_N11: - case CALLST_N12: - /* Q.2971:Call-Control-U 28/39 U11 */ - /* Q.2971:Call-Control-U 30/39 U12 */ - /* Q.2971:Call-Control-N 29/39 N11 */ - /* Q.2971:Call-Control-N 30/39 N12 */ - goto drop; - - case CALLST_NULL: - uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, - &u->u.drop_party.epref, UNI_EPSTATE_NULL); - goto drop; - - case CALLST_U3: - case CALLST_N3: - /* L3MU_17_38 */ - unx_drop_party(c, msg, u, 0); - break; - - case CALLST_U8: - if (c->uni->sb_tb) { - /* L3MU_06_0[3-6] */ - unx_drop_party(c, msg, u, 0); - break; - } - /* FALLTHRU */ - - default: - /* Q.2971:Call-Control-U 26/39 Ux */ - /* Q.2971:Call-Control-U 21/39 U10 */ - /* Q.2971:Call-Control-N 27/39 Nx */ - /* Q.2971:Call-Control-N 21/39 N10 */ - unx_drop_party(c, msg, u, 1); - break; - } - break; - - case SIGC_DROP_PARTY_ACK: - (void)uni_decode_body(msg, u, &c->uni->cx); - - if (c->type != CALL_ROOT && c->type != CALL_LEAF) { - uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, - &u->u.drop_party_ack.epref, -1); - goto drop; - } - switch (c->cstate) { - - case CALLST_U11: - case CALLST_U12: - /* Q.2971:Call-Control-U 28/39 U11 */ - /* Q.2971:Call-Control-U 30/39 U12 */ - /* Q.2971:Call-Control-N 29/39 N11 */ - /* Q.2971:Call-Control-N 30/39 N12 */ - goto drop; - - case CALLST_NULL: - uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, - &u->u.drop_party.epref, UNI_EPSTATE_NULL); - goto drop; - - case CALLST_U4: - case CALLST_N4: - case CALLST_U7: - case CALLST_N7: - case CALLST_U8: - case CALLST_N8: - case CALLST_U10: - case CALLST_N10: - /* Q.2971:Call-Control-U 26/39 Ux */ - /* Q.2971:Call-Control-U 21/39 U10 */ - /* Q.2971:Call-Control-N 27/39 Nx */ - /* Q.2971:Call-Control-N 22/39 N10 */ - unx_drop_party_ack(c, msg, u, 1); - break; - - default: - /* Q.2971 10.5 4th paragraph */ - unx_drop_party_ack(c, msg, u, 0); - break; - } - break; - - case SIGC_COBISETUP: /* XXX */ - unx_unknown(c, msg, u); - break; - - /* - * User signals - */ - case SIGC_SETUP_request: - if (c->cstate == CALLST_NULL) { - /* Q.2971:Call-Control-U 4/39 (U0) */ - /* Q.2971:Call-Control-N 4/39 (N0) */ - if (c->uni->proto == UNIPROTO_UNI40N) - un0_setup_request(c, msg, cookie, CALLST_N6); - else - un0_setup_request(c, msg, cookie, CALLST_U1); - break; - } - VERBOSE(c->uni, UNI_FAC_ERR, 1, "setup.request in cs=%s", - callstates[c->cstate].name); - uniapi_call_error(c, UNIAPI_ERROR_BAD_CALLSTATE, cookie); - uni_msg_destroy(msg); - break; - - case SIGC_SETUP_response: - if (c->cstate == CALLST_U6 || c->cstate == CALLST_U9 || - c->cstate == CALLST_U7) { - /* Q.2971:Call-Control-U 13/39 (U6) */ - /* Q.2971:Call-Control-U 14/39 (U7) */ - /* Q.2971:Call-Control-U 17/39 (U9) */ - unx_setup_response(c, msg, cookie, CALLST_U8); - break; - } - if (c->cstate == CALLST_N1 || c->cstate == CALLST_N3 || - c->cstate == CALLST_N4) { - /* Q.2971:Call-Control-N 39/39 (N1) */ - /* Q.2971:Call-Control-N 7/39 (N3) */ - /* Q.2971:Call-Control-N 8/39 (N4) */ - unx_setup_response(c, msg, cookie, CALLST_N10); - break; - } - VERBOSE(c->uni, UNI_FAC_ERR, 1, "setup.response in cs=%s", - callstates[c->cstate].name); - uniapi_call_error(c, UNIAPI_ERROR_BAD_CALLSTATE, cookie); - uni_msg_destroy(msg); - break; - - case SIGC_SETUP_COMPLETE_request: - if (c->cstate == CALLST_N8) { - /* Q.2971:Call-Control-N 15/39 (N8) */ - n8_setup_compl_request(c, msg, cookie, CALLST_N10); - break; - } - VERBOSE(c->uni, UNI_FAC_ERR, 1, "setup_compl.request in cs=%s", - callstates[c->cstate].name); - uniapi_call_error(c, UNIAPI_ERROR_BAD_CALLSTATE, cookie); - uni_msg_destroy(msg); - break; - - case SIGC_PROCEEDING_request: - if (c->cstate == CALLST_U6) { - /* Q.2971:Call-Control-U 12/39 (U6) */ - u6n1_proceeding_request(c, msg, cookie, CALLST_U9); - break; - } - if (c->cstate == CALLST_N1) { - /* Q.2971:Call-Control-N 6/39 (N1) */ - u6n1_proceeding_request(c, msg, cookie, CALLST_N3); - break; - } - VERBOSE(c->uni, UNI_FAC_ERR, 1, "proceeding.request in cs=%s", - callstates[c->cstate].name); - uniapi_call_error(c, UNIAPI_ERROR_BAD_CALLSTATE, cookie); - uni_msg_destroy(msg); - break; - - case SIGC_ALERTING_request: - if (c->cstate == CALLST_U6 || c->cstate == CALLST_U9) { - /* Q.2971:Call-Control-U 13/39 (U6) */ - /* Q.2971:Call-Control-U 17/39 (U9) */ - unx_alerting_request(c, msg, cookie, CALLST_U7); - break; - } - if (c->cstate == CALLST_N1 || c->cstate == CALLST_N3) { - /* Q.2971:Call-Control-N 38/39 (N1) */ - /* Q.2971:Call-Control-N 7/39 (N3) */ - unx_alerting_request(c, msg, cookie, CALLST_N4); - break; - } - VERBOSE(c->uni, UNI_FAC_ERR, 1, "alerting.request in cs=%s", - callstates[c->cstate].name); - uniapi_call_error(c, UNIAPI_ERROR_BAD_CALLSTATE, cookie); - uni_msg_destroy(msg); - break; - - case SIGC_RELEASE_request: - switch (c->cstate) { - - case CALLST_U1: - case CALLST_U3: - case CALLST_U4: - case CALLST_U6: - case CALLST_U7: - case CALLST_U8: - case CALLST_U9: - case CALLST_U10: - /* Q.2971:Call-Control-U 27/39 */ - unx_release_request(c, msg, cookie, CALLST_U11); - break; - - case CALLST_N1: - case CALLST_N3: - case CALLST_N4: - case CALLST_N6: - case CALLST_N7: - case CALLST_N8: - case CALLST_N9: - case CALLST_N10: - /* Q.2971:Call-Control-N 28/39 */ - unx_release_request(c, msg, cookie, CALLST_N12); - break; - - case CALLST_U11: - case CALLST_U12: - case CALLST_N11: - case CALLST_N12: - case CALLST_NULL: - VERBOSE(c->uni, UNI_FAC_ERR, 1, - "release.request in cs=%s", - callstates[c->cstate].name); - uniapi_call_error(c, UNIAPI_ERROR_BAD_CALLSTATE, - cookie); - uni_msg_destroy(msg); - break; - } - break; - - case SIGC_RELEASE_response: - if (c->cstate == CALLST_U6 || c->cstate == CALLST_U12 || - c->cstate == CALLST_N1 || c->cstate == CALLST_N11) { - /* Q.2971:Call-Control-U 12/39 (U6) */ - /* Q.2971:Call-Control-U 30/39 (U12) */ - /* Q.2971:Call-Control-N 6/39 (N1) */ - /* Q.2971:Call-Control-N 29/39 (N11) */ - unx_release_response(c, msg, cookie); - break; - } - VERBOSE(c->uni, UNI_FAC_ERR, 1, "release.response in cs=%s", - callstates[c->cstate].name); - uniapi_call_error(c, UNIAPI_ERROR_BAD_CALLSTATE, cookie); - uni_msg_destroy(msg); - break; - - case SIGC_NOTIFY_request: - /* Q.2971:Call-Control-U 18/39 */ - /* Q.2971:Call-Control-N 19/39 */ - unx_notify_request(c, msg, cookie); - break; - - case SIGC_STATUS_ENQUIRY_request: - /* Q.2971:Call-Control-U 31/39 */ - /* Q.2971:Call-Control-N 32/39 */ - unx_status_enquiry_request(c, msg, cookie); - break; - - case SIGC_ADD_PARTY_request: - if (c->cstate == CALLST_U4 || c->cstate == CALLST_U10 || - c->cstate == CALLST_N7 || c->cstate == CALLST_N10) { - /* Q.2971:Call-Control-U 9-10/39 (U4) */ - /* Q.2971:Call-Control-U 21/39 (U10) */ - /* Q.2971:Call-Control-N 12/39 (N7) */ - /* Q.2971:Call-Control-N 22/39 (N10) */ - unx_add_party_request(c, msg, cookie); - break; - } - VERBOSE(c->uni, UNI_FAC_ERR, 1, "add-party.request in cs=%s", - callstates[c->cstate].name); - uniapi_call_error(c, UNIAPI_ERROR_BAD_CALLSTATE, cookie); - uni_msg_destroy(msg); - break; - - case SIGC_PARTY_ALERTING_request: - if (c->cstate == CALLST_U7 || c->cstate == CALLST_U8 || - c->cstate == CALLST_U10 || - c->cstate == CALLST_N4 || c->cstate == CALLST_N10) { - /* Q.2971:Call-Control-U 14/39 U7 */ - /* Q.2971:Call-Control-U 15/39 U8 */ - /* Q.2971:Call-Control-U 21/39 U10 */ - /* Q.2971:Call-Control-N 8/39 N4 */ - /* Q.2971:Call-Control-N 22/39 N10 */ - unx_party_alerting_request(c, msg, cookie); - break; - } - VERBOSE(c->uni, UNI_FAC_ERR, 1, - "party-alerting.request in cs=%s", - callstates[c->cstate].name); - uniapi_call_error(c, UNIAPI_ERROR_BAD_CALLSTATE, cookie); - uni_msg_destroy(msg); - break; - - case SIGC_ADD_PARTY_ACK_request: - if (c->cstate == CALLST_U10 || c->cstate == CALLST_N10) { - /* Q.2971:Call-Control-U 21/39 (U10) */ - /* Q.2971:Call-Control-N 22/39 (N10)*/ - un10_add_party_ack_request(c, msg, cookie); - break; - } - VERBOSE(c->uni, UNI_FAC_ERR, 1, - "add-party-ack.request in cs=%s", - callstates[c->cstate].name); - uniapi_call_error(c, UNIAPI_ERROR_BAD_CALLSTATE, cookie); - uni_msg_destroy(msg); - break; - - case SIGC_ADD_PARTY_REJ_request: - if (c->cstate == CALLST_U7 || c->cstate == CALLST_U8 || - c->cstate == CALLST_U10 || - c->cstate == CALLST_N4 || c->cstate == CALLST_N10) { - /* Q.2971:Call-Control-U 14/39 U7 */ - /* Q.2971:Call-Control-U 15/39 U8 */ - /* Q.2971:Call-Control-U 21/39 U10 */ - /* Q.2971:Call-Control-N 8/39 N4 */ - /* Q.2971:Call-Control-N 22/39 N10 */ - unx_add_party_rej_request(c, msg, cookie); - break; - } - VERBOSE(c->uni, UNI_FAC_ERR, 1, - "add-party-rej.request in cs=%s", - callstates[c->cstate].name); - uniapi_call_error(c, UNIAPI_ERROR_BAD_CALLSTATE, cookie); - uni_msg_destroy(msg); - break; - - case SIGC_DROP_PARTY_request: - if (c->cstate != CALLST_U11 && c->cstate != CALLST_U12 && - c->cstate != CALLST_N11 && c->cstate != CALLST_N12 && - c->cstate != CALLST_NULL) { - /* Q.2971:Call-Control-U 21/39 U10 */ - /* Q.2971:Call-Control-U 26/39 U1-U9 */ - /* Q.2971:Call-Control-N 22/39 N10 */ - /* Q.2971:Call-Control-N 27/39 N1-N9 */ - unx_drop_party_request(c, msg, cookie); - break; - } - VERBOSE(c->uni, UNI_FAC_ERR, 1, "drop-party.request in cs=%s", - callstates[c->cstate].name); - uniapi_call_error(c, UNIAPI_ERROR_BAD_CALLSTATE, cookie); - uni_msg_destroy(msg); - break; - - case SIGC_DROP_PARTY_ACK_request: - if (c->cstate != CALLST_U11 && c->cstate != CALLST_U12 && - c->cstate != CALLST_N11 && c->cstate != CALLST_N12 && - c->cstate != CALLST_NULL) { - /* Q.2971:Call-Control-U 21/39 U10 */ - /* Q.2971:Call-Control-U 26/39 U1-U9 */ - /* Q.2971:Call-Control-N 22/39 N10 */ - /* Q.2971:Call-Control-N 27/39 N1-N9 */ - unx_drop_party_ack_request(c, msg, cookie); - break; - } - VERBOSE(c->uni, UNI_FAC_ERR, 1, - "drop-party-ack.request in cs=%s", - callstates[c->cstate].name); - uniapi_call_error(c, UNIAPI_ERROR_BAD_CALLSTATE, cookie); - uni_msg_destroy(msg); - break; - - case SIGC_ABORT_CALL_request: - { - struct uni *uni = c->uni; - - uni_destroy_call(c, 0); - uniapi_uni_error(uni, UNIAPI_OK, cookie, UNI_CALLSTATE_U0); - break; - } - - /* - * Timers - */ - case SIGC_T301: - if (c->cstate == CALLST_U4 || c->cstate == CALLST_N7) { - /* Q.2971:Call-Control-U Missing */ - /* Q.2971:Call-Control-N 14/39 */ - u4n7_t301(c); - break; - } - VERBOSE(c->uni, UNI_FAC_ERR, 1, "T301 in cs=%s", - callstates[c->cstate].name); - break; - - case SIGC_T303: - if (c->cstate == CALLST_U1 || c->cstate == CALLST_N6) { - /* Q.2971:Call-Control-U 6/39 */ - /* Q.2971:Call-Control-N 11/39 */ - u1n6_t303(c); - break; - } - VERBOSE(c->uni, UNI_FAC_ERR, 1, "T303 in cs=%s", - callstates[c->cstate].name); - break; - - case SIGC_T308: - if (c->cstate == CALLST_U11 || c->cstate == CALLST_N12) { - /* Q.2971:Call-Control-U 28/39 */ - /* Q.2971:Call-Control-N 30/39 */ - u11n12_t308(c); - break; - } - VERBOSE(c->uni, UNI_FAC_ERR, 1, "T308 in cs=%s", - callstates[c->cstate].name); - break; - - case SIGC_T310: - if (c->cstate == CALLST_U3 || c->cstate == CALLST_N9) { - /* Q.2971:Call-Control-U 7/39 */ - /* Q.2971:Call-Control-N 17/39 */ - u3n9_t310(c); - break; - } - VERBOSE(c->uni, UNI_FAC_ERR, 1, "T310 in cs=%s", - callstates[c->cstate].name); - break; - - case SIGC_T313: - if (c->cstate == CALLST_U8) { - /* Q.2971:Call-Control-U 15/39 */ - u8_t313(c); - break; - } - VERBOSE(c->uni, UNI_FAC_ERR, 1, "T313 in cs=%s", - callstates[c->cstate].name); - break; - - case SIGC_T322: - /* Q.2971:Call-Control-U 34/39 */ - /* Q.2971:Call-Control-N 35/39 */ - unx_t322(c); - break; - - case SIGC_CALL_DELETE: - CALL_FREE(c); - break; - - /* - * Party-Control - */ - case SIGC_DROP_PARTY_indication: - if (c->uni->proto == UNIPROTO_UNI40U) - /* Q.2971:Call-Control-U 23/39 */ - ux_drop_party_indication(c, msg); - else - /* Q.2971:Call-Control-N 23/39 */ - nx_drop_party_indication(c, msg); - break; - - case SIGC_DROP_PARTY_ACK_indication: - if (c->uni->proto == UNIPROTO_UNI40U) - /* Q.2971:Call-Control-U 23/39 */ - ux_drop_party_ack_indication(c, msg); - else - /* Q.2971:Call-Control-N 23/39 */ - nx_drop_party_ack_indication(c, msg); - break; - - case SIGC_ADD_PARTY_REJ_indication: - if (c->uni->proto == UNIPROTO_UNI40U) - /* Q.2971:Call-Control-U 23/39 */ - ux_add_party_rej_indication(c, msg); - else - /* Q.2971:Call-Control-N 23/39 */ - nx_add_party_rej_indication(c, msg); - break; - - - case SIGC_SEND_DROP_PARTY: - /* Q.2971:Call-Control-U 21/39 */ - /* Q.2971:Call-Control-U 25/39 */ - if (uni_party_act_count(c, 2) != 0) - (void)uni_send_output(u, c->uni); - else if(c->cstate != CALLST_U11) { - c->uni->cause = u->u.drop_party.cause; - clear_callD(c); - } - UNI_FREE(u); - break; - - case SIGC_SEND_DROP_PARTY_ACK: - /* Q.2971:Call-Control-U 21/39 */ - /* Q.2971:Call-Control-U 25/39 */ - if (uni_party_act_count(c, 2) != 0) - (void)uni_send_output(u, c->uni); - else if (c->cstate != CALLST_U11) { - c->uni->cause = u->u.drop_party_ack.cause; - clear_callD(c); - } - UNI_FREE(u); - break; - - case SIGC_SEND_ADD_PARTY_REJ: - /* Q.2971:Call-Control-U 21/39 */ - /* Q.2971:Call-Control-U 24/39 */ - unx_send_add_party_rej(c, u); - break; - - case SIGC_SEND_STATUS_ENQ: - /* Q.2971:Call-Control-U 21/39 */ - /* Q.2971:Call-Control-U 25/39 */ - unx_send_party_status_enq(c, u); - break; - - case SIGC_PARTY_DESTROYED: - c->uni->funcs->uni_output(c->uni, c->uni->arg, - UNIAPI_PARTY_DESTROYED, cookie, msg); - break; - - case SIGC_END: - break; - } - - return; - - drop: - /* - * This is for SAAL message signals that should be dropped. - */ - uni_msg_destroy(msg); - UNI_FREE(u); -} - -/**********************************************************************/ - -/* - * Timeout functions - */ -static void -t308_func(struct call *c) -{ - uni_enq_call(c, SIGC_T308, 0, NULL, NULL); -} -static void -t303_func(struct call *c) -{ - uni_enq_call(c, SIGC_T303, 0, NULL, NULL); -} -static void -t301_func(struct call *c) -{ - uni_enq_call(c, SIGC_T301, 0, NULL, NULL); -} -static void -t310_func(struct call *c) -{ - uni_enq_call(c, SIGC_T310, 0, NULL, NULL); -} -static void -t313_func(struct call *c) -{ - uni_enq_call(c, SIGC_T313, 0, NULL, NULL); -} - -static void -t322_func(struct call *c) -{ - uni_enq_call(c, SIGC_T322, 0, NULL, NULL); -} - -/**********************************************************************/ - -/* - * Check whether the peer state is compatible with our state. - * Return the new callstate we should go to (either U0 or the current - * state). - * None of the state is U0 here. My state is not U11 or U12. - * - * Well, this turns out to be not so easy: the status enquiry could have - * been sent before we changed into the current state - the status will - * report a previous state without anything been lost. - * - * Incoming states are incompatible with outgoing states. Everything is ok. - */ -static enum call_state -state_compat(struct call *c, enum uni_callstate peer) -{ - if ((c->cstate == CALLST_U1 || - c->cstate == CALLST_U3 || - c->cstate == CALLST_U4) && - (peer == UNI_CALLSTATE_N6 || - peer == UNI_CALLSTATE_N7 || - peer == UNI_CALLSTATE_N8 || - peer == UNI_CALLSTATE_N9)) - return (CALLST_NULL); - - if ((c->cstate == CALLST_N6 || - c->cstate == CALLST_N7 || - c->cstate == CALLST_N8 || - c->cstate == CALLST_N9) && - (peer == UNI_CALLSTATE_U1 || - peer == UNI_CALLSTATE_U3 || - peer == UNI_CALLSTATE_U4)) - return (CALLST_NULL); - - if ((peer == UNI_CALLSTATE_N1 || - peer == UNI_CALLSTATE_N3 || - peer == UNI_CALLSTATE_N4) && - (c->cstate == CALLST_U6 || - c->cstate == CALLST_U7 || - c->cstate == CALLST_U8 || - c->cstate == CALLST_N9)) - return (CALLST_NULL); - - if ((peer == UNI_CALLSTATE_U6 || - peer == UNI_CALLSTATE_U7 || - peer == UNI_CALLSTATE_U8 || - peer == UNI_CALLSTATE_U9) && - (c->cstate == CALLST_N1 || - c->cstate == CALLST_N3 || - c->cstate == CALLST_N4)) - return (CALLST_NULL); - - return (c->cstate); -} |