This source file includes following definitions.
- ftdm_sangoma_isdn_advance_chan_states
- ftdm_sangoma_isdn_run
- ftdm_sangoma_isdn_process_event_states
- ftdm_sangoma_isdn_process_stack_event
- ftdm_sangoma_isdn_process_state_change
- FIO_CHANNEL_OUTGOING_CALL_FUNCTION
- FIO_CHANNEL_GET_SIG_STATUS_FUNCTION
- FIO_CHANNEL_SET_SIG_STATUS_FUNCTION
- FIO_SPAN_GET_SIG_STATUS_FUNCTION
- FIO_SPAN_SET_SIG_STATUS_FUNCTION
- ftdm_sangoma_isdn_start
- ftdm_sangoma_isdn_stop
- FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION
- FIO_SIG_LOAD_FUNCTION
- FIO_SIG_UNLOAD_FUNCTION
- FIO_API_FUNCTION
- FIO_IO_LOAD_FUNCTION
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 #include "ftmod_sangoma_isdn.h"
38
39 #ifdef FTDM_DEBUG_CHAN_MEMORY
40 #include <sys/mman.h>
41 #endif
42
43 static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj);
44
45 static ftdm_status_t ftdm_sangoma_isdn_stop(ftdm_span_t *span);
46 static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span);
47
48 ftdm_channel_t* ftdm_sangoma_isdn_process_event_states(ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event);
49 static void ftdm_sangoma_isdn_advance_chan_states(ftdm_channel_t *ftdmchan);
50
51 static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan);
52 static void ftdm_sangoma_isdn_process_stack_event (ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event);
53
54 static ftdm_io_interface_t g_sngisdn_io_interface;
55 static sng_isdn_event_interface_t g_sngisdn_event_interface;
56
57 ftdm_sngisdn_data_t g_sngisdn_data;
58
59 extern ftdm_status_t sng_isdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t trace_opt);
60 extern ftdm_status_t sngisdn_check_free_ids(void);
61
62 ftdm_state_map_t sangoma_isdn_state_map = {
63 {
64 {
65 ZSD_INBOUND,
66 ZSM_UNACCEPTABLE,
67 {FTDM_ANY_STATE, FTDM_END},
68 {FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_SUSPENDED, FTDM_END}
69 },
70 {
71 ZSD_INBOUND,
72 ZSM_UNACCEPTABLE,
73 {FTDM_CHANNEL_STATE_RESTART, FTDM_END},
74 {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_END}
75 },
76 {
77 ZSD_INBOUND,
78 ZSM_UNACCEPTABLE,
79 {FTDM_CHANNEL_STATE_CANCEL, FTDM_END},
80 {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END}
81 },
82 {
83 ZSD_INBOUND,
84 ZSM_UNACCEPTABLE,
85 {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_END},
86 {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_DIALING,
87 FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP,
88 FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END}
89 },
90 {
91 ZSD_INBOUND,
92 ZSM_UNACCEPTABLE,
93 {FTDM_CHANNEL_STATE_DOWN, FTDM_END},
94 {FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_GET_CALLERID, FTDM_CHANNEL_STATE_IN_LOOP, FTDM_END}
95 },
96 {
97 ZSD_INBOUND,
98 ZSM_UNACCEPTABLE,
99 {FTDM_CHANNEL_STATE_GET_CALLERID, FTDM_END},
100 {FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_IN_LOOP, FTDM_END}
101 },
102 {
103 ZSD_INBOUND,
104 ZSM_UNACCEPTABLE,
105 {FTDM_CHANNEL_STATE_COLLECT, FTDM_END},
106 {FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_IN_LOOP, FTDM_END}
107 },
108 {
109 ZSD_INBOUND,
110 ZSM_UNACCEPTABLE,
111 {FTDM_CHANNEL_STATE_IN_LOOP, FTDM_END},
112 {FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_DOWN, FTDM_END}
113 },
114 {
115 ZSD_INBOUND,
116 ZSM_UNACCEPTABLE,
117 {FTDM_CHANNEL_STATE_RING, FTDM_END},
118 {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS, FTDM_END}
119 },
120 {
121 ZSD_INBOUND,
122 ZSM_UNACCEPTABLE,
123 {FTDM_CHANNEL_STATE_PROGRESS, FTDM_END},
124 {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END},
125 },
126 {
127 ZSD_INBOUND,
128 ZSM_UNACCEPTABLE,
129 {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END},
130 {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_UP, FTDM_END},
131 },
132 {
133 ZSD_INBOUND,
134 ZSM_UNACCEPTABLE,
135 {FTDM_CHANNEL_STATE_UP, FTDM_END},
136 {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
137 },
138 {
139 ZSD_INBOUND,
140 ZSM_UNACCEPTABLE,
141 {FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
142 {FTDM_CHANNEL_STATE_HANGUP, FTDM_END},
143 },
144 {
145 ZSD_INBOUND,
146 ZSM_UNACCEPTABLE,
147 {FTDM_CHANNEL_STATE_HANGUP, FTDM_END},
148 {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END},
149 },
150 {
151 ZSD_INBOUND,
152 ZSM_UNACCEPTABLE,
153 {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END},
154 {FTDM_CHANNEL_STATE_DOWN, FTDM_END},
155 },
156 {
157 ZSD_OUTBOUND,
158 ZSM_UNACCEPTABLE,
159 {FTDM_ANY_STATE, FTDM_END},
160 {FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}
161 },
162 {
163 ZSD_OUTBOUND,
164 ZSM_UNACCEPTABLE,
165 {FTDM_CHANNEL_STATE_RESTART, FTDM_END},
166 {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_END}
167 },
168 {
169 ZSD_OUTBOUND,
170 ZSM_UNACCEPTABLE,
171 {FTDM_CHANNEL_STATE_CANCEL, FTDM_END},
172 {FTDM_CHANNEL_STATE_HANGUP, FTDM_END}
173 },
174 {
175 ZSD_OUTBOUND,
176 ZSM_UNACCEPTABLE,
177 {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_END},
178 {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_DIALING,
179 FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP,
180 FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END}
181 },
182 {
183 ZSD_OUTBOUND,
184 ZSM_UNACCEPTABLE,
185 {FTDM_CHANNEL_STATE_DOWN, FTDM_END},
186 {FTDM_CHANNEL_STATE_DIALING, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END}
187 },
188 {
189 ZSD_OUTBOUND,
190 ZSM_UNACCEPTABLE,
191 {FTDM_CHANNEL_STATE_DIALING, FTDM_END},
192 {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS,
193 FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_DOWN, FTDM_END}
194 },
195 {
196 ZSD_OUTBOUND,
197 ZSM_UNACCEPTABLE,
198 {FTDM_CHANNEL_STATE_PROGRESS, FTDM_END},
199 {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END},
200 },
201 {
202 ZSD_OUTBOUND,
203 ZSM_UNACCEPTABLE,
204 {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END},
205 {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_UP, FTDM_END},
206 },
207 {
208 ZSD_OUTBOUND,
209 ZSM_UNACCEPTABLE,
210 {FTDM_CHANNEL_STATE_UP, FTDM_END},
211 {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
212 },
213 {
214 ZSD_OUTBOUND,
215 ZSM_UNACCEPTABLE,
216 {FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
217 {FTDM_CHANNEL_STATE_HANGUP, FTDM_END},
218 },
219 {
220 ZSD_OUTBOUND,
221 ZSM_UNACCEPTABLE,
222 {FTDM_CHANNEL_STATE_HANGUP, FTDM_END},
223 {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END},
224 },
225 {
226 ZSD_OUTBOUND,
227 ZSM_UNACCEPTABLE,
228 {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END},
229 {FTDM_CHANNEL_STATE_DOWN, FTDM_END},
230 }
231 }
232 };
233
234 static __inline__ void ftdm_sangoma_isdn_advance_chan_states(ftdm_channel_t *ftdmchan)
235 {
236 while (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
237 ftdm_sangoma_isdn_process_state_change(ftdmchan);
238 }
239 }
240
241 static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj)
242 {
243 ftdm_interrupt_t *ftdm_sangoma_isdn_int[2];
244 ftdm_status_t ret_status;
245 ftdm_span_t *span = (ftdm_span_t *) obj;
246 ftdm_channel_t *ftdmchan = NULL;
247 sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
248 sngisdn_event_data_t *sngisdn_event = NULL;
249 int32_t sleep = SNGISDN_EVENT_POLL_RATE;
250
251 ftdm_log(FTDM_LOG_INFO, "ftmod_sangoma_isdn monitor thread for span=%u started.\n", span->span_id);
252
253
254 ftdm_set_flag(span, FTDM_SPAN_IN_THREAD);
255
256
257 if (ftdm_queue_get_interrupt(span->pendingchans, &ftdm_sangoma_isdn_int[0]) != FTDM_SUCCESS) {
258 ftdm_log(FTDM_LOG_CRIT, "%s:Failed to get a ftdm_interrupt for span = %s!\n", span->name);
259 goto ftdm_sangoma_isdn_run_exit;
260 }
261
262 if (ftdm_queue_get_interrupt(signal_data->event_queue, &ftdm_sangoma_isdn_int[1]) != FTDM_SUCCESS) {
263 ftdm_log(FTDM_LOG_CRIT, "%s:Failed to get a event interrupt for span = %s!\n", span->name);
264 goto ftdm_sangoma_isdn_run_exit;
265 }
266
267 while (ftdm_running() && !(ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD))) {
268
269
270 ftdm_sched_run(signal_data->sched);
271
272 ret_status = ftdm_interrupt_multiple_wait(ftdm_sangoma_isdn_int, 2, sleep);
273
274 switch (ret_status) {
275 case FTDM_SUCCESS:
276
277 while ((ftdmchan = ftdm_queue_dequeue(span->pendingchans))) {
278
279 ftdm_channel_lock(ftdmchan);
280 ftdm_sangoma_isdn_advance_chan_states(ftdmchan);
281 ftdm_channel_unlock(ftdmchan);
282 }
283
284 while ((sngisdn_event = ftdm_queue_dequeue(signal_data->event_queue))) {
285 ftdm_sangoma_isdn_process_stack_event(span, sngisdn_event);
286 ftdm_safe_free(sngisdn_event);
287 }
288 ftdm_span_trigger_signals(span);
289 break;
290 case FTDM_TIMEOUT:
291
292 break;
293 case FTDM_FAIL:
294 ftdm_log(FTDM_LOG_ERROR,"%s:ftdm_interrupt_wait returned error!\n", span->name);
295 break;
296
297 default:
298 ftdm_log(FTDM_LOG_ERROR,"%s:ftdm_interrupt_wait returned with unknown code\n", span->name);
299 break;
300 }
301
302
303 ret_status = ftdm_span_poll_event(span, 0);
304 switch(ret_status) {
305 case FTDM_SUCCESS:
306 {
307 ftdm_event_t *event;
308 while (ftdm_span_next_event(span, &event) == FTDM_SUCCESS);
309 }
310 break;
311 case FTDM_TIMEOUT:
312
313 break;
314 default:
315 ftdm_log(FTDM_LOG_WARNING, "%s:Failed to poll span event\n", span->name);
316 }
317
318 if (ftdm_sched_get_time_to_next_timer(signal_data->sched, &sleep) == FTDM_SUCCESS) {
319 if (sleep < 0 || sleep > SNGISDN_EVENT_POLL_RATE) {
320 sleep = SNGISDN_EVENT_POLL_RATE;
321 }
322 }
323 }
324
325
326 ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD);
327
328 ftdm_log(FTDM_LOG_INFO, "ftmod_sangoma_isdn monitor thread for span %s stopping.\n", span->name);
329
330 return NULL;
331
332 ftdm_sangoma_isdn_run_exit:
333
334
335 ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD);
336
337 ftdm_log(FTDM_LOG_INFO, "ftmod_sangoma_isdn monitor thread for span %s stopping due to error.\n", span->name);
338
339 return NULL;
340 }
341
342
343
344
345
346
347
348
349
350 ftdm_channel_t* ftdm_sangoma_isdn_process_event_states(ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event)
351 {
352 ftdm_channel_t *ftdmchan = NULL;
353 switch (sngisdn_event->event_id) {
354
355 case SNGISDN_EVENT_SRV_IND:
356 case SNGISDN_EVENT_SRV_CFM:
357 case SNGISDN_EVENT_RST_CFM:
358 case SNGISDN_EVENT_RST_IND:
359 return NULL;
360 break;
361 case SNGISDN_EVENT_CON_IND:
362 case SNGISDN_EVENT_CON_CFM:
363 case SNGISDN_EVENT_CNST_IND:
364 case SNGISDN_EVENT_DISC_IND:
365 case SNGISDN_EVENT_REL_IND:
366 case SNGISDN_EVENT_DAT_IND:
367 case SNGISDN_EVENT_SSHL_IND:
368 case SNGISDN_EVENT_SSHL_CFM:
369 case SNGISDN_EVENT_RMRT_IND:
370 case SNGISDN_EVENT_RMRT_CFM:
371 case SNGISDN_EVENT_FLC_IND:
372 case SNGISDN_EVENT_FAC_IND:
373 case SNGISDN_EVENT_STA_CFM:
374 ftdmchan = sngisdn_event->sngisdn_info->ftdmchan;
375 ftdm_assert_return(ftdmchan, NULL,"Event should have a channel associated\n");
376 break;
377 }
378 ftdm_channel_lock(ftdmchan);
379 ftdm_sangoma_isdn_advance_chan_states(ftdmchan);
380 return ftdmchan;
381 }
382
383
384
385 static void ftdm_sangoma_isdn_process_stack_event (ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event)
386 {
387 ftdm_channel_t *ftdmchan = NULL;
388
389 ftdmchan = ftdm_sangoma_isdn_process_event_states(span, sngisdn_event);
390 switch(sngisdn_event->event_id) {
391 case SNGISDN_EVENT_CON_IND:
392 sngisdn_process_con_ind(sngisdn_event);
393 break;
394 case SNGISDN_EVENT_CON_CFM:
395 sngisdn_process_con_cfm(sngisdn_event);
396 break;
397 case SNGISDN_EVENT_CNST_IND:
398 sngisdn_process_cnst_ind(sngisdn_event);
399 break;
400 case SNGISDN_EVENT_DISC_IND:
401 sngisdn_process_disc_ind(sngisdn_event);
402 break;
403 case SNGISDN_EVENT_REL_IND:
404 sngisdn_process_rel_ind(sngisdn_event);
405 break;
406 case SNGISDN_EVENT_DAT_IND:
407 sngisdn_process_dat_ind(sngisdn_event);
408 break;
409 case SNGISDN_EVENT_SSHL_IND:
410 sngisdn_process_sshl_ind(sngisdn_event);
411 break;
412 case SNGISDN_EVENT_SSHL_CFM:
413 sngisdn_process_sshl_cfm(sngisdn_event);
414 break;
415 case SNGISDN_EVENT_RMRT_IND:
416 sngisdn_process_rmrt_ind(sngisdn_event);
417 break;
418 case SNGISDN_EVENT_RMRT_CFM:
419 sngisdn_process_rmrt_cfm(sngisdn_event);
420 break;
421 case SNGISDN_EVENT_FLC_IND:
422 sngisdn_process_flc_ind(sngisdn_event);
423 break;
424 case SNGISDN_EVENT_FAC_IND:
425 sngisdn_process_fac_ind(sngisdn_event);
426 break;
427 case SNGISDN_EVENT_STA_CFM:
428 sngisdn_process_sta_cfm(sngisdn_event);
429 break;
430 case SNGISDN_EVENT_SRV_IND:
431 sngisdn_process_srv_ind(sngisdn_event);
432 break;
433 case SNGISDN_EVENT_SRV_CFM:
434 sngisdn_process_srv_cfm(sngisdn_event);
435 break;
436 case SNGISDN_EVENT_RST_CFM:
437 sngisdn_process_rst_cfm(sngisdn_event);
438 break;
439 case SNGISDN_EVENT_RST_IND:
440 sngisdn_process_rst_ind(sngisdn_event);
441 break;
442 }
443 if(ftdmchan != NULL) {
444 ftdm_sangoma_isdn_advance_chan_states(ftdmchan);
445 ftdm_channel_unlock(ftdmchan);
446 }
447 }
448
449 static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
450 {
451 ftdm_sigmsg_t sigev;
452 ftdm_channel_state_t initial_state;
453 sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data;
454
455 memset(&sigev, 0, sizeof(sigev));
456
457 sigev.chan_id = ftdmchan->chan_id;
458 sigev.span_id = ftdmchan->span_id;
459 sigev.channel = ftdmchan;
460
461
462 ftdm_channel_lock(ftdmchan);
463
464 ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE);
465 #ifdef FTDM_DEBUG_CHAN_MEMORY
466 if (ftdmchan->state == FTDM_CHANNEL_STATE_DIALING) {
467 ftdm_assert(mprotect(ftdmchan, sizeof(*ftdmchan), PROT_READ)==0, "Failed to mprotect");
468 }
469 #endif
470
471
472 initial_state = ftdmchan->state;
473
474 ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "processing state change to %s\n", ftdm_channel_state2str(ftdmchan->state));
475
476 switch (ftdmchan->state) {
477 case FTDM_CHANNEL_STATE_COLLECT:
478 {
479
480 sngisdn_snd_setup_ack(ftdmchan);
481
482 }
483 break;
484 case FTDM_CHANNEL_STATE_GET_CALLERID:
485 {
486 sngisdn_set_flag(sngisdn_info, FLAG_SENT_PROCEED);
487 sngisdn_snd_proceed(ftdmchan);
488
489 }
490 break;
491 case FTDM_CHANNEL_STATE_RING:
492 {
493 ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending incoming call from %s to %s to FTDM core\n", ftdmchan->caller_data.ani.digits, ftdmchan->caller_data.dnis.digits);
494
495
496 sigev.event_id = FTDM_SIGEVENT_START;
497 ftdm_span_send_signal(ftdmchan->span, &sigev);
498 }
499 break;
500 case FTDM_CHANNEL_STATE_DIALING:
501 {
502 sngisdn_snd_setup(ftdmchan);
503 }
504 break;
505 case FTDM_CHANNEL_STATE_PROGRESS:
506 {
507
508 if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
509
510 sigev.event_id = FTDM_SIGEVENT_PROGRESS;
511 ftdm_span_send_signal(ftdmchan->span, &sigev);
512 } else if (!sngisdn_test_flag(sngisdn_info, FLAG_SENT_PROCEED)) {
513 sngisdn_set_flag(sngisdn_info, FLAG_SENT_PROCEED);
514 sngisdn_snd_proceed(ftdmchan);
515 }
516 }
517 break;
518 case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
519 {
520 if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
521 sigev.event_id = FTDM_SIGEVENT_PROGRESS_MEDIA;
522 ftdm_span_send_signal(ftdmchan->span, &sigev);
523 } else {
524 sngisdn_snd_progress(ftdmchan);
525 }
526 }
527 break;
528 case FTDM_CHANNEL_STATE_UP:
529 {
530
531 if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
532
533 sigev.event_id = FTDM_SIGEVENT_UP;
534 ftdm_span_send_signal(ftdmchan->span, &sigev);
535
536 if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP &&
537 ((sngisdn_span_data_t*)ftdmchan->span->signal_data)->signalling == SNGISDN_SIGNALING_NET) {
538
539 sngisdn_snd_con_complete(ftdmchan);
540 }
541 } else {
542
543 sngisdn_snd_connect(ftdmchan);
544 }
545 }
546 break;
547 case FTDM_CHANNEL_STATE_CANCEL:
548 {
549 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Hanging up call before informing user!\n");
550
551
552 sngisdn_snd_release(ftdmchan, 0);
553
554 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
555 }
556 break;
557 case FTDM_CHANNEL_STATE_TERMINATING:
558 {
559
560 sigev.event_id = FTDM_SIGEVENT_STOP;
561 ftdm_span_send_signal(ftdmchan->span, &sigev);
562 }
563 break;
564 case FTDM_CHANNEL_STATE_HANGUP:
565 {
566 if (sngisdn_test_flag(sngisdn_info, FLAG_REMOTE_ABORT)) {
567 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Acknowledging remote abort\n");
568 } else if (sngisdn_test_flag(sngisdn_info, FLAG_REMOTE_REL)) {
569 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Acknowledging remote hangup\n");
570 sngisdn_snd_release(ftdmchan, 0);
571 } else if (sngisdn_test_flag(sngisdn_info, FLAG_LOCAL_ABORT)) {
572
573 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Clearing local states from local abort\n");
574 } else if (sngisdn_test_flag(sngisdn_info, FLAG_GLARE)) {
575
576
577 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Waiting for RELEASE on hungup glared call\n");
578 } else if (sngisdn_test_flag(sngisdn_info, FLAG_SEND_DISC)) {
579
580 sngisdn_snd_disconnect(ftdmchan);
581 } else {
582 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Hanging up call upon local request!\n");
583
584
585 sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_REL);
586
587
588 if (ftdmchan->last_state == FTDM_CHANNEL_STATE_RING ||
589 ftdmchan->last_state == FTDM_CHANNEL_STATE_DIALING) {
590
591 sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
592 sngisdn_snd_release(ftdmchan, 0);
593
594 if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) {
595 sng_isdn_set_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN);
596 }
597 } else {
598 sngisdn_snd_disconnect(ftdmchan);
599 }
600 }
601
602
603 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
604 }
605 break;
606 case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
607 {
608 if (sngisdn_test_flag(sngisdn_info, FLAG_REMOTE_ABORT) ||
609 sngisdn_test_flag(sngisdn_info, FLAG_LOCAL_ABORT)) {
610
611 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
612 } else {
613
614 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Waiting for release from stack\n");
615 }
616 }
617 break;
618 case FTDM_CHANNEL_STATE_DOWN:
619 {
620 uint8_t glare = 0;
621
622 glare = sngisdn_test_flag(sngisdn_info, FLAG_GLARE);
623
624 clear_call_data(sngisdn_info);
625
626
627
628 if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) {
629 ftdm_channel_t *close_chan = ftdmchan;
630
631 ftdm_channel_close(&close_chan);
632 }
633 if (glare) {
634
635 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Glare detected, processing saved call\n");
636
637
638
639
640 sngisdn_rcv_con_ind(sngisdn_info->glare.suId, sngisdn_info->glare.suInstId, sngisdn_info->glare.spInstId, &sngisdn_info->glare.setup, sngisdn_info->glare.dChan, sngisdn_info->glare.ces);
641 }
642 }
643 break;
644 case FTDM_CHANNEL_STATE_RESTART:
645 {
646
647 }
648
649 break;
650 case FTDM_CHANNEL_STATE_SUSPENDED:
651 {
652
653 }
654 break;
655 default:
656 {
657 ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "unsupported sngisdn_rcvd state %s\n", ftdm_channel_state2str(ftdmchan->state));
658 }
659 break;
660 }
661
662 if (ftdmchan->state == initial_state) {
663 ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "state change flag is still set, but we did not change state\n");
664 }
665 #ifdef FTDM_DEBUG_CHAN_MEMORY
666 if (ftdmchan->state == FTDM_CHANNEL_STATE_DIALING) {
667 ftdm_assert(mprotect(ftdmchan, sizeof(*ftdmchan), PROT_READ|PROT_WRITE)==0, "Failed to mprotect");
668 }
669 #endif
670 ftdm_channel_unlock(ftdmchan);
671 return;
672 }
673
674 static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(ftdm_sangoma_isdn_outgoing_call)
675 {
676 sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data;
677 ftdm_status_t status = FTDM_FAIL;
678
679
680 ftdm_channel_lock(ftdmchan);
681
682 switch (ftdmchan->state) {
683
684 case FTDM_CHANNEL_STATE_DOWN:
685 {
686 if (sngisdn_test_flag(sngisdn_info, FLAG_GLARE)) {
687
688 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Glare detected - aborting outgoing call\n");
689
690 sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
691 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
692
693 status = FTDM_BREAK;
694 } else {
695 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DIALING);
696 status = FTDM_SUCCESS;
697 }
698 }
699 break;
700 default:
701 {
702
703 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Outgoing call requested channel in already in use\n");
704 status = FTDM_BREAK;
705 }
706 break;
707 }
708
709 ftdm_channel_unlock(ftdmchan);
710 return status;
711 }
712
713 static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(ftdm_sangoma_isdn_get_chan_sig_status)
714 {
715 if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) {
716 *status = FTDM_SIG_STATE_UP;
717 } else {
718 *status = FTDM_SIG_STATE_DOWN;
719 }
720
721 return FTDM_SUCCESS;
722 }
723
724 static FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(ftdm_sangoma_isdn_set_chan_sig_status)
725 {
726 ftdm_log(FTDM_LOG_ERROR,"Cannot set channel status in this module\n");
727 return FTDM_NOTIMPL;
728 }
729
730 static FIO_SPAN_GET_SIG_STATUS_FUNCTION(ftdm_sangoma_isdn_get_span_sig_status)
731 {
732 if (ftdm_test_flag(span->channels[1], FTDM_CHANNEL_SIG_UP)) {
733 *status = FTDM_SIG_STATE_UP;
734 } else {
735 *status = FTDM_SIG_STATE_DOWN;
736 }
737
738 return FTDM_SUCCESS;
739 }
740
741 static FIO_SPAN_SET_SIG_STATUS_FUNCTION(ftdm_sangoma_isdn_set_span_sig_status)
742 {
743 ftdm_log(FTDM_LOG_ERROR,"Cannot set span status in this module\n");
744 return FTDM_NOTIMPL;
745 }
746
747 static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span)
748 {
749 ftdm_log(FTDM_LOG_INFO,"Starting span %s:%u.\n",span->name,span->span_id);
750 if (sng_isdn_stack_start(span) != FTDM_SUCCESS) {
751 ftdm_log(FTDM_LOG_CRIT, "Failed to start span %s\n", span->name);
752 return FTDM_FAIL;
753 }
754
755 ftdm_clear_flag(span, FTDM_SPAN_STOP_THREAD);
756 ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD);
757
758
759 if (ftdm_thread_create_detached(ftdm_sangoma_isdn_run, span) != FTDM_SUCCESS) {
760 ftdm_log(FTDM_LOG_CRIT,"Failed to start Sangoma ISDN Span Monitor Thread!\n");
761 return FTDM_FAIL;
762 }
763
764 ftdm_log(FTDM_LOG_DEBUG,"Finished starting span %s\n", span->name);
765 return FTDM_SUCCESS;
766 }
767
768 static ftdm_status_t ftdm_sangoma_isdn_stop(ftdm_span_t *span)
769 {
770 ftdm_iterator_t *chaniter = NULL;
771 ftdm_iterator_t *curr = NULL;
772 unsigned i;
773 sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data;
774 ftdm_log(FTDM_LOG_INFO, "Stopping span %s\n", span->name);
775
776
777 ftdm_set_flag(span, FTDM_SPAN_STOP_THREAD);
778
779
780 while (ftdm_test_flag(span, FTDM_SPAN_IN_THREAD)) {
781 ftdm_log(FTDM_LOG_DEBUG, "Waiting for monitor thread to end for span %s\n", span->name);
782 ftdm_sleep(10);
783 }
784
785 if (sng_isdn_stack_stop(span) != FTDM_SUCCESS) {
786 ftdm_log(FTDM_LOG_CRIT, "Failed to stop span %s\n", span->name);
787 }
788
789 chaniter = ftdm_span_get_chan_iterator(span, NULL);
790 for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
791 ftdm_safe_free(((ftdm_channel_t*)ftdm_iterator_current(curr))->call_data);
792 ((ftdm_channel_t*)ftdm_iterator_current(curr))->call_data = NULL;
793 }
794 ftdm_iterator_free(chaniter);
795
796 ftdm_sched_destroy(&signal_data->sched);
797 ftdm_queue_destroy(&signal_data->event_queue);
798 for (i = 0 ; i < signal_data->num_local_numbers ; i++) {
799 if (signal_data->local_numbers[i] != NULL) {
800 ftdm_safe_free(signal_data->local_numbers[i]);
801 }
802 }
803 ftdm_safe_free(span->signal_data);
804
805 ftdm_log(FTDM_LOG_DEBUG, "Finished stopping span %s\n", span->name);
806
807 return FTDM_SUCCESS;
808 }
809
810 static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config)
811 {
812 ftdm_iterator_t *chaniter = NULL;
813 ftdm_iterator_t *curr = NULL;
814
815 sngisdn_span_data_t *span_data;
816
817 ftdm_log(FTDM_LOG_INFO, "Configuring ftmod_sangoma_isdn span = %s\n", span->name);
818
819 span_data = ftdm_calloc(1, sizeof(sngisdn_span_data_t));
820 span_data->ftdm_span = span;
821 span->signal_data = span_data;
822
823 chaniter = ftdm_span_get_chan_iterator(span, NULL);
824 for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
825 sngisdn_chan_data_t *chan_data = ftdm_calloc(1, sizeof(sngisdn_chan_data_t));
826 chan_data->ftdmchan = ((ftdm_channel_t*)ftdm_iterator_current(curr));
827 ((ftdm_channel_t*)ftdm_iterator_current(curr))->call_data = chan_data;
828
829 }
830 ftdm_iterator_free(chaniter);
831
832 if (ftmod_isdn_parse_cfg(ftdm_parameters, span) != FTDM_SUCCESS) {
833 ftdm_log(FTDM_LOG_ERROR, "Failed to parse configuration\n");
834 return FTDM_FAIL;
835 }
836
837 if (sng_isdn_stack_cfg(span) != FTDM_SUCCESS) {
838 ftdm_log(FTDM_LOG_CRIT, "Sangoma ISDN Stack configuration failed\n");
839 return FTDM_FAIL;
840 }
841
842
843 span->start = ftdm_sangoma_isdn_start;
844 span->stop = ftdm_sangoma_isdn_stop;
845 span->signal_type = FTDM_SIGTYPE_ISDN;
846 span->outgoing_call = ftdm_sangoma_isdn_outgoing_call;
847 span->channel_request = NULL;
848 span->signal_cb = sig_cb;
849 span->get_channel_sig_status = ftdm_sangoma_isdn_get_chan_sig_status;
850 span->set_channel_sig_status = ftdm_sangoma_isdn_set_chan_sig_status;
851 span->get_span_sig_status = ftdm_sangoma_isdn_get_span_sig_status;
852 span->set_span_sig_status = ftdm_sangoma_isdn_set_span_sig_status;
853 span->state_map = &sangoma_isdn_state_map;
854 ftdm_set_flag(span, FTDM_SPAN_USE_CHAN_QUEUE);
855 ftdm_set_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE);
856
857 if (span->trunk_type == FTDM_TRUNK_BRI_PTMP ||
858 span->trunk_type == FTDM_TRUNK_BRI) {
859
860 ftdm_set_flag(span, FTDM_SPAN_USE_AV_RATE);
861 sng_isdn_set_avail_rate(span, SNGISDN_AVAIL_PWR_SAVING);
862 }
863
864
865 ftdm_assert(ftdm_sched_create(&((sngisdn_span_data_t*)span->signal_data)->sched, "sngisdn_schedule") == FTDM_SUCCESS, "Failed to create a new schedule!!");
866
867
868 ftdm_assert(ftdm_queue_create(&((sngisdn_span_data_t*)span->signal_data)->event_queue, SNGISDN_EVENT_QUEUE_SIZE) == FTDM_SUCCESS, "Failed to create a new queue!!");
869
870 ftdm_log(FTDM_LOG_INFO, "Finished configuring ftmod_sangoma_isdn span = %s\n", span->name);
871 return FTDM_SUCCESS;
872 }
873
874 static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_isdn_init)
875 {
876 unsigned i;
877 ftdm_log(FTDM_LOG_INFO, "Loading ftmod_sangoma_isdn...\n");
878
879 memset(&g_sngisdn_data, 0, sizeof(g_sngisdn_data));
880
881
882 g_sngisdn_event_interface.cc.sng_con_ind = sngisdn_rcv_con_ind;
883 g_sngisdn_event_interface.cc.sng_con_cfm = sngisdn_rcv_con_cfm;
884 g_sngisdn_event_interface.cc.sng_cnst_ind = sngisdn_rcv_cnst_ind;
885 g_sngisdn_event_interface.cc.sng_disc_ind = sngisdn_rcv_disc_ind;
886 g_sngisdn_event_interface.cc.sng_rel_ind = sngisdn_rcv_rel_ind;
887 g_sngisdn_event_interface.cc.sng_dat_ind = sngisdn_rcv_dat_ind;
888 g_sngisdn_event_interface.cc.sng_sshl_ind = sngisdn_rcv_sshl_ind;
889 g_sngisdn_event_interface.cc.sng_sshl_cfm = sngisdn_rcv_sshl_cfm;
890 g_sngisdn_event_interface.cc.sng_rmrt_ind = sngisdn_rcv_rmrt_ind;
891 g_sngisdn_event_interface.cc.sng_rmrt_cfm = sngisdn_rcv_rmrt_cfm;
892 g_sngisdn_event_interface.cc.sng_flc_ind = sngisdn_rcv_flc_ind;
893 g_sngisdn_event_interface.cc.sng_fac_ind = sngisdn_rcv_fac_ind;
894 g_sngisdn_event_interface.cc.sng_sta_cfm = sngisdn_rcv_sta_cfm;
895 g_sngisdn_event_interface.cc.sng_srv_ind = sngisdn_rcv_srv_ind;
896 g_sngisdn_event_interface.cc.sng_srv_ind = sngisdn_rcv_srv_cfm;
897 g_sngisdn_event_interface.cc.sng_rst_ind = sngisdn_rcv_rst_cfm;
898 g_sngisdn_event_interface.cc.sng_rst_ind = sngisdn_rcv_rst_ind;
899 g_sngisdn_event_interface.cc.sng_rst_cfm = sngisdn_rcv_rst_cfm;
900
901 g_sngisdn_event_interface.lg.sng_log = sngisdn_rcv_sng_log;
902 g_sngisdn_event_interface.lg.sng_assert = sngisdn_rcv_sng_assert;
903
904 g_sngisdn_event_interface.sta.sng_phy_sta_ind = sngisdn_rcv_phy_ind;
905 g_sngisdn_event_interface.sta.sng_q921_sta_ind = sngisdn_rcv_q921_ind;
906 g_sngisdn_event_interface.sta.sng_q921_trc_ind = sngisdn_rcv_q921_trace;
907 g_sngisdn_event_interface.sta.sng_q931_sta_ind = sngisdn_rcv_q931_ind;
908 g_sngisdn_event_interface.sta.sng_q931_trc_ind = sngisdn_rcv_q931_trace;
909 g_sngisdn_event_interface.sta.sng_cc_sta_ind = sngisdn_rcv_cc_ind;
910
911 for(i=1;i<=MAX_VARIANTS;i++) {
912 ftdm_mutex_create(&g_sngisdn_data.ccs[i].mutex);
913 }
914
915
916 sng_isdn_init(&g_sngisdn_event_interface);
917 return FTDM_SUCCESS;
918 }
919
920 static FIO_SIG_UNLOAD_FUNCTION(ftdm_sangoma_isdn_unload)
921 {
922 unsigned i;
923 ftdm_log(FTDM_LOG_INFO, "Starting ftmod_sangoma_isdn unload...\n");
924
925 sng_isdn_free();
926
927 for(i=1;i<=MAX_VARIANTS;i++) {
928 ftdm_mutex_destroy(&g_sngisdn_data.ccs[i].mutex);
929 }
930
931 ftdm_log(FTDM_LOG_INFO, "Finished ftmod_sangoma_isdn unload!\n");
932 return FTDM_SUCCESS;
933 }
934
935 static FIO_API_FUNCTION(ftdm_sangoma_isdn_api)
936 {
937 ftdm_status_t status = FTDM_SUCCESS;
938 char *mycmd = NULL, *argv[10] = { 0 };
939 int argc = 0;
940
941 if (data) {
942 mycmd = ftdm_strdup(data);
943 argc = ftdm_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
944 }
945
946
947 if (argc <= 0) {
948 ftdm_log(FTDM_LOG_ERROR, "No parameters provided\n");
949 goto done;
950 }
951
952 if (!strcasecmp(argv[0], "trace")) {
953 char *trace_opt;
954
955 ftdm_span_t *span;
956
957 if (argc < 3) {
958 ftdm_log(FTDM_LOG_ERROR, "Usage: ftdm sangoma_isdn trace <q921|q931> <span name>\n");
959 status = FTDM_FAIL;
960 goto done;
961 }
962 trace_opt = argv[1];
963
964 status = ftdm_span_find_by_name(argv[2], &span);
965 if (FTDM_SUCCESS != status) {
966 stream->write_function(stream, "-ERR failed to find span by name %s\n", argv[2]);
967 goto done;
968 }
969 if (!strcasecmp(trace_opt, "q921")) {
970 sng_isdn_activate_trace(span, SNGISDN_TRACE_Q921);
971 } else if (!strcasecmp(trace_opt, "q931")) {
972 sng_isdn_activate_trace(span, SNGISDN_TRACE_Q931);
973 } else if (!strcasecmp(trace_opt, "disable")) {
974 sng_isdn_activate_trace(span, SNGISDN_TRACE_DISABLE);
975 } else {
976 stream->write_function(stream, "-ERR invalid trace option <q921|q931> <span name>\n");
977 }
978 }
979 if (!strcasecmp(argv[0], "l1_stats")) {
980 ftdm_span_t *span;
981 if (argc < 2) {
982 stream->write_function(stream, "Usage: ftdm sangoma_isdn l1_stats <span name>\n");
983 status = FTDM_FAIL;
984 goto done;
985 }
986 status = ftdm_span_find_by_name(argv[1], &span);
987 if (FTDM_SUCCESS != status) {
988 stream->write_function(stream, "-ERR failed to find span with name %s\n", argv[1]);
989
990 status = FTDM_SUCCESS;
991 goto done;
992 }
993 sngisdn_print_phy_stats(stream, span);
994 }
995
996 if (!strcasecmp(argv[0], "show_spans")) {
997 ftdm_span_t *span = NULL;
998 if (argc == 2) {
999 status = ftdm_span_find_by_name(argv[1], &span);
1000 if (FTDM_SUCCESS != status) {
1001 stream->write_function(stream, "-ERR failed to find span with name %s\n", argv[1]);
1002
1003 status = FTDM_SUCCESS;
1004 goto done;
1005 }
1006 sngisdn_print_span(stream, span);
1007 status = FTDM_SUCCESS;
1008 goto done;
1009 }
1010 sngisdn_print_spans(stream);
1011 }
1012 if (!strcasecmp(argv[0], "check_ids")) {
1013 sngisdn_check_free_ids();
1014 }
1015 done:
1016 ftdm_safe_free(mycmd);
1017 return status;
1018 }
1019
1020 static FIO_IO_LOAD_FUNCTION(ftdm_sangoma_isdn_io_init)
1021 {
1022 memset(&g_sngisdn_io_interface, 0, sizeof(g_sngisdn_io_interface));
1023
1024 g_sngisdn_io_interface.name = "sangoma_isdn";
1025 g_sngisdn_io_interface.api = ftdm_sangoma_isdn_api;
1026
1027 *fio = &g_sngisdn_io_interface;
1028
1029 return FTDM_SUCCESS;
1030 }
1031
1032 ftdm_module_t ftdm_module =
1033 {
1034 "sangoma_isdn",
1035 ftdm_sangoma_isdn_io_init,
1036 NULL,
1037 ftdm_sangoma_isdn_init,
1038 NULL,
1039 ftdm_sangoma_isdn_unload,
1040 ftdm_sangoma_isdn_span_config
1041 };
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057