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_coord.c,v 1.12 2004/08/05 07:11:01 brandt Exp $
30 *
31 * Coordinator
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
43 #define STR(S) [S] = #S
44 static const char *const cunames[] = {
45 STR(CU_STAT0),
46 STR(CU_STAT1),
47 STR(CU_STAT2),
48 STR(CU_STAT3),
49 };
50
51 #define DEF_PRIV_SIG(NAME, FROM) [SIG##NAME] = "SIG"#NAME,
52 static const char *const coord_sigs[] = {
53 DEF_COORD_SIGS
54 };
55 #undef DEF_PRIV_SIG
56
57 static void sig_all_calls(struct uni *, u_int sig);
58 static void set_custat(struct uni *, enum cu_stat);
59
60 static void input_dummy(struct uni *uni, struct uni_msg *m, struct uni_all *u);
61 static void input_global(struct uni *uni, struct uni_msg *m, struct uni_all *u);
62 static void input_unknown(struct uni *uni, struct uni_msg *m, struct uni_all *u);
63 static void input_cobi(struct call *c, struct uni_msg *m, struct uni_all *u);
64 static void input_call(struct call *c, struct uni_msg *m, struct uni_all *u);
65
66 TIMER_FUNC_UNI(t309, t309_func)
67
68 /*
69 * All those 'bogus signal' printouts are not specified in the SDLs.
70 */
71
72
73 /*
74 * SAAL-ESTABLISH.indication
75 *
76 * This means either a resynchronisation or error-recovery or
77 * an incoming SSCOP connection.
78 */
79 static void
80 coord_saal_establish_indication(struct uni *uni)
81 {
82 switch (uni->custat) {
83
84 case CU_STAT0: /* Q.2931:Coord-U 4/10 */
85 case CU_STAT3: /* Q.2931:Coord-U 5/10 */
86 sig_all_calls(uni, SIGC_LINK_ESTABLISH_indication);
87 set_custat(uni, CU_STAT3);
88 break;
89
90 case CU_STAT1:
91 case CU_STAT2:
92 VERBOSE0(uni, UNI_FAC_COORD,
93 "signal saal_establish.indication in CU%u", uni->custat);
94 break;
95
96 default:
97 ASSERT(0, ("CU_STAT*"));
98 }
99 }
100
101 /*
102 * SAAL-ESTABLISH.confirm
103 */
104 static void
105 coord_saal_establish_confirm(struct uni *uni)
106 {
107 switch (uni->custat) {
108
109 case CU_STAT0:
110 case CU_STAT2:
111 VERBOSE0(uni, UNI_FAC_COORD,
112 "signal saal_establish.confirm in CU%u", uni->custat);
113 break;
114
115 case CU_STAT1:
116 /*
117 * Q.2931:Co-ord-U 4/10
118 */
119 TIMER_STOP_UNI(uni, t309);
120 sig_all_calls(uni, SIGC_LINK_ESTABLISH_confirm);
121 uni->funcs->uni_output(uni, uni->arg,
122 UNIAPI_LINK_ESTABLISH_confirm, 0, NULL);
123 set_custat(uni, CU_STAT3);
124 break;
125
126 case CU_STAT3:
127 /*
128 * Q.2931:Coord-U 5/10
129 */
130 sig_all_calls(uni, SIGC_LINK_ESTABLISH_confirm);
131 uni->funcs->uni_output(uni, uni->arg,
132 UNIAPI_LINK_ESTABLISH_confirm, 0, NULL);
133 break;
134
135 default:
136 ASSERT(0, ("CU_STAT*"));
137 }
138 }
139
140 /*
141 * SAAL-RELEASE.confirm
142 */
143 static void
144 coord_saal_release_confirm(struct uni *uni)
145 {
146 switch (uni->custat) {
147
148 case CU_STAT0:
149 case CU_STAT1:
150 case CU_STAT3:
151 VERBOSE0(uni, UNI_FAC_COORD,
152 "signal saal_release.confirm in CU%u", uni->custat);
153 break;
154
155 case CU_STAT2:
156 /*
157 * Q.2931:Coord-U 5/10
158 */
159 uni->funcs->uni_output(uni, uni->arg,
160 UNIAPI_LINK_RELEASE_confirm, 0, NULL);
161 set_custat(uni, CU_STAT0);
162 break;
163
164 default:
165 ASSERT(0, ("CU_STAT*"));
166 }
167 }
168
169 /*
170 * SAAL failure.
171 */
172 static void
173 coord_saal_release_indication(struct uni *uni)
174 {
175 switch (uni->custat) {
176
177 case CU_STAT0:
178 case CU_STAT2:
179 VERBOSE0(uni, UNI_FAC_COORD,
180 "signal saal_release.indication in CU%u", uni->custat);
181 break;
182
183 case CU_STAT1:
184 case CU_STAT3:
185 /*
186 * Q.2931:Coord-U 4/10
187 * Q.2931:Coord-U 5/10
188 */
189 sig_all_calls(uni, SIGC_LINK_RELEASE_indication);
190 set_custat(uni, CU_STAT0);
191 break;
192
193 default:
194 ASSERT(0, ("CU_STAT*"));
195 }
196 }
197
198 /*
199 * Link-establish.request from USER. This can also come from
200 * a call instance. In this case 'cookie' is zero.
201 */
202 static void
203 coord_link_establish_request(struct uni *uni, uint32_t cookie)
204 {
205 switch (uni->custat) {
206
207 case CU_STAT0:
208 /*
209 * Q.2931:Coord-U 4/10
210 */
211 uni->funcs->saal_output(uni, uni->arg,
212 SAAL_ESTABLISH_request, NULL);
213 if (!TIMER_ISACT(uni, t309))
214 TIMER_START_UNI(uni, t309, uni->timer309);
215 set_custat(uni, CU_STAT1);
216 if (cookie)
217 uniapi_uni_error(uni, UNIAPI_OK, cookie, 0);
218 break;
219
220 case CU_STAT1:
221 /*
222 * Q.2931:Coord-U 4/10
223 * This is probably missing from the delay field.
224 */
225 uni_delenq_coord(uni, SIGO_LINK_ESTABLISH_request,
226 cookie, NULL);
227 break;
228
229 case CU_STAT2:
230 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALLSTATE, cookie, 0);
231 if (cookie == 0)
232 VERBOSE0(uni, UNI_FAC_COORD,
233 "signal link-establish.request in CU%u",
234 uni->custat);
235 break;
236
237 case CU_STAT3:
238 /*
239 * Q.2931:Coord-U 5/10
240 */
241 uni->funcs->uni_output(uni, uni->arg,
242 UNIAPI_LINK_ESTABLISH_confirm, 0, NULL);
243 uniapi_uni_error(uni, UNIAPI_OK, cookie, 0);
244 break;
245
246 default:
247 ASSERT(0, ("CU_STAT*"));
248 }
249 }
250
251 /*
252 * Link-release.request from user
253 */
254 static void
255 coord_link_release_request(struct uni *uni, u_int cookie)
256 {
257 switch (uni->custat) {
258
259 case CU_STAT0:
260 case CU_STAT1:
261 case CU_STAT2:
262 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALLSTATE, cookie, 0);
263 break;
264
265 case CU_STAT3:
266 /*
267 * Q.2931:Coord-U 5/10
268 */
269 uni->funcs->saal_output(uni, uni->arg,
270 SAAL_RELEASE_request, NULL);
271 set_custat(uni, CU_STAT2);
272 uniapi_uni_error(uni, UNIAPI_OK, cookie, 0);
273 break;
274
275 default:
276 ASSERT(0, ("CU_STAT*"));
277 }
278 }
279
280 /*
281 * T309 timeout signal
282 */
283 static void
284 coord_t309(struct uni *uni)
285 {
286 switch (uni->custat) {
287
288 case CU_STAT0:
289 case CU_STAT1:
290 /*
291 * Q.2931:Coord-U 4/10
292 */
293 sig_all_calls(uni, SIGC_LINK_ESTABLISH_ERROR_indication);
294 set_custat(uni, CU_STAT0);
295 /* this is not in the SDLs, but how will the call control
296 * know, that starting the LINK has failed otherwise? */
297 uni->funcs->uni_output(uni, uni->arg,
298 UNIAPI_LINK_RELEASE_confirm, 0, NULL);
299 break;
300
301 case CU_STAT2:
302 case CU_STAT3:
303 VERBOSE0(uni, UNI_FAC_COORD,
304 "signal T309 in CU%u", uni->custat);
305 break;
306
307 default:
308 ASSERT(0, ("CU_STAT*"));
309 }
310 }
311
312 /*
313 * Message from SAAL
314 */
315 static void
316 coord_saal_data_indication(struct uni *uni, struct uni_msg *m)
317 {
318 struct uni_all *u;
319 struct call *c;
320
321 memset(&uni->cause, 0, sizeof(uni->cause));
322 if ((u = UNI_ALLOC()) == NULL) {
323 uni_msg_destroy(m);
324 return;
325 }
326 if (uni_decode_head(m, u, &uni->cx)) {
327 VERBOSE(uni, UNI_FAC_COORD, 2, "bogus message - ignored");
328 uni_msg_destroy(m);
329 UNI_FREE(u);
330 return;
331 }
332 if (u->u.hdr.cref.cref == CREF_DUMMY) {
333 if (uni->cx.q2932) {
334 input_dummy(uni, m, u);
335 } else {
336 VERBOSE(uni, UNI_FAC_COORD, 2, "dummy cref - ignored");
337 UNI_FREE(u);
338 uni_msg_destroy(m);
339 }
340 return;
341 }
342
343 if (u->u.hdr.cref.cref == CREF_GLOBAL)
344 input_global(uni, m, u);
345 else if ((c = uni_find_call(uni, &u->u.hdr.cref)) == NULL)
346 input_unknown(uni, m, u);
347 else if (c->type == CALL_COBI)
348 input_cobi(c, m, u);
349 else
350 input_call(c, m, u);
351 }
352
353 /*
354 * Message with global call reference
355 *
356 * Q.2931:Coord-U (X) 7/10
357 */
358 static void
359 input_global(struct uni *uni, struct uni_msg *m, struct uni_all *u)
360 {
361 VERBOSE(uni, UNI_FAC_COORD, 2, "GLOB MTYPE = %x", u->mtype);
362
363 switch (u->mtype) {
364
365 default:
366 /*
367 * Q.2931:Coord-U 7/10
368 * Q.2931: 5.6.3.2e
369 * Amd4: 29e
370 */
371 uni_respond_status(uni, &u->u.hdr.cref,
372 u->u.hdr.cref.flag ? uni->glob_start : uni->glob_respond,
373 UNI_CAUSE_CREF_INV);
374 break;
375
376 case UNI_RESTART:
377 if (u->u.hdr.cref.flag) {
378 /*
379 * Q.2931:Coord-U 7/10 (5.6.3.2h)
380 */
381 uni_respond_status(uni, &u->u.hdr.cref,
382 uni->glob_start, UNI_CAUSE_CREF_INV);
383 break;
384 }
385 uni_enq_resp(uni, SIGR_RESTART, 0, m, u);
386 return;
387
388 case UNI_RESTART_ACK:
389 if (!u->u.hdr.cref.flag) {
390 /*
391 * Q.2931:Coord-U 7/10 (5.6.3.2h)
392 * Note, that the SDL diagram contains an error.
393 * The error with the 'YES' label should go to the
394 * box below 'OTHER'.
395 */
396 uni_respond_status(uni, &u->u.hdr.cref,
397 uni->glob_respond, UNI_CAUSE_CREF_INV);
398 break;
399 }
400 uni_enq_start(uni, SIGS_RESTART_ACK, 0, m, u);
401 return;
402
403 case UNI_STATUS:
404 if (u->u.hdr.cref.flag)
405 uni_enq_start(uni, SIGS_STATUS, 0, m, u);
406 else
407 uni_enq_resp(uni, SIGR_STATUS, 0, m, u);
408 return;
409 }
410 uni_msg_destroy(m);
411 UNI_FREE(u);
412 }
413
414 /*
415 * Q.2931:Coord-U 8/10
416 *
417 * Message for an unknown call reference
418 */
419 static void
420 input_unknown(struct uni *uni, struct uni_msg *m, struct uni_all *u)
421 {
422 struct uni_all *resp;
423 struct call *c;
424 u_int cause = UNI_CAUSE_CREF_INV;
425
426 VERBOSE(uni, UNI_FAC_COORD, 2, "UNKNOWN MTYPE = %x", u->mtype);
427
428 switch (u->mtype) {
429
430 default:
431 /*
432 * This message type is entirly unknown
433 *
434 * 5.6.4 and 5.7.1 are only when the call is not in the
435 * NULL state. This means, 5.6.3.2a takes over.
436 */
437 break;
438
439 case UNI_SETUP:
440 if (u->u.hdr.cref.flag)
441 /*
442 * 5.6.3.2c
443 */
444 goto drop;
445 if ((c = uni_create_call(uni, u->u.hdr.cref.cref, 0, 0)) != NULL) {
446 uni_enq_call(c, SIGC_SETUP, 0, m, u);
447 return;
448 }
449 goto drop;
450
451 case UNI_RELEASE_COMPL:
452 /*
453 * 5.6.3.2c
454 */
455 goto drop;
456
457 case UNI_STATUS:
458 /*
459 * 5.6.12
460 *
461 * The SDLs don't use the verify procedure and don't
462 * handle the case of an invalid callstate - we
463 * ignore the message, if the callstate is not good.
464 */
465 (void)uni_decode_body(m, u, &uni->cx);
466 if (!IE_ISGOOD(u->u.status.callstate))
467 goto drop;
468 if (u->u.status.callstate.state == UNI_CALLSTATE_U0)
469 goto drop;
470 cause = UNI_CAUSE_MSG_INCOMP;
471 break;
472
473 case UNI_STATUS_ENQ:
474 if ((resp = UNI_ALLOC()) == NULL)
475 goto drop;
476
477 (void)uni_decode_body(m, u, &uni->cx);
478 MK_MSG_RESP(resp, UNI_STATUS, &u->u.hdr.cref);
479 MK_IE_CALLSTATE(resp->u.status.callstate, UNI_CALLSTATE_U0);
480 MK_IE_CAUSE(resp->u.status.cause, UNI_CAUSE_LOC_USER,
481 UNI_CAUSE_STATUS);
482
483 if (IE_ISGOOD(u->u.status_enq.epref)) {
484 /* reflect epref as required by L3MU_PO */
485 resp->u.status.epref = u->u.status_enq.epref;
486 MK_IE_EPREF(resp->u.status.epref,
487 u->u.status_enq.epref.epref,
488 !u->u.status_enq.epref.flag);
489 MK_IE_EPSTATE(resp->u.status.epstate, UNI_EPSTATE_NULL);
490 }
491
492 (void)uni_send_output(resp, uni);
493
494 UNI_FREE(resp);
495 goto drop;
496
497 case UNI_COBISETUP:
498 if (u->u.hdr.cref.flag)
499 /*
500 * 5.6.3.2c (probably)
501 */
502 goto drop;
503 if ((c = uni_create_call(uni, u->u.hdr.cref.cref, 0, 0)) != NULL) {
504 uni_enq_call(c, SIGC_COBISETUP, 0, m, u);
505 return;
506 }
507 goto drop;
508 }
509
510 /*
511 * 5.6.3.2a)
512 *
513 * Respond with a RELEASE COMPLETE
514 */
515 if ((resp = UNI_ALLOC()) == NULL)
516 goto drop;
517
518 MK_MSG_RESP(resp, UNI_RELEASE_COMPL, &u->u.hdr.cref);
519 MK_IE_CAUSE(resp->u.release_compl.cause[0], UNI_CAUSE_LOC_USER, cause);
520 if (uni_diag(cause, UNI_CODING_ITU) == UNI_DIAG_MTYPE)
521 ADD_CAUSE_MTYPE(resp->u.release_compl.cause[0], u->mtype);
522
523 (void)uni_send_output(resp, uni);
524
525 UNI_FREE(resp);
526
527 drop:
528 UNI_FREE(u);
529 uni_msg_destroy(m);
530 }
531
532 static void
533 input_cobi(struct call *c __unused, struct uni_msg *m, struct uni_all *u)
534 {
535 /* XXX */
536 UNI_FREE(u);
537 uni_msg_destroy(m);
538 }
539
540 static void
541 input_dummy(struct uni *uni __unused, struct uni_msg *m, struct uni_all *u)
542 {
543 /* XXX */
544 UNI_FREE(u);
545 uni_msg_destroy(m);
546 }
547
548 static void
549 input_call(struct call *c, struct uni_msg *m, struct uni_all *u)
550 {
551 VERBOSE(c->uni, UNI_FAC_COORD, 2, "CALL MTYPE = %x %d/%s",
552 u->mtype, c->cref, c->mine ? "mine":"his");
553
554 switch (u->mtype) {
555
556 case UNI_SETUP:
557 /*
558 * Ignored
559 */
560 break;
561
562 case UNI_CALL_PROC:
563 uni_enq_call(c, SIGC_CALL_PROC, 0, m, u);
564 return;
565
566 case UNI_ALERTING:
567 uni_enq_call(c, SIGC_ALERTING, 0, m, u);
568 return;
569
570 case UNI_RELEASE:
571 uni_enq_call(c, SIGC_RELEASE, 0, m, u);
572 return;
573
574 case UNI_RELEASE_COMPL:
575 uni_enq_call(c, SIGC_RELEASE_COMPL, 0, m, u);
576 return;
577
578 case UNI_CONNECT:
579 uni_enq_call(c, SIGC_CONNECT, 0, m, u);
580 return;
581
582 case UNI_CONNECT_ACK:
583 uni_enq_call(c, SIGC_CONNECT_ACK, 0, m, u);
584 return;
585
586 case UNI_NOTIFY:
587 uni_enq_call(c, SIGC_NOTIFY, 0, m, u);
588 return;
589
590 case UNI_STATUS:
591 uni_enq_call(c, SIGC_STATUS, 0, m, u);
592 return;
593
594 case UNI_STATUS_ENQ:
595 uni_enq_call(c, SIGC_STATUS_ENQ, 0, m, u);
596 return;
597
598 case UNI_ADD_PARTY:
599 uni_enq_call(c, SIGC_ADD_PARTY, 0, m, u);
600 return;
601
602 case UNI_PARTY_ALERTING:
603 uni_enq_call(c, SIGC_PARTY_ALERTING, 0, m, u);
604 return;
605
606 case UNI_ADD_PARTY_ACK:
607 uni_enq_call(c, SIGC_ADD_PARTY_ACK, 0, m, u);
608 return;
609
610 case UNI_ADD_PARTY_REJ:
611 uni_enq_call(c, SIGC_ADD_PARTY_REJ, 0, m, u);
612 return;
613
614 case UNI_DROP_PARTY:
615 uni_enq_call(c, SIGC_DROP_PARTY, 0, m, u);
616 return;
617
618 case UNI_DROP_PARTY_ACK:
619 uni_enq_call(c, SIGC_DROP_PARTY_ACK, 0, m, u);
620 return;
621
622 default:
623 uni_enq_call(c, SIGC_UNKNOWN, 0, m, u);
624 return;
625 }
626 UNI_FREE(u);
627 uni_msg_destroy(m);
628 }
629
630
631 /*
632 * This macro tries to implement the delaying behaviour for
633 * message from the API when we are in the Awaiting-Establish state.
634 * In this state, the message is delayed. If we drop back to CU 0,
635 * everything gets unqueued and errors are returned for all that stuff.
636 * If we progess to CUSTAT2 we process the requests.
637 */
638 #define COMMON_DELAY(SIG, COOKIE) \
639 if (uni->custat == CU_STAT0 || uni->custat == CU_STAT2) {\
640 uniapi_uni_error(uni, UNIAPI_ERROR_BADCU, \
641 COOKIE, 0); \
642 break; \
643 } \
644 if (uni->custat == CU_STAT1) { \
645 uni_delenq_coord(uni, SIG, COOKIE, msg); \
646 break; \
647 }
648
649 /*
650 * Signal handler of the coordinator
651 */
652 void
653 uni_sig_coord(struct uni *uni, enum coord_sig sig, uint32_t cookie,
654 struct uni_msg *msg)
655 {
656 struct call *c;
657
658 if (sig >= SIGO_END) {
659 VERBOSE(uni, UNI_FAC_ERR, 1, "Signal %d outside of range to "
660 "Coord", sig);
661 if (msg)
662 uni_msg_destroy(msg);
663 return;
664 }
665
666 VERBOSE(uni, UNI_FAC_COORD, 1, "Signal %s in state %s",
667 coord_sigs[sig], cunames[uni->custat]);
668
669 switch (sig) {
670
671 case SIGO_END:
672 break;
673
674 case SIGO_DATA: /* delayed output */
675 if (uni->custat == CU_STAT0 || uni->custat == CU_STAT1)
676 break; /* drop */
677 if (uni->custat == CU_STAT1)
678 uni_delenq_coord(uni, SIGO_DATA, cookie, msg);/* ??? */
679 else
680 uni->funcs->saal_output(uni, uni->arg,
681 SAAL_DATA_request, msg);
682 msg = NULL;
683 break;
684
685 /*
686 * SAAL signals
687 */
688 case SIGO_SAAL_ESTABLISH_indication:
689 coord_saal_establish_indication(uni);
690 break;
691
692 case SIGO_SAAL_ESTABLISH_confirm:
693 coord_saal_establish_confirm(uni);
694 break;
695
696 case SIGO_SAAL_RELEASE_confirm:
697 coord_saal_release_confirm(uni);
698 break;
699
700 case SIGO_SAAL_RELEASE_indication:
701 coord_saal_release_indication(uni);
702 break;
703
704 case SIGO_SAAL_DATA_indication:
705 coord_saal_data_indication(uni, msg);
706 msg = NULL;
707 break;
708
709 case SIGO_SAAL_UDATA_indication:
710 VERBOSE0(uni, UNI_FAC_ERR, "SAAL_UDATA_indication");
711 break;
712
713 /*
714 * Signals from USER
715 */
716 case SIGO_LINK_ESTABLISH_request:
717 coord_link_establish_request(uni, cookie);
718 break;
719
720 case SIGO_LINK_RELEASE_request:
721 coord_link_release_request(uni, cookie);
722 break;
723
724 case SIGO_RESET_request:
725 uni_enq_start(uni, SIGS_RESET_request, cookie, msg, NULL);
726 msg = NULL;
727 if (uni->custat == CU_STAT0) {
728 uni->funcs->saal_output(uni, uni->arg,
729 SAAL_ESTABLISH_request, NULL);
730 if (!TIMER_ISACT(uni, t309))
731 TIMER_START_UNI(uni, t309, uni->timer309);
732 set_custat(uni, CU_STAT1);
733 }
734 break;
735
736 case SIGO_RESET_ERROR_response:
737 COMMON_DELAY(SIGO_RESET_ERROR_response, cookie);
738 uni_enq_resp(uni, SIGR_RESET_ERROR_response, cookie, msg, NULL);
739 msg = NULL;
740 break;
741
742 case SIGO_RESET_response:
743 COMMON_DELAY(SIGO_RESET_response, cookie);
744 uni_enq_resp(uni, SIGR_RESET_response, cookie, msg, NULL);
745 msg = NULL;
746 break;
747
748 case SIGO_SETUP_request:
749 if ((c = uni_create_new_call(uni, cookie)) != NULL) {
750 uni_enq_call(c, SIGC_SETUP_request, cookie, msg, NULL);
751 msg = NULL;
752 if (uni->custat == CU_STAT0) {
753 uni->funcs->saal_output(uni, uni->arg,
754 SAAL_ESTABLISH_request, NULL);
755 if (!TIMER_ISACT(uni, t309))
756 TIMER_START_UNI(uni, t309, uni->timer309);
757 set_custat(uni, CU_STAT1);
758 }
759 } else {
760 uniapi_uni_error(uni, UNIAPI_ERROR_NOMEM, cookie,
761 UNI_CALLSTATE_U0);
762 }
763 break;
764
765 case SIGO_PROCEEDING_request:
766 {
767 struct uniapi_proceeding_request *arg =
768 uni_msg_rptr(msg, struct uniapi_proceeding_request *);
769
770 COMMON_DELAY(SIGO_PROCEEDING_request, cookie);
771 if ((c = uni_find_call(uni, &arg->call_proc.hdr.cref)) != NULL) {
772 uni_enq_call(c, SIGC_PROCEEDING_request, cookie, msg, NULL);
773 msg = NULL;
774 } else {
775 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
776 UNI_CALLSTATE_U0);
777 }
778 break;
779 }
780
781 case SIGO_ALERTING_request:
782 {
783 struct uniapi_alerting_request *arg =
784 uni_msg_rptr(msg, struct uniapi_alerting_request *);
785
786 COMMON_DELAY(SIGO_ALERTING_request, cookie);
787 if ((c = uni_find_call(uni, &arg->alerting.hdr.cref)) != NULL) {
788 uni_enq_call(c, SIGC_ALERTING_request, cookie, msg, NULL);
789 msg = NULL;
790 } else {
791 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
792 UNI_CALLSTATE_U0);
793 }
794 break;
795 }
796
797 case SIGO_SETUP_response:
798 {
799 struct uniapi_setup_response *arg =
800 uni_msg_rptr(msg, struct uniapi_setup_response *);
801
802 COMMON_DELAY(SIGO_SETUP_response, cookie);
803 if ((c = uni_find_call(uni, &arg->connect.hdr.cref)) != NULL) {
804 uni_enq_call(c, SIGC_SETUP_response, cookie, msg, NULL);
805 msg = NULL;
806 } else {
807 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
808 UNI_CALLSTATE_U0);
809 }
810 break;
811 }
812
813 case SIGO_SETUP_COMPLETE_request:
814 {
815 struct uniapi_setup_complete_request *arg =
816 uni_msg_rptr(msg, struct uniapi_setup_complete_request *);
817
818 COMMON_DELAY(SIGO_SETUP_COMPLETE_request, cookie);
819 if ((c = uni_find_call(uni, &arg->connect_ack.hdr.cref)) != NULL) {
820 uni_enq_call(c, SIGC_SETUP_COMPLETE_request,
821 cookie, msg, NULL);
822 msg = NULL;
823 } else {
824 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
825 UNI_CALLSTATE_U0);
826 }
827 break;
828 }
829
830 case SIGO_RELEASE_request:
831 {
832 struct uniapi_release_request *arg =
833 uni_msg_rptr(msg, struct uniapi_release_request *);
834
835 COMMON_DELAY(SIGO_RELEASE_request, cookie);
836 if ((c = uni_find_call(uni, &arg->release.hdr.cref)) != NULL) {
837 uni_enq_call(c, SIGC_RELEASE_request, cookie, msg, NULL);
838 msg = NULL;
839 } else {
840 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
841 UNI_CALLSTATE_U0);
842 }
843 break;
844 }
845
846 case SIGO_RELEASE_response:
847 {
848 struct uniapi_release_response *arg =
849 uni_msg_rptr(msg, struct uniapi_release_response *);
850
851 COMMON_DELAY(SIGO_RELEASE_response, cookie);
852 if ((c = uni_find_call(uni, &arg->release_compl.hdr.cref)) != NULL) {
853 uni_enq_call(c, SIGC_RELEASE_response, cookie, msg, NULL);
854 msg = NULL;
855 } else {
856 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
857 UNI_CALLSTATE_U0);
858 }
859 break;
860 }
861
862 case SIGO_NOTIFY_request:
863 {
864 struct uniapi_notify_request *arg =
865 uni_msg_rptr(msg, struct uniapi_notify_request *);
866
867 COMMON_DELAY(SIGO_NOTIFY_request, cookie);
868 if ((c = uni_find_call(uni, &arg->notify.hdr.cref)) != NULL) {
869 uni_enq_call(c, SIGC_NOTIFY_request, cookie, msg, NULL);
870 msg = NULL;
871 } else {
872 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
873 UNI_CALLSTATE_U0);
874 }
875 break;
876 }
877
878 case SIGO_STATUS_ENQUIRY_request:
879 {
880 struct uniapi_status_enquiry_request *arg =
881 uni_msg_rptr(msg, struct uniapi_status_enquiry_request *);
882
883 COMMON_DELAY(SIGO_STATUS_ENQUIRY_request, cookie);
884 if ((c = uni_find_call(uni, &arg->cref)) != NULL) {
885 uni_enq_call(c, SIGC_STATUS_ENQUIRY_request, cookie, msg, NULL);
886 msg = NULL;
887 } else {
888 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
889 UNI_CALLSTATE_U0);
890 }
891 break;
892 }
893
894 case SIGO_ADD_PARTY_request:
895 {
896 struct uniapi_add_party_request *arg =
897 uni_msg_rptr(msg, struct uniapi_add_party_request *);
898
899 COMMON_DELAY(SIGO_ADD_PARTY_request, cookie);
900 if ((c = uni_find_call(uni, &arg->add.hdr.cref)) != NULL) {
901 if (c->type != CALL_ROOT) {
902 uniapi_call_error(c, UNIAPI_ERROR_BAD_CTYPE,
903 cookie);
904 break;
905 }
906 uni_enq_call(c, SIGC_ADD_PARTY_request, cookie, msg, NULL);
907 msg = NULL;
908 } else {
909 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
910 UNI_CALLSTATE_U0);
911 }
912 break;
913 }
914
915 case SIGO_PARTY_ALERTING_request:
916 {
917 struct uniapi_party_alerting_request *arg =
918 uni_msg_rptr(msg, struct uniapi_party_alerting_request *);
919
920 COMMON_DELAY(SIGO_PARTY_ALERTING_request, cookie);
921 if ((c = uni_find_call(uni, &arg->alert.hdr.cref)) != NULL) {
922 if (c->type != CALL_LEAF) {
923 uniapi_call_error(c, UNIAPI_ERROR_BAD_CTYPE,
924 cookie);
925 break;
926 }
927 uni_enq_call(c, SIGC_PARTY_ALERTING_request, cookie, msg, NULL);
928 msg = NULL;
929 } else {
930 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
931 UNI_CALLSTATE_U0);
932 }
933 break;
934 }
935
936 case SIGO_ADD_PARTY_ACK_request:
937 {
938 struct uniapi_add_party_ack_request *arg =
939 uni_msg_rptr(msg, struct uniapi_add_party_ack_request *);
940
941 COMMON_DELAY(SIGO_ADD_PARTY_ACK_request, cookie);
942 if ((c = uni_find_call(uni, &arg->ack.hdr.cref)) != NULL) {
943 if (c->type != CALL_LEAF) {
944 uniapi_call_error(c, UNIAPI_ERROR_BAD_CTYPE,
945 cookie);
946 break;
947 }
948 uni_enq_call(c, SIGC_ADD_PARTY_ACK_request, cookie, msg, NULL);
949 msg = NULL;
950 } else {
951 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
952 UNI_CALLSTATE_U0);
953 }
954 break;
955 }
956
957 case SIGO_ADD_PARTY_REJ_request:
958 {
959 struct uniapi_add_party_rej_request *arg =
960 uni_msg_rptr(msg, struct uniapi_add_party_rej_request *);
961
962 COMMON_DELAY(SIGO_ADD_PARTY_REJ_request, cookie);
963 if ((c = uni_find_call(uni, &arg->rej.hdr.cref)) != NULL) {
964 if (c->type != CALL_LEAF) {
965 uniapi_call_error(c, UNIAPI_ERROR_BAD_CTYPE,
966 cookie);
967 break;
968 }
969 uni_enq_call(c, SIGC_ADD_PARTY_REJ_request, cookie, msg, NULL);
970 msg = NULL;
971 } else {
972 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
973 UNI_CALLSTATE_U0);
974 }
975 break;
976 }
977
978 case SIGO_DROP_PARTY_request:
979 {
980 struct uniapi_drop_party_request *arg =
981 uni_msg_rptr(msg, struct uniapi_drop_party_request *);
982
983 COMMON_DELAY(SIGO_DROP_PARTY_request, cookie);
984 if ((c = uni_find_call(uni, &arg->drop.hdr.cref)) != NULL) {
985 if (c->type != CALL_ROOT && c->type != CALL_LEAF) {
986 uniapi_call_error(c, UNIAPI_ERROR_BAD_CTYPE,
987 cookie);
988 break;
989 }
990 uni_enq_call(c, SIGC_DROP_PARTY_request, cookie, msg, NULL);
991 msg = NULL;
992 } else {
993 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
994 UNI_CALLSTATE_U0);
995 }
996 break;
997 }
998
999 case SIGO_DROP_PARTY_ACK_request:
1000 {
1001 struct uniapi_drop_party_ack_request *arg =
1002 uni_msg_rptr(msg, struct uniapi_drop_party_ack_request *);
1003
1004 COMMON_DELAY(SIGO_DROP_PARTY_ACK_request, cookie);
1005 if ((c = uni_find_call(uni, &arg->ack.hdr.cref)) != NULL) {
1006 if (c->type != CALL_ROOT && c->type != CALL_LEAF) {
1007 uniapi_call_error(c, UNIAPI_ERROR_BAD_CTYPE,
1008 cookie);
1009 break;
1010 }
1011 uni_enq_call(c, SIGC_DROP_PARTY_ACK_request, cookie, msg, NULL);
1012 msg = NULL;
1013 } else {
1014 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
1015 UNI_CALLSTATE_U0);
1016 }
1017 break;
1018 }
1019
1020 case SIGO_ABORT_CALL_request:
1021 {
1022 struct uniapi_abort_call_request *arg =
1023 uni_msg_rptr(msg, struct uniapi_abort_call_request *);
1024
1025 if ((c = uni_find_call(uni, &arg->cref)) != NULL) {
1026 uni_enq_call(c, SIGC_ABORT_CALL_request, cookie, NULL, NULL);
1027 } else {
1028 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
1029 UNI_CALLSTATE_U0);
1030 }
1031 break;
1032 }
1033
1034 /*
1035 * Call-Control
1036 */
1037 case SIGO_CALL_DESTROYED:
1038 uni->funcs->uni_output(uni, uni->arg,
1039 UNIAPI_CALL_DESTROYED, 0, msg);
1040 msg = NULL;
1041 break;
1042
1043 /*
1044 * ResetRespond
1045 */
1046 case SIGO_RESET_indication:
1047 uni->funcs->uni_output(uni, uni->arg,
1048 UNIAPI_RESET_indication, 0, msg);
1049 msg = NULL;
1050 break;
1051
1052 /*
1053 * Timeouts
1054 */
1055 case SIGO_T309:
1056 coord_t309(uni);
1057 break;
1058
1059 }
1060 if (msg != NULL)
1061 uni_msg_destroy(msg);
1062 }
1063
1064 /*
1065 * Send a signal to all call instances
1066 */
1067 static void
1068 sig_all_calls(struct uni *uni, u_int sig)
1069 {
1070 struct call *call;
1071
1072 TAILQ_FOREACH(call, &uni->calls, link)
1073 uni_enq_call(call, sig, 0, NULL, NULL);
1074 }
1075
1076 /*
1077 * Set a new coordinator state - this moves all delayed coordinator
1078 * signals from the delayed queue to the signal queue.
1079 */
1080 static int
1081 cufilt(struct sig *s, void *arg __unused)
1082 {
1083 return (s->type == SIG_COORD);
1084 }
1085
1086 static void
1087 set_custat(struct uni *uni, enum cu_stat nstate)
1088 {
1089 if (uni->custat != nstate) {
1090 uni->custat = nstate;
1091 uni_undel(uni, cufilt, NULL);
1092 }
1093 }
1094
1095 /*
1096 * T309 timeout function
1097 */
1098 static void
1099 t309_func(struct uni *uni)
1100 {
1101 uni_enq_coord(uni, SIGO_T309, 0, NULL);
1102 }
1103
1104 /*
1105 * Respond with a status message
1106 */
1107 void
1108 uni_respond_status(struct uni *uni, struct uni_cref *cref,
1109 enum uni_callstate cs, enum uni_cause c1)
1110 {
1111 struct uni_all *resp;
1112
1113 if ((resp = UNI_ALLOC()) == NULL)
1114 return;
1115
1116 MK_MSG_RESP(resp, UNI_STATUS, cref);
1117 MK_IE_CALLSTATE(resp->u.status.callstate, cs);
1118 MK_IE_CAUSE(resp->u.status.cause, UNI_CAUSE_LOC_USER, c1);
1119
1120 (void)uni_send_output(resp, uni);
1121
1122 UNI_FREE(resp);
1123 }
1124
1125 /*
1126 * Respond with a status message
1127 */
1128 void
1129 uni_respond_status_mtype(struct uni *uni, struct uni_cref *cref,
1130 enum uni_callstate cs, enum uni_cause c1, u_int mtype)
1131 {
1132 struct uni_all *resp;
1133
1134 if((resp = UNI_ALLOC()) == NULL)
1135 return;
1136
1137 MK_MSG_RESP(resp, UNI_STATUS, cref);
1138 MK_IE_CALLSTATE(resp->u.status.callstate, cs);
1139 MK_IE_CAUSE(resp->u.status.cause, UNI_CAUSE_LOC_USER, c1);
1140 ADD_CAUSE_MTYPE(resp->u.status.cause, mtype);
1141
1142 (void)uni_send_output(resp, uni);
1143
1144 UNI_FREE(resp);
1145 }
1146
1147 /*
1148 * Send a message. If we are in CUSTAT1, delay the message if we
1149 * are in CUSTAT3 send it, else drop it.
1150 */
1151 int
1152 uni_send_output(struct uni_all *u, struct uni *uni)
1153 {
1154 struct uni_msg *m;
1155 int err;
1156
1157 if (uni->custat == CU_STAT0 || uni->custat == CU_STAT2)
1158 return (0);
1159
1160 m = uni_msg_alloc(1024);
1161 if ((err = uni_encode(m, u, &uni->cx)) != 0) {
1162 VERBOSE0(uni, UNI_FAC_ERR, "uni_encode failed: %08x", err);
1163 uni_msg_destroy(m);
1164 return (-1);
1165 }
1166 if (uni->custat == CU_STAT1)
1167 uni_delenq_coord(uni, SIGO_DATA, 0, m);
1168 else
1169 uni->funcs->saal_output(uni, uni->arg, SAAL_DATA_request, m);
1170 return (0);
1171 }
Cache object: 0c90efc0fae84bc54f773ee4a8ac4a68
|