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_party.c,v 1.18 2004/08/05 07:11:01 brandt Exp $
30122205Sharti *
31122205Sharti * Party instance handling
32122205Sharti */
33122205Sharti
34122205Sharti#include <netnatm/unimsg.h>
35122205Sharti#include <netnatm/saal/sscfudef.h>
36122205Sharti#include <netnatm/msg/unistruct.h>
37122205Sharti#include <netnatm/msg/unimsglib.h>
38122205Sharti#include <netnatm/sig/uni.h>
39122205Sharti
40122205Sharti#include <netnatm/sig/unipriv.h>
41122205Sharti#include <netnatm/sig/unimkmsg.h>
42122205Sharti#include <netnatm/sig/unimsgcpy.h>
43122205Sharti
44122205Shartistatic void drop_partyE(struct party *p);
45122205Shartistatic int epstate_compat(struct party *, enum uni_epstate);
46122205Sharti
47133492Sharti#define DEF_PRIV_SIG(NAME, FROM)	[SIG##NAME] =	"SIG"#NAME,
48122205Shartistatic const char *const party_sigs[] = {
49122205Sharti	DEF_PARTY_SIGS
50122205Sharti};
51122205Sharti#undef DEF_PRIV_SIG
52122205Sharti
53122205ShartiTIMER_FUNC_PARTY(t397, t397_func)
54122205ShartiTIMER_FUNC_PARTY(t398, t398_func)
55122205ShartiTIMER_FUNC_PARTY(t399, t399_func)
56122205Sharti
57122205Shartistatic __inline void
58122205Shartiset_party_state(struct party *p, enum uni_epstate state)
59122205Sharti{
60122205Sharti	if (p->state != state) {
61122205Sharti		VERBOSE(p->call->uni, UNI_FAC_CALL, 1,
62122205Sharti		    "party %u/%u %u/%u PU%u -> PU%u",
63122205Sharti		    p->call->cref, p->call->mine,
64122205Sharti		    p->epref, p->flags & PARTY_MINE, p->state, state);
65122205Sharti		p->state = state;
66122205Sharti	}
67122205Sharti}
68122205Sharti
69122205Sharti/*
70122205Sharti * Create a party with a given endpoint reference.
71122205Sharti * No check is done, that a party with this epref does not alreay exist.
72122205Sharti */
73122205Shartistruct party *
74131826Shartiuni_create_partyx(struct call *c, u_int epref, u_int mine, uint32_t cookie)
75122205Sharti{
76122205Sharti	struct party *p;
77122205Sharti	struct uni_msg *api;
78122205Sharti	struct uniapi_party_created *ind;
79122205Sharti
80122205Sharti	mine = (mine ? PARTY_MINE : 0);
81122205Sharti
82122205Sharti	if ((p = PARTY_ALLOC()) == NULL)
83122205Sharti		return (NULL);
84122205Sharti
85122205Sharti	if ((ind = ALLOC_API(struct uniapi_party_created, api)) == NULL) {
86122205Sharti		PARTY_FREE(p);
87122205Sharti		return (NULL);
88122205Sharti	}
89122205Sharti
90122205Sharti	ind->cref.cref = c->cref;
91122205Sharti	ind->cref.flag = c->mine;
92122205Sharti	MK_IE_EPREF(ind->epref, epref, mine);
93122205Sharti	ind->epref.h.act = UNI_IEACT_DEFAULT;
94122205Sharti
95122205Sharti	p->call = c;
96122205Sharti	p->epref = epref;
97122205Sharti	p->flags = mine;
98122205Sharti	p->state = UNI_EPSTATE_NULL;;
99122205Sharti
100122205Sharti	TIMER_INIT_PARTY(p, t397);
101122205Sharti	TIMER_INIT_PARTY(p, t398);
102122205Sharti	TIMER_INIT_PARTY(p, t399);
103122205Sharti
104122205Sharti	TAILQ_INSERT_HEAD(&c->parties, p, link);
105122205Sharti
106122205Sharti	c->uni->funcs->uni_output(c->uni, c->uni->arg,
107122205Sharti	    UNIAPI_PARTY_CREATED, cookie, api);
108122205Sharti
109122205Sharti	VERBOSE(c->uni, UNI_FAC_CALL, 1, "created party %u/%s %u/%s",
110122205Sharti	    p->call->cref, p->call->mine ? "mine" : "his",
111122205Sharti	    p->epref, (p->flags & PARTY_MINE) ? "mine" : "his");
112122205Sharti
113122205Sharti	return (p);
114122205Sharti
115122205Sharti}
116122205Sharti
117122205Shartistruct party *
118122205Shartiuni_create_party(struct call *c, struct uni_ie_epref *epref)
119122205Sharti{
120122205Sharti	return (uni_create_partyx(c, epref->epref, epref->flag, 0));
121122205Sharti}
122122205Sharti
123122205Shartistruct party *
124122205Shartiuni_find_party(struct call *c, struct uni_ie_epref *epref)
125122205Sharti{
126122205Sharti	struct party *p;
127122205Sharti
128122205Sharti	TAILQ_FOREACH(p, &c->parties, link)
129122205Sharti		if (p->epref == epref->epref &&
130122205Sharti		    (!(p->flags & PARTY_MINE) == !epref->flag))
131122205Sharti			return (p);
132122205Sharti	return (NULL);
133122205Sharti}
134122205Shartistruct party *
135122205Shartiuni_find_partyx(struct call *c, u_int epref, u_int mine)
136122205Sharti{
137122205Sharti	struct party *p;
138122205Sharti
139122205Sharti	TAILQ_FOREACH(p, &c->parties, link)
140122205Sharti		if (p->epref == epref && (!(p->flags & PARTY_MINE) == !mine))
141122205Sharti			return (p);
142122205Sharti	return (NULL);
143122205Sharti}
144122205Sharti
145122205Sharti/*
146122205Sharti * Destroy a party.
147122205Sharti * This function is assumed to remove the party from the parent's call
148122205Sharti * party list.
149122205Sharti */
150122205Shartivoid
151122205Shartiuni_destroy_party(struct party *p, int really)
152122205Sharti{
153122205Sharti	struct uni_msg *api;
154122205Sharti	struct uniapi_party_destroyed *ind;
155122205Sharti
156122205Sharti	TIMER_DESTROY_PARTY(p, t397);
157122205Sharti	TIMER_DESTROY_PARTY(p, t398);
158122205Sharti	TIMER_DESTROY_PARTY(p, t399);
159122205Sharti
160122205Sharti	TAILQ_REMOVE(&p->call->parties, p, link);
161122205Sharti
162122205Sharti	uni_delsig(p->call->uni, SIG_PARTY, p->call, p);
163122205Sharti
164122205Sharti	if (!really) {
165122205Sharti		ind = ALLOC_API(struct uniapi_party_destroyed, api);
166122205Sharti		if (ind != NULL) {
167122205Sharti			ind->cref.cref = p->call->cref;
168122205Sharti			ind->cref.flag = p->call->mine;
169122205Sharti			ind->epref.epref = p->epref;
170122205Sharti			ind->epref.flag = p->flags & PARTY_MINE;
171122205Sharti			ind->epref.h.act = UNI_IEACT_DEFAULT;
172122205Sharti			IE_SETPRESENT(ind->epref);
173122205Sharti
174122205Sharti			uni_enq_call(p->call, SIGC_PARTY_DESTROYED, 0, api, NULL);
175122205Sharti		}
176122205Sharti
177122205Sharti		uni_enq_party(p, SIGP_PARTY_DELETE, 0, NULL, NULL);
178122205Sharti		return;
179122205Sharti	}
180122205Sharti	PARTY_FREE(p);
181122205Sharti}
182122205Sharti
183122205Sharti/*
184122205Sharti * Count number of parties in active states.
185122205Sharti * If the argument is 0 only ACTIVE parties are counter
186122205Sharti * If the argument is 1 only parties in establishing states are counted
187122205Sharti * If the argument is 2 both are counted.
188122205Sharti */
189122205Shartiu_int
190122205Shartiuni_party_act_count(struct call *c, int kind)
191122205Sharti{
192122205Sharti	struct party *p;
193122205Sharti	u_int cnt;
194122205Sharti
195122205Sharti	cnt = 0;
196122205Sharti	TAILQ_FOREACH(p, &c->parties, link) {
197122205Sharti		switch (p->state) {
198122205Sharti
199122205Sharti		  case UNI_EPSTATE_ACTIVE:
200122205Sharti			if (kind == 0 || kind == 2)
201122205Sharti				cnt++;
202122205Sharti			break;
203122205Sharti
204122205Sharti		  case UNI_EPSTATE_ALERT_RCVD:
205122205Sharti		  case UNI_EPSTATE_ADD_INIT:
206122205Sharti		  case UNI_EPSTATE_ALERT_DLVD:
207122205Sharti		  case UNI_EPSTATE_ADD_RCVD:
208122205Sharti			if (kind == 1 || kind == 2)
209122205Sharti				cnt++;
210122205Sharti			break;
211122205Sharti
212122205Sharti		  default:
213122205Sharti			break;
214122205Sharti		}
215122205Sharti	}
216122205Sharti	return (cnt);
217122205Sharti}
218122205Sharti
219122205Shartistatic void
220122205Shartistop_all_party_timers(struct party *p)
221122205Sharti{
222122205Sharti	TIMER_STOP_PARTY(p, t397);
223122205Sharti	TIMER_STOP_PARTY(p, t398);
224122205Sharti	TIMER_STOP_PARTY(p, t399);
225122205Sharti}
226122205Sharti/************************************************************/
227122205Sharti
228122205Sharti/*
229122205Sharti * Add-party.request
230122205Sharti *
231122205Sharti * Q.2971:Party-control-U 3 (PU0)
232122205Sharti * Q.2971:Party-control-N 3 (PN0)
233122205Sharti */
234122205Shartistatic void
235131826Shartipun0_add_party_request(struct party *p, struct uni_msg *api, uint32_t cookie)
236122205Sharti{
237122205Sharti	struct uni_all *add;
238122205Sharti	struct uniapi_add_party_request *req =
239122205Sharti	    uni_msg_rptr(api, struct uniapi_add_party_request *);
240122205Sharti
241122205Sharti	if ((add = UNI_ALLOC()) == NULL) {
242122205Sharti		uni_msg_destroy(api);
243122205Sharti		uniapi_party_error(p, UNIAPI_ERROR_NOMEM, cookie);
244122205Sharti		return;
245122205Sharti	}
246122205Sharti
247122205Sharti	add->u.add_party = req->add;
248122205Sharti	MK_MSG_ORIG(add, UNI_ADD_PARTY, p->call->cref, !p->call->mine);
249122205Sharti	uni_send_output(add, p->call->uni);
250122205Sharti	UNI_FREE(add);
251122205Sharti
252122205Sharti	TIMER_START_PARTY(p, t399, p->call->uni->timer399);
253122205Sharti
254122205Sharti	set_party_state(p, UNI_EPSTATE_ADD_INIT);
255122205Sharti
256122205Sharti	uni_msg_destroy(api);
257122205Sharti	uniapi_party_error(p, UNIAPI_OK, cookie);
258122205Sharti}
259122205Sharti
260122205Sharti/*
261122205Sharti * Add-party-ack.request
262122205Sharti *
263122205Sharti * Q.2971:Party-Control-U 6 PU2
264122205Sharti * Q.2971:Party-Control-U 7 PU3
265122205Sharti * Q.2971:Party-Control-N 6 PN2
266122205Sharti * Q.2971:Party-Control-N 7 PN3
267122205Sharti */
268122205Shartistatic void
269131826Shartipunx_add_party_ack_request(struct party *p, struct uni_msg *m, uint32_t cookie)
270122205Sharti{
271122205Sharti	struct uni_all *ack;
272122205Sharti	struct uniapi_add_party_ack_request *req =
273122205Sharti	    uni_msg_rptr(m, struct uniapi_add_party_ack_request *);
274122205Sharti
275122205Sharti	if ((ack = UNI_ALLOC()) == NULL) {
276122205Sharti		uniapi_party_error(p, UNIAPI_ERROR_NOMEM, cookie);
277122205Sharti		uni_msg_destroy(m);
278122205Sharti		return;
279122205Sharti	}
280122205Sharti	ack->u.add_party_ack = req->ack;
281122205Sharti	MK_MSG_ORIG(ack, UNI_ADD_PARTY_ACK, p->call->cref, !p->call->mine);
282122205Sharti	uni_send_output(ack, p->call->uni);
283122205Sharti	UNI_FREE(ack);
284122205Sharti
285122205Sharti	set_party_state(p, UNI_EPSTATE_ACTIVE);
286122205Sharti
287122205Sharti	uni_msg_destroy(m);
288122205Sharti	uniapi_party_error(p, UNIAPI_OK, cookie);
289122205Sharti}
290122205Sharti
291122205Sharti/*
292122205Sharti * Add-party-rej.request
293122205Sharti *
294122205Sharti * Q.2971:Party-Control-U 6 PU2
295122205Sharti * Q.2971:Party-Control-N 6 PN2
296122205Sharti */
297122205Shartistatic void
298131826Shartipun2_add_party_rej_request(struct party *p, struct uni_msg *m, uint32_t cookie)
299122205Sharti{
300122205Sharti	struct uni_all *rej;
301122205Sharti	struct uniapi_add_party_rej_request *req =
302122205Sharti	    uni_msg_rptr(m, struct uniapi_add_party_rej_request *);
303122205Sharti
304122205Sharti	if ((rej = UNI_ALLOC()) == NULL) {
305122205Sharti		uniapi_party_error(p, UNIAPI_ERROR_NOMEM, cookie);
306122205Sharti		uni_msg_destroy(m);
307122205Sharti		return;
308122205Sharti	}
309122205Sharti
310122205Sharti	stop_all_party_timers(p);
311122205Sharti
312122205Sharti	rej->u.add_party_rej = req->rej;
313122205Sharti	MK_MSG_ORIG(rej, UNI_ADD_PARTY_REJ, p->call->cref, !p->call->mine);
314122205Sharti	uni_enq_call(p->call, SIGC_SEND_ADD_PARTY_REJ, cookie, NULL, rej);
315122205Sharti
316122205Sharti	uni_msg_destroy(m);
317122205Sharti	p->state = UNI_EPSTATE_NULL;
318122205Sharti	uniapi_party_error(p, UNIAPI_OK, cookie);
319122205Sharti
320122205Sharti	uni_destroy_party(p, 0);
321122205Sharti}
322122205Sharti
323122205Sharti/*
324122205Sharti * ADD PARTY in PU0, PN0
325122205Sharti *
326122205Sharti * Q.2971:Party-Control-U 3/14 PU0
327122205Sharti */
328122205Shartistatic void
329122205Shartipun0_add_party(struct party *p, struct uni_msg *m, struct uni_all *u)
330122205Sharti{
331122205Sharti	struct uniapi_add_party_indication *ind;
332122205Sharti	struct uni_msg *api;
333122205Sharti
334122205Sharti	ind = ALLOC_API(struct uniapi_add_party_indication, api);
335122205Sharti	if (ind != NULL) {
336122205Sharti		ind->add.hdr = u->u.hdr;
337122205Sharti		copy_msg_add_party(&u->u.add_party, &ind->add);
338122205Sharti		p->call->uni->funcs->uni_output(p->call->uni, p->call->uni->arg,
339122205Sharti		    UNIAPI_ADD_PARTY_indication, 0, api);
340122205Sharti	}
341122205Sharti	set_party_state(p, UNI_EPSTATE_ADD_RCVD);
342122205Sharti
343122205Sharti	uni_msg_destroy(m);
344122205Sharti	UNI_FREE(u);
345122205Sharti}
346122205Sharti
347122205Sharti/*
348122205Sharti * PARTY-ALERTING.request
349122205Sharti *
350122205Sharti * Q.2971:Party-Control-U 6 (PU2)
351122205Sharti * Q.2971:Party-Control-N 6 (PN2)
352122205Sharti */
353122205Shartistatic void
354122205Shartipun2_party_alerting_request(struct party *p, struct uni_msg *api,
355131826Sharti    uint32_t cookie)
356122205Sharti{
357122205Sharti	struct uni_all *alert;
358122205Sharti	struct uniapi_party_alerting_request *req =
359122205Sharti	    uni_msg_rptr(api, struct uniapi_party_alerting_request *);
360122205Sharti
361122205Sharti	if ((alert = UNI_ALLOC()) == NULL) {
362122205Sharti		uniapi_party_error(p, UNIAPI_ERROR_NOMEM, cookie);
363122205Sharti		uni_msg_destroy(api);
364122205Sharti		return;
365122205Sharti	}
366122205Sharti	alert->u.party_alerting = req->alert;
367122205Sharti	MK_MSG_ORIG(alert, UNI_PARTY_ALERTING,
368122205Sharti	     p->call->cref, !p->call->mine);
369122205Sharti	uni_send_output(alert, p->call->uni);
370122205Sharti	UNI_FREE(alert);
371122205Sharti
372122205Sharti	set_party_state(p, UNI_EPSTATE_ALERT_DLVD);
373122205Sharti
374122205Sharti	uni_msg_destroy(api);
375122205Sharti	uniapi_party_error(p, UNIAPI_OK, cookie);
376122205Sharti}
377122205Sharti
378122205Sharti/*
379122205Sharti * PARTY-ALERTING in state PU1/PN1
380122205Sharti *
381122205Sharti * Q.2971:Party-Control-U 14
382122205Sharti * Q.2971:Party-Control-N 5
383122205Sharti */
384122205Shartistatic void
385122205Shartipun1_party_alerting(struct party *p, struct uni_msg *m, struct uni_all *u)
386122205Sharti{
387122205Sharti	struct uniapi_party_alerting_indication *ind;
388122205Sharti	struct uni_msg *api;
389122205Sharti
390122205Sharti	ind = ALLOC_API(struct uniapi_party_alerting_indication, api);
391122205Sharti	if (ind == NULL) {
392122205Sharti		uni_msg_destroy(m);
393122205Sharti		UNI_FREE(u);
394122205Sharti		return;
395122205Sharti	}
396122205Sharti	TIMER_STOP_PARTY(p, t399);
397122205Sharti
398122205Sharti	ind->alert.hdr = u->u.hdr;
399122205Sharti	copy_msg_party_alerting(&u->u.party_alerting, &ind->alert);
400122205Sharti
401122205Sharti	p->call->uni->funcs->uni_output(p->call->uni, p->call->uni->arg,
402122205Sharti	    UNIAPI_PARTY_ALERTING_indication, 0, api);
403122205Sharti
404122205Sharti	TIMER_START_PARTY(p, t397, p->call->uni->timer397);
405122205Sharti
406122205Sharti	uni_msg_destroy(m);
407122205Sharti	UNI_FREE(u);
408122205Sharti
409122205Sharti	set_party_state(p, UNI_EPSTATE_ALERT_RCVD);
410122205Sharti}
411122205Sharti
412122205Sharti/*
413122205Sharti * ADD-PARTY-ACK
414122205Sharti *
415122205Sharti * Q.2971:Party-Control-U 4 (PU1)
416122205Sharti * Q.2971:Party-Control-U 7 (PU4)
417122205Sharti * Q.2971:Party-Control-N 4 (PN1)
418122205Sharti * Q.2971:Party-Control-N 7 (PN4)
419122205Sharti */
420122205Shartistatic void
421122205Shartipun1pun4_add_party_ack(struct party *p, struct uni_msg *m, struct uni_all *u)
422122205Sharti{
423122205Sharti	struct uniapi_add_party_ack_indication *ind;
424122205Sharti	struct uni_msg *api;
425122205Sharti
426122205Sharti	ind = ALLOC_API(struct uniapi_add_party_ack_indication, api);
427122205Sharti	if (ind == NULL) {
428122205Sharti		uni_msg_destroy(m);
429122205Sharti		UNI_FREE(u);
430122205Sharti		return;
431122205Sharti	}
432122205Sharti
433122205Sharti	if (p->state == UNI_EPSTATE_ADD_INIT)
434122205Sharti		TIMER_STOP_PARTY(p, t399);
435122205Sharti	else
436122205Sharti		TIMER_STOP_PARTY(p, t397);
437122205Sharti
438122205Sharti	ind->ack.hdr = u->u.hdr;
439122205Sharti	copy_msg_add_party_ack(&u->u.add_party_ack, &ind->ack);
440122205Sharti
441122205Sharti	p->call->uni->funcs->uni_output(p->call->uni, p->call->uni->arg,
442122205Sharti	    UNIAPI_ADD_PARTY_ACK_indication, 0, api);
443122205Sharti
444122205Sharti	uni_msg_destroy(m);
445122205Sharti	UNI_FREE(u);
446122205Sharti
447122205Sharti	set_party_state(p, UNI_EPSTATE_ACTIVE);
448122205Sharti}
449122205Sharti
450122205Sharti/*
451122205Sharti * ADD-PARTY-REJECT
452122205Sharti *
453122205Sharti * Q.2971:Party-Control-U 4 (PU1)
454122205Sharti * Q.2971:Party-Control-N 4 (PN1)
455122205Sharti */
456122205Shartistatic void
457122205Shartipun1_add_party_rej(struct party *p, struct uni_msg *m, struct uni_all *u)
458122205Sharti{
459122205Sharti	struct uniapi_add_party_rej_indication *ind;
460122205Sharti	struct uni_msg *api;
461122205Sharti
462122205Sharti	ind = ALLOC_API(struct uniapi_add_party_rej_indication, api);
463122205Sharti	if (ind == NULL) {
464122205Sharti		uni_msg_destroy(m);
465122205Sharti		UNI_FREE(u);
466122205Sharti		return;
467122205Sharti	}
468122205Sharti
469122205Sharti	TIMER_STOP_PARTY(p, t399);
470122205Sharti
471122205Sharti	ind->rej.hdr = u->u.hdr;
472122205Sharti	copy_msg_add_party_rej(&u->u.add_party_rej, &ind->rej);
473122205Sharti	uni_enq_call(p->call, SIGC_ADD_PARTY_REJ_indication, 0, api, NULL);
474122205Sharti
475122205Sharti	uni_destroy_party(p, 0);
476122205Sharti
477122205Sharti	uni_msg_destroy(m);
478122205Sharti	UNI_FREE(u);
479122205Sharti}
480122205Sharti
481122205Sharti/*
482122205Sharti * ADD-PARTY-REJECT
483122205Sharti *
484122205Sharti * Q.2971:Party-Control-U 10 (PU5)
485122205Sharti * Q.2971:Party-Control-N 10 (PN5)
486122205Sharti */
487122205Shartistatic void
488122205Shartipun5_add_party_rej(struct party *p, struct uni_msg *m, struct uni_all *u)
489122205Sharti{
490122205Sharti	struct uniapi_drop_party_ack_indication *ind;
491122205Sharti	struct uni_msg *api;
492122205Sharti
493122205Sharti	ind = ALLOC_API(struct uniapi_drop_party_ack_indication, api);
494122205Sharti	if (ind == NULL) {
495122205Sharti		uni_msg_destroy(m);
496122205Sharti		UNI_FREE(u);
497122205Sharti		return;
498122205Sharti	}
499122205Sharti
500122205Sharti	ind->drop.hdr = u->u.hdr;
501122205Sharti	COPY_FROM_ADD_REJ(u, &ind->drop);
502122205Sharti	if (IE_ISGOOD(u->u.add_party_rej.crankback))
503122205Sharti		ind->crankback = u->u.add_party_rej.crankback;
504122205Sharti	uni_enq_call(p->call, SIGC_DROP_PARTY_ACK_indication, 0, api, NULL);
505122205Sharti
506122205Sharti	TIMER_STOP_PARTY(p, t398);
507122205Sharti
508122205Sharti	uni_destroy_party(p, 0);
509122205Sharti
510122205Sharti	uni_msg_destroy(m);
511122205Sharti	UNI_FREE(u);
512122205Sharti}
513122205Sharti
514122205Sharti/*
515122205Sharti * DROP-PARTY-ACKNOWLEDGE
516122205Sharti *
517122205Sharti * Q.2971:Party-Control-U 8
518122205Sharti * Q.2971:Party-Control-N 8
519122205Sharti *
520122205Sharti * Message already verified in Call-Control!
521122205Sharti */
522122205Shartistatic void
523122205Shartipunx_drop_party_ack(struct party *p, struct uni_msg *m, struct uni_all *u)
524122205Sharti{
525122205Sharti	struct uniapi_drop_party_ack_indication *ind;
526122205Sharti	struct uni_msg *api;
527122205Sharti
528122205Sharti	stop_all_party_timers(p);
529122205Sharti
530122205Sharti	ind = ALLOC_API(struct uniapi_drop_party_ack_indication, api);
531122205Sharti	if (ind != NULL) {
532122205Sharti		ind->drop.hdr = u->u.hdr;
533122205Sharti		COPY_FROM_DROP_ACK(u, &ind->drop);
534122205Sharti		uni_enq_call(p->call, SIGC_DROP_PARTY_ACK_indication,
535122205Sharti		    0, api, NULL);
536122205Sharti	}
537122205Sharti
538122205Sharti	uni_destroy_party(p, 0);
539122205Sharti
540122205Sharti	uni_msg_destroy(m);
541122205Sharti	UNI_FREE(u);
542122205Sharti}
543122205Sharti
544122205Sharti/*
545122205Sharti * DROP PARTY message in any state except PU5/PN5
546122205Sharti *
547122205Sharti * Q.2971:Party-Control-U 9
548122205Sharti * Q.2971:Party-Control-N 9
549122205Sharti */
550122205Shartistatic void
551122205Shartipunx_drop_party(struct party *p, struct uni_msg *m, struct uni_all *u)
552122205Sharti{
553122205Sharti	struct uniapi_drop_party_indication *ind;
554122205Sharti	struct uni_msg *api;
555122205Sharti
556122205Sharti	ind = ALLOC_API(struct uniapi_drop_party_indication, api);
557122205Sharti	if (ind == NULL) {
558122205Sharti		uni_msg_destroy(m);
559122205Sharti		UNI_FREE(u);
560122205Sharti		return;
561122205Sharti	}
562122205Sharti
563122205Sharti	ind->drop.hdr = u->u.hdr;
564122205Sharti	copy_msg_drop_party(&u->u.drop_party, &ind->drop);
565122205Sharti
566122205Sharti	/* need the cause even if it is bad */
567122205Sharti	if (IE_ISERROR(u->u.drop_party.cause))
568122205Sharti		ind->drop.cause = u->u.drop_party.cause;
569122205Sharti
570122205Sharti	ind->my_cause = p->call->uni->cause;
571122205Sharti
572122205Sharti	uni_enq_call(p->call, SIGC_DROP_PARTY_indication, 0, api, NULL);
573122205Sharti
574122205Sharti	TIMER_STOP_PARTY(p, t397);
575122205Sharti	TIMER_STOP_PARTY(p, t399);
576122205Sharti
577122205Sharti	uni_msg_destroy(m);
578122205Sharti	UNI_FREE(u);
579122205Sharti
580122205Sharti	set_party_state(p, UNI_EPSTATE_DROP_RCVD);
581122205Sharti}
582122205Sharti
583122205Sharti/*
584122205Sharti * DROP PARTY message in state PU5/PN5
585122205Sharti *
586122205Sharti * Q.2971:Party-Control-U 10
587122205Sharti * Q.2971:Party-Control-N 10
588122205Sharti */
589122205Shartistatic void
590122205Shartipun5_drop_party(struct party *p, struct uni_msg *m, struct uni_all *u)
591122205Sharti{
592122205Sharti	struct uniapi_drop_party_ack_indication *ind;
593122205Sharti	struct uni_msg *api;
594122205Sharti
595122205Sharti	ind = ALLOC_API(struct uniapi_drop_party_ack_indication, api);
596122205Sharti	if (ind == NULL) {
597122205Sharti		uni_msg_destroy(m);
598122205Sharti		UNI_FREE(u);
599122205Sharti		return;
600122205Sharti	}
601122205Sharti
602122205Sharti	ind->drop.hdr = u->u.hdr;
603122205Sharti	copy_msg_drop_party(&u->u.drop_party, &ind->drop);
604122205Sharti
605122205Sharti	/* need the cause even if it is bad */
606122205Sharti	if (IE_ISERROR(u->u.drop_party.cause))
607122205Sharti		ind->drop.cause = u->u.drop_party.cause;
608122205Sharti
609122205Sharti	uni_enq_call(p->call, SIGC_DROP_PARTY_ACK_indication, 0, api, NULL);
610122205Sharti
611122205Sharti	TIMER_STOP_PARTY(p, t398);
612122205Sharti
613122205Sharti	uni_msg_destroy(m);
614122205Sharti	UNI_FREE(u);
615122205Sharti
616122205Sharti	set_party_state(p, UNI_EPSTATE_DROP_RCVD);
617122205Sharti
618122205Sharti	uni_destroy_party(p, 0);
619122205Sharti}
620122205Sharti
621122205Sharti/************************************************************/
622122205Sharti
623122205Sharti/*
624122205Sharti * T399
625122205Sharti *
626122205Sharti * Q.2971:Party-Control-U 4 (PU1)
627122205Sharti * Q.2971:Party-Control-N 4 (PN1)
628122205Sharti */
629122205Shartistatic void
630122205Shartipun1_t399(struct party *p)
631122205Sharti{
632122205Sharti	if (p->call->uni->proto == UNIPROTO_UNI40N) {
633122205Sharti		MK_IE_CAUSE(p->call->uni->cause, UNI_CAUSE_LOC_USER,
634122205Sharti		    UNI_CAUSE_NO_RESPONSE);
635122205Sharti	} else {
636122205Sharti		MK_IE_CAUSE(p->call->uni->cause, UNI_CAUSE_LOC_USER,
637122205Sharti		    UNI_CAUSE_RECOVER);
638122205Sharti		ADD_CAUSE_TIMER(p->call->uni->cause, "399");
639122205Sharti	}
640122205Sharti
641122205Sharti	drop_partyE(p);
642122205Sharti}
643122205Sharti
644122205Sharti/*
645122205Sharti * T398
646122205Sharti *
647122205Sharti * Q.2971:Party-Control-U 10 (PU5)
648122205Sharti * Q.2971:Party-Control-N 10 (PN5)
649122205Sharti */
650122205Shartistatic void
651122205Shartipun5_t398(struct party *p)
652122205Sharti{
653122205Sharti	struct uniapi_drop_party_ack_indication *ind;
654122205Sharti	struct uni_all *drop;
655122205Sharti	struct uni_msg *api;
656122205Sharti
657122205Sharti	MK_IE_CAUSE(p->call->uni->cause,
658122205Sharti	    UNI_CAUSE_LOC_USER, UNI_CAUSE_RECOVER);
659122205Sharti	ADD_CAUSE_TIMER(p->call->uni->cause, "398");
660122205Sharti	/*
661122205Sharti	 * Send indication to API
662122205Sharti	 */
663122205Sharti	ind = ALLOC_API(struct uniapi_drop_party_ack_indication, api);
664122205Sharti	if (ind != NULL) {
665122205Sharti		ind->drop.hdr.cref.cref = p->call->cref;
666122205Sharti		ind->drop.hdr.cref.flag = p->call->mine;
667122205Sharti		ind->drop.hdr.act = UNI_MSGACT_DEFAULT;
668122205Sharti		MK_IE_EPREF(ind->drop.epref, p->epref, p->flags & PARTY_MINE);
669122205Sharti		ind->drop.cause = p->call->uni->cause;
670122205Sharti		uni_enq_call(p->call, SIGC_DROP_PARTY_ACK_indication,
671122205Sharti		    0, api, NULL);
672122205Sharti	}
673122205Sharti
674122205Sharti	/*
675122205Sharti	 * Send DROP PARTY ACK
676122205Sharti	 */
677122205Sharti	if ((drop = UNI_ALLOC()) != NULL) {
678122205Sharti		MK_MSG_ORIG(drop, UNI_DROP_PARTY_ACK,
679122205Sharti		    p->call->cref, !p->call->mine);
680122205Sharti		MK_IE_EPREF(drop->u.drop_party_ack.epref,
681122205Sharti		    p->epref, !(p->flags & PARTY_MINE));
682122205Sharti		drop->u.drop_party_ack.cause = p->call->uni->cause;
683122205Sharti		uni_enq_call(p->call, SIGC_SEND_DROP_PARTY_ACK, 0, NULL, drop);
684122205Sharti	}
685122205Sharti
686122205Sharti	uni_destroy_party(p, 0);
687122205Sharti}
688122205Sharti
689122205Sharti/*
690122205Sharti * T397
691122205Sharti *
692122205Sharti * Q.2971:Party-Control-U 7 (PU4)
693122205Sharti * Q.2971:Party-Control-N 7 (PN4)
694122205Sharti */
695122205Shartistatic void
696122205Shartipun4_t397(struct party *p)
697122205Sharti{
698122205Sharti	MK_IE_CAUSE(p->call->uni->cause, UNI_CAUSE_LOC_USER,
699122205Sharti	    UNI_CAUSE_RECOVER);
700122205Sharti	ADD_CAUSE_TIMER(p->call->uni->cause, "397");
701122205Sharti
702122205Sharti	drop_partyE(p);
703122205Sharti}
704122205Sharti
705122205Sharti/************************************************************/
706122205Sharti
707122205Sharti/*
708122205Sharti * Drop a party because of an error condition.
709122205Sharti * This is label E on page Party-Control-U 8/14.
710122205Sharti *
711122205Sharti * It is assumed, that the caller has constructed the cause in
712122205Sharti * p->call->uni->cause.
713122205Sharti */
714122205Shartistatic void
715122205Shartidrop_partyE(struct party *p)
716122205Sharti{
717122205Sharti	struct uni_msg *api;
718122205Sharti	struct uniapi_drop_party_indication *ind;
719122205Sharti	struct uni_all *drop;
720122205Sharti
721122205Sharti	/*
722122205Sharti	 * Send indication to API
723122205Sharti	 */
724122205Sharti	if ((ind = ALLOC_API(struct uniapi_drop_party_indication, api)) != NULL) {
725122205Sharti		ind->drop.hdr.cref.cref = p->call->cref;
726122205Sharti		ind->drop.hdr.cref.flag = p->call->mine;
727122205Sharti		ind->drop.hdr.act = UNI_MSGACT_DEFAULT;
728122205Sharti		MK_IE_EPREF(ind->drop.epref, p->epref, p->flags & PARTY_MINE);
729122205Sharti		ind->drop.cause = p->call->uni->cause;
730122205Sharti		uni_enq_call(p->call, SIGC_DROP_PARTY_indication, 0, api, NULL);
731122205Sharti	}
732122205Sharti	TIMER_STOP_PARTY(p, t399);
733122205Sharti	TIMER_STOP_PARTY(p, t397);
734122205Sharti	TIMER_START_PARTY(p, t398, p->call->uni->timer398);
735122205Sharti
736122205Sharti	if ((drop = UNI_ALLOC()) != NULL) {
737122205Sharti		drop->u.drop_party.cause = p->call->uni->cause;
738122205Sharti		MK_MSG_ORIG(drop, UNI_DROP_PARTY, p->call->cref, !p->call->mine);
739122205Sharti		MK_IE_EPREF(drop->u.drop_party.epref, p->epref,
740122205Sharti		    !(p->flags & PARTY_MINE));
741122205Sharti		uni_enq_call(p->call, SIGC_SEND_DROP_PARTY, 0, NULL, drop);
742122205Sharti	}
743122205Sharti
744122205Sharti	set_party_state(p, UNI_EPSTATE_DROP_INIT);
745122205Sharti}
746122205Sharti
747122205Sharti/*
748122205Sharti * Drop party request in Px1, Px3, Px4 or Px7
749122205Sharti *
750122205Sharti * Q.2971:Party-Control-U 8
751122205Sharti * Q.2971:Party-Control-N 8
752122205Sharti */
753122205Shartistatic void
754131826Shartipunx_drop_party_request(struct party *p, struct uni_msg *api, uint32_t cookie)
755122205Sharti{
756122205Sharti	struct uniapi_drop_party_request *req =
757122205Sharti	    uni_msg_rptr(api, struct uniapi_drop_party_request *);
758122205Sharti	struct uni_all *drop;
759122205Sharti
760122205Sharti	if ((drop = UNI_ALLOC()) == NULL) {
761122205Sharti		uniapi_party_error(p, UNIAPI_ERROR_NOMEM, cookie);
762122205Sharti		uni_msg_destroy(api);
763122205Sharti		return;
764122205Sharti	}
765122205Sharti
766122205Sharti	TIMER_STOP_PARTY(p, t399);
767122205Sharti	TIMER_STOP_PARTY(p, t397);
768122205Sharti	TIMER_START_PARTY(p, t398, p->call->uni->timer398);
769122205Sharti
770122205Sharti	drop->u.drop_party = req->drop;
771122205Sharti	MK_MSG_ORIG(drop, UNI_DROP_PARTY, p->call->cref, !p->call->mine);
772122205Sharti	uni_enq_call(p->call, SIGC_SEND_DROP_PARTY, cookie, NULL, drop);
773122205Sharti
774122205Sharti	set_party_state(p, UNI_EPSTATE_DROP_INIT);
775122205Sharti
776122205Sharti	uni_msg_destroy(api);
777122205Sharti	uniapi_party_error(p, UNIAPI_OK, cookie);
778122205Sharti}
779122205Sharti
780122205Sharti/*
781122205Sharti * Drop-party-ack.request in Px6
782122205Sharti *
783122205Sharti * Q.2971:Party-Control-U 9
784122205Sharti * Q.2971:Party-Control-N 9
785122205Sharti */
786122205Shartistatic void
787131826Shartipun6_drop_party_ack_request(struct party *p, struct uni_msg *api, uint32_t cookie)
788122205Sharti{
789122205Sharti	struct uniapi_drop_party_ack_request *req =
790122205Sharti	    uni_msg_rptr(api, struct uniapi_drop_party_ack_request *);
791122205Sharti	struct uni_all *ack;
792122205Sharti
793122205Sharti	if ((ack = UNI_ALLOC()) == NULL) {
794122205Sharti		uni_msg_destroy(api);
795122205Sharti		uniapi_party_error(p, UNIAPI_ERROR_NOMEM, cookie);
796122205Sharti		return;
797122205Sharti	}
798122205Sharti	ack->u.drop_party_ack = req->ack;
799122205Sharti	MK_MSG_ORIG(ack, UNI_DROP_PARTY_ACK, p->call->cref, !p->call->mine);
800122205Sharti	uni_enq_call(p->call, SIGC_SEND_DROP_PARTY_ACK, cookie, NULL, ack);
801122205Sharti
802122205Sharti	stop_all_party_timers(p);
803122205Sharti
804122205Sharti	uni_msg_destroy(api);
805122205Sharti	uniapi_party_error(p, UNIAPI_OK, cookie);
806122205Sharti
807122205Sharti	uni_destroy_party(p, 0);
808122205Sharti}
809122205Sharti/************************************************************/
810122205Sharti/*
811122205Sharti * Party status enquiry request from API or call-control
812122205Sharti *
813122205Sharti * Q.2971:Party-Control-U 12
814122205Sharti * Q.2971:Party-Control-N 12
815122205Sharti */
816122205Shartistatic void
817131826Shartipunx_status_enquiry_request(struct party *p, uint32_t cookie)
818122205Sharti{
819122205Sharti	struct uni_all *enq;
820122205Sharti
821122205Sharti	if((enq = UNI_ALLOC()) == NULL) {
822122205Sharti		uniapi_party_error(p, UNIAPI_ERROR_NOMEM, cookie);
823122205Sharti		return;
824122205Sharti	}
825122205Sharti	MK_IE_EPREF(enq->u.status_enq.epref, p->epref,
826122205Sharti	    !(p->flags & PARTY_MINE));
827122205Sharti	MK_MSG_ORIG(enq, UNI_STATUS_ENQ, p->call->cref, !p->call->mine);
828122205Sharti	uni_enq_call(p->call, SIGC_SEND_STATUS_ENQ, cookie, NULL, enq);
829122205Sharti
830122205Sharti	uniapi_party_error(p, UNIAPI_OK, cookie);
831122205Sharti}
832122205Sharti
833122205Sharti/*
834122205Sharti * STATUS in any state except PU5/PN5
835122205Sharti *
836122205Sharti * Q.2971:Party-Control-U 12
837122205Sharti * Q.2971:Party-Control-N 12
838122205Sharti */
839122205Shartistatic void
840122205Shartipunx_status(struct party *p, struct uni_msg *m, struct uni_all *u)
841122205Sharti{
842122205Sharti	struct uniapi_drop_party_ack_indication *ind;
843122205Sharti	struct uni_msg *api;
844122205Sharti
845122205Sharti	if (u->u.status.epstate.state == UNI_EPSTATE_NULL) {
846122205Sharti		/* should not happend */
847122205Sharti		ind = ALLOC_API(struct uniapi_drop_party_ack_indication, api);
848122205Sharti		if (ind != NULL) {
849122205Sharti			ind->drop.hdr = u->u.hdr;
850122205Sharti			ind->drop.cause = u->u.status.cause;
851122205Sharti			ind->drop.epref = u->u.status.epref;
852122205Sharti			uni_enq_call(p->call, SIGC_DROP_PARTY_ACK_indication,
853122205Sharti			    0, api, NULL);
854122205Sharti		}
855122205Sharti		stop_all_party_timers(p);
856122205Sharti
857122205Sharti		uni_destroy_party(p, 0);
858122205Sharti	} else {
859122205Sharti		if (epstate_compat(p, u->u.status.epstate.state)) {
860122205Sharti			if(u->u.status.cause.cause == UNI_CAUSE_MANDAT ||
861122205Sharti			   u->u.status.cause.cause == UNI_CAUSE_MTYPE_NIMPL ||
862122205Sharti			   u->u.status.cause.cause == UNI_CAUSE_IE_NIMPL ||
863122205Sharti			   u->u.status.cause.cause == UNI_CAUSE_IE_INV) {
864122205Sharti				MK_IE_CAUSE(p->call->uni->cause,
865122205Sharti				    UNI_CAUSE_LOC_USER,
866122205Sharti				    UNI_CAUSE_UNSPEC);
867122205Sharti				drop_partyE(p);
868122205Sharti			}
869122205Sharti		} else {
870122205Sharti			MK_IE_CAUSE(p->call->uni->cause,
871122205Sharti			    UNI_CAUSE_LOC_USER,
872122205Sharti			    UNI_CAUSE_MSG_INCOMP);
873122205Sharti			drop_partyE(p);
874122205Sharti		}
875122205Sharti	}
876122205Sharti
877122205Sharti	uni_msg_destroy(m);
878122205Sharti	UNI_FREE(u);
879122205Sharti}
880122205Sharti
881122205Sharti/*
882122205Sharti * STATUS in PU5/PN5
883122205Sharti *
884122205Sharti * Q.2971:Party-Control-U 10
885122205Sharti * Q.2971:Party-Control-N 10
886122205Sharti */
887122205Shartistatic void
888122205Shartipun5_status(struct party *p, struct uni_msg *m, struct uni_all *u)
889122205Sharti{
890122205Sharti	struct uniapi_drop_party_ack_indication *ind;
891122205Sharti	struct uni_msg *api;
892122205Sharti
893122205Sharti	if (u->u.status.epstate.state == UNI_EPSTATE_NULL) {
894122205Sharti		ind = ALLOC_API(struct uniapi_drop_party_ack_indication, api);
895122205Sharti		if (ind != NULL) {
896122205Sharti			ind->drop.hdr = u->u.hdr;
897122205Sharti			ind->drop.cause = u->u.status.cause;
898122205Sharti			ind->drop.epref = u->u.status.epref;
899122205Sharti			uni_enq_call(p->call, SIGC_DROP_PARTY_ACK_indication,
900122205Sharti			    0, api, NULL);
901122205Sharti		}
902122205Sharti		TIMER_STOP_PARTY(p, t398);
903122205Sharti
904122205Sharti		uni_destroy_party(p, 0);
905122205Sharti	}
906122205Sharti
907122205Sharti	uni_msg_destroy(m);
908122205Sharti	UNI_FREE(u);
909122205Sharti}
910122205Sharti
911122205Sharti/************************************************************/
912122205Sharti
913122205Shartivoid
914131826Shartiuni_sig_party(struct party *p, enum party_sig sig, uint32_t cookie,
915122205Sharti    struct uni_msg *msg, struct uni_all *u)
916122205Sharti{
917122205Sharti	if (sig >= SIGP_END) {
918122205Sharti		VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
919122205Sharti		    "Signal %d outside of range to Party-Control", sig);
920122205Sharti		if (msg)
921122205Sharti			uni_msg_destroy(msg);
922122205Sharti		if (u)
923122205Sharti			UNI_FREE(u);
924122205Sharti		return;
925122205Sharti	}
926122205Sharti	VERBOSE(p->call->uni, UNI_FAC_CALL, 1,
927122205Sharti	    "Signal %s in state %u of party %u/%s (call %u/%s in state %s)"
928122205Sharti	    "; cookie %u", party_sigs[sig], p->state, p->epref,
929122205Sharti	    (p->flags & PARTY_MINE) ? "mine" : "his", p->call->cref,
930122205Sharti	    p->call->mine ? "mine" : "his", callstates[p->call->cstate].name,
931122205Sharti	    cookie);
932122205Sharti
933122205Sharti	switch (sig) {
934122205Sharti
935122205Sharti	  case SIGP_PARTY_DELETE:
936122205Sharti		PARTY_FREE(p);
937122205Sharti		break;
938122205Sharti
939122205Sharti	  /*
940122205Sharti	   * Messages
941122205Sharti	   */
942122205Sharti	  case SIGP_SETUP:
943122205Sharti		if (p->state == UNI_EPSTATE_NULL) {
944122205Sharti			/* Q.2971:Call-Control-U 3/13 */
945122205Sharti			/* Q.2971:Call-Control-N 3/13 */
946122205Sharti			set_party_state(p, UNI_EPSTATE_ADD_RCVD);
947122205Sharti			break;
948122205Sharti		}
949122205Sharti		VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
950122205Sharti		    "SETUP in ps=%u", p->state);
951122205Sharti		break;
952122205Sharti
953122205Sharti	  case SIGP_ALERTING:
954122205Sharti		if (p->state == UNI_EPSTATE_ADD_INIT) {
955122205Sharti			/* Q.2971:Call-Control-U 14 */
956122205Sharti			/* Q.2971:Call-Control-N 5 */
957122205Sharti			TIMER_START_PARTY(p, t397, p->call->uni->timer397);
958122205Sharti			set_party_state(p, UNI_EPSTATE_ALERT_RCVD);
959122205Sharti			break;
960122205Sharti		}
961122205Sharti		VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
962122205Sharti		    "ALERTING in ps=%u", p->state);
963122205Sharti		break;
964122205Sharti
965122205Sharti	  case SIGP_CONNECT:
966122205Sharti		if (p->state == UNI_EPSTATE_ADD_INIT) {
967122205Sharti			/* Q.2971:Call-Control-U 4/13 */
968122205Sharti			TIMER_STOP_PARTY(p, t399);
969122205Sharti			set_party_state(p, UNI_EPSTATE_ACTIVE);
970122205Sharti			break;
971122205Sharti		}
972122205Sharti		if (p->state == UNI_EPSTATE_ALERT_RCVD) {
973122205Sharti			/* Q.2971:Call-Control-U 7/13 */
974122205Sharti			TIMER_STOP_PARTY(p, t397);
975122205Sharti			set_party_state(p, UNI_EPSTATE_ACTIVE);
976122205Sharti			break;
977122205Sharti		}
978122205Sharti		VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
979122205Sharti		    "CONNECT in ps=%u", p->state);
980122205Sharti		break;
981122205Sharti
982122205Sharti	  case SIGP_CONNECT_ACK:
983122205Sharti		if (p->state == UNI_EPSTATE_ADD_RCVD ||
984122205Sharti		    p->state == UNI_EPSTATE_ALERT_DLVD) {
985122205Sharti			/* Q.2971:Call-Control-U 6/13 */
986122205Sharti			/* Q.2971:Call-Control-U 7/13 */
987122205Sharti			p->flags &= ~PARTY_CONNECT;
988122205Sharti			set_party_state(p, UNI_EPSTATE_ACTIVE);
989122205Sharti			break;
990122205Sharti		}
991122205Sharti		VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
992122205Sharti		    "CONNECT in ps=%u", p->state);
993122205Sharti		break;
994122205Sharti
995122205Sharti	  case SIGP_RELEASE:
996122205Sharti		if (p->state == UNI_EPSTATE_DROP_INIT) {
997122205Sharti			/* Q.2971:Party-Control-U 10/14 */
998122205Sharti			/* Q.2971:Party-Control-N 10/14 */
999122205Sharti			TIMER_STOP_PARTY(p, t398);
1000122205Sharti			uni_destroy_party(p, 0);
1001122205Sharti			break;
1002122205Sharti		}
1003122205Sharti		/* Q.2971:Party-Control-U 11/14 */
1004122205Sharti		/* Q.2971:Party-Control-N 11/14 */
1005122205Sharti		TIMER_STOP_PARTY(p, t397);
1006122205Sharti		TIMER_STOP_PARTY(p, t399);
1007122205Sharti		uni_destroy_party(p, 0);
1008122205Sharti		break;
1009122205Sharti
1010122205Sharti	  case SIGP_RELEASE_COMPL:
1011122205Sharti		/* Q.2971:Party-Control-U 11/14 */
1012122205Sharti		/* Q.2971:Party-Control-N 11/14 */
1013122205Sharti		stop_all_party_timers(p);
1014122205Sharti		uni_destroy_party(p, 0);
1015122205Sharti		break;
1016122205Sharti
1017122205Sharti	  case SIGP_RELEASE_confirm:
1018122205Sharti		/* not in the SDLs */
1019122205Sharti		stop_all_party_timers(p);
1020122205Sharti		uni_destroy_party(p, 0);
1021122205Sharti		break;
1022122205Sharti
1023122205Sharti	  case SIGP_RELEASE_request:
1024122205Sharti		if (p->state == UNI_EPSTATE_DROP_INIT) {
1025122205Sharti			/* Q.2971:Party-Control-U 10 */
1026122205Sharti			/* Q.2971:Party-Control-N 10 */
1027122205Sharti			uni_destroy_party(p, 0);
1028122205Sharti			break;
1029122205Sharti		}
1030122205Sharti		/* Q.2971:Party-Control-U 11 */
1031122205Sharti		/* Q.2971:Party-Control-N 11 */
1032122205Sharti		TIMER_STOP_PARTY(p, t397);
1033122205Sharti		TIMER_STOP_PARTY(p, t399);
1034122205Sharti		uni_destroy_party(p, 0);
1035122205Sharti		break;
1036122205Sharti
1037122205Sharti	  case SIGP_RELEASE_response:
1038122205Sharti		/* Q.2971:Party-Control-U 11 */
1039122205Sharti		/* Q.2971:Party-Control-N 11 */
1040122205Sharti		stop_all_party_timers(p);
1041122205Sharti		uni_destroy_party(p, 0);
1042122205Sharti		break;
1043122205Sharti
1044122205Sharti	  case SIGP_ADD_PARTY:
1045122205Sharti		if (p->state == UNI_EPSTATE_NULL) {
1046122205Sharti			/* Q.2971:Party-Control-U 3 PU0 */
1047122205Sharti			/* Q.2971:Party-Control-N 3 PN0 */
1048122205Sharti			pun0_add_party(p, msg, u);
1049122205Sharti			break;
1050122205Sharti		}
1051122205Sharti		if (p->state == UNI_EPSTATE_ADD_RCVD) {
1052122205Sharti			/* Q.2971:Party-Control-U 6 PU2 */
1053122205Sharti			/* Q.2971:Party-Control-N 6 PN2 */
1054122205Sharti			uni_msg_destroy(msg);
1055122205Sharti			UNI_FREE(u);
1056122205Sharti			break;
1057122205Sharti		}
1058122205Sharti		uni_bad_message(p->call, u, UNI_CAUSE_MSG_INCOMP,
1059122205Sharti		    &u->u.add_party.epref, p->state);
1060122205Sharti		uni_msg_destroy(msg);
1061122205Sharti		UNI_FREE(u);
1062122205Sharti		break;
1063122205Sharti
1064122205Sharti	  case SIGP_PARTY_ALERTING:
1065122205Sharti		if (p->state == UNI_EPSTATE_ADD_INIT) {
1066122205Sharti			/* Q.2971:Party-Control-U 14 */
1067122205Sharti			/* Q.2971:Party-Control-N 5 */
1068122205Sharti			pun1_party_alerting(p, msg, u);
1069122205Sharti			break;
1070122205Sharti		}
1071122205Sharti		uni_bad_message(p->call, u, UNI_CAUSE_MSG_INCOMP,
1072122205Sharti		    &u->u.party_alerting.epref, p->state);
1073122205Sharti		uni_msg_destroy(msg);
1074122205Sharti		UNI_FREE(u);
1075122205Sharti		break;
1076122205Sharti
1077122205Sharti	  case SIGP_ADD_PARTY_ACK:
1078122205Sharti		if (p->state == UNI_EPSTATE_ADD_INIT ||
1079122205Sharti		    p->state == UNI_EPSTATE_ALERT_RCVD) {
1080122205Sharti			/* Q.2971:Party-Control-U 4 (PU1) */
1081122205Sharti			/* Q.2971:Party-Control-U 7 (PU4) */
1082122205Sharti			/* Q.2971:Party-Control-N 4 (PN1) */
1083122205Sharti			/* Q.2971:Party-Control-N 7 (PN4) */
1084122205Sharti			pun1pun4_add_party_ack(p, msg, u);
1085122205Sharti			break;
1086122205Sharti		}
1087122205Sharti		uni_bad_message(p->call, u, UNI_CAUSE_MSG_INCOMP,
1088122205Sharti		    &u->u.add_party_ack.epref, p->state);
1089122205Sharti		uni_msg_destroy(msg);
1090122205Sharti		UNI_FREE(u);
1091122205Sharti		break;
1092122205Sharti
1093122205Sharti	  case SIGP_ADD_PARTY_REJ:
1094122205Sharti		if (p->state == UNI_EPSTATE_ADD_INIT) {
1095122205Sharti			/* Q.2971:Party-Control-U 4 (PU1) */
1096122205Sharti			/* Q.2971:Party-Control-N 4 (PN1) */
1097122205Sharti			pun1_add_party_rej(p, msg, u);
1098122205Sharti			break;
1099122205Sharti		}
1100122205Sharti		if (p->state == UNI_EPSTATE_DROP_INIT) {
1101122205Sharti			/* Q.2971:Party-Control-U 10 (PU5) */
1102122205Sharti			/* Q.2971:Party-Control-N 10 (PN5) */
1103122205Sharti			pun5_add_party_rej(p, msg, u);
1104122205Sharti			break;
1105122205Sharti		}
1106122205Sharti		uni_bad_message(p->call, u, UNI_CAUSE_MSG_INCOMP,
1107122205Sharti		    &u->u.add_party_rej.epref, p->state);
1108122205Sharti		uni_msg_destroy(msg);
1109122205Sharti		UNI_FREE(u);
1110122205Sharti		break;
1111122205Sharti
1112122205Sharti	  case SIGP_DROP_PARTY_ACK:
1113122205Sharti		/* Q.2971:Party-Control-U 8 */
1114122205Sharti		/* Q.2971:Party-Control-N 8 */
1115122205Sharti		punx_drop_party_ack(p, msg, u);
1116122205Sharti		break;
1117122205Sharti
1118122205Sharti	  case SIGP_DROP_PARTY:
1119122205Sharti		if (p->state == UNI_EPSTATE_DROP_INIT)
1120122205Sharti			/* Q.2971:Party-Control-U 10 */
1121122205Sharti			/* Q.2971:Party-Control-N 10 */
1122122205Sharti			pun5_drop_party(p, msg, u);
1123122205Sharti		else
1124122205Sharti			/* Q.2971:Party-Control-U 9 */
1125122205Sharti			/* Q.2971:Party-Control-N 9 */
1126122205Sharti			punx_drop_party(p, msg, u);
1127122205Sharti		break;
1128122205Sharti
1129122205Sharti	  case SIGP_STATUS:
1130122205Sharti		if (p->state == UNI_EPSTATE_DROP_INIT)
1131122205Sharti			/* Q.2971:Party-Control-U 10 */
1132122205Sharti			/* Q.2971:Party-Control-N 10 */
1133122205Sharti			pun5_status(p, msg, u);
1134122205Sharti		else
1135122205Sharti			/* Q.2971:Party-Control-U 12 */
1136122205Sharti			/* Q.2971:Party-Control-N 12 */
1137122205Sharti			punx_status(p, msg, u);
1138122205Sharti		break;
1139122205Sharti
1140122205Sharti	  /*
1141122205Sharti	   * User
1142122205Sharti	   */
1143122205Sharti	  case SIGP_SETUP_request:
1144122205Sharti		if (p->state == UNI_EPSTATE_NULL) {
1145122205Sharti			/* Q.2971:Party-Control-U 3 */
1146122205Sharti			/* Q.2971:Party-Control-N 3 */
1147122205Sharti			set_party_state(p, UNI_EPSTATE_ADD_INIT);
1148122205Sharti			break;
1149122205Sharti		}
1150122205Sharti		VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
1151122205Sharti		    "SETUP.request in ps=%u", p->state);
1152122205Sharti		uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie);
1153122205Sharti		break;
1154122205Sharti
1155122205Sharti	  case SIGP_SETUP_response:
1156122205Sharti		if (p->state == UNI_EPSTATE_ADD_RCVD ||
1157122205Sharti		    p->state == UNI_EPSTATE_ALERT_DLVD) {
1158122205Sharti			/* Q.2971:Party-Control-N 6 (PN2) */
1159122205Sharti			/* Q.2971:Party-Control-N 7 (PN3) */
1160122205Sharti			set_party_state(p, UNI_EPSTATE_ACTIVE);
1161122205Sharti			break;
1162122205Sharti		}
1163122205Sharti		VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
1164122205Sharti		    "SETUP.response in ps=%u", p->state);
1165122205Sharti		uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie);
1166122205Sharti		break;
1167122205Sharti
1168122205Sharti	  case SIGP_SETUP_COMPL_request:
1169122205Sharti		if (p->state == UNI_EPSTATE_ADD_INIT) {
1170122205Sharti			/* Q.2971:Party-Control-N 4 */
1171122205Sharti			TIMER_STOP_PARTY(p, t399);
1172122205Sharti			set_party_state(p, UNI_EPSTATE_ACTIVE);
1173122205Sharti			break;
1174122205Sharti		}
1175122205Sharti		if (p->state == UNI_EPSTATE_ALERT_RCVD) {
1176122205Sharti			/* Q.2971:Party-Control-N 7 */
1177122205Sharti			TIMER_STOP_PARTY(p, t397);
1178122205Sharti			set_party_state(p, UNI_EPSTATE_ACTIVE);
1179122205Sharti			break;
1180122205Sharti		}
1181122205Sharti		VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
1182122205Sharti		    "SETUP_COMPL.request in ps=%u", p->state);
1183122205Sharti		uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie);
1184122205Sharti		break;
1185122205Sharti
1186122205Sharti	  case SIGP_ADD_PARTY_request:
1187122205Sharti		if (p->state == UNI_EPSTATE_NULL) {
1188122205Sharti			/* Q.2971:Party-control-U 3 (PU0) */
1189122205Sharti			/* Q.2971:Party-control-N 3 (PN0) */
1190122205Sharti			pun0_add_party_request(p, msg, cookie);
1191122205Sharti			break;
1192122205Sharti		}
1193122205Sharti		VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
1194122205Sharti		    "Add-party.request in ps=%u", p->state);
1195122205Sharti		uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie);
1196122205Sharti		uni_msg_destroy(msg);
1197122205Sharti		break;
1198122205Sharti
1199122205Sharti	  case SIGP_ALERTING_request:
1200122205Sharti		/* Q.2971:Party-Control-U 6 (PU2) */
1201122205Sharti		/* Q.2971:Party-Control-N 6 (PN2) */
1202122205Sharti		set_party_state(p, UNI_EPSTATE_ALERT_DLVD);
1203122205Sharti		break;
1204122205Sharti
1205122205Sharti	  case SIGP_PARTY_ALERTING_request:
1206122205Sharti		if (p->state == UNI_EPSTATE_ADD_RCVD) {
1207122205Sharti			/* Q.2971:Party-Control-U 6 (PU2) */
1208122205Sharti			/* Q.2971:Party-Control-N 6 (PN2) */
1209122205Sharti			pun2_party_alerting_request(p, msg, cookie);
1210122205Sharti			break;
1211122205Sharti		}
1212122205Sharti		VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
1213122205Sharti		    "Party-alerting.request in ps=%u", p->state);
1214122205Sharti		uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie);
1215122205Sharti		uni_msg_destroy(msg);
1216122205Sharti		break;
1217122205Sharti
1218122205Sharti	  case SIGP_ADD_PARTY_ACK_request:
1219122205Sharti		if (p->state == UNI_EPSTATE_ADD_RCVD ||
1220122205Sharti		    p->state == UNI_EPSTATE_ALERT_DLVD) {
1221122205Sharti			/* Q.2971:Party-Control-U 6 PU2 */
1222122205Sharti			/* Q.2971:Party-Control-U 7 PU3 */
1223122205Sharti			/* Q.2971:Party-Control-N 6 PN2 */
1224122205Sharti			/* Q.2971:Party-Control-N 7 PN3 */
1225122205Sharti			punx_add_party_ack_request(p, msg, cookie);
1226122205Sharti			break;
1227122205Sharti		}
1228122205Sharti		VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
1229122205Sharti		    "Add-party-ack.request in ps=%u", p->state);
1230122205Sharti		uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie);
1231122205Sharti		uni_msg_destroy(msg);
1232122205Sharti		break;
1233122205Sharti
1234122205Sharti	  case SIGP_ADD_PARTY_REJ_request:
1235122205Sharti		if (p->state == UNI_EPSTATE_ADD_RCVD) {
1236122205Sharti			/* Q.2971:Party-Control-U 6 PU2 */
1237122205Sharti			/* Q.2971:Party-Control-N 6 PN2 */
1238122205Sharti			pun2_add_party_rej_request(p, msg, cookie);
1239122205Sharti			break;
1240122205Sharti		}
1241122205Sharti		VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
1242122205Sharti		    "Add-party-rej.request in ps=%u", p->state);
1243122205Sharti		uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie);
1244122205Sharti		uni_msg_destroy(msg);
1245122205Sharti		break;
1246122205Sharti
1247122205Sharti	  case SIGP_DROP_PARTY_request:
1248122205Sharti		if (p->state == UNI_EPSTATE_ADD_INIT ||
1249122205Sharti		    p->state == UNI_EPSTATE_ALERT_DLVD ||
1250122205Sharti		    p->state == UNI_EPSTATE_ALERT_RCVD ||
1251122205Sharti		    p->state == UNI_EPSTATE_ACTIVE) {
1252122205Sharti			/* Q.2971:Party-Control-U 8 */
1253122205Sharti			/* Q.2971:Party-Control-N 8 */
1254122205Sharti			punx_drop_party_request(p, msg, cookie);
1255122205Sharti			break;
1256122205Sharti		}
1257122205Sharti		VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
1258122205Sharti		    "Drop-party.request in ps=%u", p->state);
1259122205Sharti		uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie);
1260122205Sharti		uni_msg_destroy(msg);
1261122205Sharti		break;
1262122205Sharti
1263122205Sharti	  case SIGP_DROP_PARTY_ACK_request:
1264122205Sharti		if (p->state == UNI_EPSTATE_DROP_RCVD) {
1265122205Sharti			/* Q.2971:Party-Control-U 9 */
1266122205Sharti			/* Q.2971:Party-Control-N 9 */
1267122205Sharti			pun6_drop_party_ack_request(p, msg, cookie);
1268122205Sharti			break;
1269122205Sharti		}
1270122205Sharti		VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
1271122205Sharti		    "Drop-party-ack.request in ps=%u", p->state);
1272122205Sharti		uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie);
1273122205Sharti		uni_msg_destroy(msg);
1274122205Sharti		break;
1275122205Sharti
1276122205Sharti	  case SIGP_STATUS_ENQUIRY_request:
1277122205Sharti		/* Q.2971:Party-Control-U 12 */
1278122205Sharti		/* Q.2971:Party-Control-N 12 */
1279122205Sharti		punx_status_enquiry_request(p, cookie);
1280122205Sharti		break;
1281122205Sharti
1282122205Sharti	  /*
1283122205Sharti	   * Timers
1284122205Sharti	   */
1285122205Sharti	  case SIGP_T397:
1286122205Sharti		if (p->state == UNI_EPSTATE_ALERT_RCVD) {
1287122205Sharti			/* Q.2971:Party-Control-U 7 (PU4) */
1288122205Sharti			/* Q.2971:Party-Control-N 7 (PN4) */
1289122205Sharti			pun4_t397(p);
1290122205Sharti			break;
1291122205Sharti		}
1292122205Sharti		VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
1293122205Sharti		    "T397 in ps=%u", p->state);
1294122205Sharti		break;
1295122205Sharti
1296122205Sharti	  case SIGP_T398:
1297122205Sharti		if (p->state == UNI_EPSTATE_DROP_INIT) {
1298122205Sharti			/* Q.2971:Party-Control-U 10 (PU5) */
1299122205Sharti			/* Q.2971:Party-Control-N 10 (PN5) */
1300122205Sharti			pun5_t398(p);
1301122205Sharti			break;
1302122205Sharti		}
1303122205Sharti		VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
1304122205Sharti		    "T398 in ps=%u", p->state);
1305122205Sharti		break;
1306122205Sharti
1307122205Sharti	  case SIGP_T399:
1308122205Sharti		if (p->state == UNI_EPSTATE_ADD_INIT) {
1309122205Sharti			/* Q.2971:Party-Control-U 4 (PU1) */
1310122205Sharti			/* Q.2971:Party-Control-N 4 (PN1) */
1311122205Sharti			pun1_t399(p);
1312122205Sharti			break;
1313122205Sharti		}
1314122205Sharti		VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
1315122205Sharti		    "T399 in ps=%u", p->state);
1316122205Sharti		break;
1317122205Sharti
1318122205Sharti	  case SIGP_END:
1319122205Sharti		break;
1320122205Sharti	}
1321122205Sharti}
1322122205Sharti
1323122205Shartistatic void
1324122205Shartit397_func(struct party *p)
1325122205Sharti{
1326122205Sharti	uni_enq_party(p, SIGP_T397, 0, NULL, NULL);
1327122205Sharti}
1328122205Shartistatic void
1329122205Shartit398_func(struct party *p)
1330122205Sharti{
1331122205Sharti	uni_enq_party(p, SIGP_T398, 0, NULL, NULL);
1332122205Sharti}
1333122205Shartistatic void
1334122205Shartit399_func(struct party *p)
1335122205Sharti{
1336122205Sharti	uni_enq_party(p, SIGP_T399, 0, NULL, NULL);
1337122205Sharti}
1338122205Sharti
1339122205Shartistatic int
1340122205Shartiepstate_compat(struct party *p, enum uni_epstate state)
1341122205Sharti{
1342122205Sharti	if (p->state == UNI_EPSTATE_ADD_INIT ||
1343122205Sharti	    p->state == UNI_EPSTATE_ALERT_RCVD)
1344122205Sharti		if (state == UNI_EPSTATE_ADD_INIT ||
1345122205Sharti		    state == UNI_EPSTATE_ALERT_RCVD)
1346122205Sharti			return (0);
1347122205Sharti	if (p->state == UNI_EPSTATE_ADD_RCVD ||
1348122205Sharti	    p->state == UNI_EPSTATE_ALERT_DLVD)
1349122205Sharti		if (state == UNI_EPSTATE_ADD_RCVD ||
1350122205Sharti		    state == UNI_EPSTATE_ALERT_DLVD)
1351122205Sharti			return (0);
1352122205Sharti	return (1);
1353122205Sharti}
1354