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 <harti@freebsd.org>
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
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 *
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 *
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 *
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 *
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
1324 t397_func(struct party *p)
1325 {
1326 uni_enq_party(p, SIGP_T397, 0, NULL, NULL);
1327 }
1328 static void
1329 t398_func(struct party *p)
1330 {
1331 uni_enq_party(p, SIGP_T398, 0, NULL, NULL);
1332 }
1333 static void
1334 t399_func(struct party *p)
1335 {
1336 uni_enq_party(p, SIGP_T399, 0, NULL, NULL);
1337 }
1338
1339 static int
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 }
Cache object: 40e884c7192b60414db6dfa152511965
|