1122205Sharti/* 2122205Sharti * Copyright (c) 1996-2003 3122205Sharti * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4122205Sharti * All rights reserved. 5122205Sharti * 6122205Sharti * Redistribution and use in source and binary forms, with or without 7122205Sharti * modification, are permitted provided that the following conditions 8122205Sharti * are met: 9122205Sharti * 1. Redistributions of source code must retain the above copyright 10122205Sharti * notice, this list of conditions and the following disclaimer. 11122205Sharti * 2. Redistributions in binary form must reproduce the above copyright 12122205Sharti * notice, this list of conditions and the following disclaimer in the 13122205Sharti * documentation and/or other materials provided with the distribution. 14122205Sharti * 15122205Sharti * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16122205Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17122205Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18122205Sharti * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19122205Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20122205Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21122205Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22122205Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23122205Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24122205Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25122205Sharti * SUCH DAMAGE. 26122205Sharti * 27122205Sharti * Author: Hartmut Brandt <harti@freebsd.org> 28122205Sharti * 29133492Sharti * $Begemot: libunimsg/netnatm/sig/sig_call.c,v 1.65 2004/08/05 07:11:00 brandt Exp $ 30122205Sharti * 31122205Sharti * Call instance handling 32122205Sharti * 33122205Sharti * Note: 34122205Sharti * In all functions that handle messages from the user or from 35122205Sharti * the SAAL, commit memory allocation always at the begin of the 36122205Sharti * function. If allocation fails, ignore saal messages and 37122205Sharti * respond with an error to user messages. 38122205Sharti */ 39122205Sharti 40122205Sharti#include <netnatm/unimsg.h> 41122205Sharti#include <netnatm/saal/sscfudef.h> 42122205Sharti#include <netnatm/msg/unistruct.h> 43122205Sharti#include <netnatm/msg/unimsglib.h> 44122205Sharti#include <netnatm/sig/uni.h> 45122205Sharti 46122205Sharti#include <netnatm/sig/unipriv.h> 47122205Sharti#include <netnatm/sig/unimkmsg.h> 48122205Sharti#include <netnatm/sig/unimsgcpy.h> 49122205Sharti 50122205Shartistatic enum call_state state_compat(struct call *, enum uni_callstate); 51122205Shartistatic void respond_drop_party_ack(struct call *, struct uni_ie_epref *, u_int); 52122205Sharti 53122205Sharti 54133492Sharti#define DEF_PRIV_SIG(NAME, FROM) [SIG##NAME] = "SIG"#NAME, 55122205Shartistatic const char *const call_sigs[] = { 56122205Sharti DEF_CALL_SIGS 57122205Sharti}; 58122205Sharti#undef DEF_PRIV_SIG 59122205Sharti 60122205ShartiTIMER_FUNC_CALL(t308, t308_func) 61122205ShartiTIMER_FUNC_CALL(t303, t303_func) 62122205ShartiTIMER_FUNC_CALL(t301, t301_func) 63122205ShartiTIMER_FUNC_CALL(t310, t310_func) 64122205ShartiTIMER_FUNC_CALL(t313, t313_func) 65122205ShartiTIMER_FUNC_CALL(t322, t322_func) 66122205Sharti 67122205Sharticonst struct callstates callstates[] = { 68133492Sharti [CALLST_NULL] = { "NU0", UNI_CALLSTATE_U0 }, 69133492Sharti [CALLST_U1] = { "U1", UNI_CALLSTATE_U1 }, 70133492Sharti [CALLST_U3] = { "U3", UNI_CALLSTATE_U3 }, 71133492Sharti [CALLST_U4] = { "U4", UNI_CALLSTATE_U4 }, 72133492Sharti [CALLST_U6] = { "U6", UNI_CALLSTATE_U6 }, 73133492Sharti [CALLST_U7] = { "U7", UNI_CALLSTATE_U7 }, 74133492Sharti [CALLST_U8] = { "U8", UNI_CALLSTATE_U8 }, 75133492Sharti [CALLST_U9] = { "U9", UNI_CALLSTATE_U9 }, 76133492Sharti [CALLST_U10] = { "U10", UNI_CALLSTATE_U10 }, 77133492Sharti [CALLST_U11] = { "U11", UNI_CALLSTATE_U11 }, 78133492Sharti [CALLST_U12] = { "U12", UNI_CALLSTATE_U12 }, 79133492Sharti [CALLST_N1] = { "N1", UNI_CALLSTATE_N1 }, 80133492Sharti [CALLST_N3] = { "N3", UNI_CALLSTATE_N3 }, 81133492Sharti [CALLST_N4] = { "N4", UNI_CALLSTATE_N4 }, 82133492Sharti [CALLST_N6] = { "N6", UNI_CALLSTATE_N6 }, 83133492Sharti [CALLST_N7] = { "N7", UNI_CALLSTATE_N7 }, 84133492Sharti [CALLST_N8] = { "N8", UNI_CALLSTATE_N8 }, 85133492Sharti [CALLST_N9] = { "N9", UNI_CALLSTATE_N9 }, 86133492Sharti [CALLST_N10] = { "N10", UNI_CALLSTATE_N10 }, 87133492Sharti [CALLST_N11] = { "N11", UNI_CALLSTATE_N11 }, 88133492Sharti [CALLST_N12] = { "N12", UNI_CALLSTATE_N12 }, 89122205Sharti}; 90122205Sharti 91122205Shartistatic void unx_send_add_party_rej(struct call *c, struct uni_all *u); 92122205Sharti 93122205Shartistatic __inline void 94122205Shartiset_call_state(struct call *c, enum call_state state) 95122205Sharti{ 96122205Sharti ASSERT(state == CALLST_NULL || 97122205Sharti (c->uni->proto == UNIPROTO_UNI40U && 98122205Sharti (state >= CALLST_U1 && state <= CALLST_U12)) || 99122205Sharti (c->uni->proto == UNIPROTO_UNI40N && 100122205Sharti (state >= CALLST_N1 && state <= CALLST_N12)), 101122205Sharti ("setting wrong callstate for proto %u: %u", c->uni->proto, state)); 102122205Sharti 103122205Sharti if (c->cstate != state) { 104122205Sharti VERBOSE(c->uni, UNI_FAC_CALL, 1, "call %d/%d %s -> %s", 105122205Sharti c->cref, c->mine, callstates[c->cstate].name, 106122205Sharti callstates[state].name); 107122205Sharti c->cstate = state; 108122205Sharti } 109122205Sharti} 110122205Sharti 111122205Shartistatic enum uni_callstate 112122205Shartimap_callstate(enum call_state state) 113122205Sharti{ 114122205Sharti return (callstates[state].ext); 115122205Sharti} 116122205Sharti 117122205Sharti/* 118122205Sharti * Find the call. Assume, that the cref is one of a message just received. 119122205Sharti * That is, if the call reference flag is 0 it is his call, if it is 1 it 120122205Sharti * is my call. 121122205Sharti */ 122122205Shartistruct call * 123122205Shartiuni_find_call(struct uni *uni, struct uni_cref *cref) 124122205Sharti{ 125122205Sharti struct call *c; 126122205Sharti 127122205Sharti TAILQ_FOREACH(c, &uni->calls, link) 128122205Sharti if (c->cref == cref->cref && (!c->mine == !cref->flag)) 129122205Sharti return (c); 130122205Sharti return (NULL); 131122205Sharti} 132122205Shartistruct call * 133122205Shartiuni_find_callx(struct uni *uni, u_int cref, u_int mine) 134122205Sharti{ 135122205Sharti struct call *c; 136122205Sharti 137122205Sharti TAILQ_FOREACH(c, &uni->calls, link) 138122205Sharti if (c->cref == cref && !c->mine == !mine) 139122205Sharti return (c); 140122205Sharti return (NULL); 141122205Sharti} 142122205Sharti 143122205Sharti/* 144122205Sharti * Create a new call instance. The type must be set by the caller. 145122205Sharti */ 146122205Shartistruct call * 147131826Shartiuni_create_call(struct uni *uni, u_int cref, u_int mine, uint32_t cookie) 148122205Sharti{ 149122205Sharti struct call *c; 150122205Sharti struct uniapi_call_created *ind; 151122205Sharti struct uni_msg *api; 152122205Sharti 153122205Sharti if ((c = CALL_ALLOC()) == NULL) 154122205Sharti return (NULL); 155122205Sharti 156122205Sharti if ((ind = ALLOC_API(struct uniapi_call_created, api)) == NULL) { 157122205Sharti CALL_FREE(c); 158122205Sharti return (NULL); 159122205Sharti } 160122205Sharti ind->cref.cref = cref; 161122205Sharti ind->cref.flag = mine; 162122205Sharti 163122205Sharti c->uni = uni; 164122205Sharti c->type = CALL_NULL; 165122205Sharti c->cref = cref; 166122205Sharti c->mine = mine; 167122205Sharti c->cstate = CALLST_NULL; 168122205Sharti TAILQ_INIT(&c->parties); 169122205Sharti 170122205Sharti TIMER_INIT_CALL(c, t301); 171122205Sharti TIMER_INIT_CALL(c, t303); 172122205Sharti TIMER_INIT_CALL(c, t308); 173122205Sharti TIMER_INIT_CALL(c, t310); 174122205Sharti TIMER_INIT_CALL(c, t313); 175122205Sharti TIMER_INIT_CALL(c, t322); 176122205Sharti 177122205Sharti TAILQ_INSERT_HEAD(&uni->calls, c, link); 178122205Sharti 179122205Sharti uni->funcs->uni_output(uni, uni->arg, UNIAPI_CALL_CREATED, cookie, api); 180122205Sharti 181122205Sharti VERBOSE(c->uni, UNI_FAC_CALL, 1, "created call %u/%s", 182122205Sharti c->cref, c->mine ? "mine" : "his"); 183122205Sharti 184122205Sharti return (c); 185122205Sharti} 186122205Sharti 187122205Shartistruct call * 188131826Shartiuni_create_new_call(struct uni *uni, uint32_t cookie) 189122205Sharti{ 190122205Sharti struct call *c; 191131826Sharti uint32_t old = uni->cref_alloc++; 192122205Sharti 193122205Sharti again: 194122205Sharti if (uni->cref_alloc == (1 << 23)) 195122205Sharti uni->cref_alloc = 1; 196122205Sharti if (uni->cref_alloc == old) 197122205Sharti return (NULL); /* all crefs exhausted!!! */ 198122205Sharti TAILQ_FOREACH(c, &uni->calls, link) 199122205Sharti if (c->mine && c->cref == uni->cref_alloc) { 200122205Sharti uni->cref_alloc++; 201122205Sharti goto again; 202122205Sharti } 203122205Sharti return (uni_create_call(uni, uni->cref_alloc, 1, cookie)); 204122205Sharti} 205122205Sharti 206122205Sharti/* 207122205Sharti * Assume timers are all stopped. Memory is not actually freed unless 208122205Sharti * the reference count drops to 0. 209122205Sharti * This function is assumed to remove the call from the parent UNI's 210122205Sharti * call queue. 211122205Sharti */ 212122205Shartivoid 213122205Shartiuni_destroy_call(struct call *c, int really) 214122205Sharti{ 215122205Sharti struct uniapi_call_destroyed *ind; 216122205Sharti struct uni_msg *api; 217122205Sharti struct party *p; 218122205Sharti 219122205Sharti VERBOSE(c->uni, UNI_FAC_CALL, 1, "destroying call %u/%s", 220122205Sharti c->cref, c->mine ? "mine" : "his"); 221122205Sharti 222122205Sharti TIMER_DESTROY_CALL(c, t301); 223122205Sharti TIMER_DESTROY_CALL(c, t303); 224122205Sharti TIMER_DESTROY_CALL(c, t308); 225122205Sharti TIMER_DESTROY_CALL(c, t310); 226122205Sharti TIMER_DESTROY_CALL(c, t313); 227122205Sharti TIMER_DESTROY_CALL(c, t322); 228122205Sharti TAILQ_REMOVE(&c->uni->calls, c, link); 229122205Sharti 230122205Sharti uni_delsig(c->uni, SIG_CALL, c, NULL); 231122205Sharti 232122205Sharti while ((p = TAILQ_FIRST(&c->parties)) != NULL) { 233122205Sharti TAILQ_REMOVE(&c->parties, p, link); 234122205Sharti uni_destroy_party(p, really); 235122205Sharti } 236122205Sharti 237122205Sharti if (!really) { 238122205Sharti ind = ALLOC_API(struct uniapi_call_destroyed, api); 239122205Sharti if (ind != NULL) { 240122205Sharti ind->cref.cref = c->cref; 241122205Sharti ind->cref.flag = c->mine; 242122205Sharti 243122205Sharti uni_enq_coord(c->uni, SIGO_CALL_DESTROYED, 0, api); 244122205Sharti } 245122205Sharti 246122205Sharti uni_enq_call(c, SIGC_CALL_DELETE, 0, NULL, NULL); 247122205Sharti return; 248122205Sharti } 249122205Sharti 250122205Sharti CALL_FREE(c); 251122205Sharti} 252122205Sharti 253122205Shartistatic void 254122205Shartiallocate_epref(struct call *c, struct uni_ie_epref *epref) 255122205Sharti{ 256122205Sharti struct party *p; 257131826Sharti uint32_t old = c->epref_alloc++; 258122205Sharti 259122205Sharti again: 260122205Sharti if (c->epref_alloc == (1 << 15)) 261122205Sharti c->epref_alloc = 0; 262122205Sharti if (c->epref_alloc == old) 263122205Sharti return; /* all crefs exhausted!!! */ 264122205Sharti TAILQ_FOREACH(p, &c->parties, link) 265122205Sharti if (p->epref == c->epref_alloc) { 266122205Sharti c->epref_alloc++; 267122205Sharti goto again; 268122205Sharti } 269122205Sharti IE_SETPRESENT(*epref); 270122205Sharti epref->flag = 0; 271122205Sharti epref->epref = c->epref_alloc; 272122205Sharti 273122205Sharti epref->h.coding = UNI_CODING_ITU; 274122205Sharti epref->h.act = UNI_IEACT_DEFAULT; 275122205Sharti} 276122205Sharti 277122205Shartistatic void 278122205Shartireset_all_timers(struct call *c) 279122205Sharti{ 280122205Sharti TIMER_STOP_CALL(c, t301); 281122205Sharti TIMER_STOP_CALL(c, t303); 282122205Sharti TIMER_STOP_CALL(c, t308); 283122205Sharti TIMER_STOP_CALL(c, t310); 284122205Sharti TIMER_STOP_CALL(c, t313); 285122205Sharti TIMER_STOP_CALL(c, t322); 286122205Sharti} 287122205Sharti 288122205Sharti/* 289122205Sharti * Initiate call clearing because of a problem. This is label D in 290122205Sharti * the SDLs and is called from many places. 291122205Sharti * The call must have constructed the cause IE in struct call. 292122205Sharti * 293122205Sharti * Q.2971:Call-Control-U 27/39 294122205Sharti * Q.2971:Call-Control-N 28/39 295122205Sharti * 296122205Sharti * Memory problems are handled differently here: we simply ignore them 297122205Sharti * by not sending messages or user indications. Because of T308 we 298122205Sharti * may be lucky to send the message in a second run. 299122205Sharti * 300122205Sharti * It is assumed, that the cause for the release is constructed by 301122205Sharti * the calling function in uni->cause. 302122205Sharti */ 303122205Shartistatic void 304122205Sharticlear_callD(struct call *c) 305122205Sharti{ 306122205Sharti struct uni_msg *api; 307122205Sharti struct uniapi_release_indication *ind; 308122205Sharti struct party *p; 309122205Sharti struct uni_all *rel; 310122205Sharti 311122205Sharti /* 312122205Sharti * Send indication to API 313122205Sharti */ 314122205Sharti if ((ind = ALLOC_API(struct uniapi_release_indication, api)) != NULL) { 315122205Sharti ind->release.hdr.cref.cref = c->cref; 316122205Sharti ind->release.hdr.cref.flag = c->mine; 317122205Sharti ind->release.hdr.act = UNI_MSGACT_DEFAULT; 318122205Sharti ind->release.cause[0] = c->uni->cause; 319122205Sharti 320122205Sharti c->uni->funcs->uni_output(c->uni, c->uni->arg, 321122205Sharti UNIAPI_RELEASE_indication, 0, api); 322122205Sharti } 323122205Sharti 324122205Sharti reset_all_timers(c); 325122205Sharti 326122205Sharti if (c->type == CALL_LEAF || c->type == CALL_ROOT) { 327122205Sharti TAILQ_FOREACH(p, &c->parties, link) { 328122205Sharti uni_enq_party(p, SIGP_RELEASE_request, 0, NULL, NULL); 329122205Sharti } 330122205Sharti } 331122205Sharti 332122205Sharti memset(&c->msg_release, 0, sizeof(c->msg_release)); 333122205Sharti c->msg_release.cause[0] = c->uni->cause; 334122205Sharti 335122205Sharti if ((rel = UNI_ALLOC()) != NULL) { 336122205Sharti rel->u.release = c->msg_release; 337122205Sharti MK_MSG_ORIG(rel, UNI_RELEASE, c->cref, !c->mine); 338122205Sharti (void)uni_send_output(rel, c->uni); 339122205Sharti UNI_FREE(rel); 340122205Sharti } 341122205Sharti 342122205Sharti TIMER_START_CALL(c, t308, c->uni->timer308); 343122205Sharti c->cnt308 = 0; 344122205Sharti 345122205Sharti if (c->uni->proto == UNIPROTO_UNI40N) 346122205Sharti set_call_state(c, CALLST_N12); 347122205Sharti else 348122205Sharti set_call_state(c, CALLST_U11); 349122205Sharti} 350122205Sharti 351122205Sharti 352122205Sharti/**********************************************************************/ 353122205Sharti/* 354122205Sharti * SETUP message in state NULL 355122205Sharti * 356122205Sharti * Q.2971:Call-Control-U 4/39 357122205Sharti * Q.2971:Call-Control-N 4/39 358122205Sharti */ 359122205Shartistatic void 360122205Shartiun0_setup(struct call *c, struct uni_msg *m, struct uni_all *u, 361122205Sharti enum call_state new_state) 362122205Sharti{ 363122205Sharti struct uni_all *resp; 364122205Sharti struct party *p; 365122205Sharti struct uniapi_setup_indication *ind; 366122205Sharti struct uni_msg *api; 367122205Sharti enum verify v; 368122205Sharti 369122205Sharti if ((ind = ALLOC_API(struct uniapi_setup_indication, api)) == NULL) { 370122205Sharti clear: 371122205Sharti uni_destroy_call(c, 0); 372122205Sharti uni_msg_destroy(m); 373122205Sharti UNI_FREE(u); 374122205Sharti return; 375122205Sharti } 376122205Sharti 377122205Sharti /* 378122205Sharti * Analyze message 379122205Sharti */ 380122205Sharti (void)uni_decode_body(m, u, &c->uni->cx); 381122205Sharti MANDATE_IE(c->uni, u->u.setup.bearer, UNI_IE_BEARER); 382122205Sharti MANDATE_IE(c->uni, u->u.setup.traffic, UNI_IE_TRAFFIC); 383122205Sharti MANDATE_IE(c->uni, u->u.setup.called, UNI_IE_CALLED); 384122205Sharti 385122205Sharti /* 386122205Sharti * UNI4.0: 9.1.1.2 Notes 2/3 387122205Sharti */ 388122205Sharti if (!IE_ISPRESENT(u->u.setup.qos)) 389122205Sharti MANDATE_IE(c->uni, u->u.setup.exqos, UNI_IE_EXQOS); 390122205Sharti if (!IE_ISPRESENT(u->u.setup.exqos)) 391122205Sharti MANDATE_IE(c->uni, u->u.setup.qos, UNI_IE_QOS); 392122205Sharti 393122205Sharti /* 394122205Sharti * Q.2971 395122205Sharti */ 396122205Sharti if (IE_ISGOOD(u->u.setup.bearer) && 397122205Sharti u->u.setup.bearer.cfg == UNI_BEARER_MP) { 398122205Sharti if (IE_ISGOOD(u->u.setup.epref) && 399122205Sharti u->u.setup.epref.flag == 1) { 400122205Sharti IE_SETERROR(u->u.setup.epref); 401213789Srpaulo (void)UNI_SAVE_IERR(&c->uni->cx, UNI_IE_EPREF, 402122205Sharti u->u.setup.epref.h.act, UNI_IERR_BAD); 403122205Sharti } 404122205Sharti uni_mandate_epref(c->uni, &u->u.setup.epref); 405122205Sharti } 406122205Sharti 407122205Sharti v = uni_verify(c->uni, u->u.hdr.act); 408122205Sharti switch (v) { 409122205Sharti 410122205Sharti case VFY_RAI: 411122205Sharti uni_respond_status_verify(c->uni, &u->u.hdr.cref, 412122205Sharti UNI_CALLSTATE_U0, NULL, 0); 413122205Sharti /* FALLTHRU */ 414122205Sharti case VFY_I: 415122205Sharti uni_msg_destroy(api); 416122205Sharti goto clear; 417122205Sharti 418122205Sharti case VFY_RAIM: 419122205Sharti case VFY_CLR: 420122205Sharti if ((resp = UNI_ALLOC()) != NULL) { 421122205Sharti MK_MSG_RESP(resp, UNI_RELEASE_COMPL, &u->u.hdr.cref); 422122205Sharti uni_vfy_collect_ies(c->uni); 423122205Sharti resp->u.release_compl.cause[0] = c->uni->cause; 424122205Sharti uni_send_output(resp, c->uni); 425122205Sharti UNI_FREE(resp); 426122205Sharti } 427122205Sharti uni_msg_destroy(api); 428122205Sharti goto clear; 429122205Sharti 430122205Sharti case VFY_RAP: 431122205Sharti case VFY_RAPU: 432122205Sharti uni_respond_status_verify(c->uni, &u->u.hdr.cref, 433122205Sharti map_callstate(new_state), NULL, 0); 434122205Sharti /* FALLTHRU */ 435122205Sharti case VFY_OK: 436122205Sharti break; 437122205Sharti } 438122205Sharti 439122205Sharti if (u->u.setup.bearer.cfg == UNI_BEARER_P2P) { 440122205Sharti c->type = CALL_P2P; 441122205Sharti 442122205Sharti } else { 443122205Sharti c->type = CALL_LEAF; 444122205Sharti if ((p = uni_create_party(c, &u->u.setup.epref)) == NULL) { 445122205Sharti uni_msg_destroy(api); 446122205Sharti goto clear; 447122205Sharti } 448122205Sharti uni_enq_party(p, SIGP_SETUP, 0, NULL, NULL); 449122205Sharti } 450122205Sharti 451122205Sharti ind->setup.hdr = u->u.hdr; 452122205Sharti copy_msg_setup(&u->u.setup, &ind->setup); 453122205Sharti c->uni->funcs->uni_output(c->uni, c->uni->arg, 454122205Sharti UNIAPI_SETUP_indication, 0, api); 455122205Sharti 456122205Sharti uni_msg_destroy(m); 457122205Sharti UNI_FREE(u); 458122205Sharti 459122205Sharti set_call_state(c, new_state); 460122205Sharti} 461122205Sharti 462122205Sharti/* 463122205Sharti * Setup.request from user 464122205Sharti * 465122205Sharti * Q.2971:Call-Control-U 4/39 (U0) 466122205Sharti * Q.2971:Call-Control-N 4/39 (N0) 467122205Sharti */ 468122205Shartistatic void 469131826Shartiun0_setup_request(struct call *c, struct uni_msg *m, uint32_t cookie, 470122205Sharti enum call_state new_state) 471122205Sharti{ 472122205Sharti struct uniapi_setup_request *arg = 473122205Sharti uni_msg_rptr(m, struct uniapi_setup_request *); 474122205Sharti struct uni_setup *setup = &arg->setup; 475122205Sharti struct uni_all *out; 476122205Sharti struct party *p; 477122205Sharti 478122205Sharti if (!IE_ISGOOD(setup->bearer)) { 479122205Sharti uni_msg_destroy(m); 480122205Sharti uniapi_call_error(c, UNIAPI_ERROR_MISSING_IE, cookie); 481122205Sharti uni_destroy_call(c, 0); 482122205Sharti return; 483122205Sharti } 484122205Sharti if ((out = UNI_ALLOC()) == NULL) { 485122205Sharti uni_msg_destroy(m); 486122205Sharti uniapi_call_error(c, UNIAPI_ERROR_NOMEM, cookie); 487122205Sharti uni_destroy_call(c, 0); 488122205Sharti return; 489122205Sharti } 490122205Sharti 491122205Sharti c->msg_setup = *setup; 492122205Sharti 493122205Sharti if (IE_ISGOOD(setup->connid)) 494122205Sharti c->connid = setup->connid; 495122205Sharti 496122205Sharti if (setup->bearer.cfg == UNI_BEARER_P2P) { 497122205Sharti c->type = CALL_P2P; 498122205Sharti } else { 499122205Sharti c->type = CALL_ROOT; 500122205Sharti 501122205Sharti /* 502122205Sharti * If the user didn't specify a endpoint reference, 503122205Sharti * use 0. Use IE_IGNORE accoring to Appendix II Q.2971 504122205Sharti */ 505122205Sharti if (!IE_ISPRESENT(c->msg_setup.epref)) { 506122205Sharti MK_IE_EPREF(c->msg_setup.epref, 0, 0); 507122205Sharti if (c->uni->proto == UNIPROTO_UNI40N) 508122205Sharti c->msg_setup.epref.h.act = UNI_IEACT_IGNORE; 509122205Sharti 510122205Sharti } else if (!IE_ISGOOD(c->msg_setup.epref)) { 511122205Sharti uni_msg_destroy(m); 512122205Sharti uniapi_call_error(c, UNIAPI_ERROR_BAD_IE, cookie); 513122205Sharti uni_destroy_call(c, 0); 514122205Sharti return; 515122205Sharti } 516122205Sharti if ((p = uni_create_partyx(c, 0, 1, cookie)) == NULL) { 517122205Sharti uni_msg_destroy(m); 518122205Sharti uniapi_call_error(c, UNIAPI_ERROR_NOMEM, cookie); 519122205Sharti uni_destroy_call(c, 0); 520122205Sharti return; 521122205Sharti } 522122205Sharti uni_enq_party(p, SIGP_SETUP_request, cookie, NULL, NULL); 523122205Sharti } 524122205Sharti 525122205Sharti uni_msg_destroy(m); 526122205Sharti 527122205Sharti out->u.setup = c->msg_setup; 528122205Sharti MK_MSG_ORIG(out, UNI_SETUP, c->cref, !c->mine); 529122205Sharti (void)uni_send_output(out, c->uni); 530122205Sharti UNI_FREE(out); 531122205Sharti 532122205Sharti TIMER_START_CALL(c, t303, c->uni->timer303); 533122205Sharti c->cnt303 = 0; 534122205Sharti 535122205Sharti set_call_state(c, new_state); 536122205Sharti 537122205Sharti uniapi_call_error(c, UNIAPI_OK, cookie); 538122205Sharti} 539122205Sharti 540122205Sharti/* 541122205Sharti * CALL PROCEEDING message 542122205Sharti * 543122205Sharti * Q.2971:Call-Control-U 6/39 (in U1) 544122205Sharti * Q.2971:Call-Control-N 11/39 (in N6) 545122205Sharti */ 546122205Shartistatic void 547122205Shartiu1n6_call_proc(struct call *c, struct uni_msg *m, struct uni_all *u, 548122205Sharti enum call_state new_state) 549122205Sharti{ 550122205Sharti struct uni_call_proc *cp = &u->u.call_proc; 551122205Sharti struct uniapi_proceeding_indication *ind; 552122205Sharti struct uni_msg *api; 553122205Sharti 554122205Sharti ind = ALLOC_API(struct uniapi_proceeding_indication, api); 555122205Sharti if (ind == NULL) { 556122205Sharti ignore: 557122205Sharti uni_msg_destroy(m); 558122205Sharti UNI_FREE(u); 559122205Sharti return; 560122205Sharti } 561122205Sharti /* 562122205Sharti * Analyze message 563122205Sharti */ 564122205Sharti (void)uni_decode_body(m, u, &c->uni->cx); 565122205Sharti if (!IE_ISPRESENT(c->connid) && !IE_ISGOOD(cp->connid)) 566122205Sharti uni_mandate_ie(c->uni, UNI_IE_CONNID); 567122205Sharti 568122205Sharti /* 569122205Sharti * Q.2971: L3MU_01_03 requests us to ignore the message if 570122205Sharti * the EPREF is missing. 571122205Sharti */ 572122205Sharti if (c->msg_setup.bearer.cfg == UNI_BEARER_MP && 573122205Sharti IE_ISPRESENT(c->msg_setup.epref)) { 574122205Sharti if (!IE_ISPRESENT(cp->epref)) 575122205Sharti uni_mandate_ie(c->uni, UNI_IE_EPREF); \ 576122205Sharti 577122205Sharti else if (IE_ISGOOD(cp->epref) && 578122205Sharti (cp->epref.flag != 1 || 579122205Sharti cp->epref.epref != c->msg_setup.epref.epref)) { 580122205Sharti IE_SETERROR(cp->epref); 581213789Srpaulo (void)UNI_SAVE_IERR(&c->uni->cx, UNI_IE_EPREF, 582122205Sharti cp->epref.h.act, UNI_IERR_BAD); 583122205Sharti } 584122205Sharti } 585122205Sharti 586122205Sharti switch (uni_verify(c->uni, u->u.hdr.act)) { 587122205Sharti 588122205Sharti case VFY_CLR: 589122205Sharti uni_vfy_collect_ies(c->uni); 590122205Sharti clear_callD(c); 591122205Sharti /* FALLTHRU */ 592122205Sharti case VFY_I: 593122205Sharti uni_msg_destroy(api); 594122205Sharti goto ignore; 595122205Sharti 596122205Sharti case VFY_RAIM: 597122205Sharti case VFY_RAI: 598122205Sharti report: 599122205Sharti uni_respond_status_verify(c->uni, &u->u.hdr.cref, 600122205Sharti map_callstate(c->cstate), NULL, 0); 601122205Sharti uni_msg_destroy(api); 602122205Sharti goto ignore; 603122205Sharti 604122205Sharti case VFY_RAP: 605122205Sharti case VFY_RAPU: 606122205Sharti if (c->type == CALL_ROOT && !IE_ISGOOD(cp->epref)) 607122205Sharti goto report; 608122205Sharti uni_respond_status_verify(c->uni, &u->u.hdr.cref, 609122205Sharti map_callstate(new_state), NULL, 0); 610122205Sharti /* FALLTHRU */ 611122205Sharti case VFY_OK: 612122205Sharti break; 613122205Sharti } 614122205Sharti 615122205Sharti TIMER_STOP_CALL(c, t303); 616122205Sharti 617122205Sharti if (IE_ISGOOD(cp->connid)) 618122205Sharti c->connid = cp->connid; 619122205Sharti 620122205Sharti ind->call_proc.hdr = u->u.hdr; 621122205Sharti copy_msg_call_proc(cp, &ind->call_proc); 622122205Sharti c->uni->funcs->uni_output(c->uni, c->uni->arg, 623122205Sharti UNIAPI_PROCEEDING_indication, 0, api); 624122205Sharti 625122205Sharti TIMER_START_CALL(c, t310, c->uni->timer310); 626122205Sharti 627122205Sharti uni_msg_destroy(m); 628122205Sharti UNI_FREE(u); 629122205Sharti 630122205Sharti set_call_state(c, new_state); 631122205Sharti} 632122205Sharti 633122205Sharti/* 634122205Sharti * T303 tick. 635122205Sharti * 636122205Sharti * Q.2971:Call-Control-U 6/39 637122205Sharti * Q.2971:Call-Control-N 11/39 638122205Sharti */ 639122205Shartistatic void 640122205Shartiu1n6_t303(struct call *c) 641122205Sharti{ 642122205Sharti struct uni_all *msg; 643122205Sharti struct uniapi_release_confirm *conf; 644122205Sharti struct uni_msg *api; 645122205Sharti 646122205Sharti VERBOSE(c->uni, UNI_FAC_TIMEOUT, 1, "call %u/%s T303 tick %d", 647122205Sharti c->cref, c->mine ? "mine" : "his", c->cnt303 + 1); 648122205Sharti 649122205Sharti if (++c->cnt303 < c->uni->init303) { 650122205Sharti if ((msg = UNI_ALLOC()) != NULL) { 651122205Sharti msg->u.setup = c->msg_setup; 652122205Sharti MK_MSG_ORIG(msg, UNI_SETUP, c->cref, !c->mine); 653122205Sharti (void)uni_send_output(msg, c->uni); 654122205Sharti UNI_FREE(msg); 655122205Sharti } 656122205Sharti TIMER_START_CALL(c, t303, c->uni->timer303); 657122205Sharti return; 658122205Sharti } 659122205Sharti 660122205Sharti /* 661122205Sharti * Send indication to API 662122205Sharti */ 663122205Sharti if ((conf = ALLOC_API(struct uniapi_release_confirm, api)) != NULL) { 664122205Sharti conf->release.hdr.cref.cref = c->cref; 665122205Sharti conf->release.hdr.cref.flag = c->mine; 666122205Sharti conf->release.hdr.act = UNI_MSGACT_DEFAULT; 667122205Sharti MK_IE_CAUSE(conf->release.cause[0], UNI_CAUSE_LOC_USER, 668122205Sharti UNI_CAUSE_NO_RESPONSE); 669122205Sharti 670122205Sharti c->uni->funcs->uni_output(c->uni, c->uni->arg, 671122205Sharti UNIAPI_RELEASE_confirm, 0, api); 672122205Sharti } 673122205Sharti 674122205Sharti /* 675122205Sharti * send to party (there may be only one) 676122205Sharti */ 677122205Sharti if (c->type == CALL_ROOT && !TAILQ_EMPTY(&c->parties)) { 678122205Sharti uni_enq_party(TAILQ_FIRST(&c->parties), 679122205Sharti SIGP_RELEASE_confirm, 0, NULL, NULL); 680122205Sharti } 681122205Sharti uni_destroy_call(c, 0); 682122205Sharti} 683122205Sharti 684122205Sharti/* 685122205Sharti * T310 (Call Proceeding) timer tick. 686122205Sharti * 687122205Sharti * Q.2971:Call-Control-U 7/39 688122205Sharti * Q.2971:Call-Control-N 17/39 689122205Sharti */ 690122205Shartistatic void 691122205Shartiu3n9_t310(struct call *c) 692122205Sharti{ 693122205Sharti VERBOSE(c->uni, UNI_FAC_TIMEOUT, 1, "call %u/%s T310 tick", 694122205Sharti c->cref, c->mine ? "mine" : "his"); 695122205Sharti 696122205Sharti MK_IE_CAUSE(c->uni->cause, UNI_CAUSE_LOC_USER, UNI_CAUSE_NO_RESPONSE); 697122205Sharti clear_callD(c); 698122205Sharti} 699122205Sharti 700122205Sharti/* 701122205Sharti * T301 (Alerting) timer tick. 702122205Sharti * 703122205Sharti * Q.2971:Call-Control-U Missing 704122205Sharti * Q.2971:Call-Control-N 14/39 705122205Sharti */ 706122205Shartistatic void 707122205Shartiu4n7_t301(struct call *c) 708122205Sharti{ 709122205Sharti VERBOSE(c->uni, UNI_FAC_TIMEOUT, 1, "call %u/%s T301 tick", 710122205Sharti c->cref, c->mine ? "mine" : "his"); 711122205Sharti 712122205Sharti MK_IE_CAUSE(c->uni->cause, UNI_CAUSE_LOC_USER, UNI_CAUSE_NO_RESP_ALERT); 713122205Sharti clear_callD(c); 714122205Sharti} 715122205Sharti 716122205Sharti/* 717122205Sharti * ALERTING received 718122205Sharti * 719122205Sharti * Q.2971:Call-Control-U 37/39 (U1) 720122205Sharti * Q.2971:Call-Control-U 7/39 (U3) 721122205Sharti * Q.2971:Call-Control-N 9/39 (N6) 722122205Sharti * Q.2971:Call-Control-N 17/39 (N9) 723122205Sharti * 724122205Sharti * There are two errors in the user side SDL Annex A: 725122205Sharti * 726122205Sharti * - the resetted timers are swapped (T310 and T303) 727122205Sharti * 728122205Sharti * - for U1 we should go to C12, not C3 to start T301. 729122205Sharti */ 730122205Shartistatic void 731122205Shartiunx_alerting(struct call *c, struct uni_msg *m, struct uni_all *u, 732122205Sharti enum call_state new_state) 733122205Sharti{ 734122205Sharti struct uni_alerting *al = &u->u.alerting; 735122205Sharti struct uniapi_alerting_indication *ind; 736122205Sharti struct uni_msg *api; 737122205Sharti 738122205Sharti ind = ALLOC_API(struct uniapi_alerting_indication, api); 739122205Sharti if (ind == NULL) { 740122205Sharti ignore: 741122205Sharti uni_msg_destroy(m); 742122205Sharti UNI_FREE(u); 743122205Sharti return; 744122205Sharti } 745122205Sharti 746122205Sharti /* 747122205Sharti * Analyze message 748122205Sharti */ 749122205Sharti (void)uni_decode_body(m, u, &c->uni->cx); 750122205Sharti if (!IE_ISPRESENT(c->connid) && !IE_ISGOOD(al->connid)) 751122205Sharti uni_mandate_ie(c->uni, UNI_IE_CONNID); 752122205Sharti 753122205Sharti /* 754122205Sharti * Q.2971: L3MU_01_04 requests us to ignore the message if the 755122205Sharti * EPREF is missing. 756122205Sharti */ 757122205Sharti if (c->msg_setup.bearer.cfg == UNI_BEARER_MP && 758122205Sharti IE_ISPRESENT(c->msg_setup.epref)) { 759122205Sharti if (!IE_ISPRESENT(al->epref)) 760122205Sharti uni_mandate_ie(c->uni, UNI_IE_EPREF); \ 761122205Sharti 762122205Sharti else if (IE_ISGOOD(al->epref) && 763122205Sharti (al->epref.flag != 1 || 764122205Sharti al->epref.epref != c->msg_setup.epref.epref)) { 765122205Sharti IE_SETERROR(al->epref); 766213789Srpaulo (void)UNI_SAVE_IERR(&c->uni->cx, UNI_IE_EPREF, 767122205Sharti al->epref.h.act, UNI_IERR_BAD); 768122205Sharti } 769122205Sharti } 770122205Sharti 771122205Sharti switch (uni_verify(c->uni, u->u.hdr.act)) { 772122205Sharti 773122205Sharti case VFY_CLR: 774122205Sharti uni_vfy_collect_ies(c->uni); 775122205Sharti clear_callD(c); 776122205Sharti case VFY_I: 777122205Sharti uni_msg_destroy(api); 778122205Sharti goto ignore; 779122205Sharti 780122205Sharti case VFY_RAIM: 781122205Sharti case VFY_RAI: 782122205Sharti report: 783122205Sharti uni_respond_status_verify(c->uni, &u->u.hdr.cref, 784122205Sharti map_callstate(c->cstate), NULL, 0); 785122205Sharti uni_msg_destroy(api); 786122205Sharti goto ignore; 787122205Sharti 788122205Sharti case VFY_RAP: 789122205Sharti case VFY_RAPU: 790122205Sharti if (c->type == CALL_ROOT && !IE_ISGOOD(al->epref)) 791122205Sharti goto report; 792122205Sharti uni_respond_status_verify(c->uni, &u->u.hdr.cref, 793122205Sharti map_callstate(c->cstate), NULL, 0); 794122205Sharti case VFY_OK: 795122205Sharti break; 796122205Sharti } 797122205Sharti 798122205Sharti if (c->cstate == CALLST_U1 || c->cstate == CALLST_N6) 799122205Sharti TIMER_STOP_CALL(c, t303); 800122205Sharti else if (c->cstate == CALLST_U3 || c->cstate == CALLST_N9) 801122205Sharti TIMER_STOP_CALL(c, t310); 802122205Sharti 803122205Sharti if (IE_ISGOOD(al->connid)) 804122205Sharti c->connid = al->connid; 805122205Sharti 806122205Sharti ind->alerting.hdr = u->u.hdr; 807122205Sharti copy_msg_alerting(al, &ind->alerting); 808122205Sharti 809122205Sharti if (c->type == CALL_LEAF || c->type == CALL_ROOT) { 810122205Sharti uni_enq_party(TAILQ_FIRST(&c->parties), SIGP_ALERTING, 811122205Sharti 0, NULL, NULL); 812122205Sharti c->uni->funcs->uni_output(c->uni, c->uni->arg, 813122205Sharti UNIAPI_ALERTING_indication, 0, api); 814122205Sharti } else { 815122205Sharti c->uni->funcs->uni_output(c->uni, c->uni->arg, 816122205Sharti UNIAPI_ALERTING_indication, 0, api); 817122205Sharti TIMER_START_CALL(c, t301, c->uni->timer301); 818122205Sharti } 819122205Sharti UNI_FREE(u); 820122205Sharti uni_msg_destroy(m); 821122205Sharti 822122205Sharti set_call_state(c, new_state); 823122205Sharti} 824122205Sharti 825122205Sharti/* 826122205Sharti * Proceeding.request from API 827122205Sharti * 828122205Sharti * Q.2971:Call-Control-U 12/39 (U6) 829122205Sharti * Q.2971:Call-Control-N 6/39 (N1) 830122205Sharti */ 831122205Shartistatic void 832131826Shartiu6n1_proceeding_request(struct call *c, struct uni_msg *m, uint32_t cookie, 833122205Sharti enum call_state new_state) 834122205Sharti{ 835122205Sharti struct uni_all *msg; 836122205Sharti struct uniapi_proceeding_request *arg = 837122205Sharti uni_msg_rptr(m, struct uniapi_proceeding_request *); 838122205Sharti 839122205Sharti if ((msg = UNI_ALLOC()) == NULL) { 840122205Sharti uni_msg_destroy(m); 841122205Sharti uniapi_call_error(c, UNIAPI_ERROR_NOMEM, cookie); 842122205Sharti return; 843122205Sharti } 844122205Sharti 845122205Sharti if (IE_ISGOOD(arg->call_proc.connid)) 846122205Sharti c->connid = arg->call_proc.connid; 847122205Sharti 848122205Sharti msg->u.call_proc = arg->call_proc; 849122205Sharti MK_MSG_ORIG(msg, UNI_CALL_PROC, c->cref, !c->mine); 850122205Sharti (void)uni_send_output(msg, c->uni); 851122205Sharti UNI_FREE(msg); 852122205Sharti 853122205Sharti set_call_state(c, new_state); 854122205Sharti 855122205Sharti uni_msg_destroy(m); 856122205Sharti 857122205Sharti uniapi_call_error(c, UNIAPI_OK, cookie); 858122205Sharti} 859122205Sharti 860122205Sharti/* 861122205Sharti * Alerting.request from API 862122205Sharti * 863122205Sharti * Q.2971:Call-Control-U 13/39 (U6) 864122205Sharti * Q.2971:Call-Control-U 17/39 (U9) 865122205Sharti * Q.2971:Call-Control-N 38/39 (N1) 866122205Sharti * Q.2971:Call-Control-N 7/39 (N3) 867122205Sharti */ 868122205Shartistatic void 869131826Shartiunx_alerting_request(struct call *c, struct uni_msg *m, uint32_t cookie, 870122205Sharti enum call_state new_state) 871122205Sharti{ 872122205Sharti struct uni_all *msg; 873122205Sharti struct uniapi_alerting_request *arg = 874122205Sharti uni_msg_rptr(m, struct uniapi_alerting_request *); 875122205Sharti 876122205Sharti if ((msg = UNI_ALLOC()) == NULL) { 877122205Sharti uni_msg_destroy(m); 878122205Sharti uniapi_call_error(c, UNIAPI_ERROR_NOMEM, cookie); 879122205Sharti return; 880122205Sharti } 881122205Sharti 882122205Sharti if (c->type == CALL_ROOT || c->type == CALL_LEAF) { 883122205Sharti uni_enq_party(TAILQ_FIRST(&c->parties), 884122205Sharti SIGP_ALERTING_request, cookie, NULL, NULL); 885122205Sharti } 886122205Sharti 887122205Sharti /* 888122205Sharti * It's not really clear, what happens, if we send another 889122205Sharti * connid in CALL_PROC and ALERTING 890122205Sharti */ 891122205Sharti if (!IE_ISGOOD(c->connid) && IE_ISGOOD(arg->alerting.connid)) 892122205Sharti c->connid = arg->alerting.connid; 893122205Sharti 894122205Sharti msg->u.alerting = arg->alerting; 895122205Sharti MK_MSG_ORIG(msg, UNI_ALERTING, c->cref, !c->mine); 896122205Sharti (void)uni_send_output(msg, c->uni); 897122205Sharti UNI_FREE(msg); 898122205Sharti 899122205Sharti set_call_state(c, new_state); 900122205Sharti 901122205Sharti uni_msg_destroy(m); 902122205Sharti 903122205Sharti uniapi_call_error(c, UNIAPI_OK, cookie); 904122205Sharti} 905122205Sharti 906122205Sharti 907122205Sharti/* 908122205Sharti * Setup.response from API 909122205Sharti * 910122205Sharti * Q.2971:Call-Control-U 13/39 (U6) 911122205Sharti * Q.2971:Call-Control-U 14/39 (U7) 912122205Sharti * Q.2971:Call-Control-U 17/39 (U9) 913122205Sharti * Q.2971:Call-Control-N 39/39 (N1) 914122205Sharti * Q.2971:Call-Control-N 7/39 (N3) 915122205Sharti * Q.2971:Call-Control-N 8/39 (N4) 916122205Sharti */ 917122205Shartistatic void 918131826Shartiunx_setup_response(struct call *c, struct uni_msg *m, uint32_t cookie, 919122205Sharti enum call_state new_state) 920122205Sharti{ 921122205Sharti struct uni_all *msg; 922122205Sharti struct uniapi_setup_response *arg = 923122205Sharti uni_msg_rptr(m, struct uniapi_setup_response *); 924122205Sharti struct party *p; 925122205Sharti 926122205Sharti if ((msg = UNI_ALLOC()) == NULL) { 927122205Sharti uni_msg_destroy(m); 928122205Sharti uniapi_call_error(c, UNIAPI_ERROR_NOMEM, cookie); 929122205Sharti return; 930122205Sharti } 931122205Sharti 932122205Sharti if (!IE_ISGOOD(c->connid) && IE_ISGOOD(arg->connect.connid)) 933122205Sharti c->connid = arg->connect.connid; 934122205Sharti 935122205Sharti if (IE_ISGOOD(arg->connect.epref)) { 936122205Sharti p = uni_find_partyx(c, arg->connect.epref.epref, 937122205Sharti !arg->connect.epref.flag); 938122205Sharti if (p == NULL) { 939122205Sharti uniapi_call_error(c, UNIAPI_ERROR_BAD_PARTY, cookie); 940122205Sharti UNI_FREE(msg); 941122205Sharti uni_msg_destroy(m); 942122205Sharti return; 943122205Sharti } 944122205Sharti /* we need to remember that we have sent the CONNECT from this 945122205Sharti * party because the CONNECT ACK must move only this party 946122205Sharti * into P7 */ 947122205Sharti p->flags |= PARTY_CONNECT; 948122205Sharti 949122205Sharti } else if (c->type == CALL_LEAF) { 950131826Sharti /* XXX don't mandate if only one party */ 951122205Sharti uniapi_call_error(c, UNIAPI_ERROR_BAD_PARTY, cookie); 952122205Sharti UNI_FREE(msg); 953122205Sharti uni_msg_destroy(m); 954122205Sharti return; 955122205Sharti } 956122205Sharti 957122205Sharti /* inform the parties on the network side */ 958122205Sharti if (c->uni->proto == UNIPROTO_UNI40N && c->type == CALL_LEAF) 959122205Sharti TAILQ_FOREACH(p, &c->parties, link) 960122205Sharti uni_enq_party(p, SIGP_SETUP_response, 0, NULL, NULL); 961122205Sharti 962122205Sharti msg->u.connect = arg->connect; 963122205Sharti MK_MSG_ORIG(msg, UNI_CONNECT, c->cref, !c->mine); 964122205Sharti (void)uni_send_output(msg, c->uni); 965122205Sharti UNI_FREE(msg); 966122205Sharti 967122205Sharti if (c->uni->proto == UNIPROTO_UNI40U) 968122205Sharti TIMER_START_CALL(c, t313, c->uni->timer313); 969122205Sharti 970122205Sharti set_call_state(c, new_state); 971122205Sharti 972122205Sharti uni_msg_destroy(m); 973122205Sharti 974122205Sharti uniapi_call_error(c, UNIAPI_OK, cookie); 975122205Sharti} 976122205Sharti 977122205Sharti/* 978122205Sharti * Setup_complete.request 979122205Sharti * 980122205Sharti * Q.2971:Call-Control-N 15/39 (N8) 981122205Sharti */ 982122205Shartistatic void 983131826Shartin8_setup_compl_request(struct call *c, struct uni_msg *m, uint32_t cookie, 984122205Sharti enum call_state new_state) 985122205Sharti{ 986122205Sharti struct uni_all *msg; 987122205Sharti struct uniapi_setup_complete_request *arg = 988122205Sharti uni_msg_rptr(m, struct uniapi_setup_complete_request *); 989122205Sharti struct party *p; 990122205Sharti 991122205Sharti if ((msg = UNI_ALLOC()) == NULL) { 992122205Sharti uni_msg_destroy(m); 993122205Sharti uniapi_call_error(c, UNIAPI_ERROR_NOMEM, cookie); 994122205Sharti return; 995122205Sharti } 996122205Sharti 997122205Sharti /* inform the parties on the network side */ 998122205Sharti if (c->uni->proto == UNIPROTO_UNI40N && 999122205Sharti (c->type == CALL_LEAF || c->type == CALL_ROOT)) { 1000122205Sharti TAILQ_FOREACH(p, &c->parties, link) 1001122205Sharti uni_enq_party(p, SIGP_SETUP_COMPL_request, 1002122205Sharti 0, NULL, NULL); 1003122205Sharti } 1004122205Sharti 1005122205Sharti msg->u.connect_ack = arg->connect_ack; 1006122205Sharti MK_MSG_ORIG(msg, UNI_CONNECT_ACK, c->cref, !c->mine); 1007122205Sharti (void)uni_send_output(msg, c->uni); 1008122205Sharti UNI_FREE(msg); 1009122205Sharti 1010122205Sharti set_call_state(c, new_state); 1011122205Sharti 1012122205Sharti uni_msg_destroy(m); 1013122205Sharti 1014122205Sharti uniapi_call_error(c, UNIAPI_OK, cookie); 1015122205Sharti} 1016122205Sharti 1017122205Sharti/* 1018122205Sharti * CONNECT message 1019122205Sharti * 1020122205Sharti * Q.2971:Call-Control-U 7-8/39 (U3) 1021122205Sharti * Q.2971:Call-Control-U 11/39 (U4) 1022122205Sharti * Q.2971:Call-Control-U 37/39 (U1) 1023122205Sharti * Q.2971:Call-Control-N 9-10/39 (N6) 1024122205Sharti * Q.2971:Call-Control-N 14/39 (N7) 1025122205Sharti * Q.2971:Call-Control-N 17/39 (N9) 1026122205Sharti */ 1027122205Shartistatic void 1028122205Shartiunx_connect(struct call *c, struct uni_msg *m, struct uni_all *u, 1029122205Sharti enum call_state new_state) 1030122205Sharti{ 1031122205Sharti struct uni_connect *co = &u->u.connect; 1032122205Sharti struct uniapi_setup_confirm *conf; 1033122205Sharti struct uni_msg *api; 1034122205Sharti struct uni_all *ack; 1035122205Sharti struct party *p; 1036122205Sharti 1037122205Sharti conf = ALLOC_API(struct uniapi_setup_confirm, api); 1038122205Sharti if (conf == NULL) { 1039122205Sharti ignore: 1040122205Sharti UNI_FREE(u); 1041122205Sharti uni_msg_destroy(m); 1042122205Sharti return; 1043122205Sharti } 1044122205Sharti if ((ack = UNI_ALLOC()) == NULL) { 1045122205Sharti uni_msg_destroy(api); 1046122205Sharti goto ignore; 1047122205Sharti } 1048122205Sharti 1049122205Sharti /* 1050122205Sharti * Analyze message 1051122205Sharti */ 1052122205Sharti (void)uni_decode_body(m, u, &c->uni->cx); 1053122205Sharti if (!IE_ISPRESENT(c->connid) && !IE_ISGOOD(co->connid)) 1054122205Sharti uni_mandate_ie(c->uni, UNI_IE_CONNID); 1055122205Sharti 1056122205Sharti /* 1057122205Sharti * Q.2971: L3MU_01_05 requires the epref to be present. 1058122205Sharti */ 1059122205Sharti p = NULL; 1060122205Sharti if (c->msg_setup.bearer.cfg == UNI_BEARER_MP) { 1061122205Sharti if (IE_ISPRESENT(c->msg_setup.epref)) { 1062122205Sharti if (!IE_ISPRESENT(co->epref)) 1063122205Sharti uni_mandate_ie(c->uni, UNI_IE_EPREF); \ 1064122205Sharti 1065122205Sharti if (IE_ISGOOD(co->epref) && 1066122205Sharti co->epref.flag != 1) { 1067122205Sharti IE_SETERROR(co->epref); 1068213789Srpaulo (void)UNI_SAVE_IERR(&c->uni->cx, UNI_IE_EPREF, 1069122205Sharti co->epref.h.act, UNI_IERR_BAD); 1070122205Sharti } 1071122205Sharti } 1072122205Sharti 1073122205Sharti if (IE_ISGOOD(co->epref)) { 1074122205Sharti p = uni_find_party(c, &co->epref); 1075122205Sharti if (p == NULL) { 1076122205Sharti respond_drop_party_ack(c, &co->epref, 1077122205Sharti UNI_CAUSE_ENDP_INV); 1078122205Sharti uni_msg_destroy(api); 1079122205Sharti UNI_FREE(ack); 1080122205Sharti goto ignore; 1081122205Sharti } 1082122205Sharti } 1083122205Sharti } 1084122205Sharti 1085122205Sharti switch (uni_verify(c->uni, u->u.hdr.act)) { 1086122205Sharti 1087122205Sharti case VFY_CLR: 1088122205Sharti uni_vfy_collect_ies(c->uni); 1089122205Sharti clear_callD(c); 1090122205Sharti /* FALLTHRU */ 1091122205Sharti case VFY_I: 1092122205Sharti uni_msg_destroy(api); 1093122205Sharti UNI_FREE(ack); 1094122205Sharti goto ignore; 1095122205Sharti 1096122205Sharti case VFY_RAIM: 1097122205Sharti case VFY_RAI: 1098122205Sharti report: 1099122205Sharti uni_respond_status_verify(c->uni, &u->u.hdr.cref, 1100122205Sharti map_callstate(c->cstate), NULL, 0); 1101122205Sharti uni_msg_destroy(api); 1102122205Sharti UNI_FREE(ack); 1103122205Sharti goto ignore; 1104122205Sharti 1105122205Sharti case VFY_RAP: 1106122205Sharti case VFY_RAPU: 1107122205Sharti if (c->type == CALL_ROOT && !IE_ISGOOD(co->epref)) 1108122205Sharti goto report; 1109122205Sharti uni_respond_status_verify(c->uni, &u->u.hdr.cref, 1110122205Sharti map_callstate(new_state), NULL, 0); 1111122205Sharti /* FALLTHRU */ 1112122205Sharti case VFY_OK: 1113122205Sharti break; 1114122205Sharti } 1115122205Sharti 1116122205Sharti if (IE_ISGOOD(co->connid)) 1117122205Sharti c->connid = co->connid; 1118122205Sharti 1119122205Sharti if (c->cstate == CALLST_U1 || c->cstate == CALLST_N6) 1120122205Sharti TIMER_STOP_CALL(c, t303); 1121122205Sharti else if (c->cstate == CALLST_U3 || c->cstate == CALLST_N9) 1122122205Sharti TIMER_STOP_CALL(c, t310); 1123122205Sharti else if (c->cstate == CALLST_U4 || c->cstate == CALLST_N7) { 1124122205Sharti if(c->type == CALL_P2P) 1125122205Sharti TIMER_STOP_CALL(c, t301); 1126122205Sharti } 1127122205Sharti 1128122205Sharti /* 1129122205Sharti * This is sent to the party only on the user side and only 1130122205Sharti * to the one party in the epref (L3MU_05_03). 1131122205Sharti */ 1132122205Sharti if (c->uni->proto == UNIPROTO_UNI40U && 1133122205Sharti (c->type == CALL_LEAF || c->type == CALL_ROOT)) 1134122205Sharti uni_enq_party(p, SIGP_CONNECT, 0, NULL, NULL); 1135122205Sharti 1136122205Sharti conf->connect.hdr = u->u.hdr; 1137122205Sharti copy_msg_connect(co, &conf->connect); 1138122205Sharti c->uni->funcs->uni_output(c->uni, c->uni->arg, 1139122205Sharti UNIAPI_SETUP_confirm, 0, api); 1140122205Sharti 1141122205Sharti if (c->uni->proto == UNIPROTO_UNI40U) { 1142122205Sharti /* this is left to the application on the network side */ 1143122205Sharti MK_MSG_ORIG(ack, UNI_CONNECT_ACK, c->cref, !c->mine); 1144122205Sharti (void)uni_send_output(ack, c->uni); 1145122205Sharti UNI_FREE(ack); 1146122205Sharti } 1147122205Sharti 1148122205Sharti UNI_FREE(u); 1149122205Sharti uni_msg_destroy(m); 1150122205Sharti 1151122205Sharti set_call_state(c, new_state); 1152122205Sharti} 1153122205Sharti 1154122205Sharti/* 1155122205Sharti * T313 (Connect) timer tick. 1156122205Sharti * 1157122205Sharti * Q.2971:Call-Control-U 15/39 1158122205Sharti */ 1159122205Shartistatic void 1160122205Shartiu8_t313(struct call *c) 1161122205Sharti{ 1162122205Sharti VERBOSE(c->uni, UNI_FAC_TIMEOUT, 1, "call %u/%s T313 tick", 1163122205Sharti c->cref, c->mine ? "mine" : "his"); 1164122205Sharti 1165122205Sharti MK_IE_CAUSE(c->uni->cause, UNI_CAUSE_LOC_USER, UNI_CAUSE_RECOVER); 1166122205Sharti ADD_CAUSE_TIMER(c->uni->cause, "313"); 1167122205Sharti clear_callD(c); 1168122205Sharti} 1169122205Sharti 1170122205Sharti/* 1171122205Sharti * CONNECT ACKNOWLEDGE message in U8 1172122205Sharti * 1173122205Sharti * Q.2971:Call-Control-U 15-16/39 1174122205Sharti */ 1175122205Shartistatic void 1176122205Shartiu8_connect_ack(struct call *c, struct uni_msg *m, struct uni_all *u, 1177122205Sharti enum call_state new_state) 1178122205Sharti{ 1179122205Sharti struct uniapi_setup_complete_indication *ind; 1180122205Sharti struct uni_msg *api; 1181122205Sharti 1182122205Sharti ind = ALLOC_API(struct uniapi_setup_complete_indication, api); 1183122205Sharti if (ind == NULL) { 1184122205Sharti ignore: 1185122205Sharti uni_msg_destroy(m); 1186122205Sharti UNI_FREE(u); 1187122205Sharti return; 1188122205Sharti } 1189122205Sharti 1190122205Sharti /* 1191122205Sharti * Analyze message 1192122205Sharti */ 1193122205Sharti (void)uni_decode_body(m, u, &c->uni->cx); 1194122205Sharti 1195122205Sharti switch (uni_verify(c->uni, u->u.hdr.act)) { 1196122205Sharti 1197122205Sharti case VFY_CLR: 1198122205Sharti uni_vfy_collect_ies(c->uni); 1199122205Sharti clear_callD(c); 1200122205Sharti /* FALLTHRU */ 1201122205Sharti case VFY_I: 1202122205Sharti uni_msg_destroy(api); 1203122205Sharti goto ignore; 1204122205Sharti 1205122205Sharti case VFY_RAIM: 1206122205Sharti case VFY_RAI: 1207122205Sharti uni_respond_status_verify(c->uni, &u->u.hdr.cref, 1208122205Sharti map_callstate(c->cstate), NULL, 0); 1209122205Sharti uni_msg_destroy(api); 1210122205Sharti goto ignore; 1211122205Sharti 1212122205Sharti case VFY_RAP: 1213122205Sharti case VFY_RAPU: 1214122205Sharti uni_respond_status_verify(c->uni, &u->u.hdr.cref, 1215122205Sharti map_callstate(new_state), NULL, 0); 1216122205Sharti /* FALLTHRU */ 1217122205Sharti case VFY_OK: 1218122205Sharti break; 1219122205Sharti } 1220122205Sharti 1221122205Sharti TIMER_STOP_CALL(c, t313); 1222122205Sharti 1223122205Sharti if (c->type == CALL_LEAF) { 1224122205Sharti struct party *p; 1225122205Sharti 1226122205Sharti TAILQ_FOREACH(p, &c->parties, link) { 1227122205Sharti if (p->flags & PARTY_CONNECT) { 1228122205Sharti uni_enq_party(p, SIGP_CONNECT_ACK, 1229122205Sharti 0, NULL, NULL); 1230122205Sharti break; 1231122205Sharti } 1232122205Sharti } 1233122205Sharti } 1234122205Sharti 1235122205Sharti ind->connect_ack.hdr = u->u.hdr; 1236122205Sharti copy_msg_connect_ack(&u->u.connect_ack, &ind->connect_ack); 1237122205Sharti c->uni->funcs->uni_output(c->uni, c->uni->arg, 1238122205Sharti UNIAPI_SETUP_COMPLETE_indication, 0, api); 1239122205Sharti 1240122205Sharti UNI_FREE(u); 1241122205Sharti uni_msg_destroy(m); 1242122205Sharti 1243122205Sharti set_call_state(c, new_state); 1244122205Sharti} 1245122205Sharti 1246122205Sharti/* 1247122205Sharti * CONNECT ACKNOWLEDGE message in N10 1248122205Sharti * 1249122205Sharti * Q.2971:Call-Control-N 18/39 1250122205Sharti */ 1251122205Shartistatic void 1252122205Shartin10_connect_ack(struct call *c, struct uni_msg *m, struct uni_all *u) 1253122205Sharti{ 1254122205Sharti /* 1255122205Sharti * Analyze message 1256122205Sharti */ 1257122205Sharti (void)uni_decode_body(m, u, &c->uni->cx); 1258122205Sharti 1259122205Sharti switch (uni_verify(c->uni, u->u.hdr.act)) { 1260122205Sharti 1261122205Sharti case VFY_CLR: 1262122205Sharti uni_vfy_collect_ies(c->uni); 1263122205Sharti clear_callD(c); 1264122205Sharti /* FALLTHRU */ 1265122205Sharti case VFY_I: 1266122205Sharti uni_msg_destroy(m); 1267122205Sharti UNI_FREE(u); 1268122205Sharti return; 1269122205Sharti 1270122205Sharti case VFY_RAIM: 1271122205Sharti case VFY_RAI: 1272122205Sharti case VFY_RAP: 1273122205Sharti case VFY_RAPU: 1274122205Sharti uni_respond_status_verify(c->uni, &u->u.hdr.cref, 1275122205Sharti map_callstate(c->cstate), NULL, 0); 1276122205Sharti /* FALLTHRU */ 1277122205Sharti case VFY_OK: 1278122205Sharti uni_msg_destroy(m); 1279122205Sharti UNI_FREE(u); 1280122205Sharti return; 1281122205Sharti } 1282122205Sharti} 1283122205Sharti 1284122205Sharti/* 1285122205Sharti * Release.response in U6 or U12. 1286122205Sharti * 1287122205Sharti * Q.2971:Call-Control-U 12/39 (U6) 1288122205Sharti * Q.2971:Call-Control-U 30/39 (U12) 1289122205Sharti * Q.2971:Call-Control-N 6/39 (N1) 1290122205Sharti * Q.2971:Call-Control-N 29/39 (N11) 1291122205Sharti */ 1292122205Shartistatic void 1293131826Shartiunx_release_response(struct call *c, struct uni_msg *m, uint32_t cookie) 1294122205Sharti{ 1295122205Sharti struct party *p; 1296122205Sharti struct uni_all *msg; 1297122205Sharti struct uniapi_release_response *arg = 1298122205Sharti uni_msg_rptr(m, struct uniapi_release_response *); 1299122205Sharti 1300122205Sharti if ((msg = UNI_ALLOC()) == NULL) { 1301122205Sharti uniapi_call_error(c, UNIAPI_ERROR_NOMEM, cookie); 1302122205Sharti uni_msg_destroy(m); 1303122205Sharti return; 1304122205Sharti } 1305122205Sharti 1306122205Sharti if (c->cstate == CALLST_U6 || c->cstate == CALLST_N1) { 1307122205Sharti if (c->type == CALL_ROOT || c->type == CALL_LEAF) { 1308122205Sharti TAILQ_FOREACH(p, &c->parties, link) 1309122205Sharti uni_enq_party(p, SIGP_RELEASE_response, 1310122205Sharti cookie, NULL, NULL); 1311122205Sharti } 1312122205Sharti } 1313122205Sharti msg->u.release_compl = arg->release_compl; 1314122205Sharti MK_MSG_ORIG(msg, UNI_RELEASE_COMPL, c->cref, !c->mine); 1315122205Sharti (void)uni_send_output(msg, c->uni); 1316122205Sharti UNI_FREE(msg); 1317122205Sharti 1318122205Sharti uni_msg_destroy(m); 1319122205Sharti 1320122205Sharti uniapi_call_error(c, UNIAPI_OK, cookie); 1321122205Sharti 1322122205Sharti uni_destroy_call(c, 0); 1323122205Sharti} 1324122205Sharti 1325122205Sharti/* 1326122205Sharti * Got a RELEASE COMPLETE in any state expect U0 1327122205Sharti * 1328122205Sharti * Q.2971:Call-Control-U 25/39 1329122205Sharti * Q.2971:Call-Control-N 26/39 1330122205Sharti * 1331122205Sharti * This is also called from the restart processes. 1332122205Sharti */ 1333122205Shartivoid 1334122205Shartiuni_release_compl(struct call *c, struct uni_all *u) 1335122205Sharti{ 1336122205Sharti struct uni_msg *api; 1337122205Sharti struct uniapi_release_confirm *conf; 1338122205Sharti struct party *p; 1339122205Sharti u_int i, j; 1340122205Sharti 1341122205Sharti if ((conf = ALLOC_API(struct uniapi_release_confirm, api)) == NULL) 1342122205Sharti return; 1343122205Sharti 1344122205Sharti reset_all_timers(c); 1345122205Sharti if (c->type == CALL_ROOT || c->type == CALL_LEAF) { 1346122205Sharti TAILQ_FOREACH(p, &c->parties, link) 1347122205Sharti uni_enq_party(p, SIGP_RELEASE_COMPL, 0, NULL, NULL); 1348122205Sharti /* YYY optional call reoffering 10.3.3/10.3.4 */ 1349122205Sharti } 1350122205Sharti conf->release.hdr = u->u.hdr; 1351122205Sharti 1352122205Sharti for (i = j = 0; i < 2; i++) 1353122205Sharti if (IE_ISGOOD(u->u.release_compl.cause[i])) 1354122205Sharti conf->release.cause[j++] = u->u.release_compl.cause[i]; 1355122205Sharti for (i = j = 0; i < UNI_NUM_IE_GIT; i++) 1356122205Sharti if (IE_ISGOOD(u->u.release_compl.git[i])) 1357122205Sharti conf->release.git[j++] = u->u.release_compl.git[i]; 1358122205Sharti if (IE_ISGOOD(u->u.release_compl.uu)) 1359122205Sharti conf->release.uu = u->u.release_compl.uu; 1360122205Sharti if (IE_ISGOOD(u->u.release_compl.crankback)) 1361122205Sharti conf->release.crankback = u->u.release_compl.crankback; 1362122205Sharti 1363122205Sharti c->uni->funcs->uni_output(c->uni, c->uni->arg, 1364122205Sharti UNIAPI_RELEASE_confirm, 0, api); 1365122205Sharti 1366122205Sharti uni_destroy_call(c, 0); 1367122205Sharti} 1368122205Shartistatic void 1369122205Shartiunx_release_compl(struct call *c, struct uni_msg *m, struct uni_all *u) 1370122205Sharti{ 1371122205Sharti 1372122205Sharti (void)uni_decode_body(m, u, &c->uni->cx); 1373122205Sharti (void)uni_verify(c->uni, u->u.hdr.act); /* no point :-) */ 1374122205Sharti 1375122205Sharti uni_release_compl(c, u); 1376122205Sharti 1377122205Sharti uni_msg_destroy(m); 1378122205Sharti UNI_FREE(u); 1379122205Sharti} 1380122205Sharti 1381122205Sharti/* 1382122205Sharti * Got a RELEASE COMPLETE in any state expect U0 and U11 1383122205Sharti * 1384122205Sharti * Q.2971:Call-Control-U 25/39 1385122205Sharti * Q.2971:Call-Control-N 26/39 1386122205Sharti */ 1387122205Shartistatic void 1388122205Shartiunx_release(struct call *c, struct uni_msg *m, struct uni_all *u, 1389122205Sharti enum call_state new_state) 1390122205Sharti{ 1391122205Sharti struct uniapi_release_indication *ind; 1392122205Sharti struct uni_msg *api; 1393122205Sharti 1394122205Sharti if ((ind = ALLOC_API(struct uniapi_release_indication, api)) == NULL) { 1395122205Sharti uni_msg_destroy(m); 1396122205Sharti UNI_FREE(u); 1397122205Sharti return; 1398122205Sharti } 1399122205Sharti 1400122205Sharti (void)uni_decode_body(m, u, &c->uni->cx); 1401122205Sharti (void)uni_verify(c->uni, u->u.hdr.act); /* no point :-) */ 1402122205Sharti 1403122205Sharti reset_all_timers(c); 1404122205Sharti if (c->type == CALL_ROOT || c->type == CALL_LEAF) { 1405122205Sharti struct party *p; 1406122205Sharti 1407122205Sharti TAILQ_FOREACH(p, &c->parties, link) 1408122205Sharti uni_enq_party(p, SIGP_RELEASE, 0, NULL, NULL); 1409122205Sharti /* YYY optional call reoffering 10.3.3/10.3.4 */ 1410122205Sharti } 1411122205Sharti if (c->cstate != new_state) { 1412122205Sharti /* 1413122205Sharti * According to Q.2971 we should send a 2nd 1414122205Sharti * Release.indication. 1415122205Sharti * According to Q.2931 the recipte of a RELEASE in U12/N11 1416122205Sharti * is illegal. 1417122205Sharti * According to us make it legal, but don't send a 2nd 1418122205Sharti * indication. 1419122205Sharti */ 1420122205Sharti ind->release.hdr = u->u.hdr; 1421122205Sharti copy_msg_release(&u->u.release, &ind->release); 1422122205Sharti 1423122205Sharti c->uni->funcs->uni_output(c->uni, c->uni->arg, 1424122205Sharti UNIAPI_RELEASE_indication, 0, api); 1425122205Sharti } else 1426122205Sharti uni_msg_destroy(api); 1427122205Sharti 1428122205Sharti uni_msg_destroy(m); 1429122205Sharti UNI_FREE(u); 1430122205Sharti 1431122205Sharti set_call_state(c, new_state); 1432122205Sharti} 1433122205Sharti 1434122205Sharti/* 1435122205Sharti * Got RELEASE in U11 or N12 1436122205Sharti * 1437122205Sharti * Q.2971:Call-Control-U 28/39 1438122205Sharti * Q.2971:Call-Control-N 30/39 1439122205Sharti */ 1440122205Shartistatic void 1441122205Shartiu11n12_release(struct call *c, struct uni_msg *m, struct uni_all *u) 1442122205Sharti{ 1443122205Sharti struct uniapi_release_confirm *conf; 1444122205Sharti struct uni_msg *api; 1445122205Sharti 1446122205Sharti if ((conf = ALLOC_API(struct uniapi_release_confirm, api)) == NULL) { 1447122205Sharti uni_msg_destroy(m); 1448122205Sharti UNI_FREE(u); 1449122205Sharti return; 1450122205Sharti } 1451122205Sharti 1452122205Sharti (void)uni_decode_body(m, u, &c->uni->cx); 1453122205Sharti (void)uni_verify(c->uni, u->u.hdr.act); /* no point :-) */ 1454122205Sharti 1455122205Sharti TIMER_STOP_CALL(c, t308); 1456122205Sharti 1457122205Sharti conf->release.hdr = u->u.hdr; 1458122205Sharti copy_msg_release(&u->u.release, &conf->release); 1459122205Sharti 1460122205Sharti c->uni->funcs->uni_output(c->uni, c->uni->arg, 1461122205Sharti UNIAPI_RELEASE_confirm, 0, api); 1462122205Sharti 1463122205Sharti uni_msg_destroy(m); 1464122205Sharti UNI_FREE(u); 1465122205Sharti 1466122205Sharti uni_destroy_call(c, 0); 1467122205Sharti} 1468122205Sharti 1469122205Sharti/* 1470122205Sharti * NOTIFY message 1471122205Sharti * 1472122205Sharti * Q.2971:Call-Control-U 18/39 1473122205Sharti * Q.2971:Call-Control-N 19/39 1474122205Sharti */ 1475122205Shartistatic void 1476122205Shartiunx_notify(struct call *c, struct uni_msg *m, struct uni_all *u) 1477122205Sharti{ 1478122205Sharti struct uniapi_notify_indication *ind; 1479122205Sharti struct uni_msg *api; 1480122205Sharti struct party *p = NULL; 1481122205Sharti 1482122205Sharti if ((ind = ALLOC_API(struct uniapi_notify_indication, api)) == NULL) { 1483122205Sharti ignore: 1484122205Sharti uni_msg_destroy(m); 1485122205Sharti UNI_FREE(u); 1486122205Sharti return; 1487122205Sharti } 1488122205Sharti 1489122205Sharti /* 1490122205Sharti * Analyze message 1491122205Sharti */ 1492122205Sharti (void)uni_decode_body(m, u, &c->uni->cx); 1493122205Sharti MANDATE_IE(c->uni, u->u.notify.notify, UNI_IE_NOTIFY); 1494122205Sharti 1495122205Sharti if (IE_ISGOOD(u->u.notify.epref)) { 1496122205Sharti if ((p = uni_find_party(c, &u->u.notify.epref)) == NULL) { 1497122205Sharti respond_drop_party_ack(c, &u->u.notify.epref, 1498122205Sharti UNI_CAUSE_ENDP_INV); 1499122205Sharti uni_msg_destroy(api); 1500122205Sharti goto ignore; 1501122205Sharti } 1502122205Sharti } 1503122205Sharti 1504122205Sharti switch (uni_verify(c->uni, u->u.hdr.act)) { 1505122205Sharti 1506122205Sharti case VFY_CLR: 1507122205Sharti uni_msg_destroy(api); 1508122205Sharti uni_vfy_collect_ies(c->uni); 1509122205Sharti clear_callD(c); 1510122205Sharti goto ignore; 1511122205Sharti 1512122205Sharti case VFY_RAIM: 1513122205Sharti case VFY_RAI: 1514122205Sharti uni_respond_status_verify(c->uni, &u->u.hdr.cref, 1515122205Sharti map_callstate(c->cstate), &u->u.notify.epref, 1516122205Sharti p ? p->state : 0); 1517122205Sharti /* FALLTHRU */ 1518122205Sharti case VFY_I: 1519122205Sharti uni_msg_destroy(api); 1520122205Sharti goto ignore; 1521122205Sharti 1522122205Sharti case VFY_RAP: 1523122205Sharti case VFY_RAPU: 1524122205Sharti uni_respond_status_verify(c->uni, &u->u.hdr.cref, 1525122205Sharti map_callstate(c->cstate), &u->u.notify.epref, 1526122205Sharti p ? p->state : 0); 1527122205Sharti case VFY_OK: 1528122205Sharti /* FALLTHRU */ 1529122205Sharti break; 1530122205Sharti } 1531122205Sharti 1532122205Sharti ind->notify.hdr = u->u.hdr; 1533122205Sharti copy_msg_notify(&u->u.notify, &ind->notify); 1534122205Sharti c->uni->funcs->uni_output(c->uni, c->uni->arg, 1535122205Sharti UNIAPI_NOTIFY_indication, 0, api); 1536122205Sharti 1537122205Sharti UNI_FREE(u); 1538122205Sharti uni_msg_destroy(m); 1539122205Sharti} 1540122205Sharti 1541122205Sharti/* 1542122205Sharti * Notify.request from user 1543122205Sharti * 1544122205Sharti * Q.2971:Call-Control-U 18/39 1545122205Sharti * Q.2971:Call-Control-N 19/39 1546122205Sharti */ 1547122205Shartistatic void 1548131826Shartiunx_notify_request(struct call *c, struct uni_msg *m, uint32_t cookie) 1549122205Sharti{ 1550122205Sharti struct uni_all *msg; 1551122205Sharti struct uniapi_notify_request *arg = 1552122205Sharti uni_msg_rptr(m, struct uniapi_notify_request *); 1553122205Sharti 1554122205Sharti if ((msg = UNI_ALLOC()) == NULL) { 1555122205Sharti uni_msg_destroy(m); 1556122205Sharti uniapi_call_error(c, UNIAPI_ERROR_NOMEM, cookie); 1557122205Sharti return; 1558122205Sharti } 1559122205Sharti 1560122205Sharti msg->u.notify = arg->notify; 1561122205Sharti MK_MSG_ORIG(msg, UNI_NOTIFY, c->cref, !c->mine); 1562122205Sharti (void)uni_send_output(msg, c->uni); 1563122205Sharti UNI_FREE(msg); 1564122205Sharti 1565122205Sharti uni_msg_destroy(m); 1566122205Sharti 1567122205Sharti uniapi_call_error(c, UNIAPI_OK, cookie); 1568122205Sharti} 1569122205Sharti 1570122205Sharti/**********************************************************************/ 1571122205Sharti 1572122205Sharti/* 1573122205Sharti * Release.request from API in any state except U11, U12, N11, N12 1574122205Sharti * 1575122205Sharti * Q.2971:Call-Control-U 27/39 1576122205Sharti * Q.2971:Call-Control-N 28/39 1577122205Sharti */ 1578122205Shartistatic void 1579131826Shartiunx_release_request(struct call *c, struct uni_msg *m, uint32_t cookie, 1580122205Sharti enum call_state new_state) 1581122205Sharti{ 1582122205Sharti struct uni_all *msg; 1583122205Sharti struct uniapi_release_request *arg = 1584122205Sharti uni_msg_rptr(m, struct uniapi_release_request *); 1585122205Sharti struct party *p; 1586122205Sharti 1587122205Sharti if ((msg = UNI_ALLOC()) == NULL) { 1588122205Sharti uni_msg_destroy(m); 1589122205Sharti uniapi_call_error(c, UNIAPI_ERROR_NOMEM, cookie); 1590122205Sharti return; 1591122205Sharti } 1592122205Sharti 1593122205Sharti reset_all_timers(c); 1594122205Sharti 1595122205Sharti if (c->type == CALL_LEAF || c->type == CALL_ROOT) { 1596122205Sharti TAILQ_FOREACH(p, &c->parties, link) { 1597122205Sharti uni_enq_party(p, SIGP_RELEASE_request, cookie, 1598122205Sharti NULL, NULL); 1599122205Sharti } 1600122205Sharti } 1601122205Sharti 1602122205Sharti c->msg_release = arg->release; 1603122205Sharti if (!IE_ISPRESENT(c->msg_release.cause[0]) && 1604122205Sharti !IE_ISPRESENT(c->msg_release.cause[1])) 1605122205Sharti MK_IE_CAUSE(c->msg_release.cause[0], UNI_CAUSE_LOC_USER, 1606122205Sharti UNI_CAUSE_UNSPEC); 1607122205Sharti 1608122205Sharti msg->u.release = c->msg_release; 1609122205Sharti MK_MSG_ORIG(msg, UNI_RELEASE, c->cref, !c->mine); 1610122205Sharti (void)uni_send_output(msg, c->uni); 1611122205Sharti UNI_FREE(msg); 1612122205Sharti 1613122205Sharti TIMER_START_CALL(c, t308, c->uni->timer308); 1614122205Sharti c->cnt308 = 0; 1615122205Sharti 1616122205Sharti set_call_state(c, new_state); 1617122205Sharti 1618122205Sharti uni_msg_destroy(m); 1619122205Sharti 1620122205Sharti uniapi_call_error(c, UNIAPI_OK, cookie); 1621122205Sharti} 1622122205Sharti 1623122205Sharti/* 1624122205Sharti * Message with unknown EPREF - send a drop party according to 9.5.3.2.3a) 1625122205Sharti */ 1626122205Shartistatic void 1627122205Shartirespond_drop_party_ack(struct call *c, struct uni_ie_epref *epref, 1628122205Sharti u_int cause) 1629122205Sharti{ 1630122205Sharti struct uni_all *msg; 1631122205Sharti 1632122205Sharti if ((msg = UNI_ALLOC()) == NULL) 1633122205Sharti return; 1634122205Sharti 1635122205Sharti MK_MSG_ORIG(msg, UNI_DROP_PARTY_ACK, c->cref, !c->mine); 1636122205Sharti MK_IE_EPREF(msg->u.drop_party_ack.epref, epref->epref, !epref->flag); 1637122205Sharti MK_IE_CAUSE(msg->u.drop_party_ack.cause, UNI_CAUSE_LOC_USER, cause); 1638122205Sharti (void)uni_send_output(msg, c->uni); 1639122205Sharti UNI_FREE(msg); 1640122205Sharti} 1641122205Sharti 1642122205Sharti/* 1643122205Sharti * T308 (RELEASE) timer 1644122205Sharti * 1645122205Sharti * Q.2971:Call-Control-U 28/39 1646122205Sharti * Q.2971:Call-Control-N 30/39 1647122205Sharti */ 1648122205Shartistatic void 1649122205Shartiu11n12_t308(struct call *c) 1650122205Sharti{ 1651122205Sharti struct uni_all *msg; 1652122205Sharti struct uni_msg *api; 1653122205Sharti struct uniapi_release_confirm *conf; 1654122205Sharti 1655122205Sharti VERBOSE(c->uni, UNI_FAC_TIMEOUT, 1, "call %u/%s T308 tick %d", 1656122205Sharti c->cref, c->mine ? "mine" : "his", c->cnt308 + 1); 1657122205Sharti 1658122205Sharti if (++c->cnt308 < c->uni->init308) { 1659122205Sharti if ((msg = UNI_ALLOC()) != NULL) { 1660122205Sharti msg->u.release = c->msg_release; 1661122205Sharti MK_MSG_ORIG(msg, UNI_RELEASE, c->cref, !c->mine); 1662122205Sharti if (!IE_ISPRESENT(msg->u.release.cause[1])) { 1663122205Sharti MK_IE_CAUSE(msg->u.release.cause[1], 1664122205Sharti UNI_CAUSE_LOC_USER, UNI_CAUSE_RECOVER); 1665122205Sharti ADD_CAUSE_TIMER(msg->u.release.cause[1], "308"); 1666122205Sharti } 1667122205Sharti (void)uni_send_output(msg, c->uni); 1668122205Sharti UNI_FREE(msg); 1669122205Sharti } 1670122205Sharti TIMER_START_CALL(c, t308, c->uni->timer308); 1671122205Sharti return; 1672122205Sharti } 1673122205Sharti 1674122205Sharti /* 1675122205Sharti * Send indication to API 1676122205Sharti */ 1677122205Sharti if ((conf = ALLOC_API(struct uniapi_release_confirm, api)) != NULL) { 1678122205Sharti conf->release.hdr.cref.cref = c->cref; 1679122205Sharti conf->release.hdr.cref.flag = c->mine; 1680122205Sharti conf->release.hdr.act = UNI_MSGACT_DEFAULT; 1681122205Sharti MK_IE_CAUSE(conf->release.cause[0], UNI_CAUSE_LOC_USER, 1682122205Sharti UNI_CAUSE_RECOVER); 1683122205Sharti ADD_CAUSE_TIMER(conf->release.cause[0], "308"); 1684122205Sharti 1685122205Sharti c->uni->funcs->uni_output(c->uni, c->uni->arg, 1686122205Sharti UNIAPI_RELEASE_confirm, 0, api); 1687122205Sharti } 1688122205Sharti 1689122205Sharti uni_destroy_call(c, 0); 1690122205Sharti} 1691122205Sharti/**********************************************************************/ 1692122205Sharti 1693122205Sharti/* 1694122205Sharti * STATUS in U11/U12 1695122205Sharti * 1696122205Sharti * Q.2971:Call-Control-U 29/39 (U11) 1697122205Sharti * Q.2971:Call-Control-U 30/39 (U12) 1698122205Sharti * Q.2971:Call-Control-N 29/39 (N11) 1699122205Sharti * Q.2971:Call-Control-N 31/39 (N12) 1700122205Sharti */ 1701122205Shartistatic void 1702122205Shartiun11un12_status(struct call *c, struct uni_msg *m, struct uni_all *u) 1703122205Sharti{ 1704122205Sharti enum call_state ns; 1705122205Sharti struct uniapi_release_confirm *conf; 1706122205Sharti struct uni_msg *api; 1707122205Sharti struct party *p; 1708122205Sharti struct uniapi_status_indication *stat; 1709122205Sharti 1710122205Sharti /* 1711122205Sharti * Analyze message 1712122205Sharti */ 1713122205Sharti (void)uni_decode_body(m, u, &c->uni->cx); 1714122205Sharti MANDATE_IE(c->uni, u->u.status.callstate, UNI_IE_CALLSTATE); 1715122205Sharti MANDATE_IE(c->uni, u->u.status.cause, UNI_IE_CAUSE); 1716122205Sharti 1717122205Sharti ns = c->cstate; 1718122205Sharti if (IE_ISGOOD(u->u.status.callstate) && 1719122205Sharti u->u.status.callstate.state == UNI_CALLSTATE_U0) 1720122205Sharti ns = CALLST_NULL; 1721122205Sharti 1722122205Sharti p = NULL; 1723122205Sharti if (IE_ISGOOD(u->u.status.epref)) 1724122205Sharti p = uni_find_party(c, &u->u.status.epref); 1725122205Sharti 1726122205Sharti switch (uni_verify(c->uni, u->u.hdr.act)) { 1727122205Sharti 1728122205Sharti case VFY_CLR: 1729122205Sharti uni_vfy_collect_ies(c->uni); 1730122205Sharti clear_callD(c); 1731122205Sharti uni_msg_destroy(m); 1732122205Sharti UNI_FREE(u); 1733122205Sharti return; 1734122205Sharti 1735122205Sharti case VFY_RAIM: 1736122205Sharti case VFY_RAI: 1737122205Sharti case VFY_RAP: 1738122205Sharti case VFY_RAPU: 1739122205Sharti uni_respond_status_verify(c->uni, &u->u.hdr.cref, 1740122205Sharti map_callstate(ns), &u->u.status.epref, 1741122205Sharti p ? p->state : UNI_EPSTATE_NULL); 1742122205Sharti case VFY_I: 1743122205Sharti case VFY_OK: 1744122205Sharti break; 1745122205Sharti } 1746122205Sharti 1747122205Sharti if (ns == c->cstate) { 1748122205Sharti /* 1749122205Sharti * Inform API 1750122205Sharti */ 1751122205Sharti stat = ALLOC_API(struct uniapi_status_indication, api); 1752122205Sharti if (stat != NULL) { 1753122205Sharti stat->cref = u->u.hdr.cref; 1754122205Sharti stat->my_state = map_callstate(c->cstate); 1755122205Sharti stat->his_state = u->u.status.callstate; 1756122205Sharti stat->his_cause = u->u.status.cause; 1757122205Sharti stat->epref = u->u.status.epref; 1758122205Sharti stat->epstate = u->u.status.epstate; 1759122205Sharti stat->my_cause = 0; 1760122205Sharti c->uni->funcs->uni_output(c->uni, c->uni->arg, 1761122205Sharti UNIAPI_STATUS_indication, 0, api); 1762122205Sharti } 1763122205Sharti 1764122205Sharti uni_msg_destroy(m); 1765122205Sharti UNI_FREE(u); 1766122205Sharti 1767122205Sharti return; 1768122205Sharti } 1769122205Sharti 1770122205Sharti uni_msg_destroy(m); 1771122205Sharti UNI_FREE(u); 1772122205Sharti 1773122205Sharti /* 1774122205Sharti * Send indication to API 1775122205Sharti */ 1776122205Sharti if ((conf = ALLOC_API(struct uniapi_release_confirm, api)) != NULL) { 1777122205Sharti conf->release.hdr.cref.cref = c->cref; 1778122205Sharti conf->release.hdr.cref.flag = c->mine; 1779122205Sharti conf->release.hdr.act = UNI_MSGACT_DEFAULT; 1780122205Sharti MK_IE_CAUSE(conf->release.cause[0], UNI_CAUSE_LOC_USER, 1781122205Sharti UNI_CAUSE_MSG_INCOMP); 1782122205Sharti ADD_CAUSE_MTYPE(conf->release.cause[0], UNI_STATUS); 1783122205Sharti 1784122205Sharti c->uni->funcs->uni_output(c->uni, c->uni->arg, 1785122205Sharti UNIAPI_RELEASE_confirm, 0, api); 1786122205Sharti } 1787122205Sharti 1788122205Sharti uni_destroy_call(c, 0); 1789122205Sharti} 1790122205Sharti 1791122205Shartistatic int 1792122205Shartistatus_enq_filter(struct sig *sig, void *arg) 1793122205Sharti{ 1794122205Sharti return (sig->type == SIG_CALL && 1795122205Sharti (struct call *)arg == sig->call && 1796122205Sharti sig->sig == SIGC_SEND_STATUS_ENQ); 1797122205Sharti} 1798122205Sharti 1799122205Sharti/* 1800122205Sharti * STATUS in any state except U0/U11/U12 N0/N11/N12 1801122205Sharti * 1802122205Sharti * Q.2971:Call-Control-U 32/39 1803122205Sharti * Q.2971:Call-Control-N 33/39 1804122205Sharti */ 1805122205Shartistatic void 1806122205Shartiunx_status(struct call *c, struct uni_msg *m, struct uni_all *u) 1807122205Sharti{ 1808122205Sharti struct uniapi_status_indication *stat; 1809122205Sharti struct uniapi_release_confirm *conf; 1810122205Sharti enum call_state ns; 1811122205Sharti struct uni_msg *api; 1812122205Sharti struct party *p; 1813122205Sharti 1814122205Sharti /* 1815122205Sharti * Analyze message 1816122205Sharti */ 1817122205Sharti (void)uni_decode_body(m, u, &c->uni->cx); 1818122205Sharti MANDATE_IE(c->uni, u->u.status.callstate, UNI_IE_CALLSTATE); 1819122205Sharti MANDATE_IE(c->uni, u->u.status.cause, UNI_IE_CAUSE); 1820122205Sharti 1821122205Sharti ns = c->cstate; 1822122205Sharti if (IE_ISGOOD(u->u.status.callstate)) 1823122205Sharti ns = state_compat(c, u->u.status.callstate.state); 1824122205Sharti 1825122205Sharti p = NULL; 1826122205Sharti if (IE_ISGOOD(u->u.status.epref)) { 1827122205Sharti p = uni_find_party(c, &u->u.status.epref); 1828122205Sharti MANDATE_IE(c->uni, u->u.status.epstate, UNI_IE_EPSTATE); 1829122205Sharti } 1830122205Sharti 1831122205Sharti switch (uni_verify(c->uni, u->u.hdr.act)) { 1832122205Sharti 1833122205Sharti case VFY_CLR: 1834122205Sharti uni_vfy_collect_ies(c->uni); 1835122205Sharti clear_callD(c); 1836122205Sharti uni_msg_destroy(m); 1837122205Sharti UNI_FREE(u); 1838122205Sharti return; 1839122205Sharti 1840122205Sharti case VFY_RAIM: 1841122205Sharti case VFY_RAI: 1842122205Sharti case VFY_RAP: 1843122205Sharti case VFY_RAPU: 1844122205Sharti uni_respond_status_verify(c->uni, &u->u.hdr.cref, 1845122205Sharti map_callstate(ns), &u->u.notify.epref, 1846122205Sharti p ? p->state : UNI_EPSTATE_NULL); 1847122205Sharti /* FALLTHRU */ 1848122205Sharti case VFY_I: 1849122205Sharti case VFY_OK: 1850122205Sharti break; 1851122205Sharti } 1852122205Sharti 1853122205Sharti if (u->u.status.callstate.state == UNI_CALLSTATE_U0) { 1854122205Sharti /* release_complete */ 1855122205Sharti uni_msg_destroy(m); 1856122205Sharti UNI_FREE(u); 1857122205Sharti 1858122205Sharti if (c->type == CALL_LEAF || c->type == CALL_ROOT) { 1859122205Sharti TAILQ_FOREACH(p, &c->parties, link) 1860122205Sharti uni_enq_party(p, SIGP_RELEASE_COMPL, 1861122205Sharti 0, NULL, NULL); 1862122205Sharti } 1863122205Sharti /* 1864122205Sharti * Send indication to API 1865122205Sharti */ 1866122205Sharti conf = ALLOC_API(struct uniapi_release_confirm, api); 1867122205Sharti if (conf != NULL) { 1868122205Sharti conf->release.hdr.cref.cref = c->cref; 1869122205Sharti conf->release.hdr.cref.flag = c->mine; 1870122205Sharti conf->release.hdr.act = UNI_MSGACT_DEFAULT; 1871122205Sharti MK_IE_CAUSE(conf->release.cause[0], UNI_CAUSE_LOC_USER, 1872122205Sharti UNI_CAUSE_MSG_INCOMP); 1873122205Sharti ADD_CAUSE_MTYPE(conf->release.cause[0], UNI_STATUS); 1874122205Sharti 1875122205Sharti c->uni->funcs->uni_output(c->uni, c->uni->arg, 1876122205Sharti UNIAPI_RELEASE_confirm, 0, api); 1877122205Sharti } 1878122205Sharti uni_destroy_call(c, 0); 1879122205Sharti return; 1880122205Sharti } 1881122205Sharti 1882122205Sharti if (IE_ISGOOD(u->u.status.cause) && 1883122205Sharti u->u.status.cause.cause == UNI_CAUSE_STATUS) { 1884122205Sharti c->se_active = 0; 1885122205Sharti TIMER_STOP_CALL(c, t322); 1886122205Sharti uni_undel(c->uni, status_enq_filter, c); 1887122205Sharti } 1888122205Sharti 1889122205Sharti /* 1890122205Sharti * Inform API 1891122205Sharti */ 1892122205Sharti if ((stat = ALLOC_API(struct uniapi_status_indication, api)) != NULL) { 1893122205Sharti stat->cref = u->u.hdr.cref; 1894122205Sharti stat->my_state = map_callstate(c->cstate); 1895122205Sharti stat->his_state = u->u.status.callstate; 1896122205Sharti stat->his_cause = u->u.status.cause; 1897122205Sharti stat->epref = u->u.status.epref; 1898122205Sharti stat->epstate = u->u.status.epstate; 1899122205Sharti } 1900122205Sharti 1901122205Sharti if (ns == c->cstate) { 1902122205Sharti /* compatible or recovered */ 1903122205Sharti if (p != NULL) 1904122205Sharti uni_enq_party(p, SIGP_STATUS, 0, m, u); 1905122205Sharti else { 1906122205Sharti if (IE_ISGOOD(u->u.status.epref) && 1907122205Sharti (!IE_ISGOOD(u->u.status.epstate) || 1908122205Sharti u->u.status.epstate.state != UNI_EPSTATE_NULL)) 1909122205Sharti respond_drop_party_ack(c, &u->u.status.epref, 1910122205Sharti UNI_CAUSE_MSG_INCOMP); 1911122205Sharti 1912122205Sharti uni_msg_destroy(m); 1913122205Sharti UNI_FREE(u); 1914122205Sharti } 1915122205Sharti if (stat != NULL) { 1916122205Sharti stat->my_cause = 0; 1917122205Sharti c->uni->funcs->uni_output(c->uni, c->uni->arg, 1918122205Sharti UNIAPI_STATUS_indication, 0, api); 1919122205Sharti } 1920122205Sharti 1921122205Sharti return; 1922122205Sharti } 1923122205Sharti 1924122205Sharti /* incompatible */ 1925122205Sharti if (stat != NULL) { 1926122205Sharti stat->my_cause = UNI_CAUSE_MSG_INCOMP; 1927122205Sharti c->uni->funcs->uni_output(c->uni, c->uni->arg, 1928122205Sharti UNIAPI_STATUS_indication, 0, api); 1929122205Sharti } 1930122205Sharti 1931122205Sharti MK_IE_CAUSE(c->uni->cause, UNI_CAUSE_LOC_USER, UNI_CAUSE_MSG_INCOMP); 1932122205Sharti 1933122205Sharti uni_msg_destroy(m); 1934122205Sharti UNI_FREE(u); 1935122205Sharti 1936122205Sharti clear_callD(c); 1937122205Sharti} 1938122205Sharti 1939122205Sharti/* 1940122205Sharti * Enquiry peer status 1941122205Sharti * 1942122205Sharti * Q.2971:Call-Control-U 31/39 1943122205Sharti * Q.2971:Call-Control-N 32/39 1944122205Sharti */ 1945122205Shartistatic void 1946131826Shartiunx_status_enquiry_request(struct call *c, struct uni_msg *msg, uint32_t cookie) 1947122205Sharti{ 1948122205Sharti struct uniapi_status_enquiry_request *arg = 1949122205Sharti uni_msg_rptr(msg, struct uniapi_status_enquiry_request *); 1950122205Sharti struct party *p; 1951122205Sharti struct uni_all *stat; 1952122205Sharti 1953122205Sharti if (c->se_active) { 1954122205Sharti /* This case is not handled in the SDLs */ 1955122205Sharti uniapi_call_error(c, UNIAPI_ERROR_BUSY, cookie); 1956122205Sharti uni_msg_destroy(msg); 1957122205Sharti return; 1958122205Sharti } 1959122205Sharti if ((c->type == CALL_ROOT || c->type == CALL_LEAF) && 1960122205Sharti IE_ISGOOD(arg->epref)) { 1961122205Sharti if ((p = uni_find_partyx(c, arg->epref.epref, !arg->epref.flag)) 1962122205Sharti == NULL) { 1963122205Sharti uniapi_call_error(c, UNIAPI_ERROR_BAD_PARTY, cookie); 1964122205Sharti uni_msg_destroy(msg); 1965122205Sharti return; 1966122205Sharti } 1967122205Sharti uni_msg_destroy(msg); 1968122205Sharti uni_enq_party(p, SIGP_STATUS_ENQUIRY_request, cookie, 1969122205Sharti NULL, NULL); 1970122205Sharti return; 1971122205Sharti } 1972122205Sharti if ((stat = UNI_ALLOC()) == NULL) { 1973122205Sharti uniapi_call_error(c, UNIAPI_ERROR_NOMEM, cookie); 1974122205Sharti uni_msg_destroy(msg); 1975122205Sharti return; 1976122205Sharti } 1977122205Sharti memset(&c->stat_epref, 0, sizeof(c->stat_epref)); 1978122205Sharti MK_MSG_ORIG(stat, UNI_STATUS_ENQ, c->cref, !c->mine); 1979122205Sharti (void)uni_send_output(stat, c->uni); 1980122205Sharti UNI_FREE(stat); 1981122205Sharti 1982122205Sharti TIMER_START_CALL(c, t322, c->uni->timer322); 1983122205Sharti c->cnt322 = 0; 1984122205Sharti c->se_active = 1; 1985122205Sharti 1986122205Sharti uniapi_call_error(c, UNIAPI_OK, cookie); 1987122205Sharti} 1988122205Sharti 1989122205Sharti/* 1990122205Sharti * T322 tick 1991122205Sharti * 1992122205Sharti * Q.2971:Call-Control-U 34/39 1993122205Sharti * Q.2971:Call-Control-N 35/39 1994122205Sharti */ 1995122205Shartistatic void 1996122205Shartiunx_t322(struct call *c) 1997122205Sharti{ 1998122205Sharti struct uni_all *stat; 1999122205Sharti 2000122205Sharti VERBOSE(c->uni, UNI_FAC_TIMEOUT, 1, "call %u/%s T322 tick %d", 2001122205Sharti c->cref, c->mine ? "mine" : "his", c->cnt322 + 1); 2002122205Sharti 2003122205Sharti if (++c->cnt322 < c->uni->init322) { 2004122205Sharti if ((stat = UNI_ALLOC()) != NULL) { 2005122205Sharti MK_MSG_ORIG(stat, UNI_STATUS_ENQ, c->cref, !c->mine); 2006122205Sharti stat->u.status_enq.epref = c->stat_epref; 2007122205Sharti (void)uni_send_output(stat, c->uni); 2008122205Sharti UNI_FREE(stat); 2009122205Sharti } 2010122205Sharti TIMER_START_CALL(c, t322, c->uni->timer322); 2011122205Sharti return; 2012122205Sharti } 2013122205Sharti c->se_active = 0; 2014122205Sharti 2015122205Sharti MK_IE_CAUSE(c->uni->cause, UNI_CAUSE_LOC_USER, UNI_CAUSE_RECOVER); 2016122205Sharti ADD_CAUSE_TIMER(c->uni->cause, "322"); 2017122205Sharti 2018122205Sharti clear_callD(c); 2019122205Sharti} 2020122205Sharti 2021122205Sharti/* 2022122205Sharti * STATUS ENQUIRY message 2023122205Sharti * 2024122205Sharti * Q.2971:Call-Control-U 31/39 2025122205Sharti * Q.2971:Call-Control-N 32/39 2026122205Sharti */ 2027122205Shartistatic void 2028122205Shartiunx_status_enq(struct call *c, struct uni_msg *m, struct uni_all *u) 2029122205Sharti{ 2030122205Sharti struct party *p = NULL; 2031122205Sharti u_int epref, flag; 2032122205Sharti 2033122205Sharti /* 2034122205Sharti * Analyze message 2035122205Sharti */ 2036122205Sharti (void)uni_decode_body(m, u, &c->uni->cx); 2037122205Sharti 2038122205Sharti switch (uni_verify(c->uni, u->u.hdr.act)) { 2039122205Sharti 2040122205Sharti case VFY_CLR: 2041122205Sharti uni_vfy_collect_ies(c->uni); 2042122205Sharti clear_callD(c); 2043122205Sharti uni_msg_destroy(m); 2044122205Sharti UNI_FREE(u); 2045122205Sharti return; 2046122205Sharti 2047122205Sharti case VFY_RAIM: 2048122205Sharti case VFY_RAI: 2049122205Sharti case VFY_RAP: 2050122205Sharti case VFY_RAPU: 2051122205Sharti case VFY_I: 2052122205Sharti case VFY_OK: 2053122205Sharti break; 2054122205Sharti } 2055122205Sharti 2056122205Sharti uni_msg_destroy(m); 2057122205Sharti 2058122205Sharti if ((c->type == CALL_ROOT || c->type == CALL_LEAF) && 2059122205Sharti IE_ISGOOD(u->u.status_enq.epref)) { 2060122205Sharti p = uni_find_party(c, &u->u.status_enq.epref); 2061122205Sharti 2062122205Sharti epref = u->u.status_enq.epref.epref; 2063122205Sharti flag = u->u.status_enq.epref.flag; 2064122205Sharti memset(u, 0, sizeof(*u)); 2065122205Sharti MK_IE_EPREF(u->u.status.epref, epref, !flag); 2066122205Sharti 2067122205Sharti if (p != NULL) 2068122205Sharti MK_IE_EPSTATE(u->u.status.epstate, p->state); 2069122205Sharti else 2070122205Sharti MK_IE_EPSTATE(u->u.status.epstate, UNI_EPSTATE_NULL); 2071122205Sharti } else 2072122205Sharti memset(u, 0, sizeof(*u)); 2073122205Sharti 2074122205Sharti 2075122205Sharti MK_MSG_ORIG(u, UNI_STATUS, c->cref, !c->mine); 2076122205Sharti MK_IE_CALLSTATE(u->u.status.callstate, map_callstate(c->cstate)); 2077122205Sharti MK_IE_CAUSE(u->u.status.cause, UNI_CAUSE_LOC_USER, UNI_CAUSE_STATUS); 2078122205Sharti (void)uni_send_output(u, c->uni); 2079122205Sharti UNI_FREE(u); 2080122205Sharti} 2081122205Sharti 2082122205Sharti/**********************************************************************/ 2083122205Sharti 2084122205Sharti/* 2085122205Sharti * Link-release.indication from SAAL in state U10 or N10. 2086122205Sharti * 2087122205Sharti * Q.2971:Call-Control-U 19/39 2088122205Sharti * Q.2971:Call-Control-N 20/39 2089122205Sharti */ 2090122205Shartistatic void 2091122205Shartiun10_link_release_indication(struct call *c) 2092122205Sharti{ 2093122205Sharti struct party *p; 2094122205Sharti 2095122205Sharti if (c->type == CALL_LEAF || c->type == CALL_ROOT) 2096122205Sharti TAILQ_FOREACH(p, &c->parties, link) { 2097122205Sharti if (p->state != UNI_EPSTATE_ACTIVE) 2098122205Sharti uni_enq_party(p, SIGP_RELEASE_COMPL, 2099122205Sharti 0, NULL, NULL); 2100122205Sharti } 2101122205Sharti 2102122205Sharti uni_enq_coord(c->uni, SIGO_LINK_ESTABLISH_request, 0, NULL); 2103122205Sharti} 2104122205Sharti 2105122205Sharti/* 2106122205Sharti * Link-release.indication from SAAL in all state except U10 and N10. 2107122205Sharti * 2108122205Sharti * Q.2971:Call-Control-U 36/39 2109122205Sharti * Q.2971:Call-Control-N 37/39 2110122205Sharti */ 2111122205Shartistatic void 2112122205Shartiunx_link_release_indication(struct call *c) 2113122205Sharti{ 2114122205Sharti struct uniapi_release_confirm *conf; 2115122205Sharti struct uni_msg *api; 2116122205Sharti struct party *p; 2117122205Sharti 2118122205Sharti if (c->type == CALL_LEAF || c->type == CALL_ROOT) 2119122205Sharti TAILQ_FOREACH(p, &c->parties, link) 2120122205Sharti uni_enq_party(p, SIGP_RELEASE_COMPL, 0, NULL, NULL); 2121122205Sharti 2122122205Sharti if ((conf = ALLOC_API(struct uniapi_release_confirm, api)) != NULL) { 2123122205Sharti conf->release.hdr.cref.cref = c->cref; 2124122205Sharti conf->release.hdr.cref.flag = c->mine; 2125122205Sharti conf->release.hdr.act = UNI_MSGACT_DEFAULT; 2126122205Sharti MK_IE_CAUSE(conf->release.cause[0], UNI_CAUSE_LOC_USER, 2127122205Sharti UNI_CAUSE_DST_OOO); 2128122205Sharti 2129122205Sharti c->uni->funcs->uni_output(c->uni, c->uni->arg, 2130122205Sharti UNIAPI_RELEASE_confirm, 0, api); 2131122205Sharti } 2132122205Sharti 2133122205Sharti uni_destroy_call(c, 0); 2134122205Sharti} 2135122205Sharti 2136122205Sharti/* 2137122205Sharti * Failed to establish SAAL link. Can happen only in U10 or N10. 2138122205Sharti * 2139122205Sharti * Q.2971:Call-Control-U 19/39 2140122205Sharti * Q.2971:Call-Control-N 20/39 2141122205Sharti */ 2142122205Shartistatic void 2143122205Shartiun10_link_establish_error_indication(struct call *c) 2144122205Sharti{ 2145122205Sharti struct party *p; 2146122205Sharti struct uni_msg *api; 2147122205Sharti struct uniapi_release_confirm *conf; 2148122205Sharti 2149122205Sharti if (c->type == CALL_LEAF || c->type == CALL_ROOT) 2150122205Sharti TAILQ_FOREACH(p, &c->parties, link) 2151122205Sharti uni_enq_party(p, SIGP_RELEASE_COMPL, 0, NULL, NULL); 2152122205Sharti 2153122205Sharti if ((conf = ALLOC_API(struct uniapi_release_confirm, api)) != NULL) { 2154122205Sharti conf->release.hdr.cref.cref = c->cref; 2155122205Sharti conf->release.hdr.cref.flag = c->mine; 2156122205Sharti conf->release.hdr.act = UNI_MSGACT_DEFAULT; 2157122205Sharti MK_IE_CAUSE(conf->release.cause[0], UNI_CAUSE_LOC_USER, 2158122205Sharti UNI_CAUSE_DST_OOO); 2159122205Sharti 2160122205Sharti c->uni->funcs->uni_output(c->uni, c->uni->arg, 2161122205Sharti UNIAPI_RELEASE_confirm, 0, api); 2162122205Sharti } 2163122205Sharti 2164122205Sharti uni_destroy_call(c, 0); 2165122205Sharti} 2166122205Sharti 2167122205Sharti/* 2168122205Sharti * Issue a STATUS ENQUIRY of we are not busy 2169122205Sharti * 2170122205Sharti * Q.2971: Call-Control-U: 34/39 2171122205Sharti * Q.2971: Call-Control-N: 34/39 2172122205Sharti */ 2173122205Shartistatic void 2174122205Sharticall_se(struct call *c) 2175122205Sharti{ 2176122205Sharti struct uni_all *stat; 2177122205Sharti 2178122205Sharti c->cnt322 = 0; 2179122205Sharti if (c->se_active) 2180122205Sharti return; 2181122205Sharti 2182122205Sharti memset(&c->stat_epref, 0, sizeof(c->stat_epref)); 2183122205Sharti if ((stat = UNI_ALLOC()) != NULL) { 2184122205Sharti MK_MSG_ORIG(stat, UNI_STATUS_ENQ, c->cref, !c->mine); 2185122205Sharti (void)uni_send_output(stat, c->uni); 2186122205Sharti UNI_FREE(stat); 2187122205Sharti } 2188122205Sharti 2189122205Sharti TIMER_START_CALL(c, t322, c->uni->timer322); 2190122205Sharti c->se_active = 1; 2191122205Sharti} 2192122205Sharti 2193122205Sharti/* 2194122205Sharti * Link-establish.indication in U10 2195122205Sharti * 2196122205Sharti * Q.2971:Call-Control-U 19-20/39 2197122205Sharti * Q.2971:Call-Control-N 20-22/39 2198122205Sharti */ 2199122205Shartistatic void 2200122205Shartiun10_link_establish_indication(struct call *c) 2201122205Sharti{ 2202122205Sharti int act = 0; 2203122205Sharti struct party *p; 2204122205Sharti 2205122205Sharti if (c->type == CALL_ROOT || c->type == CALL_LEAF) { 2206122205Sharti TAILQ_FOREACH(p, &c->parties, link) 2207122205Sharti if (p->state == UNI_EPSTATE_ACTIVE) { 2208122205Sharti act = 1; 2209122205Sharti uni_enq_party(p, SIGP_STATUS_ENQUIRY_request, 2210122205Sharti 0, NULL, NULL); 2211122205Sharti } 2212122205Sharti if (act) 2213122205Sharti return; 2214122205Sharti } 2215122205Sharti call_se(c); 2216122205Sharti} 2217122205Sharti 2218122205Sharti/* 2219122205Sharti * Link-establish.indication in NOT U10/U11/U12 N10/N11/N12 2220122205Sharti * 2221122205Sharti * Q.2971:Call-Control-U 36/39 2222122205Sharti * Q.2971:Call-Control-N 37/39 2223122205Sharti */ 2224122205Shartistatic void 2225122205Shartiunx_link_establish_indication(struct call *c) 2226122205Sharti{ 2227122205Sharti call_se(c); 2228122205Sharti} 2229122205Sharti 2230122205Sharti/* 2231122205Sharti * Link-establish.confirm in U10 or N10 2232122205Sharti * 2233122205Sharti * Q.2971:Call-Control-U 19/39 2234122205Sharti * Q.2971:Call-Control-N 20/39 2235122205Sharti */ 2236122205Shartistatic void 2237122205Shartiun10_link_establish_confirm(struct call *c) 2238122205Sharti{ 2239122205Sharti struct party *p; 2240122205Sharti 2241122205Sharti if (c->type == CALL_ROOT || c->type == CALL_LEAF) { 2242122205Sharti TAILQ_FOREACH(p, &c->parties, link) 2243122205Sharti uni_enq_party(p, SIGP_STATUS_ENQUIRY_request, 2244122205Sharti 0, NULL, NULL); 2245122205Sharti return; 2246122205Sharti } 2247122205Sharti 2248122205Sharti call_se(c); 2249122205Sharti} 2250122205Sharti 2251122205Sharti/* 2252122205Sharti * STATUS ENQ from party 2253122205Sharti * 2254122205Sharti * Q.2971:Call-Control-U 21/39 2255122205Sharti * Q.2971:Call-Control-U 25/39 2256122205Sharti */ 2257122205Shartistatic void 2258122205Shartiunx_send_party_status_enq(struct call *c, struct uni_all *u) 2259122205Sharti{ 2260122205Sharti if (c->se_active) { 2261122205Sharti uni_delenq_sig(c->uni, SIG_CALL, c, NULL, 2262122205Sharti SIGC_SEND_STATUS_ENQ, 0, NULL, u); 2263122205Sharti return; 2264122205Sharti } 2265122205Sharti 2266122205Sharti c->stat_epref = u->u.status_enq.epref; 2267122205Sharti (void)uni_send_output(u, c->uni); 2268122205Sharti UNI_FREE(u); 2269122205Sharti 2270122205Sharti TIMER_START_CALL(c, t322, c->uni->timer322); 2271122205Sharti c->se_active = 1; 2272122205Sharti} 2273122205Sharti 2274122205Sharti/**********************************************************************/ 2275122205Sharti 2276122205Shartistatic void 2277122205Shartimake_drop_cause(struct call *c, struct uni_ie_cause *cause) 2278122205Sharti{ 2279122205Sharti 2280122205Sharti if (!IE_ISGOOD(*cause)) { 2281122205Sharti /* 9.5.7.1 paragraph 2 */ 2282122205Sharti if (IE_ISPRESENT(*cause)) 2283122205Sharti MK_IE_CAUSE(c->uni->cause, UNI_CAUSE_LOC_USER, 2284122205Sharti UNI_CAUSE_IE_INV); 2285122205Sharti else 2286122205Sharti MK_IE_CAUSE(c->uni->cause, UNI_CAUSE_LOC_USER, 2287122205Sharti UNI_CAUSE_MANDAT); 2288122205Sharti c->uni->cause.u.ie.len = 1; 2289122205Sharti c->uni->cause.u.ie.ie[0] = UNI_IE_CAUSE; 2290122205Sharti c->uni->cause.h.present |= UNI_CAUSE_IE_P; 2291122205Sharti 2292122205Sharti } else if (!IE_ISGOOD(c->uni->cause)) 2293122205Sharti c->uni->cause = *cause; 2294122205Sharti} 2295122205Sharti 2296122205Sharti/* 2297122205Sharti * Drop-party.indication from Party-Control in any state. 2298122205Sharti * 2299122205Sharti * Q.2971:Call-Control-U 23/39 2300122205Sharti */ 2301122205Shartistatic void 2302122205Shartiux_drop_party_indication(struct call *c, struct uni_msg *api) 2303122205Sharti{ 2304122205Sharti struct uniapi_drop_party_indication *drop = 2305122205Sharti uni_msg_rptr(api, struct uniapi_drop_party_indication *); 2306122205Sharti 2307122205Sharti if (uni_party_act_count(c, 2) == 0) { 2308122205Sharti if (c->cstate != CALLST_U11) { 2309122205Sharti make_drop_cause(c, &drop->drop.cause); 2310122205Sharti clear_callD(c); 2311122205Sharti } 2312122205Sharti uni_msg_destroy(api); 2313122205Sharti return; 2314122205Sharti } 2315122205Sharti c->uni->funcs->uni_output(c->uni, c->uni->arg, 2316122205Sharti UNIAPI_DROP_PARTY_indication, 0, api); 2317122205Sharti} 2318122205Sharti 2319122205Sharti/* 2320122205Sharti * Drop-party.indication from Party-Control in any state. 2321122205Sharti * 2322122205Sharti * Q.2971:Call-Control-N 23/39 2323122205Sharti */ 2324122205Shartistatic void 2325122205Shartinx_drop_party_indication(struct call *c, struct uni_msg *api) 2326122205Sharti{ 2327122205Sharti struct uniapi_drop_party_indication *drop = 2328122205Sharti uni_msg_rptr(api, struct uniapi_drop_party_indication *); 2329122205Sharti 2330122205Sharti if (uni_party_act_count(c, 0) == 0) { 2331122205Sharti if (uni_party_act_count(c, 1) == 0) { 2332122205Sharti if (c->cstate != CALLST_U11) { 2333122205Sharti make_drop_cause(c, &drop->drop.cause); 2334122205Sharti clear_callD(c); 2335122205Sharti } 2336122205Sharti uni_msg_destroy(api); 2337122205Sharti } else { 2338122205Sharti c->uni->funcs->uni_output(c->uni, c->uni->arg, 2339122205Sharti UNIAPI_DROP_PARTY_indication, 0, api); 2340122205Sharti set_call_state(c, CALLST_N7); 2341122205Sharti } 2342122205Sharti } else { 2343122205Sharti c->uni->funcs->uni_output(c->uni, c->uni->arg, 2344122205Sharti UNIAPI_DROP_PARTY_indication, 0, api); 2345122205Sharti } 2346122205Sharti} 2347122205Sharti 2348122205Sharti/* 2349122205Sharti * Drop-party-ack.indication from Party-Control in any state. 2350122205Sharti * 2351122205Sharti * Q.2971:Call-Control-U 23/39 2352122205Sharti */ 2353122205Shartistatic void 2354122205Shartiux_drop_party_ack_indication(struct call *c, struct uni_msg *api) 2355122205Sharti{ 2356122205Sharti struct uniapi_drop_party_ack_indication *drop = 2357122205Sharti uni_msg_rptr(api, struct uniapi_drop_party_ack_indication *); 2358122205Sharti 2359122205Sharti if (uni_party_act_count(c, 2) == 0) { 2360122205Sharti if (c->cstate != CALLST_U11) { 2361122205Sharti make_drop_cause(c, &drop->drop.cause); 2362122205Sharti clear_callD(c); 2363122205Sharti } 2364122205Sharti uni_msg_destroy(api); 2365122205Sharti return; 2366122205Sharti } 2367122205Sharti c->uni->funcs->uni_output(c->uni, c->uni->arg, 2368122205Sharti UNIAPI_DROP_PARTY_ACK_indication, 0, api); 2369122205Sharti} 2370122205Sharti 2371122205Sharti/* 2372122205Sharti * Drop-party-ack.indication from Party-Control in any state. 2373122205Sharti * 2374122205Sharti * Q.2971:Call-Control-N 23/39 2375122205Sharti */ 2376122205Shartistatic void 2377122205Shartinx_drop_party_ack_indication(struct call *c, struct uni_msg *api) 2378122205Sharti{ 2379122205Sharti struct uniapi_drop_party_ack_indication *drop = 2380122205Sharti uni_msg_rptr(api, struct uniapi_drop_party_ack_indication *); 2381122205Sharti 2382122205Sharti if (uni_party_act_count(c, 0) == 0) { 2383122205Sharti if (uni_party_act_count(c, 1) == 0) { 2384122205Sharti if (c->cstate != CALLST_U11) { 2385122205Sharti make_drop_cause(c, &drop->drop.cause); 2386122205Sharti clear_callD(c); 2387122205Sharti } 2388122205Sharti uni_msg_destroy(api); 2389122205Sharti } else { 2390122205Sharti c->uni->funcs->uni_output(c->uni, c->uni->arg, 2391122205Sharti UNIAPI_DROP_PARTY_ACK_indication, 0, api); 2392122205Sharti set_call_state(c, CALLST_N7); 2393122205Sharti } 2394122205Sharti } else { 2395122205Sharti c->uni->funcs->uni_output(c->uni, c->uni->arg, 2396122205Sharti UNIAPI_DROP_PARTY_ACK_indication, 0, api); 2397122205Sharti } 2398122205Sharti} 2399122205Sharti 2400122205Sharti/* 2401122205Sharti * Add-party-rej.indication from Party-Control in any state. 2402122205Sharti * 2403122205Sharti * Q.2971:Call-Control-U 23/39 2404122205Sharti */ 2405122205Shartistatic void 2406122205Shartiux_add_party_rej_indication(struct call *c, struct uni_msg *api) 2407122205Sharti{ 2408122205Sharti struct uniapi_add_party_rej_indication *rej = 2409122205Sharti uni_msg_rptr(api, struct uniapi_add_party_rej_indication *); 2410122205Sharti 2411122205Sharti if (uni_party_act_count(c, 2) == 0) { 2412122205Sharti if (c->cstate != CALLST_U11) { 2413122205Sharti make_drop_cause(c, &rej->rej.cause); 2414122205Sharti clear_callD(c); 2415122205Sharti } 2416122205Sharti uni_msg_destroy(api); 2417122205Sharti return; 2418122205Sharti } 2419122205Sharti c->uni->funcs->uni_output(c->uni, c->uni->arg, 2420122205Sharti UNIAPI_ADD_PARTY_REJ_indication, 0, api); 2421122205Sharti} 2422122205Sharti 2423122205Sharti/* 2424122205Sharti * Add-party-rej.indication from Party-Control in any state. 2425122205Sharti * 2426122205Sharti * Q.2971:Call-Control-N 23/39 2427122205Sharti */ 2428122205Shartistatic void 2429122205Shartinx_add_party_rej_indication(struct call *c, struct uni_msg *api) 2430122205Sharti{ 2431122205Sharti struct uniapi_add_party_rej_indication *rej = 2432122205Sharti uni_msg_rptr(api, struct uniapi_add_party_rej_indication *); 2433122205Sharti 2434122205Sharti if (uni_party_act_count(c, 0) == 0) { 2435122205Sharti if (uni_party_act_count(c, 1) == 0) { 2436122205Sharti if (c->cstate != CALLST_U11) { 2437122205Sharti make_drop_cause(c, &rej->rej.cause); 2438122205Sharti clear_callD(c); 2439122205Sharti } 2440122205Sharti uni_msg_destroy(api); 2441122205Sharti } else { 2442122205Sharti c->uni->funcs->uni_output(c->uni, c->uni->arg, 2443122205Sharti UNIAPI_ADD_PARTY_REJ_indication, 0, api); 2444122205Sharti set_call_state(c, CALLST_N7); 2445122205Sharti } 2446122205Sharti } else { 2447122205Sharti c->uni->funcs->uni_output(c->uni, c->uni->arg, 2448122205Sharti UNIAPI_ADD_PARTY_REJ_indication, 0, api); 2449122205Sharti } 2450122205Sharti} 2451122205Sharti 2452122205Sharti/* 2453122205Sharti * Add-party.request from API in U4 or U10 2454122205Sharti * 2455122205Sharti * Q.2971:Call-Control-U 9-10/39 (U4) 2456122205Sharti * Q.2971:Call-Control-U 21/39 (U10) 2457122205Sharti * Q.2971:Call-Control-N 12/39 (N7) 2458122205Sharti * Q.2971:Call-Control-N 22/39 (N10) 2459122205Sharti */ 2460122205Shartistatic void 2461131826Shartiunx_add_party_request(struct call *c, struct uni_msg *msg, uint32_t cookie) 2462122205Sharti{ 2463122205Sharti struct uniapi_add_party_request *add = 2464122205Sharti uni_msg_rptr(msg, struct uniapi_add_party_request *); 2465122205Sharti struct party *p; 2466122205Sharti 2467122205Sharti if (IE_ISGOOD(add->add.epref)) { 2468122205Sharti if (add->add.epref.flag != 0) { 2469122205Sharti uni_msg_destroy(msg); 2470122205Sharti uniapi_call_error(c, UNIAPI_ERROR_BAD_IE, cookie); 2471122205Sharti return; 2472122205Sharti } 2473122205Sharti p = uni_find_partyx(c, add->add.epref.epref, 1); 2474122205Sharti if (p != NULL) { 2475122205Sharti uni_msg_destroy(msg); 2476122205Sharti uniapi_call_error(c, UNIAPI_ERROR_EPREF_INUSE, cookie); 2477122205Sharti return; 2478122205Sharti } 2479122205Sharti } else if (!IE_ISPRESENT(add->add.epref)) { 2480122205Sharti allocate_epref(c, &add->add.epref); 2481122205Sharti if (!IE_ISPRESENT(add->add.epref)) { 2482122205Sharti uni_msg_destroy(msg); 2483122205Sharti uniapi_call_error(c, UNIAPI_ERROR_EPREF_INUSE, cookie); 2484122205Sharti return; 2485122205Sharti } 2486122205Sharti } else { 2487122205Sharti uni_msg_destroy(msg); 2488122205Sharti uniapi_call_error(c, UNIAPI_ERROR_BAD_IE, cookie); 2489122205Sharti return; 2490122205Sharti } 2491122205Sharti 2492122205Sharti if ((p = uni_create_partyx(c, add->add.epref.epref, 1, cookie)) == NULL) { 2493122205Sharti uni_msg_destroy(msg); 2494122205Sharti uniapi_call_error(c, UNIAPI_ERROR_NOMEM, cookie); 2495122205Sharti return; 2496122205Sharti } 2497122205Sharti uni_enq_party(p, SIGP_ADD_PARTY_request, cookie, msg, NULL); 2498122205Sharti} 2499122205Sharti 2500122205Sharti/* 2501122205Sharti * Add-party-ack.request from API in U10/N10 2502122205Sharti * 2503122205Sharti * Q.2971:Call-Control-U 21/39 2504122205Sharti * Q.2971:Call-Control-N 22/39 2505122205Sharti */ 2506122205Shartistatic void 2507131826Shartiun10_add_party_ack_request(struct call *c, struct uni_msg *msg, uint32_t cookie) 2508122205Sharti{ 2509122205Sharti struct uniapi_add_party_ack_request *ack = 2510122205Sharti uni_msg_rptr(msg, struct uniapi_add_party_ack_request *); 2511122205Sharti struct party *p; 2512122205Sharti 2513122205Sharti if (!IE_ISGOOD(ack->ack.epref)) { 2514122205Sharti uni_msg_destroy(msg); 2515122205Sharti uniapi_call_error(c, UNIAPI_ERROR_BAD_IE, cookie); 2516122205Sharti return; 2517122205Sharti } 2518122205Sharti if (ack->ack.epref.flag != 1) { 2519122205Sharti uni_msg_destroy(msg); 2520122205Sharti uniapi_call_error(c, UNIAPI_ERROR_BAD_IE, cookie); 2521122205Sharti return; 2522122205Sharti } 2523122205Sharti if ((p = uni_find_partyx(c, ack->ack.epref.epref, 0)) == NULL) { 2524122205Sharti uni_msg_destroy(msg); 2525122205Sharti uniapi_call_error(c, UNIAPI_ERROR_BAD_PARTY, cookie); 2526122205Sharti return; 2527122205Sharti } 2528122205Sharti 2529122205Sharti uni_enq_party(p, SIGP_ADD_PARTY_ACK_request, cookie, msg, NULL); 2530122205Sharti} 2531122205Sharti 2532122205Sharti/* 2533122205Sharti * Party-alerting.request from API in U7/U8/U10 2534122205Sharti * 2535122205Sharti * Q.2971:Call-Control-U 14/39 U7 2536122205Sharti * Q.2971:Call-Control-U 15/39 U8 2537122205Sharti * Q.2971:Call-Control-U 21/39 U10 2538122205Sharti * Q.2971:Call-Control-N 8/39 N4 2539122205Sharti * Q.2971:Call-Control-N 22/39 N10 2540122205Sharti */ 2541122205Shartistatic void 2542131826Shartiunx_party_alerting_request(struct call *c, struct uni_msg *msg, uint32_t cookie) 2543122205Sharti{ 2544122205Sharti struct uniapi_party_alerting_request *alert = 2545122205Sharti uni_msg_rptr(msg, struct uniapi_party_alerting_request *); 2546122205Sharti struct party *p; 2547122205Sharti 2548122205Sharti if (!IE_ISGOOD(alert->alert.epref)) { 2549122205Sharti uni_msg_destroy(msg); 2550122205Sharti uniapi_call_error(c, UNIAPI_ERROR_BAD_IE, cookie); 2551122205Sharti return; 2552122205Sharti } 2553122205Sharti if (alert->alert.epref.flag != 1) { 2554122205Sharti uni_msg_destroy(msg); 2555122205Sharti uniapi_call_error(c, UNIAPI_ERROR_BAD_IE, cookie); 2556122205Sharti return; 2557122205Sharti } 2558122205Sharti if ((p = uni_find_partyx(c, alert->alert.epref.epref, 0)) == NULL) { 2559122205Sharti uni_msg_destroy(msg); 2560122205Sharti uniapi_call_error(c, UNIAPI_ERROR_BAD_PARTY, cookie); 2561122205Sharti return; 2562122205Sharti } 2563122205Sharti 2564122205Sharti uni_enq_party(p, SIGP_PARTY_ALERTING_request, cookie, msg, NULL); 2565122205Sharti} 2566122205Sharti 2567122205Sharti/* 2568122205Sharti * Add-party-rej.request from API in U7/U8/U10/N4/N10 2569122205Sharti * 2570122205Sharti * Q.2971:Call-Control-U 14/39 U7 2571122205Sharti * Q.2971:Call-Control-U 15/39 U8 2572122205Sharti * Q.2971:Call-Control-U 21/39 U10 2573122205Sharti * Q.2971:Call-Control-N 8/39 N4 2574122205Sharti * Q.2971:Call-Control-N 22/39 N10 2575122205Sharti */ 2576122205Shartistatic void 2577131826Shartiunx_add_party_rej_request(struct call *c, struct uni_msg *msg, uint32_t cookie) 2578122205Sharti{ 2579122205Sharti struct uniapi_add_party_rej_request *rej = 2580122205Sharti uni_msg_rptr(msg, struct uniapi_add_party_rej_request *); 2581122205Sharti struct party *p; 2582122205Sharti 2583122205Sharti if (!IE_ISGOOD(rej->rej.epref)) { 2584122205Sharti uni_msg_destroy(msg); 2585122205Sharti uniapi_call_error(c, UNIAPI_ERROR_BAD_IE, cookie); 2586122205Sharti return; 2587122205Sharti } 2588122205Sharti if (rej->rej.epref.flag != 1) { 2589122205Sharti uni_msg_destroy(msg); 2590122205Sharti uniapi_call_error(c, UNIAPI_ERROR_BAD_IE, cookie); 2591122205Sharti return; 2592122205Sharti } 2593122205Sharti if ((p = uni_find_partyx(c, rej->rej.epref.epref, 0)) == NULL) { 2594122205Sharti uni_msg_destroy(msg); 2595122205Sharti uniapi_call_error(c, UNIAPI_ERROR_BAD_PARTY, cookie); 2596122205Sharti return; 2597122205Sharti } 2598122205Sharti 2599122205Sharti uni_enq_party(p, SIGP_ADD_PARTY_REJ_request, cookie, msg, NULL); 2600122205Sharti} 2601122205Sharti 2602122205Sharti/* 2603122205Sharti * Drop-party.request from API in U1-U10 2604122205Sharti * 2605122205Sharti * Q.2971:Call-Control-U 21/39 U10 2606122205Sharti * Q.2971:Call-Control-U 26/39 U1-U9 2607122205Sharti * Q.2971:Call-Control-N 22/39 N10 2608122205Sharti * Q.2971:Call-Control-N 27/39 N1-N9 2609122205Sharti */ 2610122205Shartistatic void 2611131826Shartiunx_drop_party_request(struct call *c, struct uni_msg *msg, uint32_t cookie) 2612122205Sharti{ 2613122205Sharti struct uniapi_drop_party_request *drop = 2614122205Sharti uni_msg_rptr(msg, struct uniapi_drop_party_request *); 2615122205Sharti struct party *p; 2616122205Sharti 2617122205Sharti if (!IE_ISGOOD(drop->drop.epref)) { 2618122205Sharti uni_msg_destroy(msg); 2619122205Sharti uniapi_call_error(c, UNIAPI_ERROR_BAD_IE, cookie); 2620122205Sharti return; 2621122205Sharti } 2622122205Sharti if ((p = uni_find_partyx(c, drop->drop.epref.epref, !drop->drop.epref.flag)) == NULL) { 2623122205Sharti uni_msg_destroy(msg); 2624122205Sharti uniapi_call_error(c, UNIAPI_ERROR_BAD_PARTY, cookie); 2625122205Sharti return; 2626122205Sharti } 2627122205Sharti 2628122205Sharti uni_enq_party(p, SIGP_DROP_PARTY_request, cookie, msg, NULL); 2629122205Sharti} 2630122205Sharti 2631122205Sharti/* 2632122205Sharti * Drop-party-ack.request from API in U1-U10 2633122205Sharti * 2634122205Sharti * Q.2971:Call-Control-U 21/39 U10 2635122205Sharti * Q.2971:Call-Control-U 26/39 U1-U9 2636122205Sharti * Q.2971:Call-Control-N 22/39 N10 2637122205Sharti * Q.2971:Call-Control-N 27/39 N1-N9 2638122205Sharti */ 2639122205Shartistatic void 2640122205Shartiunx_drop_party_ack_request(struct call *c, struct uni_msg *msg, 2641131826Sharti uint32_t cookie) 2642122205Sharti{ 2643122205Sharti struct uniapi_drop_party_ack_request *ack = 2644122205Sharti uni_msg_rptr(msg, struct uniapi_drop_party_ack_request *); 2645122205Sharti struct party *p; 2646122205Sharti 2647122205Sharti if (!IE_ISGOOD(ack->ack.epref)) { 2648122205Sharti uni_msg_destroy(msg); 2649122205Sharti uniapi_call_error(c, UNIAPI_ERROR_BAD_IE, cookie); 2650122205Sharti return; 2651122205Sharti } 2652122205Sharti if ((p = uni_find_partyx(c, ack->ack.epref.epref, !ack->ack.epref.flag)) == NULL) { 2653122205Sharti uni_msg_destroy(msg); 2654122205Sharti uniapi_call_error(c, UNIAPI_ERROR_BAD_PARTY, cookie); 2655122205Sharti return; 2656122205Sharti } 2657122205Sharti 2658122205Sharti uni_enq_party(p, SIGP_DROP_PARTY_ACK_request, cookie, msg, NULL); 2659122205Sharti} 2660122205Sharti 2661122205Sharti/* 2662122205Sharti * ADD PARTY in U7/U8/U10 2663122205Sharti * 2664122205Sharti * Q.2971:Call-Control-U 14/39 U7 2665122205Sharti * Q.2971:Call-Control-U 15/39 U8 2666122205Sharti * Q.2971:Call-Control-U 21/39 U10 2667122205Sharti * Q.2971:Call-Control-N 8/39 N4 2668122205Sharti * Q.2971:Call-Control-N 21/39 N10 2669122205Sharti * 2670122205Sharti * Body already decoded 2671131826Sharti * XXX check EPREF flag 2672122205Sharti */ 2673122205Shartistatic void 2674122205Shartiunx_add_party(struct call *c, struct uni_msg *m, struct uni_all *u, 2675122205Sharti int legal) 2676122205Sharti{ 2677122205Sharti struct uni_all *resp; 2678122205Sharti struct uni_ierr *e1; 2679122205Sharti struct party *p = NULL; 2680122205Sharti enum verify vfy; 2681122205Sharti 2682122205Sharti uni_mandate_epref(c->uni, &u->u.add_party.epref); 2683122205Sharti MANDATE_IE(c->uni, u->u.add_party.called, UNI_IE_CALLED); 2684122205Sharti 2685122205Sharti /* 2686122205Sharti * Do part of the verify handish: according to 9.5.7.2 we must send 2687122205Sharti * an ADD_PARTY_REJ if mandatory IEs are bad or missing instead of 2688122205Sharti * clearing the call. But we must send a STATUS, if it is the EPREF! 2689122205Sharti */ 2690122205Sharti if (IE_ISGOOD(u->u.add_party.epref)) { 2691122205Sharti c->uni->cause.u.ie.len = 0; 2692122205Sharti FOREACH_ERR(e1, c->uni) { 2693122205Sharti if (e1->err == UNI_IERR_MIS) { 2694122205Sharti MK_IE_CAUSE(c->uni->cause, UNI_CAUSE_LOC_USER, 2695122205Sharti UNI_CAUSE_MANDAT); 2696122205Sharti goto rej; 2697122205Sharti } 2698122205Sharti } 2699122205Sharti FOREACH_ERR(e1, c->uni) { 2700122205Sharti if (e1->man && e1->ie != UNI_IE_EPREF && 2701122205Sharti e1->act == UNI_IEACT_DEFAULT) { 2702122205Sharti MK_IE_CAUSE(c->uni->cause, UNI_CAUSE_LOC_USER, 2703122205Sharti UNI_CAUSE_IE_INV); 2704122205Sharti rej: 2705122205Sharti uni_vfy_collect_ies(c->uni); 2706122205Sharti if ((resp = UNI_ALLOC()) != NULL) { 2707122205Sharti MK_MSG_RESP(resp, UNI_ADD_PARTY_REJ, 2708122205Sharti &u->u.hdr.cref); 2709122205Sharti MK_IE_EPREF(resp->u.add_party_rej.epref, 2710122205Sharti u->u.add_party.epref.epref, 2711122205Sharti !u->u.add_party.epref.flag); 2712122205Sharti resp->u.add_party_rej.cause = 2713122205Sharti c->uni->cause; 2714122205Sharti 2715122205Sharti unx_send_add_party_rej(c, resp); 2716122205Sharti } 2717122205Sharti goto ignore; 2718122205Sharti } 2719122205Sharti } 2720122205Sharti p = uni_find_partyx(c, u->u.add_party.epref.epref, 2721122205Sharti u->u.add_party.epref.flag); 2722122205Sharti } 2723122205Sharti 2724122205Sharti vfy = uni_verify(c->uni, u->u.hdr.act); 2725122205Sharti 2726122205Sharti switch (vfy) { 2727122205Sharti 2728122205Sharti case VFY_CLR: 2729122205Sharti uni_vfy_collect_ies(c->uni); 2730122205Sharti clear_callD(c); 2731122205Sharti goto ignore; 2732122205Sharti 2733122205Sharti case VFY_RAIM: 2734122205Sharti case VFY_RAI: 2735122205Sharti uni_respond_status_verify(c->uni, &u->u.hdr.cref, 2736122205Sharti map_callstate(c->cstate), &u->u.add_party.epref, 2737122205Sharti p ? p->state : UNI_EPSTATE_NULL); 2738122205Sharti /* FALLTHRU */ 2739122205Sharti case VFY_I: 2740122205Sharti goto ignore; 2741122205Sharti 2742122205Sharti case VFY_RAP: 2743122205Sharti case VFY_RAPU: 2744122205Sharti uni_respond_status_verify(c->uni, &u->u.hdr.cref, 2745122205Sharti map_callstate(c->cstate), &u->u.add_party.epref, 2746122205Sharti UNI_EPSTATE_ADD_RCVD); 2747122205Sharti case VFY_OK: 2748122205Sharti /* FALLTHRU */ 2749122205Sharti break; 2750122205Sharti } 2751122205Sharti if (!legal) { 2752122205Sharti uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, 2753122205Sharti &u->u.add_party.epref, -1); 2754122205Sharti return; 2755122205Sharti } 2756131826Sharti 2757131826Sharti if (IE_ISGOOD(u->u.add_party.epref) && p == NULL && 2758131826Sharti u->u.add_party.epref.flag) { 2759131826Sharti IE_SETERROR(u->u.add_party.epref); 2760213789Srpaulo (void)UNI_SAVE_IERR(&c->uni->cx, UNI_IE_EPREF, 2761131826Sharti u->u.add_party.epref.h.act, UNI_IERR_BAD); 2762131826Sharti } 2763131826Sharti 2764122205Sharti if (!IE_ISGOOD(u->u.add_party.epref)) { 2765122205Sharti /* 9.5.3.2.2 */ 2766122205Sharti if (vfy == VFY_OK) { 2767122205Sharti MK_IE_CAUSE(c->uni->cause, UNI_CAUSE_LOC_USER, 2768122205Sharti UNI_CAUSE_IE_INV); 2769122205Sharti 2770122205Sharti uni_respond_status_verify(c->uni, &u->u.hdr.cref, 2771122205Sharti map_callstate(c->cstate), NULL, 0); 2772122205Sharti } 2773122205Sharti goto ignore; 2774122205Sharti } 2775122205Sharti 2776122205Sharti 2777122205Sharti if (p == NULL && (p = uni_create_party(c, &u->u.add_party.epref)) 2778122205Sharti == NULL) 2779122205Sharti goto ignore; 2780122205Sharti 2781122205Sharti uni_enq_party(p, SIGP_ADD_PARTY, 0, m, u); 2782122205Sharti return; 2783122205Sharti 2784122205Sharti ignore: 2785122205Sharti uni_msg_destroy(m); 2786122205Sharti UNI_FREE(u); 2787122205Sharti} 2788122205Sharti 2789122205Sharti/* 2790122205Sharti * ADD PARTY ACKNOWLEDGE 2791122205Sharti * 2792122205Sharti * Q.2971:Call-Control-U 21/39 U10 2793122205Sharti * Q.2971:Call-Control-N 15/39 N8 2794122205Sharti * Q.2971:Call-Control-N 22/39 N10 2795122205Sharti */ 2796122205Shartistatic void 2797122205Shartiun10n8_add_party_ack(struct call *c, struct uni_msg *m, struct uni_all *u, 2798122205Sharti int legal) 2799122205Sharti{ 2800122205Sharti struct party *p = NULL; 2801122205Sharti 2802122205Sharti if (IE_ISGOOD(u->u.add_party_ack.epref)) { 2803122205Sharti if (u->u.add_party_ack.epref.flag == 0) { 2804122205Sharti IE_SETERROR(u->u.add_party_ack.epref); 2805213789Srpaulo (void)UNI_SAVE_IERR(&c->uni->cx, UNI_IE_EPREF, 2806122205Sharti u->u.add_party_ack.epref.h.act, UNI_IERR_BAD); 2807122205Sharti } else { 2808122205Sharti p = uni_find_partyx(c, u->u.add_party_ack.epref.epref, 1); 2809122205Sharti if (p == NULL) { 2810122205Sharti respond_drop_party_ack(c, 2811122205Sharti &u->u.add_party_ack.epref, 2812122205Sharti UNI_CAUSE_ENDP_INV); 2813122205Sharti goto ignore; 2814122205Sharti } 2815122205Sharti } 2816122205Sharti } 2817122205Sharti uni_mandate_epref(c->uni, &u->u.add_party_ack.epref); 2818122205Sharti 2819122205Sharti switch (uni_verify(c->uni, u->u.hdr.act)) { 2820122205Sharti 2821122205Sharti case VFY_CLR: 2822122205Sharti uni_vfy_collect_ies(c->uni); 2823122205Sharti clear_callD(c); 2824122205Sharti goto ignore; 2825122205Sharti 2826122205Sharti case VFY_RAIM: 2827122205Sharti case VFY_RAI: 2828122205Sharti report: 2829122205Sharti uni_respond_status_verify(c->uni, &u->u.hdr.cref, 2830122205Sharti map_callstate(c->cstate), &u->u.add_party_ack.epref, 2831122205Sharti p ? p->state : UNI_EPSTATE_NULL); 2832122205Sharti case VFY_I: 2833122205Sharti goto ignore; 2834122205Sharti 2835122205Sharti case VFY_RAP: 2836122205Sharti case VFY_RAPU: 2837122205Sharti uni_respond_status_verify(c->uni, &u->u.hdr.cref, 2838122205Sharti map_callstate(c->cstate), &u->u.add_party_ack.epref, 2839122205Sharti p ? UNI_EPSTATE_ACTIVE : UNI_EPSTATE_NULL); 2840122205Sharti if (!IE_ISGOOD(u->u.party_alerting.epref)) 2841122205Sharti /* See below */ 2842122205Sharti goto ignore; 2843122205Sharti break; 2844122205Sharti case VFY_OK: 2845122205Sharti if (!IE_ISGOOD(u->u.party_alerting.epref)) 2846122205Sharti /* this happens when the EPREF has bad format. 2847122205Sharti * The rules require us the message to be ignored 2848122205Sharti * (9.5.3.2.2e) and to report status. 2849122205Sharti */ 2850122205Sharti goto report; 2851122205Sharti break; 2852122205Sharti } 2853122205Sharti if (legal) { 2854122205Sharti /* p is != NULL here */ 2855122205Sharti uni_enq_party(p, SIGP_ADD_PARTY_ACK, 0, m, u); 2856122205Sharti return; 2857122205Sharti } 2858122205Sharti if (p == NULL) 2859122205Sharti /* Q.2971 9.5.3.2.3a) */ 2860122205Sharti respond_drop_party_ack(c, &u->u.add_party_ack.epref, 2861122205Sharti UNI_CAUSE_ENDP_INV); 2862122205Sharti else 2863122205Sharti uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, 2864122205Sharti &u->u.add_party_ack.epref, p->state); 2865122205Sharti 2866122205Sharti ignore: 2867122205Sharti uni_msg_destroy(m); 2868122205Sharti UNI_FREE(u); 2869122205Sharti} 2870122205Sharti 2871122205Sharti/* 2872122205Sharti * Make the EPREF action default 2873122205Sharti */ 2874122205Shartistatic void 2875122205Shartidefault_act_epref(struct uni *uni, struct uni_ie_epref *epref) 2876122205Sharti{ 2877122205Sharti struct uni_ierr *e; 2878122205Sharti 2879122205Sharti FOREACH_ERR(e, uni) 2880122205Sharti if (e->ie == UNI_IE_EPREF) { 2881122205Sharti e->act = UNI_IEACT_DEFAULT; 2882122205Sharti break; 2883122205Sharti } 2884122205Sharti epref->h.act = UNI_IEACT_DEFAULT; 2885122205Sharti} 2886122205Sharti 2887122205Sharti/* 2888122205Sharti * PARTY ALERTING message 2889122205Sharti * 2890122205Sharti * Q.2971:Call-Control-U 9/39 U4 2891122205Sharti * Q.2971:Call-Control-U 21/39 U10 2892122205Sharti * Q.2971:Call-Control-N 12/39 N7 2893122205Sharti * Q.2971:Call-Control-N 15/39 N8 2894122205Sharti * Q.2971:Call-Control-N 22/39 N10 2895122205Sharti */ 2896122205Shartistatic void 2897122205Shartiunx_party_alerting(struct call *c, struct uni_msg *m, struct uni_all *u, 2898122205Sharti int legal) 2899122205Sharti{ 2900122205Sharti struct party *p = NULL; 2901122205Sharti 2902122205Sharti if (IE_ISGOOD(u->u.party_alerting.epref)) { 2903122205Sharti if (u->u.party_alerting.epref.flag == 0) { 2904122205Sharti IE_SETERROR(u->u.party_alerting.epref); 2905213789Srpaulo (void)UNI_SAVE_IERR(&c->uni->cx, UNI_IE_EPREF, 2906122205Sharti u->u.party_alerting.epref.h.act, UNI_IERR_BAD); 2907122205Sharti } else { 2908122205Sharti p = uni_find_partyx(c, u->u.party_alerting.epref.epref, 1); 2909122205Sharti if (p == NULL) { 2910122205Sharti respond_drop_party_ack(c, 2911122205Sharti &u->u.party_alerting.epref, 2912122205Sharti UNI_CAUSE_ENDP_INV); 2913122205Sharti goto ignore; 2914122205Sharti } 2915122205Sharti } 2916122205Sharti } 2917122205Sharti uni_mandate_epref(c->uni, &u->u.party_alerting.epref); 2918122205Sharti 2919122205Sharti switch (uni_verify(c->uni, u->u.hdr.act)) { 2920122205Sharti 2921122205Sharti case VFY_CLR: 2922122205Sharti uni_vfy_collect_ies(c->uni); 2923122205Sharti clear_callD(c); 2924122205Sharti goto ignore; 2925122205Sharti 2926122205Sharti case VFY_RAIM: 2927122205Sharti case VFY_RAI: 2928122205Sharti report: 2929122205Sharti uni_respond_status_verify(c->uni, &u->u.hdr.cref, 2930122205Sharti map_callstate(c->cstate), &u->u.party_alerting.epref, 2931122205Sharti p ? p->state : UNI_EPSTATE_NULL); 2932122205Sharti case VFY_I: 2933122205Sharti goto ignore; 2934122205Sharti 2935122205Sharti case VFY_RAP: 2936122205Sharti case VFY_RAPU: 2937122205Sharti uni_respond_status_verify(c->uni, &u->u.hdr.cref, 2938122205Sharti map_callstate(c->cstate), &u->u.party_alerting.epref, 2939122205Sharti p ? UNI_EPSTATE_ALERT_RCVD : UNI_EPSTATE_NULL); 2940122205Sharti if (!IE_ISGOOD(u->u.party_alerting.epref)) 2941122205Sharti /* See below */ 2942122205Sharti goto ignore; 2943122205Sharti break; 2944122205Sharti 2945122205Sharti case VFY_OK: 2946122205Sharti if (!IE_ISGOOD(u->u.party_alerting.epref)) 2947122205Sharti /* The rules require us the message to be ignored 2948122205Sharti * (9.5.3.2.2e) and to report status. 2949122205Sharti */ 2950122205Sharti goto report; 2951122205Sharti break; 2952122205Sharti } 2953122205Sharti if (legal) { 2954122205Sharti /* p is != NULL here */ 2955122205Sharti uni_enq_party(p, SIGP_PARTY_ALERTING, 0, m, u); 2956122205Sharti return; 2957122205Sharti } 2958122205Sharti if (p == NULL) 2959122205Sharti /* Q.2971 9.5.3.2.3a) */ 2960122205Sharti respond_drop_party_ack(c, &u->u.party_alerting.epref, 2961122205Sharti UNI_CAUSE_ENDP_INV); 2962122205Sharti else 2963122205Sharti uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, 2964122205Sharti &u->u.party_alerting.epref, p->state); 2965122205Sharti 2966122205Sharti ignore: 2967122205Sharti uni_msg_destroy(m); 2968122205Sharti UNI_FREE(u); 2969122205Sharti} 2970122205Sharti 2971122205Sharti/* 2972122205Sharti * Handle a bad/missing cause in a DROP_PARTY_ACK or ADD_PARTY_REJ 2973122205Sharti * 2974122205Sharti * If the IE is missing or bad and the action is defaulted handle as 2975122205Sharti * cause #1 according to 9.5.7.1/2. 2976122205Sharti * Otherwise keep the IE. 2977122205Sharti */ 2978122205Shartistatic void 2979122205Shartihandle_bad_drop_cause(struct call *c, struct uni_ie_cause *cause, int mkcause) 2980122205Sharti{ 2981122205Sharti 2982122205Sharti if (IE_ISGOOD(*cause)) 2983122205Sharti return; 2984122205Sharti 2985122205Sharti if (!IE_ISPRESENT(*cause)) { 2986122205Sharti /* 9.5.7.1 */ 2987122205Sharti /* cannot make cause here because we need the 96 error */ 2988122205Sharti uni_vfy_remove_cause(c->uni); 2989122205Sharti return; 2990122205Sharti } 2991122205Sharti if (cause->h.act != UNI_IEACT_DEFAULT) 2992122205Sharti return; 2993122205Sharti 2994122205Sharti /* 9.5.7.2 */ 2995122205Sharti uni_vfy_remove_cause(c->uni); 2996122205Sharti if (mkcause) 2997122205Sharti MK_IE_CAUSE(*cause, UNI_CAUSE_LOC_USER, UNI_CAUSE_UNSPEC); 2998122205Sharti} 2999122205Sharti 3000122205Sharti/* 3001122205Sharti * ADD PARTY REJ from party control 3002122205Sharti * Q.2971:Call-Control-U 21/39 3003122205Sharti * Q.2971:Call-Control-U 24/39 3004122205Sharti */ 3005122205Shartistatic void 3006122205Shartiunx_send_add_party_rej(struct call *c, struct uni_all *u) 3007122205Sharti{ 3008122205Sharti 3009122205Sharti if (uni_party_act_count(c, 2) == 0) { 3010122205Sharti if (c->cstate != CALLST_U11 && c->cstate != CALLST_N12) { 3011122205Sharti c->uni->cause = u->u.add_party_rej.cause; 3012122205Sharti clear_callD(c); 3013122205Sharti } 3014122205Sharti } else 3015122205Sharti (void)uni_send_output(u, c->uni); 3016122205Sharti UNI_FREE(u); 3017122205Sharti} 3018122205Sharti 3019122205Sharti/* 3020122205Sharti * ADD_PARTY_REJECT in U4/U10 3021122205Sharti * 3022122205Sharti * Q.2971:Call-Control-U 9/39 U4 3023122205Sharti * Q.2971:Call-Control-U 21/39 U10 3024122205Sharti * Q.2971:Call-Control-N 12/39 N7 3025122205Sharti * Q.2971:Call-Control-N 15/39 N8 3026122205Sharti * Q.2971:Call-Control-N 22/39 N10 3027122205Sharti */ 3028122205Shartistatic void 3029122205Shartiunx_add_party_rej(struct call *c, struct uni_msg *m, struct uni_all *u, 3030122205Sharti int legal) 3031122205Sharti{ 3032122205Sharti struct uni_add_party_rej *ar = &u->u.add_party_rej; 3033122205Sharti struct party *p; 3034122205Sharti 3035122205Sharti if (IE_ISGOOD(ar->epref)) { 3036122205Sharti p = uni_find_partyx(c, ar->epref.epref, ar->epref.flag); 3037122205Sharti if (p == NULL) 3038122205Sharti goto ignore; 3039122205Sharti 3040122205Sharti if (legal) { 3041122205Sharti handle_bad_drop_cause(c, &ar->cause, 0); 3042122205Sharti uni_vfy_remove_unknown(c->uni); 3043122205Sharti switch (uni_verify(c->uni, u->u.hdr.act)) { 3044122205Sharti 3045122205Sharti case VFY_CLR: 3046122205Sharti goto clear; 3047122205Sharti 3048122205Sharti case VFY_RAIM: 3049122205Sharti case VFY_RAI: 3050122205Sharti uni_respond_status_verify(c->uni, 3051122205Sharti &u->u.hdr.cref, map_callstate(c->cstate), 3052122205Sharti &ar->epref, p->state); 3053122205Sharti case VFY_I: 3054122205Sharti goto ignore; 3055122205Sharti 3056122205Sharti case VFY_RAPU: 3057122205Sharti uni_vfy_collect_ies(c->uni); 3058122205Sharti break; 3059122205Sharti 3060122205Sharti case VFY_RAP: 3061122205Sharti uni_respond_status_verify(c->uni, 3062122205Sharti &u->u.hdr.cref, map_callstate(c->cstate), 3063122205Sharti &ar->epref, p->state); 3064122205Sharti case VFY_OK: 3065122205Sharti break; 3066122205Sharti } 3067122205Sharti uni_enq_party(p, SIGP_ADD_PARTY_REJ, 0, m, u); 3068122205Sharti return; 3069122205Sharti } 3070122205Sharti uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, 3071122205Sharti &ar->epref, -1); 3072122205Sharti return; 3073122205Sharti } 3074122205Sharti 3075122205Sharti /* Q.2971: 9.5.3.2.1 last paragraph 3076122205Sharti * 9.5.3.2.2 second to last paragraph 3077122205Sharti * Make the action indicator default. 3078122205Sharti */ 3079122205Sharti default_act_epref(c->uni, &ar->epref); 3080122205Sharti if (!IE_ISPRESENT(ar->epref)) 3081122205Sharti uni_mandate_ie(c->uni, UNI_IE_EPREF); 3082122205Sharti (void)uni_verify(c->uni, u->u.hdr.act); 3083122205Sharti 3084122205Sharti clear: 3085122205Sharti uni_vfy_collect_ies(c->uni); 3086122205Sharti clear_callD(c); 3087122205Sharti 3088122205Sharti ignore: 3089122205Sharti uni_msg_destroy(m); 3090122205Sharti UNI_FREE(u); 3091122205Sharti} 3092122205Sharti 3093122205Sharti/* 3094122205Sharti * DROP_PARTY 3095122205Sharti * 3096122205Sharti * Q.2971:Call-Control-U 26/39 Ux 3097122205Sharti * Q.2971:Call-Control-U 21/39 U10 3098122205Sharti * Q.2971:Call-Control-N 27/39 Nx 3099122205Sharti * Q.2971:Call-Control-N 22/39 N10 3100122205Sharti */ 3101122205Shartistatic void 3102122205Shartiunx_drop_party(struct call *c, struct uni_msg *m, struct uni_all *u, int legal) 3103122205Sharti{ 3104122205Sharti struct uni_drop_party *dp = &u->u.drop_party; 3105122205Sharti struct party *p; 3106122205Sharti struct uni_ierr *e; 3107122205Sharti 3108122205Sharti if (IE_ISGOOD(dp->epref)) { 3109122205Sharti p = uni_find_partyx(c, dp->epref.epref, dp->epref.flag); 3110122205Sharti if (p == NULL) { 3111122205Sharti respond_drop_party_ack(c, &dp->epref, 3112122205Sharti UNI_CAUSE_ENDP_INV); 3113122205Sharti goto ignore; 3114122205Sharti } 3115122205Sharti handle_bad_drop_cause(c, &dp->cause, 0); 3116122205Sharti uni_vfy_remove_unknown(c->uni); 3117122205Sharti switch (uni_verify(c->uni, u->u.hdr.act)) { 3118122205Sharti 3119122205Sharti case VFY_CLR: 3120122205Sharti goto clear; 3121122205Sharti 3122122205Sharti case VFY_RAIM: 3123122205Sharti case VFY_RAI: 3124122205Sharti uni_respond_status_verify(c->uni, &u->u.hdr.cref, 3125122205Sharti map_callstate(c->cstate), 3126122205Sharti &u->u.drop_party.epref, p->state); 3127122205Sharti case VFY_I: 3128122205Sharti goto ignore; 3129122205Sharti 3130122205Sharti case VFY_RAPU: 3131122205Sharti uni_vfy_collect_ies(c->uni); 3132122205Sharti break; 3133122205Sharti 3134122205Sharti case VFY_RAP: 3135122205Sharti uni_respond_status_verify(c->uni, &u->u.hdr.cref, 3136122205Sharti map_callstate(c->cstate), 3137122205Sharti &dp->epref, UNI_EPSTATE_DROP_RCVD); 3138122205Sharti case VFY_OK: 3139122205Sharti break; 3140122205Sharti } 3141122205Sharti if (legal) { 3142122205Sharti uni_enq_party(p, SIGP_DROP_PARTY, 0, m, u); 3143122205Sharti return; 3144122205Sharti } 3145122205Sharti uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, &dp->epref, -1); 3146122205Sharti goto ignore; 3147122205Sharti } 3148122205Sharti 3149122205Sharti /* Q.2971: 9.5.3.2.1 last paragraph 3150122205Sharti * 9.5.3.2.2 second to last paragraph 3151122205Sharti * Make the action indicator default. 3152122205Sharti */ 3153122205Sharti FOREACH_ERR(e, c->uni) 3154122205Sharti if (e->ie == UNI_IE_EPREF) { 3155122205Sharti e->act = UNI_IEACT_DEFAULT; 3156122205Sharti break; 3157122205Sharti } 3158122205Sharti dp->epref.h.act = UNI_IEACT_DEFAULT; 3159122205Sharti 3160122205Sharti if (!IE_ISPRESENT(dp->epref)) 3161122205Sharti uni_mandate_ie(c->uni, UNI_IE_EPREF); 3162122205Sharti (void)uni_verify(c->uni, u->u.hdr.act); 3163122205Sharti 3164122205Sharti clear: 3165122205Sharti uni_vfy_collect_ies(c->uni); 3166122205Sharti clear_callD(c); 3167122205Sharti uni_msg_destroy(m); 3168122205Sharti UNI_FREE(u); 3169122205Sharti return; 3170122205Sharti 3171122205Sharti ignore: 3172122205Sharti uni_msg_destroy(m); 3173122205Sharti UNI_FREE(u); 3174122205Sharti} 3175122205Sharti 3176122205Sharti/* 3177122205Sharti * DROP_PARTY_ACK 3178122205Sharti * 3179122205Sharti * Q.2971:Call-Control-U 26/39 Ux 3180122205Sharti * Q.2971:Call-Control-U 21/39 U10 3181122205Sharti * Q.2971:Call-Control-N 27/39 Nx 3182122205Sharti * Q.2971:Call-Control-N 22/39 N10 3183122205Sharti */ 3184122205Shartistatic void 3185122205Shartiunx_drop_party_ack(struct call *c, struct uni_msg *m, struct uni_all *u, 3186122205Sharti int legal) 3187122205Sharti{ 3188122205Sharti struct party *p; 3189122205Sharti struct uni_drop_party_ack *ack = &u->u.drop_party_ack; 3190122205Sharti 3191122205Sharti if (IE_ISGOOD(u->u.drop_party_ack.epref)) { 3192122205Sharti p = uni_find_partyx(c, ack->epref.epref, ack->epref.flag); 3193122205Sharti if (p != NULL) { 3194122205Sharti handle_bad_drop_cause(c, &ack->cause, 1); 3195122205Sharti uni_vfy_remove_unknown(c->uni); 3196122205Sharti switch (uni_verify(c->uni, u->u.hdr.act)) { 3197122205Sharti 3198122205Sharti case VFY_CLR: 3199122205Sharti goto clear; 3200122205Sharti 3201122205Sharti case VFY_RAIM: 3202122205Sharti case VFY_RAI: 3203122205Sharti uni_respond_status_verify(c->uni, 3204122205Sharti &u->u.hdr.cref, map_callstate(c->cstate), 3205122205Sharti &ack->epref, p->state); 3206122205Sharti case VFY_I: 3207122205Sharti goto ignore; 3208122205Sharti 3209122205Sharti case VFY_RAP: 3210122205Sharti uni_respond_status_verify(c->uni, 3211122205Sharti &u->u.hdr.cref, map_callstate(c->cstate), 3212122205Sharti &ack->epref, UNI_EPSTATE_NULL); 3213122205Sharti case VFY_RAPU: 3214122205Sharti case VFY_OK: 3215122205Sharti break; 3216122205Sharti } 3217122205Sharti if (legal) { 3218122205Sharti uni_enq_party(p, SIGP_DROP_PARTY_ACK, 0, m, u); 3219122205Sharti return; 3220122205Sharti } 3221122205Sharti uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, 3222122205Sharti &ack->epref, -1); 3223122205Sharti } 3224122205Sharti goto ignore; 3225122205Sharti } 3226122205Sharti 3227122205Sharti /* Q.2971: 9.5.3.2.1 last paragraph 3228122205Sharti * 9.5.3.2.2 second to last paragraph 3229122205Sharti */ 3230122205Sharti (void)uni_verify(c->uni, u->u.hdr.act); 3231122205Sharti MK_IE_CAUSE(c->uni->cause, UNI_CAUSE_LOC_USER, UNI_CAUSE_IE_INV); 3232122205Sharti 3233122205Sharti clear: 3234122205Sharti uni_vfy_collect_ies(c->uni); 3235122205Sharti clear_callD(c); 3236122205Sharti uni_msg_destroy(m); 3237122205Sharti UNI_FREE(u); 3238122205Sharti return; 3239122205Sharti 3240122205Sharti ignore: 3241122205Sharti uni_msg_destroy(m); 3242122205Sharti UNI_FREE(u); 3243122205Sharti} 3244122205Sharti 3245122205Sharti/**********************************************************************/ 3246122205Sharti 3247122205Sharti/* 3248122205Sharti * Bad or unrecognized message. 3249122205Sharti * 3250122205Sharti * Q.2971:Call-Control-U 35/39 3251122205Sharti */ 3252122205Shartivoid 3253122205Shartiuni_bad_message(struct call *c, struct uni_all *u, u_int cause, 3254122205Sharti struct uni_ie_epref *epref, int ps) 3255122205Sharti{ 3256122205Sharti struct uni_all *resp; 3257122205Sharti struct party *p; 3258122205Sharti 3259122205Sharti if ((u->u.hdr.act == UNI_MSGACT_CLEAR && 3260122205Sharti (c->cstate == CALLST_U11 || 3261122205Sharti c->cstate == CALLST_U12 || 3262122205Sharti c->cstate == CALLST_N11 || 3263122205Sharti c->cstate == CALLST_N12)) || 3264122205Sharti u->u.hdr.act == UNI_MSGACT_IGNORE) 3265122205Sharti return; 3266122205Sharti 3267122205Sharti MK_IE_CAUSE(c->uni->cause, UNI_CAUSE_LOC_USER, cause); 3268122205Sharti ADD_CAUSE_MTYPE(c->uni->cause, u->mtype); 3269122205Sharti 3270122205Sharti if (u->u.hdr.act == UNI_MSGACT_CLEAR) { 3271122205Sharti clear_callD(c); 3272122205Sharti return; 3273122205Sharti } 3274122205Sharti 3275122205Sharti /* 3276122205Sharti * Send STATUS 3277122205Sharti */ 3278122205Sharti if ((resp = UNI_ALLOC()) != NULL) { 3279122205Sharti MK_MSG_RESP(resp, UNI_STATUS, &u->u.hdr.cref); 3280122205Sharti MK_IE_CALLSTATE(resp->u.status.callstate, 3281122205Sharti map_callstate(c->cstate)); 3282122205Sharti resp->u.status.cause = c->uni->cause; 3283122205Sharti 3284122205Sharti if (epref != NULL && IE_ISGOOD(*epref)) { 3285122205Sharti MK_IE_EPREF(resp->u.status.epref, epref->epref, !epref->flag); 3286122205Sharti if (ps == -1) { 3287122205Sharti p = uni_find_party(c, epref); 3288122205Sharti if (p == NULL) 3289122205Sharti ps = UNI_EPSTATE_NULL; 3290122205Sharti else 3291122205Sharti ps = p->state; 3292122205Sharti } 3293122205Sharti MK_IE_EPSTATE(resp->u.status.epstate, ps); 3294122205Sharti } 3295122205Sharti (void)uni_send_output(resp, c->uni); 3296122205Sharti 3297122205Sharti UNI_FREE(resp); 3298122205Sharti } 3299122205Sharti} 3300122205Sharti 3301122205Sharti/**********************************************************************/ 3302122205Sharti 3303122205Sharti/* 3304122205Sharti * Unknown message in any state. 3305122205Sharti * 3306122205Sharti * Q.2971:Call-Control 35/39 3307122205Sharti * Q.2971:Call-Control 36/39 3308122205Sharti */ 3309122205Shartistatic void 3310122205Shartiunx_unknown(struct call *c, struct uni_msg *m, struct uni_all *u) 3311122205Sharti{ 3312122205Sharti /* 3313122205Sharti * Unrecognized message. Cannot call verify here, because 3314122205Sharti * it doesn't know about unrecognized messages. 3315122205Sharti */ 3316122205Sharti if (u->u.hdr.act == UNI_MSGACT_CLEAR) { 3317122205Sharti MK_IE_CAUSE(c->uni->cause, UNI_CAUSE_LOC_USER, 3318122205Sharti UNI_CAUSE_MTYPE_NIMPL); 3319122205Sharti ADD_CAUSE_MTYPE(c->uni->cause, u->mtype); 3320122205Sharti clear_callD(c); 3321122205Sharti } else if(u->u.hdr.act == UNI_MSGACT_IGNORE) { 3322122205Sharti ; 3323122205Sharti } else { 3324122205Sharti (void)uni_decode_body(m, u, &c->uni->cx); 3325122205Sharti uni_bad_message(c, u, UNI_CAUSE_MTYPE_NIMPL, 3326122205Sharti &u->u.unknown.epref, -1); 3327122205Sharti } 3328122205Sharti uni_msg_destroy(m); 3329122205Sharti UNI_FREE(u); 3330122205Sharti} 3331122205Sharti/**********************************************************************/ 3332122205Sharti 3333122205Shartivoid 3334131826Shartiuni_sig_call(struct call *c, enum call_sig sig, uint32_t cookie, 3335122205Sharti struct uni_msg *msg, struct uni_all *u) 3336122205Sharti{ 3337122205Sharti if (sig >= SIGC_END) { 3338122205Sharti VERBOSE(c->uni, UNI_FAC_ERR, 1, 3339122205Sharti "Signal %d outside of range to Call-Control", sig); 3340122205Sharti if (msg) 3341122205Sharti uni_msg_destroy(msg); 3342122205Sharti if (u) 3343122205Sharti UNI_FREE(u); 3344122205Sharti return; 3345122205Sharti } 3346122205Sharti 3347122205Sharti VERBOSE(c->uni, UNI_FAC_CALL, 1, "Signal %s in state %s of call %u/%s" 3348122205Sharti "; cookie %u", call_sigs[sig], callstates[c->cstate].name, c->cref, 3349122205Sharti c->mine ? "mine" : "his", cookie); 3350122205Sharti 3351122205Sharti switch (sig) { 3352122205Sharti 3353122205Sharti case SIGC_LINK_RELEASE_indication: 3354122205Sharti if (c->cstate == CALLST_U10 || c->cstate == CALLST_N10) 3355122205Sharti /* Q.2971:Call-Control-U 36/39 */ 3356122205Sharti /* Q.2971:Call-Control-N 20/39 */ 3357122205Sharti un10_link_release_indication(c); 3358122205Sharti else 3359122205Sharti /* Q.2971:Call-Control-U 36/39 */ 3360122205Sharti /* Q.2971:Call-Control-N 37/39 */ 3361122205Sharti unx_link_release_indication(c); 3362122205Sharti break; 3363122205Sharti 3364122205Sharti case SIGC_LINK_ESTABLISH_ERROR_indication: 3365122205Sharti if (c->cstate != CALLST_U10 && c->cstate != CALLST_N10) { 3366122205Sharti VERBOSE(c->uni, UNI_FAC_ERR, 1, 3367122205Sharti "link-establish-error.indication in cs=%s", 3368122205Sharti callstates[c->cstate].name); 3369122205Sharti break; 3370122205Sharti } 3371122205Sharti /* Q.2971:Call-Control-U 19/39 */ 3372122205Sharti /* Q.2971:Call-Control-N 20/39 */ 3373122205Sharti un10_link_establish_error_indication(c); 3374122205Sharti break; 3375122205Sharti 3376122205Sharti case SIGC_LINK_ESTABLISH_indication: 3377122205Sharti switch (c->cstate) { 3378122205Sharti 3379122205Sharti case CALLST_U1: case CALLST_N1: 3380122205Sharti case CALLST_U3: case CALLST_N3: 3381122205Sharti case CALLST_U4: case CALLST_N4: 3382122205Sharti case CALLST_U6: case CALLST_N6: 3383122205Sharti case CALLST_U7: case CALLST_N7: 3384122205Sharti case CALLST_U8: case CALLST_N8: 3385122205Sharti case CALLST_U9: case CALLST_N9: 3386122205Sharti /* Q.2971:Call-Control-U 36/39 */ 3387122205Sharti /* Q.2971:Call-Control-N 37/39 */ 3388122205Sharti unx_link_establish_indication(c); 3389122205Sharti break; 3390122205Sharti 3391122205Sharti case CALLST_U10: case CALLST_N10: 3392122205Sharti /* Q.2971:Call-Control-U 19/39 */ 3393122205Sharti /* Q.2971:Call-Control-N 20/39 */ 3394122205Sharti un10_link_establish_indication(c); 3395122205Sharti break; 3396122205Sharti 3397122205Sharti case CALLST_U11: case CALLST_N11: 3398122205Sharti case CALLST_U12: case CALLST_N12: 3399122205Sharti /* Q.2971:Call-Control-U 36/39 */ 3400122205Sharti /* Q.2971:Call-Control-N 37/39 */ 3401122205Sharti break; 3402122205Sharti 3403122205Sharti default: 3404122205Sharti VERBOSE(c->uni, UNI_FAC_ERR, 1, 3405122205Sharti "link-establish.indication in cs=%s", 3406122205Sharti callstates[c->cstate].name); 3407122205Sharti } 3408122205Sharti break; 3409122205Sharti 3410122205Sharti case SIGC_LINK_ESTABLISH_confirm: 3411122205Sharti if (c->cstate != CALLST_U10 && c->cstate != CALLST_N10) { 3412122205Sharti VERBOSE(c->uni, UNI_FAC_ERR, 1, 3413122205Sharti "link-establish.confirm in cs=%s", 3414122205Sharti callstates[c->cstate].name); 3415122205Sharti break; 3416122205Sharti } 3417122205Sharti /* Q.2971:Call-Control-U 19/39 */ 3418122205Sharti /* Q.2971:Call-Control-N 20/39 */ 3419122205Sharti un10_link_establish_confirm(c); 3420122205Sharti break; 3421122205Sharti 3422122205Sharti case SIGC_UNKNOWN: 3423122205Sharti /* Q.2971:Call-Control 35/39 */ 3424122205Sharti /* Q.2971:Call-Control 36/39 */ 3425122205Sharti unx_unknown(c, msg, u); 3426122205Sharti break; 3427122205Sharti 3428122205Sharti case SIGC_SETUP: 3429122205Sharti if (c->cstate != CALLST_NULL) { 3430122205Sharti (void)uni_decode_body(msg, u, &c->uni->cx); 3431122205Sharti uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, 3432122205Sharti &u->u.setup.epref, -1); 3433122205Sharti goto drop; 3434122205Sharti } 3435122205Sharti if (c->uni->proto == UNIPROTO_UNI40N) 3436122205Sharti /* Q.2971:Call-Control-N 4/39 */ 3437122205Sharti un0_setup(c, msg, u, CALLST_N1); 3438122205Sharti else 3439122205Sharti /* Q.2971:Call-Control-U 4/39 */ 3440122205Sharti un0_setup(c, msg, u, CALLST_U6); 3441122205Sharti break; 3442122205Sharti 3443122205Sharti case SIGC_CALL_PROC: 3444122205Sharti if (c->cstate == CALLST_U1) { 3445122205Sharti /* Q.2971:Call-Control-U 6/39 */ 3446122205Sharti u1n6_call_proc(c, msg, u, CALLST_U3); 3447122205Sharti break; 3448122205Sharti } 3449122205Sharti if (c->cstate == CALLST_N6) { 3450122205Sharti /* Q.2971:Call-Control-N 11/39 */ 3451122205Sharti u1n6_call_proc(c, msg, u, CALLST_N9); 3452122205Sharti break; 3453122205Sharti } 3454122205Sharti (void)uni_decode_body(msg, u, &c->uni->cx); 3455122205Sharti uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, 3456122205Sharti &u->u.call_proc.epref, -1); 3457122205Sharti goto drop; 3458122205Sharti 3459122205Sharti case SIGC_ALERTING: 3460122205Sharti if (c->cstate == CALLST_U1 || c->cstate == CALLST_U3) { 3461122205Sharti /* Q.2971:Call-Control-U 37/39 (U1) */ 3462122205Sharti /* Q.2971:Call-Control-U 7/39 (U3) */ 3463122205Sharti unx_alerting(c, msg, u, CALLST_U4); 3464122205Sharti break; 3465122205Sharti } 3466122205Sharti if (c->cstate == CALLST_N6) { 3467122205Sharti /* Q.2971:Call-Control-N 9/39 (N6) */ 3468122205Sharti /* Q.2971:Call-Control-N 17/39 (N9) */ 3469122205Sharti unx_alerting(c, msg, u, CALLST_N7); 3470122205Sharti break; 3471122205Sharti } 3472122205Sharti (void)uni_decode_body(msg, u, &c->uni->cx); 3473122205Sharti uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, 3474122205Sharti &u->u.alerting.epref, -1); 3475122205Sharti goto drop; 3476122205Sharti 3477122205Sharti case SIGC_CONNECT: 3478122205Sharti if (c->cstate == CALLST_U1 || c->cstate == CALLST_U3 || 3479122205Sharti c->cstate == CALLST_U4) { 3480122205Sharti /* Q.2971:Call-Control-U 7-8/39 (U3) */ 3481122205Sharti /* Q.2971:Call-Control-U 11/39 (U4) */ 3482122205Sharti /* Q.2971:Call-Control-U 37/39 (U1) */ 3483122205Sharti unx_connect(c, msg, u, CALLST_U10); 3484122205Sharti break; 3485122205Sharti } 3486122205Sharti if (c->cstate == CALLST_N6 || c->cstate == CALLST_N7 || 3487122205Sharti c->cstate == CALLST_N9) { 3488122205Sharti /* Q.2971:Call-Control-N 9-10/39 (N6) */ 3489122205Sharti /* Q.2971:Call-Control-N 14/39 (N7) */ 3490122205Sharti /* Q.2971:Call-Control-N 17/39 (N9) */ 3491122205Sharti unx_connect(c, msg, u, CALLST_N8); 3492122205Sharti break; 3493122205Sharti } 3494122205Sharti (void)uni_decode_body(msg, u, &c->uni->cx); 3495122205Sharti uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, 3496122205Sharti &u->u.connect.epref, -1); 3497122205Sharti goto drop; 3498122205Sharti 3499122205Sharti case SIGC_CONNECT_ACK: 3500122205Sharti if (c->cstate == CALLST_U8) { 3501122205Sharti /* Q.2971:Call-Control-U 15-16/39 */ 3502122205Sharti u8_connect_ack(c, msg, u, CALLST_U10); 3503122205Sharti break; 3504122205Sharti } 3505122205Sharti if (c->cstate == CALLST_N10) { 3506122205Sharti /* Q.2971:Call-Control-N 18/39 */ 3507122205Sharti n10_connect_ack(c, msg, u); 3508122205Sharti break; 3509122205Sharti } 3510122205Sharti uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, NULL, 0); 3511122205Sharti goto drop; 3512122205Sharti 3513122205Sharti case SIGC_RELEASE: 3514122205Sharti switch (c->cstate) { 3515122205Sharti 3516122205Sharti default: 3517122205Sharti uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, NULL, 0); 3518122205Sharti goto drop; 3519122205Sharti 3520122205Sharti case CALLST_U11: 3521122205Sharti case CALLST_N12: 3522122205Sharti /* Q.2971:Call-Control-U 28/39 */ 3523122205Sharti /* Q.2971:Call-Control-N 30/39 */ 3524122205Sharti u11n12_release(c, msg, u); 3525122205Sharti break; 3526122205Sharti 3527122205Sharti case CALLST_U1: 3528122205Sharti case CALLST_U3: 3529122205Sharti case CALLST_U4: 3530122205Sharti case CALLST_U6: 3531122205Sharti case CALLST_U7: 3532122205Sharti case CALLST_U8: 3533122205Sharti case CALLST_U9: 3534122205Sharti case CALLST_U10: 3535122205Sharti case CALLST_U12: 3536122205Sharti /* Q.2971:Call-Control-U 25/39 */ 3537122205Sharti unx_release(c, msg, u, CALLST_U12); 3538122205Sharti break; 3539122205Sharti 3540122205Sharti case CALLST_N1: 3541122205Sharti case CALLST_N3: 3542122205Sharti case CALLST_N4: 3543122205Sharti case CALLST_N6: 3544122205Sharti case CALLST_N7: 3545122205Sharti case CALLST_N8: 3546122205Sharti case CALLST_N9: 3547122205Sharti case CALLST_N10: 3548122205Sharti case CALLST_N11: 3549122205Sharti /* Q.2971:Call-Control-N 26/39 */ 3550122205Sharti unx_release(c, msg, u, CALLST_N11); 3551122205Sharti break; 3552122205Sharti } 3553122205Sharti break; 3554122205Sharti 3555122205Sharti case SIGC_RELEASE_COMPL: 3556122205Sharti /* Q.2971:Call-Control-U 25/39 */ 3557122205Sharti /* Q.2971:Call-Control-N 26/39 */ 3558122205Sharti unx_release_compl(c, msg, u); 3559122205Sharti break; 3560122205Sharti 3561122205Sharti case SIGC_NOTIFY: 3562122205Sharti /* Q.2971:Call-Control-U 18/39 */ 3563122205Sharti /* Q.2971:Call-Control-N 19/39 */ 3564122205Sharti unx_notify(c, msg, u); 3565122205Sharti break; 3566122205Sharti 3567122205Sharti case SIGC_STATUS: 3568122205Sharti if (c->cstate == CALLST_U11 || c->cstate == CALLST_U12 || 3569122205Sharti c->cstate == CALLST_N11 || c->cstate == CALLST_N12) { 3570122205Sharti /* Q.2971:Call-Control-U 29/39 (U11) */ 3571122205Sharti /* Q.2971:Call-Control-U 30/39 (U12) */ 3572122205Sharti /* Q.2971:Call-Control-N 29/39 (N11) */ 3573122205Sharti /* Q.2971:Call-Control-N 31/39 (N12) */ 3574122205Sharti un11un12_status(c, msg, u); 3575122205Sharti break; 3576122205Sharti } 3577122205Sharti /* Q.2971:Call-Control-U 32/39 */ 3578122205Sharti /* Q.2971:Call-Control-N 33/39 */ 3579122205Sharti unx_status(c, msg, u); 3580122205Sharti break; 3581122205Sharti 3582122205Sharti case SIGC_STATUS_ENQ: 3583122205Sharti /* Q.2971:Call-Control-U 31/39 */ 3584122205Sharti /* Q.2971:Call-Control-N 32/39 */ 3585122205Sharti unx_status_enq(c, msg, u); 3586122205Sharti break; 3587122205Sharti 3588122205Sharti case SIGC_ADD_PARTY: 3589122205Sharti (void)uni_decode_body(msg, u, &c->uni->cx); 3590122205Sharti 3591122205Sharti if (c->type != CALL_LEAF && c->type != CALL_ROOT) { 3592122205Sharti uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, 3593122205Sharti &u->u.add_party.epref, UNI_EPSTATE_NULL); 3594122205Sharti goto drop; 3595122205Sharti } 3596122205Sharti switch (c->cstate) { 3597122205Sharti case CALLST_U7: 3598122205Sharti case CALLST_U8: 3599122205Sharti case CALLST_U10: 3600122205Sharti case CALLST_N4: 3601122205Sharti case CALLST_N10: 3602122205Sharti /* Q.2971:Call-Control-U 14/39 U7 */ 3603122205Sharti /* Q.2971:Call-Control-U 15/39 U8 */ 3604122205Sharti /* Q.2971:Call-Control-U 21/39 U10 */ 3605122205Sharti /* Q.2971:Call-Control-N 8/39 N4 */ 3606122205Sharti /* Q.2971:Call-Control-N 21/39 N10 */ 3607122205Sharti unx_add_party(c, msg, u, 1); 3608122205Sharti break; 3609122205Sharti 3610122205Sharti default: 3611122205Sharti unx_add_party(c, msg, u, 0); 3612122205Sharti goto drop; 3613122205Sharti } 3614122205Sharti break; 3615122205Sharti 3616122205Sharti case SIGC_PARTY_ALERTING: 3617122205Sharti (void)uni_decode_body(msg, u, &c->uni->cx); 3618122205Sharti 3619122205Sharti if (c->type != CALL_ROOT) { 3620122205Sharti uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, 3621122205Sharti &u->u.party_alerting.epref, -1); 3622122205Sharti goto drop; 3623122205Sharti } 3624122205Sharti switch (c->cstate) { 3625122205Sharti 3626122205Sharti default: 3627122205Sharti /* Q.2971 9.5.3.2.3a) */ 3628122205Sharti unx_party_alerting(c, msg, u, 0); 3629122205Sharti break; 3630122205Sharti 3631122205Sharti case CALLST_U4: 3632122205Sharti case CALLST_U10: 3633122205Sharti /* Q.2971:Call-Control-U 9/39 U4 */ 3634122205Sharti /* Q.2971:Call-Control-U 21/39 U10 */ 3635122205Sharti /* Q.2971:Call-Control-N 12/39 N7 */ 3636122205Sharti /* Q.2971:Call-Control-N 15/39 N8 */ 3637122205Sharti /* Q.2971:Call-Control-N 22/39 N10 */ 3638122205Sharti unx_party_alerting(c, msg, u, 1); 3639122205Sharti break; 3640122205Sharti } 3641122205Sharti break; 3642122205Sharti 3643122205Sharti case SIGC_ADD_PARTY_ACK: 3644122205Sharti (void)uni_decode_body(msg, u, &c->uni->cx); 3645122205Sharti 3646122205Sharti if (c->type != CALL_ROOT) { 3647122205Sharti uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, 3648122205Sharti &u->u.add_party_rej.epref, -1); 3649122205Sharti goto drop; 3650122205Sharti } 3651122205Sharti switch (c->cstate) { 3652122205Sharti 3653122205Sharti case CALLST_U10: 3654122205Sharti /* Q.2971:Call-Control-U 21/39 U10 */ 3655122205Sharti /* Q.2971:Call-Control-N 15/39 N8 */ 3656122205Sharti /* Q.2971:Call-Control-N 22/39 N10 */ 3657122205Sharti un10n8_add_party_ack(c, msg, u, 1); 3658122205Sharti break; 3659122205Sharti 3660122205Sharti default: 3661122205Sharti /* Q.2971 9.5.3.2.3a) */ 3662122205Sharti un10n8_add_party_ack(c, msg, u, 0); 3663122205Sharti break; 3664122205Sharti } 3665122205Sharti break; 3666122205Sharti 3667122205Sharti case SIGC_ADD_PARTY_REJ: 3668122205Sharti (void)uni_decode_body(msg, u, &c->uni->cx); 3669122205Sharti 3670122205Sharti if (c->type != CALL_ROOT) { 3671122205Sharti uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, 3672122205Sharti &u->u.add_party_rej.epref, -1); 3673122205Sharti goto drop; 3674122205Sharti } 3675122205Sharti switch (c->cstate) { 3676122205Sharti 3677122205Sharti case CALLST_U4: 3678122205Sharti case CALLST_U10: 3679122205Sharti case CALLST_N7: 3680122205Sharti case CALLST_N8: 3681122205Sharti case CALLST_N10: 3682122205Sharti /* Q.2971:Call-Control-U 9/39 U4 */ 3683122205Sharti /* Q.2971:Call-Control-U 21/39 U10 */ 3684122205Sharti /* Q.2971:Call-Control-N 12/39 N7 */ 3685122205Sharti /* Q.2971:Call-Control-N 15/39 N8 */ 3686122205Sharti /* Q.2971:Call-Control-N 22/39 N10 */ 3687122205Sharti unx_add_party_rej(c, msg, u, 1); 3688122205Sharti break; 3689122205Sharti 3690122205Sharti default: 3691122205Sharti /* Q.2971: 9.5.3.2.3b */ 3692122205Sharti unx_add_party_rej(c, msg, u, 0); 3693122205Sharti break; 3694122205Sharti } 3695122205Sharti break; 3696122205Sharti 3697122205Sharti case SIGC_DROP_PARTY: 3698122205Sharti (void)uni_decode_body(msg, u, &c->uni->cx); 3699122205Sharti 3700122205Sharti if (c->type != CALL_ROOT && c->type != CALL_LEAF) { 3701122205Sharti uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, 3702122205Sharti &u->u.drop_party.epref, -1); 3703122205Sharti goto drop; 3704122205Sharti } 3705122205Sharti switch (c->cstate) { 3706122205Sharti case CALLST_U11: 3707122205Sharti case CALLST_U12: 3708122205Sharti case CALLST_N11: 3709122205Sharti case CALLST_N12: 3710122205Sharti /* Q.2971:Call-Control-U 28/39 U11 */ 3711122205Sharti /* Q.2971:Call-Control-U 30/39 U12 */ 3712122205Sharti /* Q.2971:Call-Control-N 29/39 N11 */ 3713122205Sharti /* Q.2971:Call-Control-N 30/39 N12 */ 3714122205Sharti goto drop; 3715122205Sharti 3716122205Sharti case CALLST_NULL: 3717122205Sharti uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, 3718122205Sharti &u->u.drop_party.epref, UNI_EPSTATE_NULL); 3719122205Sharti goto drop; 3720122205Sharti 3721122205Sharti case CALLST_U3: 3722122205Sharti case CALLST_N3: 3723122205Sharti /* L3MU_17_38 */ 3724122205Sharti unx_drop_party(c, msg, u, 0); 3725122205Sharti break; 3726122205Sharti 3727122205Sharti case CALLST_U8: 3728122205Sharti if (c->uni->sb_tb) { 3729122205Sharti /* L3MU_06_0[3-6] */ 3730122205Sharti unx_drop_party(c, msg, u, 0); 3731122205Sharti break; 3732122205Sharti } 3733122205Sharti /* FALLTHRU */ 3734122205Sharti 3735122205Sharti default: 3736122205Sharti /* Q.2971:Call-Control-U 26/39 Ux */ 3737122205Sharti /* Q.2971:Call-Control-U 21/39 U10 */ 3738122205Sharti /* Q.2971:Call-Control-N 27/39 Nx */ 3739122205Sharti /* Q.2971:Call-Control-N 21/39 N10 */ 3740122205Sharti unx_drop_party(c, msg, u, 1); 3741122205Sharti break; 3742122205Sharti } 3743122205Sharti break; 3744122205Sharti 3745122205Sharti case SIGC_DROP_PARTY_ACK: 3746122205Sharti (void)uni_decode_body(msg, u, &c->uni->cx); 3747122205Sharti 3748122205Sharti if (c->type != CALL_ROOT && c->type != CALL_LEAF) { 3749122205Sharti uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, 3750122205Sharti &u->u.drop_party_ack.epref, -1); 3751122205Sharti goto drop; 3752122205Sharti } 3753122205Sharti switch (c->cstate) { 3754122205Sharti 3755122205Sharti case CALLST_U11: 3756122205Sharti case CALLST_U12: 3757122205Sharti /* Q.2971:Call-Control-U 28/39 U11 */ 3758122205Sharti /* Q.2971:Call-Control-U 30/39 U12 */ 3759122205Sharti /* Q.2971:Call-Control-N 29/39 N11 */ 3760122205Sharti /* Q.2971:Call-Control-N 30/39 N12 */ 3761122205Sharti goto drop; 3762122205Sharti 3763122205Sharti case CALLST_NULL: 3764122205Sharti uni_bad_message(c, u, UNI_CAUSE_MSG_INCOMP, 3765122205Sharti &u->u.drop_party.epref, UNI_EPSTATE_NULL); 3766122205Sharti goto drop; 3767122205Sharti 3768122205Sharti case CALLST_U4: 3769122205Sharti case CALLST_N4: 3770122205Sharti case CALLST_U7: 3771122205Sharti case CALLST_N7: 3772122205Sharti case CALLST_U8: 3773122205Sharti case CALLST_N8: 3774122205Sharti case CALLST_U10: 3775122205Sharti case CALLST_N10: 3776122205Sharti /* Q.2971:Call-Control-U 26/39 Ux */ 3777122205Sharti /* Q.2971:Call-Control-U 21/39 U10 */ 3778122205Sharti /* Q.2971:Call-Control-N 27/39 Nx */ 3779122205Sharti /* Q.2971:Call-Control-N 22/39 N10 */ 3780122205Sharti unx_drop_party_ack(c, msg, u, 1); 3781122205Sharti break; 3782122205Sharti 3783122205Sharti default: 3784122205Sharti /* Q.2971 10.5 4th paragraph */ 3785122205Sharti unx_drop_party_ack(c, msg, u, 0); 3786122205Sharti break; 3787122205Sharti } 3788122205Sharti break; 3789122205Sharti 3790122205Sharti case SIGC_COBISETUP: /* XXX */ 3791122205Sharti unx_unknown(c, msg, u); 3792122205Sharti break; 3793122205Sharti 3794122205Sharti /* 3795122205Sharti * User signals 3796122205Sharti */ 3797122205Sharti case SIGC_SETUP_request: 3798122205Sharti if (c->cstate == CALLST_NULL) { 3799122205Sharti /* Q.2971:Call-Control-U 4/39 (U0) */ 3800122205Sharti /* Q.2971:Call-Control-N 4/39 (N0) */ 3801122205Sharti if (c->uni->proto == UNIPROTO_UNI40N) 3802122205Sharti un0_setup_request(c, msg, cookie, CALLST_N6); 3803122205Sharti else 3804122205Sharti un0_setup_request(c, msg, cookie, CALLST_U1); 3805122205Sharti break; 3806122205Sharti } 3807122205Sharti VERBOSE(c->uni, UNI_FAC_ERR, 1, "setup.request in cs=%s", 3808122205Sharti callstates[c->cstate].name); 3809122205Sharti uniapi_call_error(c, UNIAPI_ERROR_BAD_CALLSTATE, cookie); 3810122205Sharti uni_msg_destroy(msg); 3811122205Sharti break; 3812122205Sharti 3813122205Sharti case SIGC_SETUP_response: 3814122205Sharti if (c->cstate == CALLST_U6 || c->cstate == CALLST_U9 || 3815122205Sharti c->cstate == CALLST_U7) { 3816122205Sharti /* Q.2971:Call-Control-U 13/39 (U6) */ 3817122205Sharti /* Q.2971:Call-Control-U 14/39 (U7) */ 3818122205Sharti /* Q.2971:Call-Control-U 17/39 (U9) */ 3819122205Sharti unx_setup_response(c, msg, cookie, CALLST_U8); 3820122205Sharti break; 3821122205Sharti } 3822122205Sharti if (c->cstate == CALLST_N1 || c->cstate == CALLST_N3 || 3823122205Sharti c->cstate == CALLST_N4) { 3824122205Sharti /* Q.2971:Call-Control-N 39/39 (N1) */ 3825122205Sharti /* Q.2971:Call-Control-N 7/39 (N3) */ 3826122205Sharti /* Q.2971:Call-Control-N 8/39 (N4) */ 3827122205Sharti unx_setup_response(c, msg, cookie, CALLST_N10); 3828122205Sharti break; 3829122205Sharti } 3830122205Sharti VERBOSE(c->uni, UNI_FAC_ERR, 1, "setup.response in cs=%s", 3831122205Sharti callstates[c->cstate].name); 3832122205Sharti uniapi_call_error(c, UNIAPI_ERROR_BAD_CALLSTATE, cookie); 3833122205Sharti uni_msg_destroy(msg); 3834122205Sharti break; 3835122205Sharti 3836122205Sharti case SIGC_SETUP_COMPLETE_request: 3837122205Sharti if (c->cstate == CALLST_N8) { 3838122205Sharti /* Q.2971:Call-Control-N 15/39 (N8) */ 3839122205Sharti n8_setup_compl_request(c, msg, cookie, CALLST_N10); 3840122205Sharti break; 3841122205Sharti } 3842122205Sharti VERBOSE(c->uni, UNI_FAC_ERR, 1, "setup_compl.request in cs=%s", 3843122205Sharti callstates[c->cstate].name); 3844122205Sharti uniapi_call_error(c, UNIAPI_ERROR_BAD_CALLSTATE, cookie); 3845122205Sharti uni_msg_destroy(msg); 3846122205Sharti break; 3847122205Sharti 3848122205Sharti case SIGC_PROCEEDING_request: 3849122205Sharti if (c->cstate == CALLST_U6) { 3850122205Sharti /* Q.2971:Call-Control-U 12/39 (U6) */ 3851122205Sharti u6n1_proceeding_request(c, msg, cookie, CALLST_U9); 3852122205Sharti break; 3853122205Sharti } 3854122205Sharti if (c->cstate == CALLST_N1) { 3855122205Sharti /* Q.2971:Call-Control-N 6/39 (N1) */ 3856122205Sharti u6n1_proceeding_request(c, msg, cookie, CALLST_N3); 3857122205Sharti break; 3858122205Sharti } 3859122205Sharti VERBOSE(c->uni, UNI_FAC_ERR, 1, "proceeding.request in cs=%s", 3860122205Sharti callstates[c->cstate].name); 3861122205Sharti uniapi_call_error(c, UNIAPI_ERROR_BAD_CALLSTATE, cookie); 3862122205Sharti uni_msg_destroy(msg); 3863122205Sharti break; 3864122205Sharti 3865122205Sharti case SIGC_ALERTING_request: 3866122205Sharti if (c->cstate == CALLST_U6 || c->cstate == CALLST_U9) { 3867122205Sharti /* Q.2971:Call-Control-U 13/39 (U6) */ 3868122205Sharti /* Q.2971:Call-Control-U 17/39 (U9) */ 3869122205Sharti unx_alerting_request(c, msg, cookie, CALLST_U7); 3870122205Sharti break; 3871122205Sharti } 3872131826Sharti if (c->cstate == CALLST_N1 || c->cstate == CALLST_N3) { 3873122205Sharti /* Q.2971:Call-Control-N 38/39 (N1) */ 3874122205Sharti /* Q.2971:Call-Control-N 7/39 (N3) */ 3875122205Sharti unx_alerting_request(c, msg, cookie, CALLST_N4); 3876122205Sharti break; 3877122205Sharti } 3878122205Sharti VERBOSE(c->uni, UNI_FAC_ERR, 1, "alerting.request in cs=%s", 3879122205Sharti callstates[c->cstate].name); 3880122205Sharti uniapi_call_error(c, UNIAPI_ERROR_BAD_CALLSTATE, cookie); 3881122205Sharti uni_msg_destroy(msg); 3882122205Sharti break; 3883122205Sharti 3884122205Sharti case SIGC_RELEASE_request: 3885122205Sharti switch (c->cstate) { 3886122205Sharti 3887122205Sharti case CALLST_U1: 3888122205Sharti case CALLST_U3: 3889122205Sharti case CALLST_U4: 3890122205Sharti case CALLST_U6: 3891122205Sharti case CALLST_U7: 3892122205Sharti case CALLST_U8: 3893122205Sharti case CALLST_U9: 3894122205Sharti case CALLST_U10: 3895122205Sharti /* Q.2971:Call-Control-U 27/39 */ 3896122205Sharti unx_release_request(c, msg, cookie, CALLST_U11); 3897122205Sharti break; 3898122205Sharti 3899122205Sharti case CALLST_N1: 3900122205Sharti case CALLST_N3: 3901122205Sharti case CALLST_N4: 3902122205Sharti case CALLST_N6: 3903122205Sharti case CALLST_N7: 3904122205Sharti case CALLST_N8: 3905122205Sharti case CALLST_N9: 3906122205Sharti case CALLST_N10: 3907122205Sharti /* Q.2971:Call-Control-N 28/39 */ 3908122205Sharti unx_release_request(c, msg, cookie, CALLST_N12); 3909122205Sharti break; 3910122205Sharti 3911122205Sharti case CALLST_U11: 3912122205Sharti case CALLST_U12: 3913122205Sharti case CALLST_N11: 3914122205Sharti case CALLST_N12: 3915122205Sharti case CALLST_NULL: 3916122205Sharti VERBOSE(c->uni, UNI_FAC_ERR, 1, 3917122205Sharti "release.request in cs=%s", 3918122205Sharti callstates[c->cstate].name); 3919122205Sharti uniapi_call_error(c, UNIAPI_ERROR_BAD_CALLSTATE, 3920122205Sharti cookie); 3921122205Sharti uni_msg_destroy(msg); 3922122205Sharti break; 3923122205Sharti } 3924122205Sharti break; 3925122205Sharti 3926122205Sharti case SIGC_RELEASE_response: 3927122205Sharti if (c->cstate == CALLST_U6 || c->cstate == CALLST_U12 || 3928122205Sharti c->cstate == CALLST_N1 || c->cstate == CALLST_N11) { 3929122205Sharti /* Q.2971:Call-Control-U 12/39 (U6) */ 3930122205Sharti /* Q.2971:Call-Control-U 30/39 (U12) */ 3931122205Sharti /* Q.2971:Call-Control-N 6/39 (N1) */ 3932122205Sharti /* Q.2971:Call-Control-N 29/39 (N11) */ 3933122205Sharti unx_release_response(c, msg, cookie); 3934122205Sharti break; 3935122205Sharti } 3936122205Sharti VERBOSE(c->uni, UNI_FAC_ERR, 1, "release.response in cs=%s", 3937122205Sharti callstates[c->cstate].name); 3938122205Sharti uniapi_call_error(c, UNIAPI_ERROR_BAD_CALLSTATE, cookie); 3939122205Sharti uni_msg_destroy(msg); 3940122205Sharti break; 3941122205Sharti 3942122205Sharti case SIGC_NOTIFY_request: 3943122205Sharti /* Q.2971:Call-Control-U 18/39 */ 3944122205Sharti /* Q.2971:Call-Control-N 19/39 */ 3945122205Sharti unx_notify_request(c, msg, cookie); 3946122205Sharti break; 3947122205Sharti 3948122205Sharti case SIGC_STATUS_ENQUIRY_request: 3949122205Sharti /* Q.2971:Call-Control-U 31/39 */ 3950122205Sharti /* Q.2971:Call-Control-N 32/39 */ 3951122205Sharti unx_status_enquiry_request(c, msg, cookie); 3952122205Sharti break; 3953122205Sharti 3954122205Sharti case SIGC_ADD_PARTY_request: 3955122205Sharti if (c->cstate == CALLST_U4 || c->cstate == CALLST_U10 || 3956122205Sharti c->cstate == CALLST_N7 || c->cstate == CALLST_N10) { 3957122205Sharti /* Q.2971:Call-Control-U 9-10/39 (U4) */ 3958122205Sharti /* Q.2971:Call-Control-U 21/39 (U10) */ 3959122205Sharti /* Q.2971:Call-Control-N 12/39 (N7) */ 3960122205Sharti /* Q.2971:Call-Control-N 22/39 (N10) */ 3961122205Sharti unx_add_party_request(c, msg, cookie); 3962122205Sharti break; 3963122205Sharti } 3964122205Sharti VERBOSE(c->uni, UNI_FAC_ERR, 1, "add-party.request in cs=%s", 3965122205Sharti callstates[c->cstate].name); 3966122205Sharti uniapi_call_error(c, UNIAPI_ERROR_BAD_CALLSTATE, cookie); 3967122205Sharti uni_msg_destroy(msg); 3968122205Sharti break; 3969122205Sharti 3970122205Sharti case SIGC_PARTY_ALERTING_request: 3971122205Sharti if (c->cstate == CALLST_U7 || c->cstate == CALLST_U8 || 3972122205Sharti c->cstate == CALLST_U10 || 3973122205Sharti c->cstate == CALLST_N4 || c->cstate == CALLST_N10) { 3974122205Sharti /* Q.2971:Call-Control-U 14/39 U7 */ 3975122205Sharti /* Q.2971:Call-Control-U 15/39 U8 */ 3976122205Sharti /* Q.2971:Call-Control-U 21/39 U10 */ 3977122205Sharti /* Q.2971:Call-Control-N 8/39 N4 */ 3978122205Sharti /* Q.2971:Call-Control-N 22/39 N10 */ 3979122205Sharti unx_party_alerting_request(c, msg, cookie); 3980122205Sharti break; 3981122205Sharti } 3982122205Sharti VERBOSE(c->uni, UNI_FAC_ERR, 1, 3983122205Sharti "party-alerting.request in cs=%s", 3984122205Sharti callstates[c->cstate].name); 3985122205Sharti uniapi_call_error(c, UNIAPI_ERROR_BAD_CALLSTATE, cookie); 3986122205Sharti uni_msg_destroy(msg); 3987122205Sharti break; 3988122205Sharti 3989122205Sharti case SIGC_ADD_PARTY_ACK_request: 3990122205Sharti if (c->cstate == CALLST_U10 || c->cstate == CALLST_N10) { 3991122205Sharti /* Q.2971:Call-Control-U 21/39 (U10) */ 3992122205Sharti /* Q.2971:Call-Control-N 22/39 (N10)*/ 3993122205Sharti un10_add_party_ack_request(c, msg, cookie); 3994122205Sharti break; 3995122205Sharti } 3996122205Sharti VERBOSE(c->uni, UNI_FAC_ERR, 1, 3997122205Sharti "add-party-ack.request in cs=%s", 3998122205Sharti callstates[c->cstate].name); 3999122205Sharti uniapi_call_error(c, UNIAPI_ERROR_BAD_CALLSTATE, cookie); 4000122205Sharti uni_msg_destroy(msg); 4001122205Sharti break; 4002122205Sharti 4003122205Sharti case SIGC_ADD_PARTY_REJ_request: 4004122205Sharti if (c->cstate == CALLST_U7 || c->cstate == CALLST_U8 || 4005122205Sharti c->cstate == CALLST_U10 || 4006122205Sharti c->cstate == CALLST_N4 || c->cstate == CALLST_N10) { 4007122205Sharti /* Q.2971:Call-Control-U 14/39 U7 */ 4008122205Sharti /* Q.2971:Call-Control-U 15/39 U8 */ 4009122205Sharti /* Q.2971:Call-Control-U 21/39 U10 */ 4010122205Sharti /* Q.2971:Call-Control-N 8/39 N4 */ 4011122205Sharti /* Q.2971:Call-Control-N 22/39 N10 */ 4012122205Sharti unx_add_party_rej_request(c, msg, cookie); 4013122205Sharti break; 4014122205Sharti } 4015122205Sharti VERBOSE(c->uni, UNI_FAC_ERR, 1, 4016122205Sharti "add-party-rej.request in cs=%s", 4017122205Sharti callstates[c->cstate].name); 4018122205Sharti uniapi_call_error(c, UNIAPI_ERROR_BAD_CALLSTATE, cookie); 4019122205Sharti uni_msg_destroy(msg); 4020122205Sharti break; 4021122205Sharti 4022122205Sharti case SIGC_DROP_PARTY_request: 4023122205Sharti if (c->cstate != CALLST_U11 && c->cstate != CALLST_U12 && 4024122205Sharti c->cstate != CALLST_N11 && c->cstate != CALLST_N12 && 4025122205Sharti c->cstate != CALLST_NULL) { 4026122205Sharti /* Q.2971:Call-Control-U 21/39 U10 */ 4027122205Sharti /* Q.2971:Call-Control-U 26/39 U1-U9 */ 4028122205Sharti /* Q.2971:Call-Control-N 22/39 N10 */ 4029122205Sharti /* Q.2971:Call-Control-N 27/39 N1-N9 */ 4030122205Sharti unx_drop_party_request(c, msg, cookie); 4031122205Sharti break; 4032122205Sharti } 4033122205Sharti VERBOSE(c->uni, UNI_FAC_ERR, 1, "drop-party.request in cs=%s", 4034122205Sharti callstates[c->cstate].name); 4035122205Sharti uniapi_call_error(c, UNIAPI_ERROR_BAD_CALLSTATE, cookie); 4036122205Sharti uni_msg_destroy(msg); 4037122205Sharti break; 4038122205Sharti 4039122205Sharti case SIGC_DROP_PARTY_ACK_request: 4040122205Sharti if (c->cstate != CALLST_U11 && c->cstate != CALLST_U12 && 4041122205Sharti c->cstate != CALLST_N11 && c->cstate != CALLST_N12 && 4042122205Sharti c->cstate != CALLST_NULL) { 4043122205Sharti /* Q.2971:Call-Control-U 21/39 U10 */ 4044122205Sharti /* Q.2971:Call-Control-U 26/39 U1-U9 */ 4045122205Sharti /* Q.2971:Call-Control-N 22/39 N10 */ 4046122205Sharti /* Q.2971:Call-Control-N 27/39 N1-N9 */ 4047122205Sharti unx_drop_party_ack_request(c, msg, cookie); 4048122205Sharti break; 4049122205Sharti } 4050122205Sharti VERBOSE(c->uni, UNI_FAC_ERR, 1, 4051122205Sharti "drop-party-ack.request in cs=%s", 4052122205Sharti callstates[c->cstate].name); 4053122205Sharti uniapi_call_error(c, UNIAPI_ERROR_BAD_CALLSTATE, cookie); 4054122205Sharti uni_msg_destroy(msg); 4055122205Sharti break; 4056122205Sharti 4057122205Sharti case SIGC_ABORT_CALL_request: 4058122205Sharti { 4059122205Sharti struct uni *uni = c->uni; 4060122205Sharti 4061122205Sharti uni_destroy_call(c, 0); 4062122205Sharti uniapi_uni_error(uni, UNIAPI_OK, cookie, UNI_CALLSTATE_U0); 4063122205Sharti break; 4064122205Sharti } 4065122205Sharti 4066122205Sharti /* 4067122205Sharti * Timers 4068122205Sharti */ 4069122205Sharti case SIGC_T301: 4070122205Sharti if (c->cstate == CALLST_U4 || c->cstate == CALLST_N7) { 4071122205Sharti /* Q.2971:Call-Control-U Missing */ 4072122205Sharti /* Q.2971:Call-Control-N 14/39 */ 4073122205Sharti u4n7_t301(c); 4074122205Sharti break; 4075122205Sharti } 4076122205Sharti VERBOSE(c->uni, UNI_FAC_ERR, 1, "T301 in cs=%s", 4077122205Sharti callstates[c->cstate].name); 4078122205Sharti break; 4079122205Sharti 4080122205Sharti case SIGC_T303: 4081122205Sharti if (c->cstate == CALLST_U1 || c->cstate == CALLST_N6) { 4082122205Sharti /* Q.2971:Call-Control-U 6/39 */ 4083122205Sharti /* Q.2971:Call-Control-N 11/39 */ 4084122205Sharti u1n6_t303(c); 4085122205Sharti break; 4086122205Sharti } 4087122205Sharti VERBOSE(c->uni, UNI_FAC_ERR, 1, "T303 in cs=%s", 4088122205Sharti callstates[c->cstate].name); 4089122205Sharti break; 4090122205Sharti 4091122205Sharti case SIGC_T308: 4092122205Sharti if (c->cstate == CALLST_U11 || c->cstate == CALLST_N12) { 4093122205Sharti /* Q.2971:Call-Control-U 28/39 */ 4094122205Sharti /* Q.2971:Call-Control-N 30/39 */ 4095122205Sharti u11n12_t308(c); 4096122205Sharti break; 4097122205Sharti } 4098122205Sharti VERBOSE(c->uni, UNI_FAC_ERR, 1, "T308 in cs=%s", 4099122205Sharti callstates[c->cstate].name); 4100122205Sharti break; 4101122205Sharti 4102122205Sharti case SIGC_T310: 4103122205Sharti if (c->cstate == CALLST_U3 || c->cstate == CALLST_N9) { 4104122205Sharti /* Q.2971:Call-Control-U 7/39 */ 4105122205Sharti /* Q.2971:Call-Control-N 17/39 */ 4106122205Sharti u3n9_t310(c); 4107122205Sharti break; 4108122205Sharti } 4109122205Sharti VERBOSE(c->uni, UNI_FAC_ERR, 1, "T310 in cs=%s", 4110122205Sharti callstates[c->cstate].name); 4111122205Sharti break; 4112122205Sharti 4113122205Sharti case SIGC_T313: 4114122205Sharti if (c->cstate == CALLST_U8) { 4115122205Sharti /* Q.2971:Call-Control-U 15/39 */ 4116122205Sharti u8_t313(c); 4117122205Sharti break; 4118122205Sharti } 4119122205Sharti VERBOSE(c->uni, UNI_FAC_ERR, 1, "T313 in cs=%s", 4120122205Sharti callstates[c->cstate].name); 4121122205Sharti break; 4122122205Sharti 4123122205Sharti case SIGC_T322: 4124122205Sharti /* Q.2971:Call-Control-U 34/39 */ 4125122205Sharti /* Q.2971:Call-Control-N 35/39 */ 4126122205Sharti unx_t322(c); 4127122205Sharti break; 4128122205Sharti 4129122205Sharti case SIGC_CALL_DELETE: 4130122205Sharti CALL_FREE(c); 4131122205Sharti break; 4132122205Sharti 4133122205Sharti /* 4134122205Sharti * Party-Control 4135122205Sharti */ 4136122205Sharti case SIGC_DROP_PARTY_indication: 4137122205Sharti if (c->uni->proto == UNIPROTO_UNI40U) 4138122205Sharti /* Q.2971:Call-Control-U 23/39 */ 4139122205Sharti ux_drop_party_indication(c, msg); 4140122205Sharti else 4141122205Sharti /* Q.2971:Call-Control-N 23/39 */ 4142122205Sharti nx_drop_party_indication(c, msg); 4143122205Sharti break; 4144122205Sharti 4145122205Sharti case SIGC_DROP_PARTY_ACK_indication: 4146122205Sharti if (c->uni->proto == UNIPROTO_UNI40U) 4147122205Sharti /* Q.2971:Call-Control-U 23/39 */ 4148122205Sharti ux_drop_party_ack_indication(c, msg); 4149122205Sharti else 4150122205Sharti /* Q.2971:Call-Control-N 23/39 */ 4151122205Sharti nx_drop_party_ack_indication(c, msg); 4152122205Sharti break; 4153122205Sharti 4154122205Sharti case SIGC_ADD_PARTY_REJ_indication: 4155122205Sharti if (c->uni->proto == UNIPROTO_UNI40U) 4156122205Sharti /* Q.2971:Call-Control-U 23/39 */ 4157122205Sharti ux_add_party_rej_indication(c, msg); 4158122205Sharti else 4159122205Sharti /* Q.2971:Call-Control-N 23/39 */ 4160122205Sharti nx_add_party_rej_indication(c, msg); 4161122205Sharti break; 4162122205Sharti 4163122205Sharti 4164122205Sharti case SIGC_SEND_DROP_PARTY: 4165122205Sharti /* Q.2971:Call-Control-U 21/39 */ 4166122205Sharti /* Q.2971:Call-Control-U 25/39 */ 4167122205Sharti if (uni_party_act_count(c, 2) != 0) 4168122205Sharti (void)uni_send_output(u, c->uni); 4169122205Sharti else if(c->cstate != CALLST_U11) { 4170122205Sharti c->uni->cause = u->u.drop_party.cause; 4171122205Sharti clear_callD(c); 4172122205Sharti } 4173122205Sharti UNI_FREE(u); 4174122205Sharti break; 4175122205Sharti 4176122205Sharti case SIGC_SEND_DROP_PARTY_ACK: 4177122205Sharti /* Q.2971:Call-Control-U 21/39 */ 4178122205Sharti /* Q.2971:Call-Control-U 25/39 */ 4179122205Sharti if (uni_party_act_count(c, 2) != 0) 4180122205Sharti (void)uni_send_output(u, c->uni); 4181122205Sharti else if (c->cstate != CALLST_U11) { 4182122205Sharti c->uni->cause = u->u.drop_party_ack.cause; 4183122205Sharti clear_callD(c); 4184122205Sharti } 4185122205Sharti UNI_FREE(u); 4186122205Sharti break; 4187122205Sharti 4188122205Sharti case SIGC_SEND_ADD_PARTY_REJ: 4189122205Sharti /* Q.2971:Call-Control-U 21/39 */ 4190122205Sharti /* Q.2971:Call-Control-U 24/39 */ 4191122205Sharti unx_send_add_party_rej(c, u); 4192122205Sharti break; 4193122205Sharti 4194122205Sharti case SIGC_SEND_STATUS_ENQ: 4195122205Sharti /* Q.2971:Call-Control-U 21/39 */ 4196122205Sharti /* Q.2971:Call-Control-U 25/39 */ 4197122205Sharti unx_send_party_status_enq(c, u); 4198122205Sharti break; 4199122205Sharti 4200122205Sharti case SIGC_PARTY_DESTROYED: 4201122205Sharti c->uni->funcs->uni_output(c->uni, c->uni->arg, 4202122205Sharti UNIAPI_PARTY_DESTROYED, cookie, msg); 4203122205Sharti break; 4204122205Sharti 4205122205Sharti case SIGC_END: 4206122205Sharti break; 4207122205Sharti } 4208122205Sharti 4209122205Sharti return; 4210122205Sharti 4211122205Sharti drop: 4212122205Sharti /* 4213122205Sharti * This is for SAAL message signals that should be dropped. 4214122205Sharti */ 4215122205Sharti uni_msg_destroy(msg); 4216122205Sharti UNI_FREE(u); 4217122205Sharti} 4218122205Sharti 4219122205Sharti/**********************************************************************/ 4220122205Sharti 4221122205Sharti/* 4222122205Sharti * Timeout functions 4223122205Sharti */ 4224122205Shartistatic void 4225122205Shartit308_func(struct call *c) 4226122205Sharti{ 4227122205Sharti uni_enq_call(c, SIGC_T308, 0, NULL, NULL); 4228122205Sharti} 4229122205Shartistatic void 4230122205Shartit303_func(struct call *c) 4231122205Sharti{ 4232122205Sharti uni_enq_call(c, SIGC_T303, 0, NULL, NULL); 4233122205Sharti} 4234122205Shartistatic void 4235122205Shartit301_func(struct call *c) 4236122205Sharti{ 4237122205Sharti uni_enq_call(c, SIGC_T301, 0, NULL, NULL); 4238122205Sharti} 4239122205Shartistatic void 4240122205Shartit310_func(struct call *c) 4241122205Sharti{ 4242122205Sharti uni_enq_call(c, SIGC_T310, 0, NULL, NULL); 4243122205Sharti} 4244122205Shartistatic void 4245122205Shartit313_func(struct call *c) 4246122205Sharti{ 4247122205Sharti uni_enq_call(c, SIGC_T313, 0, NULL, NULL); 4248122205Sharti} 4249122205Sharti 4250122205Shartistatic void 4251122205Shartit322_func(struct call *c) 4252122205Sharti{ 4253122205Sharti uni_enq_call(c, SIGC_T322, 0, NULL, NULL); 4254122205Sharti} 4255122205Sharti 4256122205Sharti/**********************************************************************/ 4257122205Sharti 4258122205Sharti/* 4259122205Sharti * Check whether the peer state is compatible with our state. 4260122205Sharti * Return the new callstate we should go to (either U0 or the current 4261122205Sharti * state). 4262122205Sharti * None of the state is U0 here. My state is not U11 or U12. 4263122205Sharti * 4264122205Sharti * Well, this turns out to be not so easy: the status enquiry could have 4265122205Sharti * been sent before we changed into the current state - the status will 4266122205Sharti * report a previous state without anything been lost. 4267122205Sharti * 4268122205Sharti * Incoming states are incompatible with outgoing states. Everything is ok. 4269122205Sharti */ 4270122205Shartistatic enum call_state 4271122205Shartistate_compat(struct call *c, enum uni_callstate peer) 4272122205Sharti{ 4273122205Sharti if ((c->cstate == CALLST_U1 || 4274122205Sharti c->cstate == CALLST_U3 || 4275122205Sharti c->cstate == CALLST_U4) && 4276122205Sharti (peer == UNI_CALLSTATE_N6 || 4277122205Sharti peer == UNI_CALLSTATE_N7 || 4278122205Sharti peer == UNI_CALLSTATE_N8 || 4279122205Sharti peer == UNI_CALLSTATE_N9)) 4280122205Sharti return (CALLST_NULL); 4281122205Sharti 4282122205Sharti if ((c->cstate == CALLST_N6 || 4283122205Sharti c->cstate == CALLST_N7 || 4284122205Sharti c->cstate == CALLST_N8 || 4285122205Sharti c->cstate == CALLST_N9) && 4286122205Sharti (peer == UNI_CALLSTATE_U1 || 4287122205Sharti peer == UNI_CALLSTATE_U3 || 4288122205Sharti peer == UNI_CALLSTATE_U4)) 4289122205Sharti return (CALLST_NULL); 4290122205Sharti 4291122205Sharti if ((peer == UNI_CALLSTATE_N1 || 4292122205Sharti peer == UNI_CALLSTATE_N3 || 4293122205Sharti peer == UNI_CALLSTATE_N4) && 4294122205Sharti (c->cstate == CALLST_U6 || 4295122205Sharti c->cstate == CALLST_U7 || 4296122205Sharti c->cstate == CALLST_U8 || 4297122205Sharti c->cstate == CALLST_N9)) 4298122205Sharti return (CALLST_NULL); 4299122205Sharti 4300122205Sharti if ((peer == UNI_CALLSTATE_U6 || 4301122205Sharti peer == UNI_CALLSTATE_U7 || 4302122205Sharti peer == UNI_CALLSTATE_U8 || 4303122205Sharti peer == UNI_CALLSTATE_U9) && 4304122205Sharti (c->cstate == CALLST_N1 || 4305122205Sharti c->cstate == CALLST_N3 || 4306122205Sharti c->cstate == CALLST_N4)) 4307122205Sharti return (CALLST_NULL); 4308122205Sharti 4309122205Sharti return (c->cstate); 4310122205Sharti} 4311