summaryrefslogtreecommitdiffstats
path: root/sys/contrib/ngatm/netnatm/sig/sig_party.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/ngatm/netnatm/sig/sig_party.c')
-rw-r--r--sys/contrib/ngatm/netnatm/sig/sig_party.c1353
1 files changed, 1353 insertions, 0 deletions
diff --git a/sys/contrib/ngatm/netnatm/sig/sig_party.c b/sys/contrib/ngatm/netnatm/sig/sig_party.c
new file mode 100644
index 0000000..f9d5cd0
--- /dev/null
+++ b/sys/contrib/ngatm/netnatm/sig/sig_party.c
@@ -0,0 +1,1353 @@
+/*
+ * Copyright (c) 1996-2003
+ * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ *
+ * $Begemot: libunimsg/netnatm/sig/sig_party.c,v 1.18 2004/08/05 07:11:01 brandt Exp $
+ *
+ * Party instance handling
+ */
+
+#include <netnatm/unimsg.h>
+#include <netnatm/saal/sscfudef.h>
+#include <netnatm/msg/unistruct.h>
+#include <netnatm/msg/unimsglib.h>
+#include <netnatm/sig/uni.h>
+
+#include <netnatm/sig/unipriv.h>
+#include <netnatm/sig/unimkmsg.h>
+#include <netnatm/sig/unimsgcpy.h>
+
+static void drop_partyE(struct party *p);
+static int epstate_compat(struct party *, enum uni_epstate);
+
+#define DEF_PRIV_SIG(NAME, FROM) [SIG##NAME] = "SIG"#NAME,
+static const char *const party_sigs[] = {
+ DEF_PARTY_SIGS
+};
+#undef DEF_PRIV_SIG
+
+TIMER_FUNC_PARTY(t397, t397_func)
+TIMER_FUNC_PARTY(t398, t398_func)
+TIMER_FUNC_PARTY(t399, t399_func)
+
+static __inline void
+set_party_state(struct party *p, enum uni_epstate state)
+{
+ if (p->state != state) {
+ VERBOSE(p->call->uni, UNI_FAC_CALL, 1,
+ "party %u/%u %u/%u PU%u -> PU%u",
+ p->call->cref, p->call->mine,
+ p->epref, p->flags & PARTY_MINE, p->state, state);
+ p->state = state;
+ }
+}
+
+/*
+ * Create a party with a given endpoint reference.
+ * No check is done, that a party with this epref does not alreay exist.
+ */
+struct party *
+uni_create_partyx(struct call *c, u_int epref, u_int mine, uint32_t cookie)
+{
+ struct party *p;
+ struct uni_msg *api;
+ struct uniapi_party_created *ind;
+
+ mine = (mine ? PARTY_MINE : 0);
+
+ if ((p = PARTY_ALLOC()) == NULL)
+ return (NULL);
+
+ if ((ind = ALLOC_API(struct uniapi_party_created, api)) == NULL) {
+ PARTY_FREE(p);
+ return (NULL);
+ }
+
+ ind->cref.cref = c->cref;
+ ind->cref.flag = c->mine;
+ MK_IE_EPREF(ind->epref, epref, mine);
+ ind->epref.h.act = UNI_IEACT_DEFAULT;
+
+ p->call = c;
+ p->epref = epref;
+ p->flags = mine;
+ p->state = UNI_EPSTATE_NULL;;
+
+ TIMER_INIT_PARTY(p, t397);
+ TIMER_INIT_PARTY(p, t398);
+ TIMER_INIT_PARTY(p, t399);
+
+ TAILQ_INSERT_HEAD(&c->parties, p, link);
+
+ c->uni->funcs->uni_output(c->uni, c->uni->arg,
+ UNIAPI_PARTY_CREATED, cookie, api);
+
+ VERBOSE(c->uni, UNI_FAC_CALL, 1, "created party %u/%s %u/%s",
+ p->call->cref, p->call->mine ? "mine" : "his",
+ p->epref, (p->flags & PARTY_MINE) ? "mine" : "his");
+
+ return (p);
+
+}
+
+struct party *
+uni_create_party(struct call *c, struct uni_ie_epref *epref)
+{
+ return (uni_create_partyx(c, epref->epref, epref->flag, 0));
+}
+
+struct party *
+uni_find_party(struct call *c, struct uni_ie_epref *epref)
+{
+ struct party *p;
+
+ TAILQ_FOREACH(p, &c->parties, link)
+ if (p->epref == epref->epref &&
+ (!(p->flags & PARTY_MINE) == !epref->flag))
+ return (p);
+ return (NULL);
+}
+struct party *
+uni_find_partyx(struct call *c, u_int epref, u_int mine)
+{
+ struct party *p;
+
+ TAILQ_FOREACH(p, &c->parties, link)
+ if (p->epref == epref && (!(p->flags & PARTY_MINE) == !mine))
+ return (p);
+ return (NULL);
+}
+
+/*
+ * Destroy a party.
+ * This function is assumed to remove the party from the parent's call
+ * party list.
+ */
+void
+uni_destroy_party(struct party *p, int really)
+{
+ struct uni_msg *api;
+ struct uniapi_party_destroyed *ind;
+
+ TIMER_DESTROY_PARTY(p, t397);
+ TIMER_DESTROY_PARTY(p, t398);
+ TIMER_DESTROY_PARTY(p, t399);
+
+ TAILQ_REMOVE(&p->call->parties, p, link);
+
+ uni_delsig(p->call->uni, SIG_PARTY, p->call, p);
+
+ if (!really) {
+ ind = ALLOC_API(struct uniapi_party_destroyed, api);
+ if (ind != NULL) {
+ ind->cref.cref = p->call->cref;
+ ind->cref.flag = p->call->mine;
+ ind->epref.epref = p->epref;
+ ind->epref.flag = p->flags & PARTY_MINE;
+ ind->epref.h.act = UNI_IEACT_DEFAULT;
+ IE_SETPRESENT(ind->epref);
+
+ uni_enq_call(p->call, SIGC_PARTY_DESTROYED, 0, api, NULL);
+ }
+
+ uni_enq_party(p, SIGP_PARTY_DELETE, 0, NULL, NULL);
+ return;
+ }
+ PARTY_FREE(p);
+}
+
+/*
+ * Count number of parties in active states.
+ * If the argument is 0 only ACTIVE parties are counter
+ * If the argument is 1 only parties in establishing states are counted
+ * If the argument is 2 both are counted.
+ */
+u_int
+uni_party_act_count(struct call *c, int kind)
+{
+ struct party *p;
+ u_int cnt;
+
+ cnt = 0;
+ TAILQ_FOREACH(p, &c->parties, link) {
+ switch (p->state) {
+
+ case UNI_EPSTATE_ACTIVE:
+ if (kind == 0 || kind == 2)
+ cnt++;
+ break;
+
+ case UNI_EPSTATE_ALERT_RCVD:
+ case UNI_EPSTATE_ADD_INIT:
+ case UNI_EPSTATE_ALERT_DLVD:
+ case UNI_EPSTATE_ADD_RCVD:
+ if (kind == 1 || kind == 2)
+ cnt++;
+ break;
+
+ default:
+ break;
+ }
+ }
+ return (cnt);
+}
+
+static void
+stop_all_party_timers(struct party *p)
+{
+ TIMER_STOP_PARTY(p, t397);
+ TIMER_STOP_PARTY(p, t398);
+ TIMER_STOP_PARTY(p, t399);
+}
+/************************************************************/
+
+/*
+ * Add-party.request
+ *
+ * Q.2971:Party-control-U 3 (PU0)
+ * Q.2971:Party-control-N 3 (PN0)
+ */
+static void
+pun0_add_party_request(struct party *p, struct uni_msg *api, uint32_t cookie)
+{
+ struct uni_all *add;
+ struct uniapi_add_party_request *req =
+ uni_msg_rptr(api, struct uniapi_add_party_request *);
+
+ if ((add = UNI_ALLOC()) == NULL) {
+ uni_msg_destroy(api);
+ uniapi_party_error(p, UNIAPI_ERROR_NOMEM, cookie);
+ return;
+ }
+
+ add->u.add_party = req->add;
+ MK_MSG_ORIG(add, UNI_ADD_PARTY, p->call->cref, !p->call->mine);
+ uni_send_output(add, p->call->uni);
+ UNI_FREE(add);
+
+ TIMER_START_PARTY(p, t399, p->call->uni->timer399);
+
+ set_party_state(p, UNI_EPSTATE_ADD_INIT);
+
+ uni_msg_destroy(api);
+ uniapi_party_error(p, UNIAPI_OK, cookie);
+}
+
+/*
+ * Add-party-ack.request
+ *
+ * Q.2971:Party-Control-U 6 PU2
+ * Q.2971:Party-Control-U 7 PU3
+ * Q.2971:Party-Control-N 6 PN2
+ * Q.2971:Party-Control-N 7 PN3
+ */
+static void
+punx_add_party_ack_request(struct party *p, struct uni_msg *m, uint32_t cookie)
+{
+ struct uni_all *ack;
+ struct uniapi_add_party_ack_request *req =
+ uni_msg_rptr(m, struct uniapi_add_party_ack_request *);
+
+ if ((ack = UNI_ALLOC()) == NULL) {
+ uniapi_party_error(p, UNIAPI_ERROR_NOMEM, cookie);
+ uni_msg_destroy(m);
+ return;
+ }
+ ack->u.add_party_ack = req->ack;
+ MK_MSG_ORIG(ack, UNI_ADD_PARTY_ACK, p->call->cref, !p->call->mine);
+ uni_send_output(ack, p->call->uni);
+ UNI_FREE(ack);
+
+ set_party_state(p, UNI_EPSTATE_ACTIVE);
+
+ uni_msg_destroy(m);
+ uniapi_party_error(p, UNIAPI_OK, cookie);
+}
+
+/*
+ * Add-party-rej.request
+ *
+ * Q.2971:Party-Control-U 6 PU2
+ * Q.2971:Party-Control-N 6 PN2
+ */
+static void
+pun2_add_party_rej_request(struct party *p, struct uni_msg *m, uint32_t cookie)
+{
+ struct uni_all *rej;
+ struct uniapi_add_party_rej_request *req =
+ uni_msg_rptr(m, struct uniapi_add_party_rej_request *);
+
+ if ((rej = UNI_ALLOC()) == NULL) {
+ uniapi_party_error(p, UNIAPI_ERROR_NOMEM, cookie);
+ uni_msg_destroy(m);
+ return;
+ }
+
+ stop_all_party_timers(p);
+
+ rej->u.add_party_rej = req->rej;
+ MK_MSG_ORIG(rej, UNI_ADD_PARTY_REJ, p->call->cref, !p->call->mine);
+ uni_enq_call(p->call, SIGC_SEND_ADD_PARTY_REJ, cookie, NULL, rej);
+
+ uni_msg_destroy(m);
+ p->state = UNI_EPSTATE_NULL;
+ uniapi_party_error(p, UNIAPI_OK, cookie);
+
+ uni_destroy_party(p, 0);
+}
+
+/*
+ * ADD PARTY in PU0, PN0
+ *
+ * Q.2971:Party-Control-U 3/14 PU0
+ */
+static void
+pun0_add_party(struct party *p, struct uni_msg *m, struct uni_all *u)
+{
+ struct uniapi_add_party_indication *ind;
+ struct uni_msg *api;
+
+ ind = ALLOC_API(struct uniapi_add_party_indication, api);
+ if (ind != NULL) {
+ ind->add.hdr = u->u.hdr;
+ copy_msg_add_party(&u->u.add_party, &ind->add);
+ p->call->uni->funcs->uni_output(p->call->uni, p->call->uni->arg,
+ UNIAPI_ADD_PARTY_indication, 0, api);
+ }
+ set_party_state(p, UNI_EPSTATE_ADD_RCVD);
+
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+}
+
+/*
+ * PARTY-ALERTING.request
+ *
+ * Q.2971:Party-Control-U 6 (PU2)
+ * Q.2971:Party-Control-N 6 (PN2)
+ */
+static void
+pun2_party_alerting_request(struct party *p, struct uni_msg *api,
+ uint32_t cookie)
+{
+ struct uni_all *alert;
+ struct uniapi_party_alerting_request *req =
+ uni_msg_rptr(api, struct uniapi_party_alerting_request *);
+
+ if ((alert = UNI_ALLOC()) == NULL) {
+ uniapi_party_error(p, UNIAPI_ERROR_NOMEM, cookie);
+ uni_msg_destroy(api);
+ return;
+ }
+ alert->u.party_alerting = req->alert;
+ MK_MSG_ORIG(alert, UNI_PARTY_ALERTING,
+ p->call->cref, !p->call->mine);
+ uni_send_output(alert, p->call->uni);
+ UNI_FREE(alert);
+
+ set_party_state(p, UNI_EPSTATE_ALERT_DLVD);
+
+ uni_msg_destroy(api);
+ uniapi_party_error(p, UNIAPI_OK, cookie);
+}
+
+/*
+ * PARTY-ALERTING in state PU1/PN1
+ *
+ * Q.2971:Party-Control-U 14
+ * Q.2971:Party-Control-N 5
+ */
+static void
+pun1_party_alerting(struct party *p, struct uni_msg *m, struct uni_all *u)
+{
+ struct uniapi_party_alerting_indication *ind;
+ struct uni_msg *api;
+
+ ind = ALLOC_API(struct uniapi_party_alerting_indication, api);
+ if (ind == NULL) {
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+ return;
+ }
+ TIMER_STOP_PARTY(p, t399);
+
+ ind->alert.hdr = u->u.hdr;
+ copy_msg_party_alerting(&u->u.party_alerting, &ind->alert);
+
+ p->call->uni->funcs->uni_output(p->call->uni, p->call->uni->arg,
+ UNIAPI_PARTY_ALERTING_indication, 0, api);
+
+ TIMER_START_PARTY(p, t397, p->call->uni->timer397);
+
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+
+ set_party_state(p, UNI_EPSTATE_ALERT_RCVD);
+}
+
+/*
+ * ADD-PARTY-ACK
+ *
+ * Q.2971:Party-Control-U 4 (PU1)
+ * Q.2971:Party-Control-U 7 (PU4)
+ * Q.2971:Party-Control-N 4 (PN1)
+ * Q.2971:Party-Control-N 7 (PN4)
+ */
+static void
+pun1pun4_add_party_ack(struct party *p, struct uni_msg *m, struct uni_all *u)
+{
+ struct uniapi_add_party_ack_indication *ind;
+ struct uni_msg *api;
+
+ ind = ALLOC_API(struct uniapi_add_party_ack_indication, api);
+ if (ind == NULL) {
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+ return;
+ }
+
+ if (p->state == UNI_EPSTATE_ADD_INIT)
+ TIMER_STOP_PARTY(p, t399);
+ else
+ TIMER_STOP_PARTY(p, t397);
+
+ ind->ack.hdr = u->u.hdr;
+ copy_msg_add_party_ack(&u->u.add_party_ack, &ind->ack);
+
+ p->call->uni->funcs->uni_output(p->call->uni, p->call->uni->arg,
+ UNIAPI_ADD_PARTY_ACK_indication, 0, api);
+
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+
+ set_party_state(p, UNI_EPSTATE_ACTIVE);
+}
+
+/*
+ * ADD-PARTY-REJECT
+ *
+ * Q.2971:Party-Control-U 4 (PU1)
+ * Q.2971:Party-Control-N 4 (PN1)
+ */
+static void
+pun1_add_party_rej(struct party *p, struct uni_msg *m, struct uni_all *u)
+{
+ struct uniapi_add_party_rej_indication *ind;
+ struct uni_msg *api;
+
+ ind = ALLOC_API(struct uniapi_add_party_rej_indication, api);
+ if (ind == NULL) {
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+ return;
+ }
+
+ TIMER_STOP_PARTY(p, t399);
+
+ ind->rej.hdr = u->u.hdr;
+ copy_msg_add_party_rej(&u->u.add_party_rej, &ind->rej);
+ uni_enq_call(p->call, SIGC_ADD_PARTY_REJ_indication, 0, api, NULL);
+
+ uni_destroy_party(p, 0);
+
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+}
+
+/*
+ * ADD-PARTY-REJECT
+ *
+ * Q.2971:Party-Control-U 10 (PU5)
+ * Q.2971:Party-Control-N 10 (PN5)
+ */
+static void
+pun5_add_party_rej(struct party *p, struct uni_msg *m, struct uni_all *u)
+{
+ struct uniapi_drop_party_ack_indication *ind;
+ struct uni_msg *api;
+
+ ind = ALLOC_API(struct uniapi_drop_party_ack_indication, api);
+ if (ind == NULL) {
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+ return;
+ }
+
+ ind->drop.hdr = u->u.hdr;
+ COPY_FROM_ADD_REJ(u, &ind->drop);
+ if (IE_ISGOOD(u->u.add_party_rej.crankback))
+ ind->crankback = u->u.add_party_rej.crankback;
+ uni_enq_call(p->call, SIGC_DROP_PARTY_ACK_indication, 0, api, NULL);
+
+ TIMER_STOP_PARTY(p, t398);
+
+ uni_destroy_party(p, 0);
+
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+}
+
+/*
+ * DROP-PARTY-ACKNOWLEDGE
+ *
+ * Q.2971:Party-Control-U 8
+ * Q.2971:Party-Control-N 8
+ *
+ * Message already verified in Call-Control!
+ */
+static void
+punx_drop_party_ack(struct party *p, struct uni_msg *m, struct uni_all *u)
+{
+ struct uniapi_drop_party_ack_indication *ind;
+ struct uni_msg *api;
+
+ stop_all_party_timers(p);
+
+ ind = ALLOC_API(struct uniapi_drop_party_ack_indication, api);
+ if (ind != NULL) {
+ ind->drop.hdr = u->u.hdr;
+ COPY_FROM_DROP_ACK(u, &ind->drop);
+ uni_enq_call(p->call, SIGC_DROP_PARTY_ACK_indication,
+ 0, api, NULL);
+ }
+
+ uni_destroy_party(p, 0);
+
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+}
+
+/*
+ * DROP PARTY message in any state except PU5/PN5
+ *
+ * Q.2971:Party-Control-U 9
+ * Q.2971:Party-Control-N 9
+ */
+static void
+punx_drop_party(struct party *p, struct uni_msg *m, struct uni_all *u)
+{
+ struct uniapi_drop_party_indication *ind;
+ struct uni_msg *api;
+
+ ind = ALLOC_API(struct uniapi_drop_party_indication, api);
+ if (ind == NULL) {
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+ return;
+ }
+
+ ind->drop.hdr = u->u.hdr;
+ copy_msg_drop_party(&u->u.drop_party, &ind->drop);
+
+ /* need the cause even if it is bad */
+ if (IE_ISERROR(u->u.drop_party.cause))
+ ind->drop.cause = u->u.drop_party.cause;
+
+ ind->my_cause = p->call->uni->cause;
+
+ uni_enq_call(p->call, SIGC_DROP_PARTY_indication, 0, api, NULL);
+
+ TIMER_STOP_PARTY(p, t397);
+ TIMER_STOP_PARTY(p, t399);
+
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+
+ set_party_state(p, UNI_EPSTATE_DROP_RCVD);
+}
+
+/*
+ * DROP PARTY message in state PU5/PN5
+ *
+ * Q.2971:Party-Control-U 10
+ * Q.2971:Party-Control-N 10
+ */
+static void
+pun5_drop_party(struct party *p, struct uni_msg *m, struct uni_all *u)
+{
+ struct uniapi_drop_party_ack_indication *ind;
+ struct uni_msg *api;
+
+ ind = ALLOC_API(struct uniapi_drop_party_ack_indication, api);
+ if (ind == NULL) {
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+ return;
+ }
+
+ ind->drop.hdr = u->u.hdr;
+ copy_msg_drop_party(&u->u.drop_party, &ind->drop);
+
+ /* need the cause even if it is bad */
+ if (IE_ISERROR(u->u.drop_party.cause))
+ ind->drop.cause = u->u.drop_party.cause;
+
+ uni_enq_call(p->call, SIGC_DROP_PARTY_ACK_indication, 0, api, NULL);
+
+ TIMER_STOP_PARTY(p, t398);
+
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+
+ set_party_state(p, UNI_EPSTATE_DROP_RCVD);
+
+ uni_destroy_party(p, 0);
+}
+
+/************************************************************/
+
+/*
+ * T399
+ *
+ * Q.2971:Party-Control-U 4 (PU1)
+ * Q.2971:Party-Control-N 4 (PN1)
+ */
+static void
+pun1_t399(struct party *p)
+{
+ if (p->call->uni->proto == UNIPROTO_UNI40N) {
+ MK_IE_CAUSE(p->call->uni->cause, UNI_CAUSE_LOC_USER,
+ UNI_CAUSE_NO_RESPONSE);
+ } else {
+ MK_IE_CAUSE(p->call->uni->cause, UNI_CAUSE_LOC_USER,
+ UNI_CAUSE_RECOVER);
+ ADD_CAUSE_TIMER(p->call->uni->cause, "399");
+ }
+
+ drop_partyE(p);
+}
+
+/*
+ * T398
+ *
+ * Q.2971:Party-Control-U 10 (PU5)
+ * Q.2971:Party-Control-N 10 (PN5)
+ */
+static void
+pun5_t398(struct party *p)
+{
+ struct uniapi_drop_party_ack_indication *ind;
+ struct uni_all *drop;
+ struct uni_msg *api;
+
+ MK_IE_CAUSE(p->call->uni->cause,
+ UNI_CAUSE_LOC_USER, UNI_CAUSE_RECOVER);
+ ADD_CAUSE_TIMER(p->call->uni->cause, "398");
+ /*
+ * Send indication to API
+ */
+ ind = ALLOC_API(struct uniapi_drop_party_ack_indication, api);
+ if (ind != NULL) {
+ ind->drop.hdr.cref.cref = p->call->cref;
+ ind->drop.hdr.cref.flag = p->call->mine;
+ ind->drop.hdr.act = UNI_MSGACT_DEFAULT;
+ MK_IE_EPREF(ind->drop.epref, p->epref, p->flags & PARTY_MINE);
+ ind->drop.cause = p->call->uni->cause;
+ uni_enq_call(p->call, SIGC_DROP_PARTY_ACK_indication,
+ 0, api, NULL);
+ }
+
+ /*
+ * Send DROP PARTY ACK
+ */
+ if ((drop = UNI_ALLOC()) != NULL) {
+ MK_MSG_ORIG(drop, UNI_DROP_PARTY_ACK,
+ p->call->cref, !p->call->mine);
+ MK_IE_EPREF(drop->u.drop_party_ack.epref,
+ p->epref, !(p->flags & PARTY_MINE));
+ drop->u.drop_party_ack.cause = p->call->uni->cause;
+ uni_enq_call(p->call, SIGC_SEND_DROP_PARTY_ACK, 0, NULL, drop);
+ }
+
+ uni_destroy_party(p, 0);
+}
+
+/*
+ * T397
+ *
+ * Q.2971:Party-Control-U 7 (PU4)
+ * Q.2971:Party-Control-N 7 (PN4)
+ */
+static void
+pun4_t397(struct party *p)
+{
+ MK_IE_CAUSE(p->call->uni->cause, UNI_CAUSE_LOC_USER,
+ UNI_CAUSE_RECOVER);
+ ADD_CAUSE_TIMER(p->call->uni->cause, "397");
+
+ drop_partyE(p);
+}
+
+/************************************************************/
+
+/*
+ * Drop a party because of an error condition.
+ * This is label E on page Party-Control-U 8/14.
+ *
+ * It is assumed, that the caller has constructed the cause in
+ * p->call->uni->cause.
+ */
+static void
+drop_partyE(struct party *p)
+{
+ struct uni_msg *api;
+ struct uniapi_drop_party_indication *ind;
+ struct uni_all *drop;
+
+ /*
+ * Send indication to API
+ */
+ if ((ind = ALLOC_API(struct uniapi_drop_party_indication, api)) != NULL) {
+ ind->drop.hdr.cref.cref = p->call->cref;
+ ind->drop.hdr.cref.flag = p->call->mine;
+ ind->drop.hdr.act = UNI_MSGACT_DEFAULT;
+ MK_IE_EPREF(ind->drop.epref, p->epref, p->flags & PARTY_MINE);
+ ind->drop.cause = p->call->uni->cause;
+ uni_enq_call(p->call, SIGC_DROP_PARTY_indication, 0, api, NULL);
+ }
+ TIMER_STOP_PARTY(p, t399);
+ TIMER_STOP_PARTY(p, t397);
+ TIMER_START_PARTY(p, t398, p->call->uni->timer398);
+
+ if ((drop = UNI_ALLOC()) != NULL) {
+ drop->u.drop_party.cause = p->call->uni->cause;
+ MK_MSG_ORIG(drop, UNI_DROP_PARTY, p->call->cref, !p->call->mine);
+ MK_IE_EPREF(drop->u.drop_party.epref, p->epref,
+ !(p->flags & PARTY_MINE));
+ uni_enq_call(p->call, SIGC_SEND_DROP_PARTY, 0, NULL, drop);
+ }
+
+ set_party_state(p, UNI_EPSTATE_DROP_INIT);
+}
+
+/*
+ * Drop party request in Px1, Px3, Px4 or Px7
+ *
+ * Q.2971:Party-Control-U 8
+ * Q.2971:Party-Control-N 8
+ */
+static void
+punx_drop_party_request(struct party *p, struct uni_msg *api, uint32_t cookie)
+{
+ struct uniapi_drop_party_request *req =
+ uni_msg_rptr(api, struct uniapi_drop_party_request *);
+ struct uni_all *drop;
+
+ if ((drop = UNI_ALLOC()) == NULL) {
+ uniapi_party_error(p, UNIAPI_ERROR_NOMEM, cookie);
+ uni_msg_destroy(api);
+ return;
+ }
+
+ TIMER_STOP_PARTY(p, t399);
+ TIMER_STOP_PARTY(p, t397);
+ TIMER_START_PARTY(p, t398, p->call->uni->timer398);
+
+ drop->u.drop_party = req->drop;
+ MK_MSG_ORIG(drop, UNI_DROP_PARTY, p->call->cref, !p->call->mine);
+ uni_enq_call(p->call, SIGC_SEND_DROP_PARTY, cookie, NULL, drop);
+
+ set_party_state(p, UNI_EPSTATE_DROP_INIT);
+
+ uni_msg_destroy(api);
+ uniapi_party_error(p, UNIAPI_OK, cookie);
+}
+
+/*
+ * Drop-party-ack.request in Px6
+ *
+ * Q.2971:Party-Control-U 9
+ * Q.2971:Party-Control-N 9
+ */
+static void
+pun6_drop_party_ack_request(struct party *p, struct uni_msg *api, uint32_t cookie)
+{
+ struct uniapi_drop_party_ack_request *req =
+ uni_msg_rptr(api, struct uniapi_drop_party_ack_request *);
+ struct uni_all *ack;
+
+ if ((ack = UNI_ALLOC()) == NULL) {
+ uni_msg_destroy(api);
+ uniapi_party_error(p, UNIAPI_ERROR_NOMEM, cookie);
+ return;
+ }
+ ack->u.drop_party_ack = req->ack;
+ MK_MSG_ORIG(ack, UNI_DROP_PARTY_ACK, p->call->cref, !p->call->mine);
+ uni_enq_call(p->call, SIGC_SEND_DROP_PARTY_ACK, cookie, NULL, ack);
+
+ stop_all_party_timers(p);
+
+ uni_msg_destroy(api);
+ uniapi_party_error(p, UNIAPI_OK, cookie);
+
+ uni_destroy_party(p, 0);
+}
+/************************************************************/
+/*
+ * Party status enquiry request from API or call-control
+ *
+ * Q.2971:Party-Control-U 12
+ * Q.2971:Party-Control-N 12
+ */
+static void
+punx_status_enquiry_request(struct party *p, uint32_t cookie)
+{
+ struct uni_all *enq;
+
+ if((enq = UNI_ALLOC()) == NULL) {
+ uniapi_party_error(p, UNIAPI_ERROR_NOMEM, cookie);
+ return;
+ }
+ MK_IE_EPREF(enq->u.status_enq.epref, p->epref,
+ !(p->flags & PARTY_MINE));
+ MK_MSG_ORIG(enq, UNI_STATUS_ENQ, p->call->cref, !p->call->mine);
+ uni_enq_call(p->call, SIGC_SEND_STATUS_ENQ, cookie, NULL, enq);
+
+ uniapi_party_error(p, UNIAPI_OK, cookie);
+}
+
+/*
+ * STATUS in any state except PU5/PN5
+ *
+ * Q.2971:Party-Control-U 12
+ * Q.2971:Party-Control-N 12
+ */
+static void
+punx_status(struct party *p, struct uni_msg *m, struct uni_all *u)
+{
+ struct uniapi_drop_party_ack_indication *ind;
+ struct uni_msg *api;
+
+ if (u->u.status.epstate.state == UNI_EPSTATE_NULL) {
+ /* should not happend */
+ ind = ALLOC_API(struct uniapi_drop_party_ack_indication, api);
+ if (ind != NULL) {
+ ind->drop.hdr = u->u.hdr;
+ ind->drop.cause = u->u.status.cause;
+ ind->drop.epref = u->u.status.epref;
+ uni_enq_call(p->call, SIGC_DROP_PARTY_ACK_indication,
+ 0, api, NULL);
+ }
+ stop_all_party_timers(p);
+
+ uni_destroy_party(p, 0);
+ } else {
+ if (epstate_compat(p, u->u.status.epstate.state)) {
+ if(u->u.status.cause.cause == UNI_CAUSE_MANDAT ||
+ u->u.status.cause.cause == UNI_CAUSE_MTYPE_NIMPL ||
+ u->u.status.cause.cause == UNI_CAUSE_IE_NIMPL ||
+ u->u.status.cause.cause == UNI_CAUSE_IE_INV) {
+ MK_IE_CAUSE(p->call->uni->cause,
+ UNI_CAUSE_LOC_USER,
+ UNI_CAUSE_UNSPEC);
+ drop_partyE(p);
+ }
+ } else {
+ MK_IE_CAUSE(p->call->uni->cause,
+ UNI_CAUSE_LOC_USER,
+ UNI_CAUSE_MSG_INCOMP);
+ drop_partyE(p);
+ }
+ }
+
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+}
+
+/*
+ * STATUS in PU5/PN5
+ *
+ * Q.2971:Party-Control-U 10
+ * Q.2971:Party-Control-N 10
+ */
+static void
+pun5_status(struct party *p, struct uni_msg *m, struct uni_all *u)
+{
+ struct uniapi_drop_party_ack_indication *ind;
+ struct uni_msg *api;
+
+ if (u->u.status.epstate.state == UNI_EPSTATE_NULL) {
+ ind = ALLOC_API(struct uniapi_drop_party_ack_indication, api);
+ if (ind != NULL) {
+ ind->drop.hdr = u->u.hdr;
+ ind->drop.cause = u->u.status.cause;
+ ind->drop.epref = u->u.status.epref;
+ uni_enq_call(p->call, SIGC_DROP_PARTY_ACK_indication,
+ 0, api, NULL);
+ }
+ TIMER_STOP_PARTY(p, t398);
+
+ uni_destroy_party(p, 0);
+ }
+
+ uni_msg_destroy(m);
+ UNI_FREE(u);
+}
+
+/************************************************************/
+
+void
+uni_sig_party(struct party *p, enum party_sig sig, uint32_t cookie,
+ struct uni_msg *msg, struct uni_all *u)
+{
+ if (sig >= SIGP_END) {
+ VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
+ "Signal %d outside of range to Party-Control", sig);
+ if (msg)
+ uni_msg_destroy(msg);
+ if (u)
+ UNI_FREE(u);
+ return;
+ }
+ VERBOSE(p->call->uni, UNI_FAC_CALL, 1,
+ "Signal %s in state %u of party %u/%s (call %u/%s in state %s)"
+ "; cookie %u", party_sigs[sig], p->state, p->epref,
+ (p->flags & PARTY_MINE) ? "mine" : "his", p->call->cref,
+ p->call->mine ? "mine" : "his", callstates[p->call->cstate].name,
+ cookie);
+
+ switch (sig) {
+
+ case SIGP_PARTY_DELETE:
+ PARTY_FREE(p);
+ break;
+
+ /*
+ * Messages
+ */
+ case SIGP_SETUP:
+ if (p->state == UNI_EPSTATE_NULL) {
+ /* Q.2971:Call-Control-U 3/13 */
+ /* Q.2971:Call-Control-N 3/13 */
+ set_party_state(p, UNI_EPSTATE_ADD_RCVD);
+ break;
+ }
+ VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
+ "SETUP in ps=%u", p->state);
+ break;
+
+ case SIGP_ALERTING:
+ if (p->state == UNI_EPSTATE_ADD_INIT) {
+ /* Q.2971:Call-Control-U 14 */
+ /* Q.2971:Call-Control-N 5 */
+ TIMER_START_PARTY(p, t397, p->call->uni->timer397);
+ set_party_state(p, UNI_EPSTATE_ALERT_RCVD);
+ break;
+ }
+ VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
+ "ALERTING in ps=%u", p->state);
+ break;
+
+ case SIGP_CONNECT:
+ if (p->state == UNI_EPSTATE_ADD_INIT) {
+ /* Q.2971:Call-Control-U 4/13 */
+ TIMER_STOP_PARTY(p, t399);
+ set_party_state(p, UNI_EPSTATE_ACTIVE);
+ break;
+ }
+ if (p->state == UNI_EPSTATE_ALERT_RCVD) {
+ /* Q.2971:Call-Control-U 7/13 */
+ TIMER_STOP_PARTY(p, t397);
+ set_party_state(p, UNI_EPSTATE_ACTIVE);
+ break;
+ }
+ VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
+ "CONNECT in ps=%u", p->state);
+ break;
+
+ case SIGP_CONNECT_ACK:
+ if (p->state == UNI_EPSTATE_ADD_RCVD ||
+ p->state == UNI_EPSTATE_ALERT_DLVD) {
+ /* Q.2971:Call-Control-U 6/13 */
+ /* Q.2971:Call-Control-U 7/13 */
+ p->flags &= ~PARTY_CONNECT;
+ set_party_state(p, UNI_EPSTATE_ACTIVE);
+ break;
+ }
+ VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
+ "CONNECT in ps=%u", p->state);
+ break;
+
+ case SIGP_RELEASE:
+ if (p->state == UNI_EPSTATE_DROP_INIT) {
+ /* Q.2971:Party-Control-U 10/14 */
+ /* Q.2971:Party-Control-N 10/14 */
+ TIMER_STOP_PARTY(p, t398);
+ uni_destroy_party(p, 0);
+ break;
+ }
+ /* Q.2971:Party-Control-U 11/14 */
+ /* Q.2971:Party-Control-N 11/14 */
+ TIMER_STOP_PARTY(p, t397);
+ TIMER_STOP_PARTY(p, t399);
+ uni_destroy_party(p, 0);
+ break;
+
+ case SIGP_RELEASE_COMPL:
+ /* Q.2971:Party-Control-U 11/14 */
+ /* Q.2971:Party-Control-N 11/14 */
+ stop_all_party_timers(p);
+ uni_destroy_party(p, 0);
+ break;
+
+ case SIGP_RELEASE_confirm:
+ /* not in the SDLs */
+ stop_all_party_timers(p);
+ uni_destroy_party(p, 0);
+ break;
+
+ case SIGP_RELEASE_request:
+ if (p->state == UNI_EPSTATE_DROP_INIT) {
+ /* Q.2971:Party-Control-U 10 */
+ /* Q.2971:Party-Control-N 10 */
+ uni_destroy_party(p, 0);
+ break;
+ }
+ /* Q.2971:Party-Control-U 11 */
+ /* Q.2971:Party-Control-N 11 */
+ TIMER_STOP_PARTY(p, t397);
+ TIMER_STOP_PARTY(p, t399);
+ uni_destroy_party(p, 0);
+ break;
+
+ case SIGP_RELEASE_response:
+ /* Q.2971:Party-Control-U 11 */
+ /* Q.2971:Party-Control-N 11 */
+ stop_all_party_timers(p);
+ uni_destroy_party(p, 0);
+ break;
+
+ case SIGP_ADD_PARTY:
+ if (p->state == UNI_EPSTATE_NULL) {
+ /* Q.2971:Party-Control-U 3 PU0 */
+ /* Q.2971:Party-Control-N 3 PN0 */
+ pun0_add_party(p, msg, u);
+ break;
+ }
+ if (p->state == UNI_EPSTATE_ADD_RCVD) {
+ /* Q.2971:Party-Control-U 6 PU2 */
+ /* Q.2971:Party-Control-N 6 PN2 */
+ uni_msg_destroy(msg);
+ UNI_FREE(u);
+ break;
+ }
+ uni_bad_message(p->call, u, UNI_CAUSE_MSG_INCOMP,
+ &u->u.add_party.epref, p->state);
+ uni_msg_destroy(msg);
+ UNI_FREE(u);
+ break;
+
+ case SIGP_PARTY_ALERTING:
+ if (p->state == UNI_EPSTATE_ADD_INIT) {
+ /* Q.2971:Party-Control-U 14 */
+ /* Q.2971:Party-Control-N 5 */
+ pun1_party_alerting(p, msg, u);
+ break;
+ }
+ uni_bad_message(p->call, u, UNI_CAUSE_MSG_INCOMP,
+ &u->u.party_alerting.epref, p->state);
+ uni_msg_destroy(msg);
+ UNI_FREE(u);
+ break;
+
+ case SIGP_ADD_PARTY_ACK:
+ if (p->state == UNI_EPSTATE_ADD_INIT ||
+ p->state == UNI_EPSTATE_ALERT_RCVD) {
+ /* Q.2971:Party-Control-U 4 (PU1) */
+ /* Q.2971:Party-Control-U 7 (PU4) */
+ /* Q.2971:Party-Control-N 4 (PN1) */
+ /* Q.2971:Party-Control-N 7 (PN4) */
+ pun1pun4_add_party_ack(p, msg, u);
+ break;
+ }
+ uni_bad_message(p->call, u, UNI_CAUSE_MSG_INCOMP,
+ &u->u.add_party_ack.epref, p->state);
+ uni_msg_destroy(msg);
+ UNI_FREE(u);
+ break;
+
+ case SIGP_ADD_PARTY_REJ:
+ if (p->state == UNI_EPSTATE_ADD_INIT) {
+ /* Q.2971:Party-Control-U 4 (PU1) */
+ /* Q.2971:Party-Control-N 4 (PN1) */
+ pun1_add_party_rej(p, msg, u);
+ break;
+ }
+ if (p->state == UNI_EPSTATE_DROP_INIT) {
+ /* Q.2971:Party-Control-U 10 (PU5) */
+ /* Q.2971:Party-Control-N 10 (PN5) */
+ pun5_add_party_rej(p, msg, u);
+ break;
+ }
+ uni_bad_message(p->call, u, UNI_CAUSE_MSG_INCOMP,
+ &u->u.add_party_rej.epref, p->state);
+ uni_msg_destroy(msg);
+ UNI_FREE(u);
+ break;
+
+ case SIGP_DROP_PARTY_ACK:
+ /* Q.2971:Party-Control-U 8 */
+ /* Q.2971:Party-Control-N 8 */
+ punx_drop_party_ack(p, msg, u);
+ break;
+
+ case SIGP_DROP_PARTY:
+ if (p->state == UNI_EPSTATE_DROP_INIT)
+ /* Q.2971:Party-Control-U 10 */
+ /* Q.2971:Party-Control-N 10 */
+ pun5_drop_party(p, msg, u);
+ else
+ /* Q.2971:Party-Control-U 9 */
+ /* Q.2971:Party-Control-N 9 */
+ punx_drop_party(p, msg, u);
+ break;
+
+ case SIGP_STATUS:
+ if (p->state == UNI_EPSTATE_DROP_INIT)
+ /* Q.2971:Party-Control-U 10 */
+ /* Q.2971:Party-Control-N 10 */
+ pun5_status(p, msg, u);
+ else
+ /* Q.2971:Party-Control-U 12 */
+ /* Q.2971:Party-Control-N 12 */
+ punx_status(p, msg, u);
+ break;
+
+ /*
+ * User
+ */
+ case SIGP_SETUP_request:
+ if (p->state == UNI_EPSTATE_NULL) {
+ /* Q.2971:Party-Control-U 3 */
+ /* Q.2971:Party-Control-N 3 */
+ set_party_state(p, UNI_EPSTATE_ADD_INIT);
+ break;
+ }
+ VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
+ "SETUP.request in ps=%u", p->state);
+ uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie);
+ break;
+
+ case SIGP_SETUP_response:
+ if (p->state == UNI_EPSTATE_ADD_RCVD ||
+ p->state == UNI_EPSTATE_ALERT_DLVD) {
+ /* Q.2971:Party-Control-N 6 (PN2) */
+ /* Q.2971:Party-Control-N 7 (PN3) */
+ set_party_state(p, UNI_EPSTATE_ACTIVE);
+ break;
+ }
+ VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
+ "SETUP.response in ps=%u", p->state);
+ uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie);
+ break;
+
+ case SIGP_SETUP_COMPL_request:
+ if (p->state == UNI_EPSTATE_ADD_INIT) {
+ /* Q.2971:Party-Control-N 4 */
+ TIMER_STOP_PARTY(p, t399);
+ set_party_state(p, UNI_EPSTATE_ACTIVE);
+ break;
+ }
+ if (p->state == UNI_EPSTATE_ALERT_RCVD) {
+ /* Q.2971:Party-Control-N 7 */
+ TIMER_STOP_PARTY(p, t397);
+ set_party_state(p, UNI_EPSTATE_ACTIVE);
+ break;
+ }
+ VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
+ "SETUP_COMPL.request in ps=%u", p->state);
+ uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie);
+ break;
+
+ case SIGP_ADD_PARTY_request:
+ if (p->state == UNI_EPSTATE_NULL) {
+ /* Q.2971:Party-control-U 3 (PU0) */
+ /* Q.2971:Party-control-N 3 (PN0) */
+ pun0_add_party_request(p, msg, cookie);
+ break;
+ }
+ VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
+ "Add-party.request in ps=%u", p->state);
+ uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie);
+ uni_msg_destroy(msg);
+ break;
+
+ case SIGP_ALERTING_request:
+ /* Q.2971:Party-Control-U 6 (PU2) */
+ /* Q.2971:Party-Control-N 6 (PN2) */
+ set_party_state(p, UNI_EPSTATE_ALERT_DLVD);
+ break;
+
+ case SIGP_PARTY_ALERTING_request:
+ if (p->state == UNI_EPSTATE_ADD_RCVD) {
+ /* Q.2971:Party-Control-U 6 (PU2) */
+ /* Q.2971:Party-Control-N 6 (PN2) */
+ pun2_party_alerting_request(p, msg, cookie);
+ break;
+ }
+ VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
+ "Party-alerting.request in ps=%u", p->state);
+ uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie);
+ uni_msg_destroy(msg);
+ break;
+
+ case SIGP_ADD_PARTY_ACK_request:
+ if (p->state == UNI_EPSTATE_ADD_RCVD ||
+ p->state == UNI_EPSTATE_ALERT_DLVD) {
+ /* Q.2971:Party-Control-U 6 PU2 */
+ /* Q.2971:Party-Control-U 7 PU3 */
+ /* Q.2971:Party-Control-N 6 PN2 */
+ /* Q.2971:Party-Control-N 7 PN3 */
+ punx_add_party_ack_request(p, msg, cookie);
+ break;
+ }
+ VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
+ "Add-party-ack.request in ps=%u", p->state);
+ uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie);
+ uni_msg_destroy(msg);
+ break;
+
+ case SIGP_ADD_PARTY_REJ_request:
+ if (p->state == UNI_EPSTATE_ADD_RCVD) {
+ /* Q.2971:Party-Control-U 6 PU2 */
+ /* Q.2971:Party-Control-N 6 PN2 */
+ pun2_add_party_rej_request(p, msg, cookie);
+ break;
+ }
+ VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
+ "Add-party-rej.request in ps=%u", p->state);
+ uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie);
+ uni_msg_destroy(msg);
+ break;
+
+ case SIGP_DROP_PARTY_request:
+ if (p->state == UNI_EPSTATE_ADD_INIT ||
+ p->state == UNI_EPSTATE_ALERT_DLVD ||
+ p->state == UNI_EPSTATE_ALERT_RCVD ||
+ p->state == UNI_EPSTATE_ACTIVE) {
+ /* Q.2971:Party-Control-U 8 */
+ /* Q.2971:Party-Control-N 8 */
+ punx_drop_party_request(p, msg, cookie);
+ break;
+ }
+ VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
+ "Drop-party.request in ps=%u", p->state);
+ uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie);
+ uni_msg_destroy(msg);
+ break;
+
+ case SIGP_DROP_PARTY_ACK_request:
+ if (p->state == UNI_EPSTATE_DROP_RCVD) {
+ /* Q.2971:Party-Control-U 9 */
+ /* Q.2971:Party-Control-N 9 */
+ pun6_drop_party_ack_request(p, msg, cookie);
+ break;
+ }
+ VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
+ "Drop-party-ack.request in ps=%u", p->state);
+ uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie);
+ uni_msg_destroy(msg);
+ break;
+
+ case SIGP_STATUS_ENQUIRY_request:
+ /* Q.2971:Party-Control-U 12 */
+ /* Q.2971:Party-Control-N 12 */
+ punx_status_enquiry_request(p, cookie);
+ break;
+
+ /*
+ * Timers
+ */
+ case SIGP_T397:
+ if (p->state == UNI_EPSTATE_ALERT_RCVD) {
+ /* Q.2971:Party-Control-U 7 (PU4) */
+ /* Q.2971:Party-Control-N 7 (PN4) */
+ pun4_t397(p);
+ break;
+ }
+ VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
+ "T397 in ps=%u", p->state);
+ break;
+
+ case SIGP_T398:
+ if (p->state == UNI_EPSTATE_DROP_INIT) {
+ /* Q.2971:Party-Control-U 10 (PU5) */
+ /* Q.2971:Party-Control-N 10 (PN5) */
+ pun5_t398(p);
+ break;
+ }
+ VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
+ "T398 in ps=%u", p->state);
+ break;
+
+ case SIGP_T399:
+ if (p->state == UNI_EPSTATE_ADD_INIT) {
+ /* Q.2971:Party-Control-U 4 (PU1) */
+ /* Q.2971:Party-Control-N 4 (PN1) */
+ pun1_t399(p);
+ break;
+ }
+ VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
+ "T399 in ps=%u", p->state);
+ break;
+
+ case SIGP_END:
+ break;
+ }
+}
+
+static void
+t397_func(struct party *p)
+{
+ uni_enq_party(p, SIGP_T397, 0, NULL, NULL);
+}
+static void
+t398_func(struct party *p)
+{
+ uni_enq_party(p, SIGP_T398, 0, NULL, NULL);
+}
+static void
+t399_func(struct party *p)
+{
+ uni_enq_party(p, SIGP_T399, 0, NULL, NULL);
+}
+
+static int
+epstate_compat(struct party *p, enum uni_epstate state)
+{
+ if (p->state == UNI_EPSTATE_ADD_INIT ||
+ p->state == UNI_EPSTATE_ALERT_RCVD)
+ if (state == UNI_EPSTATE_ADD_INIT ||
+ state == UNI_EPSTATE_ALERT_RCVD)
+ return (0);
+ if (p->state == UNI_EPSTATE_ADD_RCVD ||
+ p->state == UNI_EPSTATE_ALERT_DLVD)
+ if (state == UNI_EPSTATE_ADD_RCVD ||
+ state == UNI_EPSTATE_ALERT_DLVD)
+ return (0);
+ return (1);
+}
OpenPOWER on IntegriCloud