1 /*
2  * Copyright (c) 1996-2003
3  *	Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4  * 	All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  * Author: Hartmut Brandt <[email protected]>
28  *
29  * $Begemot: libunimsg/netnatm/sig/sig_party.c,v 1.18 2004/08/05 07:11:01 brandt Exp $
30  *
31  * Party instance handling
32  */
33 
34 #include <netnatm/unimsg.h>
35 #include <netnatm/saal/sscfudef.h>
36 #include <netnatm/msg/unistruct.h>
37 #include <netnatm/msg/unimsglib.h>
38 #include <netnatm/sig/uni.h>
39 
40 #include <netnatm/sig/unipriv.h>
41 #include <netnatm/sig/unimkmsg.h>
42 #include <netnatm/sig/unimsgcpy.h>
43 
44 static void drop_partyE(struct party *p);
45 static int epstate_compat(struct party *, enum uni_epstate);
46 
47 #define DEF_PRIV_SIG(NAME, FROM)	[SIG##NAME] =	"SIG"#NAME,
48 static const char *const party_sigs[] = {
49 	DEF_PARTY_SIGS
50 };
51 #undef DEF_PRIV_SIG
52 
TIMER_FUNC_PARTY(t397,t397_func)53 TIMER_FUNC_PARTY(t397, t397_func)
54 TIMER_FUNC_PARTY(t398, t398_func)
55 TIMER_FUNC_PARTY(t399, t399_func)
56 
57 static __inline void
58 set_party_state(struct party *p, enum uni_epstate state)
59 {
60 	if (p->state != state) {
61 		VERBOSE(p->call->uni, UNI_FAC_CALL, 1,
62 		    "party %u/%u %u/%u PU%u -> PU%u",
63 		    p->call->cref, p->call->mine,
64 		    p->epref, p->flags & PARTY_MINE, p->state, state);
65 		p->state = state;
66 	}
67 }
68 
69 /*
70  * Create a party with a given endpoint reference.
71  * No check is done, that a party with this epref does not alreay exist.
72  */
73 struct party *
uni_create_partyx(struct call * c,u_int epref,u_int mine,uint32_t cookie)74 uni_create_partyx(struct call *c, u_int epref, u_int mine, uint32_t cookie)
75 {
76 	struct party *p;
77 	struct uni_msg *api;
78 	struct uniapi_party_created *ind;
79 
80 	mine = (mine ? PARTY_MINE : 0);
81 
82 	if ((p = PARTY_ALLOC()) == NULL)
83 		return (NULL);
84 
85 	if ((ind = ALLOC_API(struct uniapi_party_created, api)) == NULL) {
86 		PARTY_FREE(p);
87 		return (NULL);
88 	}
89 
90 	ind->cref.cref = c->cref;
91 	ind->cref.flag = c->mine;
92 	MK_IE_EPREF(ind->epref, epref, mine);
93 	ind->epref.h.act = UNI_IEACT_DEFAULT;
94 
95 	p->call = c;
96 	p->epref = epref;
97 	p->flags = mine;
98 	p->state = UNI_EPSTATE_NULL;;
99 
100 	TIMER_INIT_PARTY(p, t397);
101 	TIMER_INIT_PARTY(p, t398);
102 	TIMER_INIT_PARTY(p, t399);
103 
104 	TAILQ_INSERT_HEAD(&c->parties, p, link);
105 
106 	c->uni->funcs->uni_output(c->uni, c->uni->arg,
107 	    UNIAPI_PARTY_CREATED, cookie, api);
108 
109 	VERBOSE(c->uni, UNI_FAC_CALL, 1, "created party %u/%s %u/%s",
110 	    p->call->cref, p->call->mine ? "mine" : "his",
111 	    p->epref, (p->flags & PARTY_MINE) ? "mine" : "his");
112 
113 	return (p);
114 
115 }
116 
117 struct party *
uni_create_party(struct call * c,struct uni_ie_epref * epref)118 uni_create_party(struct call *c, struct uni_ie_epref *epref)
119 {
120 	return (uni_create_partyx(c, epref->epref, epref->flag, 0));
121 }
122 
123 struct party *
uni_find_party(struct call * c,struct uni_ie_epref * epref)124 uni_find_party(struct call *c, struct uni_ie_epref *epref)
125 {
126 	struct party *p;
127 
128 	TAILQ_FOREACH(p, &c->parties, link)
129 		if (p->epref == epref->epref &&
130 		    (!(p->flags & PARTY_MINE) == !epref->flag))
131 			return (p);
132 	return (NULL);
133 }
134 struct party *
uni_find_partyx(struct call * c,u_int epref,u_int mine)135 uni_find_partyx(struct call *c, u_int epref, u_int mine)
136 {
137 	struct party *p;
138 
139 	TAILQ_FOREACH(p, &c->parties, link)
140 		if (p->epref == epref && (!(p->flags & PARTY_MINE) == !mine))
141 			return (p);
142 	return (NULL);
143 }
144 
145 /*
146  * Destroy a party.
147  * This function is assumed to remove the party from the parent's call
148  * party list.
149  */
150 void
uni_destroy_party(struct party * p,int really)151 uni_destroy_party(struct party *p, int really)
152 {
153 	struct uni_msg *api;
154 	struct uniapi_party_destroyed *ind;
155 
156 	TIMER_DESTROY_PARTY(p, t397);
157 	TIMER_DESTROY_PARTY(p, t398);
158 	TIMER_DESTROY_PARTY(p, t399);
159 
160 	TAILQ_REMOVE(&p->call->parties, p, link);
161 
162 	uni_delsig(p->call->uni, SIG_PARTY, p->call, p);
163 
164 	if (!really) {
165 		ind = ALLOC_API(struct uniapi_party_destroyed, api);
166 		if (ind != NULL) {
167 			ind->cref.cref = p->call->cref;
168 			ind->cref.flag = p->call->mine;
169 			ind->epref.epref = p->epref;
170 			ind->epref.flag = p->flags & PARTY_MINE;
171 			ind->epref.h.act = UNI_IEACT_DEFAULT;
172 			IE_SETPRESENT(ind->epref);
173 
174 			uni_enq_call(p->call, SIGC_PARTY_DESTROYED, 0, api, NULL);
175 		}
176 
177 		uni_enq_party(p, SIGP_PARTY_DELETE, 0, NULL, NULL);
178 		return;
179 	}
180 	PARTY_FREE(p);
181 }
182 
183 /*
184  * Count number of parties in active states.
185  * If the argument is 0 only ACTIVE parties are counter
186  * If the argument is 1 only parties in establishing states are counted
187  * If the argument is 2 both are counted.
188  */
189 u_int
uni_party_act_count(struct call * c,int kind)190 uni_party_act_count(struct call *c, int kind)
191 {
192 	struct party *p;
193 	u_int cnt;
194 
195 	cnt = 0;
196 	TAILQ_FOREACH(p, &c->parties, link) {
197 		switch (p->state) {
198 
199 		  case UNI_EPSTATE_ACTIVE:
200 			if (kind == 0 || kind == 2)
201 				cnt++;
202 			break;
203 
204 		  case UNI_EPSTATE_ALERT_RCVD:
205 		  case UNI_EPSTATE_ADD_INIT:
206 		  case UNI_EPSTATE_ALERT_DLVD:
207 		  case UNI_EPSTATE_ADD_RCVD:
208 			if (kind == 1 || kind == 2)
209 				cnt++;
210 			break;
211 
212 		  default:
213 			break;
214 		}
215 	}
216 	return (cnt);
217 }
218 
219 static void
stop_all_party_timers(struct party * p)220 stop_all_party_timers(struct party *p)
221 {
222 	TIMER_STOP_PARTY(p, t397);
223 	TIMER_STOP_PARTY(p, t398);
224 	TIMER_STOP_PARTY(p, t399);
225 }
226 /************************************************************/
227 
228 /*
229  * Add-party.request
230  *
231  * Q.2971:Party-control-U 3 (PU0)
232  * Q.2971:Party-control-N 3 (PN0)
233  */
234 static void
pun0_add_party_request(struct party * p,struct uni_msg * api,uint32_t cookie)235 pun0_add_party_request(struct party *p, struct uni_msg *api, uint32_t cookie)
236 {
237 	struct uni_all *add;
238 	struct uniapi_add_party_request *req =
239 	    uni_msg_rptr(api, struct uniapi_add_party_request *);
240 
241 	if ((add = UNI_ALLOC()) == NULL) {
242 		uni_msg_destroy(api);
243 		uniapi_party_error(p, UNIAPI_ERROR_NOMEM, cookie);
244 		return;
245 	}
246 
247 	add->u.add_party = req->add;
248 	MK_MSG_ORIG(add, UNI_ADD_PARTY, p->call->cref, !p->call->mine);
249 	uni_send_output(add, p->call->uni);
250 	UNI_FREE(add);
251 
252 	TIMER_START_PARTY(p, t399, p->call->uni->timer399);
253 
254 	set_party_state(p, UNI_EPSTATE_ADD_INIT);
255 
256 	uni_msg_destroy(api);
257 	uniapi_party_error(p, UNIAPI_OK, cookie);
258 }
259 
260 /*
261  * Add-party-ack.request
262  *
263  * Q.2971:Party-Control-U 6 PU2
264  * Q.2971:Party-Control-U 7 PU3
265  * Q.2971:Party-Control-N 6 PN2
266  * Q.2971:Party-Control-N 7 PN3
267  */
268 static void
punx_add_party_ack_request(struct party * p,struct uni_msg * m,uint32_t cookie)269 punx_add_party_ack_request(struct party *p, struct uni_msg *m, uint32_t cookie)
270 {
271 	struct uni_all *ack;
272 	struct uniapi_add_party_ack_request *req =
273 	    uni_msg_rptr(m, struct uniapi_add_party_ack_request *);
274 
275 	if ((ack = UNI_ALLOC()) == NULL) {
276 		uniapi_party_error(p, UNIAPI_ERROR_NOMEM, cookie);
277 		uni_msg_destroy(m);
278 		return;
279 	}
280 	ack->u.add_party_ack = req->ack;
281 	MK_MSG_ORIG(ack, UNI_ADD_PARTY_ACK, p->call->cref, !p->call->mine);
282 	uni_send_output(ack, p->call->uni);
283 	UNI_FREE(ack);
284 
285 	set_party_state(p, UNI_EPSTATE_ACTIVE);
286 
287 	uni_msg_destroy(m);
288 	uniapi_party_error(p, UNIAPI_OK, cookie);
289 }
290 
291 /*
292  * Add-party-rej.request
293  *
294  * Q.2971:Party-Control-U 6 PU2
295  * Q.2971:Party-Control-N 6 PN2
296  */
297 static void
pun2_add_party_rej_request(struct party * p,struct uni_msg * m,uint32_t cookie)298 pun2_add_party_rej_request(struct party *p, struct uni_msg *m, uint32_t cookie)
299 {
300 	struct uni_all *rej;
301 	struct uniapi_add_party_rej_request *req =
302 	    uni_msg_rptr(m, struct uniapi_add_party_rej_request *);
303 
304 	if ((rej = UNI_ALLOC()) == NULL) {
305 		uniapi_party_error(p, UNIAPI_ERROR_NOMEM, cookie);
306 		uni_msg_destroy(m);
307 		return;
308 	}
309 
310 	stop_all_party_timers(p);
311 
312 	rej->u.add_party_rej = req->rej;
313 	MK_MSG_ORIG(rej, UNI_ADD_PARTY_REJ, p->call->cref, !p->call->mine);
314 	uni_enq_call(p->call, SIGC_SEND_ADD_PARTY_REJ, cookie, NULL, rej);
315 
316 	uni_msg_destroy(m);
317 	p->state = UNI_EPSTATE_NULL;
318 	uniapi_party_error(p, UNIAPI_OK, cookie);
319 
320 	uni_destroy_party(p, 0);
321 }
322 
323 /*
324  * ADD PARTY in PU0, PN0
325  *
326  * Q.2971:Party-Control-U 3/14 PU0
327  */
328 static void
pun0_add_party(struct party * p,struct uni_msg * m,struct uni_all * u)329 pun0_add_party(struct party *p, struct uni_msg *m, struct uni_all *u)
330 {
331 	struct uniapi_add_party_indication *ind;
332 	struct uni_msg *api;
333 
334 	ind = ALLOC_API(struct uniapi_add_party_indication, api);
335 	if (ind != NULL) {
336 		ind->add.hdr = u->u.hdr;
337 		copy_msg_add_party(&u->u.add_party, &ind->add);
338 		p->call->uni->funcs->uni_output(p->call->uni, p->call->uni->arg,
339 		    UNIAPI_ADD_PARTY_indication, 0, api);
340 	}
341 	set_party_state(p, UNI_EPSTATE_ADD_RCVD);
342 
343 	uni_msg_destroy(m);
344 	UNI_FREE(u);
345 }
346 
347 /*
348  * PARTY-ALERTING.request
349  *
350  * Q.2971:Party-Control-U 6 (PU2)
351  * Q.2971:Party-Control-N 6 (PN2)
352  */
353 static void
pun2_party_alerting_request(struct party * p,struct uni_msg * api,uint32_t cookie)354 pun2_party_alerting_request(struct party *p, struct uni_msg *api,
355     uint32_t cookie)
356 {
357 	struct uni_all *alert;
358 	struct uniapi_party_alerting_request *req =
359 	    uni_msg_rptr(api, struct uniapi_party_alerting_request *);
360 
361 	if ((alert = UNI_ALLOC()) == NULL) {
362 		uniapi_party_error(p, UNIAPI_ERROR_NOMEM, cookie);
363 		uni_msg_destroy(api);
364 		return;
365 	}
366 	alert->u.party_alerting = req->alert;
367 	MK_MSG_ORIG(alert, UNI_PARTY_ALERTING,
368 	     p->call->cref, !p->call->mine);
369 	uni_send_output(alert, p->call->uni);
370 	UNI_FREE(alert);
371 
372 	set_party_state(p, UNI_EPSTATE_ALERT_DLVD);
373 
374 	uni_msg_destroy(api);
375 	uniapi_party_error(p, UNIAPI_OK, cookie);
376 }
377 
378 /*
379  * PARTY-ALERTING in state PU1/PN1
380  *
381  * Q.2971:Party-Control-U 14
382  * Q.2971:Party-Control-N 5
383  */
384 static void
pun1_party_alerting(struct party * p,struct uni_msg * m,struct uni_all * u)385 pun1_party_alerting(struct party *p, struct uni_msg *m, struct uni_all *u)
386 {
387 	struct uniapi_party_alerting_indication *ind;
388 	struct uni_msg *api;
389 
390 	ind = ALLOC_API(struct uniapi_party_alerting_indication, api);
391 	if (ind == NULL) {
392 		uni_msg_destroy(m);
393 		UNI_FREE(u);
394 		return;
395 	}
396 	TIMER_STOP_PARTY(p, t399);
397 
398 	ind->alert.hdr = u->u.hdr;
399 	copy_msg_party_alerting(&u->u.party_alerting, &ind->alert);
400 
401 	p->call->uni->funcs->uni_output(p->call->uni, p->call->uni->arg,
402 	    UNIAPI_PARTY_ALERTING_indication, 0, api);
403 
404 	TIMER_START_PARTY(p, t397, p->call->uni->timer397);
405 
406 	uni_msg_destroy(m);
407 	UNI_FREE(u);
408 
409 	set_party_state(p, UNI_EPSTATE_ALERT_RCVD);
410 }
411 
412 /*
413  * ADD-PARTY-ACK
414  *
415  * Q.2971:Party-Control-U 4 (PU1)
416  * Q.2971:Party-Control-U 7 (PU4)
417  * Q.2971:Party-Control-N 4 (PN1)
418  * Q.2971:Party-Control-N 7 (PN4)
419  */
420 static void
pun1pun4_add_party_ack(struct party * p,struct uni_msg * m,struct uni_all * u)421 pun1pun4_add_party_ack(struct party *p, struct uni_msg *m, struct uni_all *u)
422 {
423 	struct uniapi_add_party_ack_indication *ind;
424 	struct uni_msg *api;
425 
426 	ind = ALLOC_API(struct uniapi_add_party_ack_indication, api);
427 	if (ind == NULL) {
428 		uni_msg_destroy(m);
429 		UNI_FREE(u);
430 		return;
431 	}
432 
433 	if (p->state == UNI_EPSTATE_ADD_INIT)
434 		TIMER_STOP_PARTY(p, t399);
435 	else
436 		TIMER_STOP_PARTY(p, t397);
437 
438 	ind->ack.hdr = u->u.hdr;
439 	copy_msg_add_party_ack(&u->u.add_party_ack, &ind->ack);
440 
441 	p->call->uni->funcs->uni_output(p->call->uni, p->call->uni->arg,
442 	    UNIAPI_ADD_PARTY_ACK_indication, 0, api);
443 
444 	uni_msg_destroy(m);
445 	UNI_FREE(u);
446 
447 	set_party_state(p, UNI_EPSTATE_ACTIVE);
448 }
449 
450 /*
451  * ADD-PARTY-REJECT
452  *
453  * Q.2971:Party-Control-U 4 (PU1)
454  * Q.2971:Party-Control-N 4 (PN1)
455  */
456 static void
pun1_add_party_rej(struct party * p,struct uni_msg * m,struct uni_all * u)457 pun1_add_party_rej(struct party *p, struct uni_msg *m, struct uni_all *u)
458 {
459 	struct uniapi_add_party_rej_indication *ind;
460 	struct uni_msg *api;
461 
462 	ind = ALLOC_API(struct uniapi_add_party_rej_indication, api);
463 	if (ind == NULL) {
464 		uni_msg_destroy(m);
465 		UNI_FREE(u);
466 		return;
467 	}
468 
469 	TIMER_STOP_PARTY(p, t399);
470 
471 	ind->rej.hdr = u->u.hdr;
472 	copy_msg_add_party_rej(&u->u.add_party_rej, &ind->rej);
473 	uni_enq_call(p->call, SIGC_ADD_PARTY_REJ_indication, 0, api, NULL);
474 
475 	uni_destroy_party(p, 0);
476 
477 	uni_msg_destroy(m);
478 	UNI_FREE(u);
479 }
480 
481 /*
482  * ADD-PARTY-REJECT
483  *
484  * Q.2971:Party-Control-U 10 (PU5)
485  * Q.2971:Party-Control-N 10 (PN5)
486  */
487 static void
pun5_add_party_rej(struct party * p,struct uni_msg * m,struct uni_all * u)488 pun5_add_party_rej(struct party *p, struct uni_msg *m, struct uni_all *u)
489 {
490 	struct uniapi_drop_party_ack_indication *ind;
491 	struct uni_msg *api;
492 
493 	ind = ALLOC_API(struct uniapi_drop_party_ack_indication, api);
494 	if (ind == NULL) {
495 		uni_msg_destroy(m);
496 		UNI_FREE(u);
497 		return;
498 	}
499 
500 	ind->drop.hdr = u->u.hdr;
501 	COPY_FROM_ADD_REJ(u, &ind->drop);
502 	if (IE_ISGOOD(u->u.add_party_rej.crankback))
503 		ind->crankback = u->u.add_party_rej.crankback;
504 	uni_enq_call(p->call, SIGC_DROP_PARTY_ACK_indication, 0, api, NULL);
505 
506 	TIMER_STOP_PARTY(p, t398);
507 
508 	uni_destroy_party(p, 0);
509 
510 	uni_msg_destroy(m);
511 	UNI_FREE(u);
512 }
513 
514 /*
515  * DROP-PARTY-ACKNOWLEDGE
516  *
517  * Q.2971:Party-Control-U 8
518  * Q.2971:Party-Control-N 8
519  *
520  * Message already verified in Call-Control!
521  */
522 static void
punx_drop_party_ack(struct party * p,struct uni_msg * m,struct uni_all * u)523 punx_drop_party_ack(struct party *p, struct uni_msg *m, struct uni_all *u)
524 {
525 	struct uniapi_drop_party_ack_indication *ind;
526 	struct uni_msg *api;
527 
528 	stop_all_party_timers(p);
529 
530 	ind = ALLOC_API(struct uniapi_drop_party_ack_indication, api);
531 	if (ind != NULL) {
532 		ind->drop.hdr = u->u.hdr;
533 		COPY_FROM_DROP_ACK(u, &ind->drop);
534 		uni_enq_call(p->call, SIGC_DROP_PARTY_ACK_indication,
535 		    0, api, NULL);
536 	}
537 
538 	uni_destroy_party(p, 0);
539 
540 	uni_msg_destroy(m);
541 	UNI_FREE(u);
542 }
543 
544 /*
545  * DROP PARTY message in any state except PU5/PN5
546  *
547  * Q.2971:Party-Control-U 9
548  * Q.2971:Party-Control-N 9
549  */
550 static void
punx_drop_party(struct party * p,struct uni_msg * m,struct uni_all * u)551 punx_drop_party(struct party *p, struct uni_msg *m, struct uni_all *u)
552 {
553 	struct uniapi_drop_party_indication *ind;
554 	struct uni_msg *api;
555 
556 	ind = ALLOC_API(struct uniapi_drop_party_indication, api);
557 	if (ind == NULL) {
558 		uni_msg_destroy(m);
559 		UNI_FREE(u);
560 		return;
561 	}
562 
563 	ind->drop.hdr = u->u.hdr;
564 	copy_msg_drop_party(&u->u.drop_party, &ind->drop);
565 
566 	/* need the cause even if it is bad */
567 	if (IE_ISERROR(u->u.drop_party.cause))
568 		ind->drop.cause = u->u.drop_party.cause;
569 
570 	ind->my_cause = p->call->uni->cause;
571 
572 	uni_enq_call(p->call, SIGC_DROP_PARTY_indication, 0, api, NULL);
573 
574 	TIMER_STOP_PARTY(p, t397);
575 	TIMER_STOP_PARTY(p, t399);
576 
577 	uni_msg_destroy(m);
578 	UNI_FREE(u);
579 
580 	set_party_state(p, UNI_EPSTATE_DROP_RCVD);
581 }
582 
583 /*
584  * DROP PARTY message in state PU5/PN5
585  *
586  * Q.2971:Party-Control-U 10
587  * Q.2971:Party-Control-N 10
588  */
589 static void
pun5_drop_party(struct party * p,struct uni_msg * m,struct uni_all * u)590 pun5_drop_party(struct party *p, struct uni_msg *m, struct uni_all *u)
591 {
592 	struct uniapi_drop_party_ack_indication *ind;
593 	struct uni_msg *api;
594 
595 	ind = ALLOC_API(struct uniapi_drop_party_ack_indication, api);
596 	if (ind == NULL) {
597 		uni_msg_destroy(m);
598 		UNI_FREE(u);
599 		return;
600 	}
601 
602 	ind->drop.hdr = u->u.hdr;
603 	copy_msg_drop_party(&u->u.drop_party, &ind->drop);
604 
605 	/* need the cause even if it is bad */
606 	if (IE_ISERROR(u->u.drop_party.cause))
607 		ind->drop.cause = u->u.drop_party.cause;
608 
609 	uni_enq_call(p->call, SIGC_DROP_PARTY_ACK_indication, 0, api, NULL);
610 
611 	TIMER_STOP_PARTY(p, t398);
612 
613 	uni_msg_destroy(m);
614 	UNI_FREE(u);
615 
616 	set_party_state(p, UNI_EPSTATE_DROP_RCVD);
617 
618 	uni_destroy_party(p, 0);
619 }
620 
621 /************************************************************/
622 
623 /*
624  * T399
625  *
626  * Q.2971:Party-Control-U 4 (PU1)
627  * Q.2971:Party-Control-N 4 (PN1)
628  */
629 static void
pun1_t399(struct party * p)630 pun1_t399(struct party *p)
631 {
632 	if (p->call->uni->proto == UNIPROTO_UNI40N) {
633 		MK_IE_CAUSE(p->call->uni->cause, UNI_CAUSE_LOC_USER,
634 		    UNI_CAUSE_NO_RESPONSE);
635 	} else {
636 		MK_IE_CAUSE(p->call->uni->cause, UNI_CAUSE_LOC_USER,
637 		    UNI_CAUSE_RECOVER);
638 		ADD_CAUSE_TIMER(p->call->uni->cause, "399");
639 	}
640 
641 	drop_partyE(p);
642 }
643 
644 /*
645  * T398
646  *
647  * Q.2971:Party-Control-U 10 (PU5)
648  * Q.2971:Party-Control-N 10 (PN5)
649  */
650 static void
pun5_t398(struct party * p)651 pun5_t398(struct party *p)
652 {
653 	struct uniapi_drop_party_ack_indication *ind;
654 	struct uni_all *drop;
655 	struct uni_msg *api;
656 
657 	MK_IE_CAUSE(p->call->uni->cause,
658 	    UNI_CAUSE_LOC_USER, UNI_CAUSE_RECOVER);
659 	ADD_CAUSE_TIMER(p->call->uni->cause, "398");
660 	/*
661 	 * Send indication to API
662 	 */
663 	ind = ALLOC_API(struct uniapi_drop_party_ack_indication, api);
664 	if (ind != NULL) {
665 		ind->drop.hdr.cref.cref = p->call->cref;
666 		ind->drop.hdr.cref.flag = p->call->mine;
667 		ind->drop.hdr.act = UNI_MSGACT_DEFAULT;
668 		MK_IE_EPREF(ind->drop.epref, p->epref, p->flags & PARTY_MINE);
669 		ind->drop.cause = p->call->uni->cause;
670 		uni_enq_call(p->call, SIGC_DROP_PARTY_ACK_indication,
671 		    0, api, NULL);
672 	}
673 
674 	/*
675 	 * Send DROP PARTY ACK
676 	 */
677 	if ((drop = UNI_ALLOC()) != NULL) {
678 		MK_MSG_ORIG(drop, UNI_DROP_PARTY_ACK,
679 		    p->call->cref, !p->call->mine);
680 		MK_IE_EPREF(drop->u.drop_party_ack.epref,
681 		    p->epref, !(p->flags & PARTY_MINE));
682 		drop->u.drop_party_ack.cause = p->call->uni->cause;
683 		uni_enq_call(p->call, SIGC_SEND_DROP_PARTY_ACK, 0, NULL, drop);
684 	}
685 
686 	uni_destroy_party(p, 0);
687 }
688 
689 /*
690  * T397
691  *
692  * Q.2971:Party-Control-U 7 (PU4)
693  * Q.2971:Party-Control-N 7 (PN4)
694  */
695 static void
pun4_t397(struct party * p)696 pun4_t397(struct party *p)
697 {
698 	MK_IE_CAUSE(p->call->uni->cause, UNI_CAUSE_LOC_USER,
699 	    UNI_CAUSE_RECOVER);
700 	ADD_CAUSE_TIMER(p->call->uni->cause, "397");
701 
702 	drop_partyE(p);
703 }
704 
705 /************************************************************/
706 
707 /*
708  * Drop a party because of an error condition.
709  * This is label E on page Party-Control-U 8/14.
710  *
711  * It is assumed, that the caller has constructed the cause in
712  * p->call->uni->cause.
713  */
714 static void
drop_partyE(struct party * p)715 drop_partyE(struct party *p)
716 {
717 	struct uni_msg *api;
718 	struct uniapi_drop_party_indication *ind;
719 	struct uni_all *drop;
720 
721 	/*
722 	 * Send indication to API
723 	 */
724 	if ((ind = ALLOC_API(struct uniapi_drop_party_indication, api)) != NULL) {
725 		ind->drop.hdr.cref.cref = p->call->cref;
726 		ind->drop.hdr.cref.flag = p->call->mine;
727 		ind->drop.hdr.act = UNI_MSGACT_DEFAULT;
728 		MK_IE_EPREF(ind->drop.epref, p->epref, p->flags & PARTY_MINE);
729 		ind->drop.cause = p->call->uni->cause;
730 		uni_enq_call(p->call, SIGC_DROP_PARTY_indication, 0, api, NULL);
731 	}
732 	TIMER_STOP_PARTY(p, t399);
733 	TIMER_STOP_PARTY(p, t397);
734 	TIMER_START_PARTY(p, t398, p->call->uni->timer398);
735 
736 	if ((drop = UNI_ALLOC()) != NULL) {
737 		drop->u.drop_party.cause = p->call->uni->cause;
738 		MK_MSG_ORIG(drop, UNI_DROP_PARTY, p->call->cref, !p->call->mine);
739 		MK_IE_EPREF(drop->u.drop_party.epref, p->epref,
740 		    !(p->flags & PARTY_MINE));
741 		uni_enq_call(p->call, SIGC_SEND_DROP_PARTY, 0, NULL, drop);
742 	}
743 
744 	set_party_state(p, UNI_EPSTATE_DROP_INIT);
745 }
746 
747 /*
748  * Drop party request in Px1, Px3, Px4 or Px7
749  *
750  * Q.2971:Party-Control-U 8
751  * Q.2971:Party-Control-N 8
752  */
753 static void
punx_drop_party_request(struct party * p,struct uni_msg * api,uint32_t cookie)754 punx_drop_party_request(struct party *p, struct uni_msg *api, uint32_t cookie)
755 {
756 	struct uniapi_drop_party_request *req =
757 	    uni_msg_rptr(api, struct uniapi_drop_party_request *);
758 	struct uni_all *drop;
759 
760 	if ((drop = UNI_ALLOC()) == NULL) {
761 		uniapi_party_error(p, UNIAPI_ERROR_NOMEM, cookie);
762 		uni_msg_destroy(api);
763 		return;
764 	}
765 
766 	TIMER_STOP_PARTY(p, t399);
767 	TIMER_STOP_PARTY(p, t397);
768 	TIMER_START_PARTY(p, t398, p->call->uni->timer398);
769 
770 	drop->u.drop_party = req->drop;
771 	MK_MSG_ORIG(drop, UNI_DROP_PARTY, p->call->cref, !p->call->mine);
772 	uni_enq_call(p->call, SIGC_SEND_DROP_PARTY, cookie, NULL, drop);
773 
774 	set_party_state(p, UNI_EPSTATE_DROP_INIT);
775 
776 	uni_msg_destroy(api);
777 	uniapi_party_error(p, UNIAPI_OK, cookie);
778 }
779 
780 /*
781  * Drop-party-ack.request in Px6
782  *
783  * Q.2971:Party-Control-U 9
784  * Q.2971:Party-Control-N 9
785  */
786 static void
pun6_drop_party_ack_request(struct party * p,struct uni_msg * api,uint32_t cookie)787 pun6_drop_party_ack_request(struct party *p, struct uni_msg *api, uint32_t cookie)
788 {
789 	struct uniapi_drop_party_ack_request *req =
790 	    uni_msg_rptr(api, struct uniapi_drop_party_ack_request *);
791 	struct uni_all *ack;
792 
793 	if ((ack = UNI_ALLOC()) == NULL) {
794 		uni_msg_destroy(api);
795 		uniapi_party_error(p, UNIAPI_ERROR_NOMEM, cookie);
796 		return;
797 	}
798 	ack->u.drop_party_ack = req->ack;
799 	MK_MSG_ORIG(ack, UNI_DROP_PARTY_ACK, p->call->cref, !p->call->mine);
800 	uni_enq_call(p->call, SIGC_SEND_DROP_PARTY_ACK, cookie, NULL, ack);
801 
802 	stop_all_party_timers(p);
803 
804 	uni_msg_destroy(api);
805 	uniapi_party_error(p, UNIAPI_OK, cookie);
806 
807 	uni_destroy_party(p, 0);
808 }
809 /************************************************************/
810 /*
811  * Party status enquiry request from API or call-control
812  *
813  * Q.2971:Party-Control-U 12
814  * Q.2971:Party-Control-N 12
815  */
816 static void
punx_status_enquiry_request(struct party * p,uint32_t cookie)817 punx_status_enquiry_request(struct party *p, uint32_t cookie)
818 {
819 	struct uni_all *enq;
820 
821 	if((enq = UNI_ALLOC()) == NULL) {
822 		uniapi_party_error(p, UNIAPI_ERROR_NOMEM, cookie);
823 		return;
824 	}
825 	MK_IE_EPREF(enq->u.status_enq.epref, p->epref,
826 	    !(p->flags & PARTY_MINE));
827 	MK_MSG_ORIG(enq, UNI_STATUS_ENQ, p->call->cref, !p->call->mine);
828 	uni_enq_call(p->call, SIGC_SEND_STATUS_ENQ, cookie, NULL, enq);
829 
830 	uniapi_party_error(p, UNIAPI_OK, cookie);
831 }
832 
833 /*
834  * STATUS in any state except PU5/PN5
835  *
836  * Q.2971:Party-Control-U 12
837  * Q.2971:Party-Control-N 12
838  */
839 static void
punx_status(struct party * p,struct uni_msg * m,struct uni_all * u)840 punx_status(struct party *p, struct uni_msg *m, struct uni_all *u)
841 {
842 	struct uniapi_drop_party_ack_indication *ind;
843 	struct uni_msg *api;
844 
845 	if (u->u.status.epstate.state == UNI_EPSTATE_NULL) {
846 		/* should not happend */
847 		ind = ALLOC_API(struct uniapi_drop_party_ack_indication, api);
848 		if (ind != NULL) {
849 			ind->drop.hdr = u->u.hdr;
850 			ind->drop.cause = u->u.status.cause;
851 			ind->drop.epref = u->u.status.epref;
852 			uni_enq_call(p->call, SIGC_DROP_PARTY_ACK_indication,
853 			    0, api, NULL);
854 		}
855 		stop_all_party_timers(p);
856 
857 		uni_destroy_party(p, 0);
858 	} else {
859 		if (epstate_compat(p, u->u.status.epstate.state)) {
860 			if(u->u.status.cause.cause == UNI_CAUSE_MANDAT ||
861 			   u->u.status.cause.cause == UNI_CAUSE_MTYPE_NIMPL ||
862 			   u->u.status.cause.cause == UNI_CAUSE_IE_NIMPL ||
863 			   u->u.status.cause.cause == UNI_CAUSE_IE_INV) {
864 				MK_IE_CAUSE(p->call->uni->cause,
865 				    UNI_CAUSE_LOC_USER,
866 				    UNI_CAUSE_UNSPEC);
867 				drop_partyE(p);
868 			}
869 		} else {
870 			MK_IE_CAUSE(p->call->uni->cause,
871 			    UNI_CAUSE_LOC_USER,
872 			    UNI_CAUSE_MSG_INCOMP);
873 			drop_partyE(p);
874 		}
875 	}
876 
877 	uni_msg_destroy(m);
878 	UNI_FREE(u);
879 }
880 
881 /*
882  * STATUS in PU5/PN5
883  *
884  * Q.2971:Party-Control-U 10
885  * Q.2971:Party-Control-N 10
886  */
887 static void
pun5_status(struct party * p,struct uni_msg * m,struct uni_all * u)888 pun5_status(struct party *p, struct uni_msg *m, struct uni_all *u)
889 {
890 	struct uniapi_drop_party_ack_indication *ind;
891 	struct uni_msg *api;
892 
893 	if (u->u.status.epstate.state == UNI_EPSTATE_NULL) {
894 		ind = ALLOC_API(struct uniapi_drop_party_ack_indication, api);
895 		if (ind != NULL) {
896 			ind->drop.hdr = u->u.hdr;
897 			ind->drop.cause = u->u.status.cause;
898 			ind->drop.epref = u->u.status.epref;
899 			uni_enq_call(p->call, SIGC_DROP_PARTY_ACK_indication,
900 			    0, api, NULL);
901 		}
902 		TIMER_STOP_PARTY(p, t398);
903 
904 		uni_destroy_party(p, 0);
905 	}
906 
907 	uni_msg_destroy(m);
908 	UNI_FREE(u);
909 }
910 
911 /************************************************************/
912 
913 void
uni_sig_party(struct party * p,enum party_sig sig,uint32_t cookie,struct uni_msg * msg,struct uni_all * u)914 uni_sig_party(struct party *p, enum party_sig sig, uint32_t cookie,
915     struct uni_msg *msg, struct uni_all *u)
916 {
917 	if (sig >= SIGP_END) {
918 		VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
919 		    "Signal %d outside of range to Party-Control", sig);
920 		if (msg)
921 			uni_msg_destroy(msg);
922 		if (u)
923 			UNI_FREE(u);
924 		return;
925 	}
926 	VERBOSE(p->call->uni, UNI_FAC_CALL, 1,
927 	    "Signal %s in state %u of party %u/%s (call %u/%s in state %s)"
928 	    "; cookie %u", party_sigs[sig], p->state, p->epref,
929 	    (p->flags & PARTY_MINE) ? "mine" : "his", p->call->cref,
930 	    p->call->mine ? "mine" : "his", callstates[p->call->cstate].name,
931 	    cookie);
932 
933 	switch (sig) {
934 
935 	  case SIGP_PARTY_DELETE:
936 		PARTY_FREE(p);
937 		break;
938 
939 	  /*
940 	   * Messages
941 	   */
942 	  case SIGP_SETUP:
943 		if (p->state == UNI_EPSTATE_NULL) {
944 			/* Q.2971:Call-Control-U 3/13 */
945 			/* Q.2971:Call-Control-N 3/13 */
946 			set_party_state(p, UNI_EPSTATE_ADD_RCVD);
947 			break;
948 		}
949 		VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
950 		    "SETUP in ps=%u", p->state);
951 		break;
952 
953 	  case SIGP_ALERTING:
954 		if (p->state == UNI_EPSTATE_ADD_INIT) {
955 			/* Q.2971:Call-Control-U 14 */
956 			/* Q.2971:Call-Control-N 5 */
957 			TIMER_START_PARTY(p, t397, p->call->uni->timer397);
958 			set_party_state(p, UNI_EPSTATE_ALERT_RCVD);
959 			break;
960 		}
961 		VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
962 		    "ALERTING in ps=%u", p->state);
963 		break;
964 
965 	  case SIGP_CONNECT:
966 		if (p->state == UNI_EPSTATE_ADD_INIT) {
967 			/* Q.2971:Call-Control-U 4/13 */
968 			TIMER_STOP_PARTY(p, t399);
969 			set_party_state(p, UNI_EPSTATE_ACTIVE);
970 			break;
971 		}
972 		if (p->state == UNI_EPSTATE_ALERT_RCVD) {
973 			/* Q.2971:Call-Control-U 7/13 */
974 			TIMER_STOP_PARTY(p, t397);
975 			set_party_state(p, UNI_EPSTATE_ACTIVE);
976 			break;
977 		}
978 		VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
979 		    "CONNECT in ps=%u", p->state);
980 		break;
981 
982 	  case SIGP_CONNECT_ACK:
983 		if (p->state == UNI_EPSTATE_ADD_RCVD ||
984 		    p->state == UNI_EPSTATE_ALERT_DLVD) {
985 			/* Q.2971:Call-Control-U 6/13 */
986 			/* Q.2971:Call-Control-U 7/13 */
987 			p->flags &= ~PARTY_CONNECT;
988 			set_party_state(p, UNI_EPSTATE_ACTIVE);
989 			break;
990 		}
991 		VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
992 		    "CONNECT in ps=%u", p->state);
993 		break;
994 
995 	  case SIGP_RELEASE:
996 		if (p->state == UNI_EPSTATE_DROP_INIT) {
997 			/* Q.2971:Party-Control-U 10/14 */
998 			/* Q.2971:Party-Control-N 10/14 */
999 			TIMER_STOP_PARTY(p, t398);
1000 			uni_destroy_party(p, 0);
1001 			break;
1002 		}
1003 		/* Q.2971:Party-Control-U 11/14 */
1004 		/* Q.2971:Party-Control-N 11/14 */
1005 		TIMER_STOP_PARTY(p, t397);
1006 		TIMER_STOP_PARTY(p, t399);
1007 		uni_destroy_party(p, 0);
1008 		break;
1009 
1010 	  case SIGP_RELEASE_COMPL:
1011 		/* Q.2971:Party-Control-U 11/14 */
1012 		/* Q.2971:Party-Control-N 11/14 */
1013 		stop_all_party_timers(p);
1014 		uni_destroy_party(p, 0);
1015 		break;
1016 
1017 	  case SIGP_RELEASE_confirm:
1018 		/* not in the SDLs */
1019 		stop_all_party_timers(p);
1020 		uni_destroy_party(p, 0);
1021 		break;
1022 
1023 	  case SIGP_RELEASE_request:
1024 		if (p->state == UNI_EPSTATE_DROP_INIT) {
1025 			/* Q.2971:Party-Control-U 10 */
1026 			/* Q.2971:Party-Control-N 10 */
1027 			uni_destroy_party(p, 0);
1028 			break;
1029 		}
1030 		/* Q.2971:Party-Control-U 11 */
1031 		/* Q.2971:Party-Control-N 11 */
1032 		TIMER_STOP_PARTY(p, t397);
1033 		TIMER_STOP_PARTY(p, t399);
1034 		uni_destroy_party(p, 0);
1035 		break;
1036 
1037 	  case SIGP_RELEASE_response:
1038 		/* Q.2971:Party-Control-U 11 */
1039 		/* Q.2971:Party-Control-N 11 */
1040 		stop_all_party_timers(p);
1041 		uni_destroy_party(p, 0);
1042 		break;
1043 
1044 	  case SIGP_ADD_PARTY:
1045 		if (p->state == UNI_EPSTATE_NULL) {
1046 			/* Q.2971:Party-Control-U 3 PU0 */
1047 			/* Q.2971:Party-Control-N 3 PN0 */
1048 			pun0_add_party(p, msg, u);
1049 			break;
1050 		}
1051 		if (p->state == UNI_EPSTATE_ADD_RCVD) {
1052 			/* Q.2971:Party-Control-U 6 PU2 */
1053 			/* Q.2971:Party-Control-N 6 PN2 */
1054 			uni_msg_destroy(msg);
1055 			UNI_FREE(u);
1056 			break;
1057 		}
1058 		uni_bad_message(p->call, u, UNI_CAUSE_MSG_INCOMP,
1059 		    &u->u.add_party.epref, p->state);
1060 		uni_msg_destroy(msg);
1061 		UNI_FREE(u);
1062 		break;
1063 
1064 	  case SIGP_PARTY_ALERTING:
1065 		if (p->state == UNI_EPSTATE_ADD_INIT) {
1066 			/* Q.2971:Party-Control-U 14 */
1067 			/* Q.2971:Party-Control-N 5 */
1068 			pun1_party_alerting(p, msg, u);
1069 			break;
1070 		}
1071 		uni_bad_message(p->call, u, UNI_CAUSE_MSG_INCOMP,
1072 		    &u->u.party_alerting.epref, p->state);
1073 		uni_msg_destroy(msg);
1074 		UNI_FREE(u);
1075 		break;
1076 
1077 	  case SIGP_ADD_PARTY_ACK:
1078 		if (p->state == UNI_EPSTATE_ADD_INIT ||
1079 		    p->state == UNI_EPSTATE_ALERT_RCVD) {
1080 			/* Q.2971:Party-Control-U 4 (PU1) */
1081 			/* Q.2971:Party-Control-U 7 (PU4) */
1082 			/* Q.2971:Party-Control-N 4 (PN1) */
1083 			/* Q.2971:Party-Control-N 7 (PN4) */
1084 			pun1pun4_add_party_ack(p, msg, u);
1085 			break;
1086 		}
1087 		uni_bad_message(p->call, u, UNI_CAUSE_MSG_INCOMP,
1088 		    &u->u.add_party_ack.epref, p->state);
1089 		uni_msg_destroy(msg);
1090 		UNI_FREE(u);
1091 		break;
1092 
1093 	  case SIGP_ADD_PARTY_REJ:
1094 		if (p->state == UNI_EPSTATE_ADD_INIT) {
1095 			/* Q.2971:Party-Control-U 4 (PU1) */
1096 			/* Q.2971:Party-Control-N 4 (PN1) */
1097 			pun1_add_party_rej(p, msg, u);
1098 			break;
1099 		}
1100 		if (p->state == UNI_EPSTATE_DROP_INIT) {
1101 			/* Q.2971:Party-Control-U 10 (PU5) */
1102 			/* Q.2971:Party-Control-N 10 (PN5) */
1103 			pun5_add_party_rej(p, msg, u);
1104 			break;
1105 		}
1106 		uni_bad_message(p->call, u, UNI_CAUSE_MSG_INCOMP,
1107 		    &u->u.add_party_rej.epref, p->state);
1108 		uni_msg_destroy(msg);
1109 		UNI_FREE(u);
1110 		break;
1111 
1112 	  case SIGP_DROP_PARTY_ACK:
1113 		/* Q.2971:Party-Control-U 8 */
1114 		/* Q.2971:Party-Control-N 8 */
1115 		punx_drop_party_ack(p, msg, u);
1116 		break;
1117 
1118 	  case SIGP_DROP_PARTY:
1119 		if (p->state == UNI_EPSTATE_DROP_INIT)
1120 			/* Q.2971:Party-Control-U 10 */
1121 			/* Q.2971:Party-Control-N 10 */
1122 			pun5_drop_party(p, msg, u);
1123 		else
1124 			/* Q.2971:Party-Control-U 9 */
1125 			/* Q.2971:Party-Control-N 9 */
1126 			punx_drop_party(p, msg, u);
1127 		break;
1128 
1129 	  case SIGP_STATUS:
1130 		if (p->state == UNI_EPSTATE_DROP_INIT)
1131 			/* Q.2971:Party-Control-U 10 */
1132 			/* Q.2971:Party-Control-N 10 */
1133 			pun5_status(p, msg, u);
1134 		else
1135 			/* Q.2971:Party-Control-U 12 */
1136 			/* Q.2971:Party-Control-N 12 */
1137 			punx_status(p, msg, u);
1138 		break;
1139 
1140 	  /*
1141 	   * User
1142 	   */
1143 	  case SIGP_SETUP_request:
1144 		if (p->state == UNI_EPSTATE_NULL) {
1145 			/* Q.2971:Party-Control-U 3 */
1146 			/* Q.2971:Party-Control-N 3 */
1147 			set_party_state(p, UNI_EPSTATE_ADD_INIT);
1148 			break;
1149 		}
1150 		VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
1151 		    "SETUP.request in ps=%u", p->state);
1152 		uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie);
1153 		break;
1154 
1155 	  case SIGP_SETUP_response:
1156 		if (p->state == UNI_EPSTATE_ADD_RCVD ||
1157 		    p->state == UNI_EPSTATE_ALERT_DLVD) {
1158 			/* Q.2971:Party-Control-N 6 (PN2) */
1159 			/* Q.2971:Party-Control-N 7 (PN3) */
1160 			set_party_state(p, UNI_EPSTATE_ACTIVE);
1161 			break;
1162 		}
1163 		VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
1164 		    "SETUP.response in ps=%u", p->state);
1165 		uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie);
1166 		break;
1167 
1168 	  case SIGP_SETUP_COMPL_request:
1169 		if (p->state == UNI_EPSTATE_ADD_INIT) {
1170 			/* Q.2971:Party-Control-N 4 */
1171 			TIMER_STOP_PARTY(p, t399);
1172 			set_party_state(p, UNI_EPSTATE_ACTIVE);
1173 			break;
1174 		}
1175 		if (p->state == UNI_EPSTATE_ALERT_RCVD) {
1176 			/* Q.2971:Party-Control-N 7 */
1177 			TIMER_STOP_PARTY(p, t397);
1178 			set_party_state(p, UNI_EPSTATE_ACTIVE);
1179 			break;
1180 		}
1181 		VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
1182 		    "SETUP_COMPL.request in ps=%u", p->state);
1183 		uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie);
1184 		break;
1185 
1186 	  case SIGP_ADD_PARTY_request:
1187 		if (p->state == UNI_EPSTATE_NULL) {
1188 			/* Q.2971:Party-control-U 3 (PU0) */
1189 			/* Q.2971:Party-control-N 3 (PN0) */
1190 			pun0_add_party_request(p, msg, cookie);
1191 			break;
1192 		}
1193 		VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
1194 		    "Add-party.request in ps=%u", p->state);
1195 		uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie);
1196 		uni_msg_destroy(msg);
1197 		break;
1198 
1199 	  case SIGP_ALERTING_request:
1200 		/* Q.2971:Party-Control-U 6 (PU2) */
1201 		/* Q.2971:Party-Control-N 6 (PN2) */
1202 		set_party_state(p, UNI_EPSTATE_ALERT_DLVD);
1203 		break;
1204 
1205 	  case SIGP_PARTY_ALERTING_request:
1206 		if (p->state == UNI_EPSTATE_ADD_RCVD) {
1207 			/* Q.2971:Party-Control-U 6 (PU2) */
1208 			/* Q.2971:Party-Control-N 6 (PN2) */
1209 			pun2_party_alerting_request(p, msg, cookie);
1210 			break;
1211 		}
1212 		VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
1213 		    "Party-alerting.request in ps=%u", p->state);
1214 		uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie);
1215 		uni_msg_destroy(msg);
1216 		break;
1217 
1218 	  case SIGP_ADD_PARTY_ACK_request:
1219 		if (p->state == UNI_EPSTATE_ADD_RCVD ||
1220 		    p->state == UNI_EPSTATE_ALERT_DLVD) {
1221 			/* Q.2971:Party-Control-U 6 PU2 */
1222 			/* Q.2971:Party-Control-U 7 PU3 */
1223 			/* Q.2971:Party-Control-N 6 PN2 */
1224 			/* Q.2971:Party-Control-N 7 PN3 */
1225 			punx_add_party_ack_request(p, msg, cookie);
1226 			break;
1227 		}
1228 		VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
1229 		    "Add-party-ack.request in ps=%u", p->state);
1230 		uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie);
1231 		uni_msg_destroy(msg);
1232 		break;
1233 
1234 	  case SIGP_ADD_PARTY_REJ_request:
1235 		if (p->state == UNI_EPSTATE_ADD_RCVD) {
1236 			/* Q.2971:Party-Control-U 6 PU2 */
1237 			/* Q.2971:Party-Control-N 6 PN2 */
1238 			pun2_add_party_rej_request(p, msg, cookie);
1239 			break;
1240 		}
1241 		VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
1242 		    "Add-party-rej.request in ps=%u", p->state);
1243 		uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie);
1244 		uni_msg_destroy(msg);
1245 		break;
1246 
1247 	  case SIGP_DROP_PARTY_request:
1248 		if (p->state == UNI_EPSTATE_ADD_INIT ||
1249 		    p->state == UNI_EPSTATE_ALERT_DLVD ||
1250 		    p->state == UNI_EPSTATE_ALERT_RCVD ||
1251 		    p->state == UNI_EPSTATE_ACTIVE) {
1252 			/* Q.2971:Party-Control-U 8 */
1253 			/* Q.2971:Party-Control-N 8 */
1254 			punx_drop_party_request(p, msg, cookie);
1255 			break;
1256 		}
1257 		VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
1258 		    "Drop-party.request in ps=%u", p->state);
1259 		uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie);
1260 		uni_msg_destroy(msg);
1261 		break;
1262 
1263 	  case SIGP_DROP_PARTY_ACK_request:
1264 		if (p->state == UNI_EPSTATE_DROP_RCVD) {
1265 			/* Q.2971:Party-Control-U 9 */
1266 			/* Q.2971:Party-Control-N 9 */
1267 			pun6_drop_party_ack_request(p, msg, cookie);
1268 			break;
1269 		}
1270 		VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
1271 		    "Drop-party-ack.request in ps=%u", p->state);
1272 		uniapi_party_error(p, UNIAPI_ERROR_BAD_EPSTATE, cookie);
1273 		uni_msg_destroy(msg);
1274 		break;
1275 
1276 	  case SIGP_STATUS_ENQUIRY_request:
1277 		/* Q.2971:Party-Control-U 12 */
1278 		/* Q.2971:Party-Control-N 12 */
1279 		punx_status_enquiry_request(p, cookie);
1280 		break;
1281 
1282 	  /*
1283 	   * Timers
1284 	   */
1285 	  case SIGP_T397:
1286 		if (p->state == UNI_EPSTATE_ALERT_RCVD) {
1287 			/* Q.2971:Party-Control-U 7 (PU4) */
1288 			/* Q.2971:Party-Control-N 7 (PN4) */
1289 			pun4_t397(p);
1290 			break;
1291 		}
1292 		VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
1293 		    "T397 in ps=%u", p->state);
1294 		break;
1295 
1296 	  case SIGP_T398:
1297 		if (p->state == UNI_EPSTATE_DROP_INIT) {
1298 			/* Q.2971:Party-Control-U 10 (PU5) */
1299 			/* Q.2971:Party-Control-N 10 (PN5) */
1300 			pun5_t398(p);
1301 			break;
1302 		}
1303 		VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
1304 		    "T398 in ps=%u", p->state);
1305 		break;
1306 
1307 	  case SIGP_T399:
1308 		if (p->state == UNI_EPSTATE_ADD_INIT) {
1309 			/* Q.2971:Party-Control-U 4 (PU1) */
1310 			/* Q.2971:Party-Control-N 4 (PN1) */
1311 			pun1_t399(p);
1312 			break;
1313 		}
1314 		VERBOSE(p->call->uni, UNI_FAC_ERR, 1,
1315 		    "T399 in ps=%u", p->state);
1316 		break;
1317 
1318 	  case SIGP_END:
1319 		break;
1320 	}
1321 }
1322 
1323 static void
t397_func(struct party * p)1324 t397_func(struct party *p)
1325 {
1326 	uni_enq_party(p, SIGP_T397, 0, NULL, NULL);
1327 }
1328 static void
t398_func(struct party * p)1329 t398_func(struct party *p)
1330 {
1331 	uni_enq_party(p, SIGP_T398, 0, NULL, NULL);
1332 }
1333 static void
t399_func(struct party * p)1334 t399_func(struct party *p)
1335 {
1336 	uni_enq_party(p, SIGP_T399, 0, NULL, NULL);
1337 }
1338 
1339 static int
epstate_compat(struct party * p,enum uni_epstate state)1340 epstate_compat(struct party *p, enum uni_epstate state)
1341 {
1342 	if (p->state == UNI_EPSTATE_ADD_INIT ||
1343 	    p->state == UNI_EPSTATE_ALERT_RCVD)
1344 		if (state == UNI_EPSTATE_ADD_INIT ||
1345 		    state == UNI_EPSTATE_ALERT_RCVD)
1346 			return (0);
1347 	if (p->state == UNI_EPSTATE_ADD_RCVD ||
1348 	    p->state == UNI_EPSTATE_ALERT_DLVD)
1349 		if (state == UNI_EPSTATE_ADD_RCVD ||
1350 		    state == UNI_EPSTATE_ALERT_DLVD)
1351 			return (0);
1352 	return (1);
1353 }
1354