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 ret_status = ftdm_interrupt_multiple_wait(ftdm_sangoma_isdn_int, 2, sleep);
270
271 ftdm_sched_run(signal_data->sched);
272 switch (ret_status) {
273 case FTDM_SUCCESS:
274
275 while ((ftdmchan = ftdm_queue_dequeue(span->pendingchans))) {
276
277 ftdm_channel_lock(ftdmchan);
278 ftdm_sangoma_isdn_advance_chan_states(ftdmchan);
279 ftdm_channel_unlock(ftdmchan);
280 }
281
282 while ((sngisdn_event = ftdm_queue_dequeue(signal_data->event_queue))) {
283 ftdm_sangoma_isdn_process_stack_event(span, sngisdn_event);
284 ftdm_safe_free(sngisdn_event);
285 }
286 ftdm_span_trigger_signals(span);
287 break;
288 case FTDM_TIMEOUT:
289
290 break;
291 case FTDM_FAIL:
292 ftdm_log(FTDM_LOG_ERROR,"ftdm_interrupt_wait returned error!\non span = %s\n", span->name);
293 break;
294
295 default:
296 ftdm_log(FTDM_LOG_ERROR,"ftdm_interrupt_wait returned with unknown code on span = %s\n", span->name);
297 break;
298 }
299 if (ftdm_sched_get_time_to_next_timer(signal_data->sched, &sleep) == FTDM_SUCCESS) {
300 if (sleep < 0 || sleep > SNGISDN_EVENT_POLL_RATE) {
301 sleep = SNGISDN_EVENT_POLL_RATE;
302 }
303 }
304 }
305
306
307 ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD);
308
309 ftdm_log(FTDM_LOG_INFO, "ftmod_sangoma_isdn monitor thread for span %s stopping.\n", span->name);
310
311 return NULL;
312
313 ftdm_sangoma_isdn_run_exit:
314
315
316 ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD);
317
318 ftdm_log(FTDM_LOG_INFO, "ftmod_sangoma_isdn monitor thread for span %s stopping due to error.\n", span->name);
319
320 return NULL;
321 }
322
323
324
325
326
327
328
329
330
331 ftdm_channel_t* ftdm_sangoma_isdn_process_event_states(ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event)
332 {
333 ftdm_channel_t *ftdmchan = NULL;
334 switch (sngisdn_event->event_id) {
335
336 case SNGISDN_EVENT_SRV_IND:
337 case SNGISDN_EVENT_SRV_CFM:
338 case SNGISDN_EVENT_RST_CFM:
339 case SNGISDN_EVENT_RST_IND:
340 return NULL;
341 break;
342 case SNGISDN_EVENT_CON_IND:
343 case SNGISDN_EVENT_CON_CFM:
344 case SNGISDN_EVENT_CNST_IND:
345 case SNGISDN_EVENT_DISC_IND:
346 case SNGISDN_EVENT_REL_IND:
347 case SNGISDN_EVENT_DAT_IND:
348 case SNGISDN_EVENT_SSHL_IND:
349 case SNGISDN_EVENT_SSHL_CFM:
350 case SNGISDN_EVENT_RMRT_IND:
351 case SNGISDN_EVENT_RMRT_CFM:
352 case SNGISDN_EVENT_FLC_IND:
353 case SNGISDN_EVENT_FAC_IND:
354 case SNGISDN_EVENT_STA_CFM:
355 ftdmchan = sngisdn_event->sngisdn_info->ftdmchan;
356 ftdm_assert_return(ftdmchan, NULL,"Event should have a channel associated\n");
357 break;
358 }
359 ftdm_channel_lock(ftdmchan);
360 ftdm_sangoma_isdn_advance_chan_states(ftdmchan);
361 return ftdmchan;
362 }
363
364
365
366 static void ftdm_sangoma_isdn_process_stack_event (ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event)
367 {
368 ftdm_channel_t *ftdmchan = NULL;
369
370 ftdmchan = ftdm_sangoma_isdn_process_event_states(span, sngisdn_event);
371 switch(sngisdn_event->event_id) {
372 case SNGISDN_EVENT_CON_IND:
373 sngisdn_process_con_ind(sngisdn_event);
374 break;
375 case SNGISDN_EVENT_CON_CFM:
376 sngisdn_process_con_cfm(sngisdn_event);
377 break;
378 case SNGISDN_EVENT_CNST_IND:
379 sngisdn_process_cnst_ind(sngisdn_event);
380 break;
381 case SNGISDN_EVENT_DISC_IND:
382 sngisdn_process_disc_ind(sngisdn_event);
383 break;
384 case SNGISDN_EVENT_REL_IND:
385 sngisdn_process_rel_ind(sngisdn_event);
386 break;
387 case SNGISDN_EVENT_DAT_IND:
388 sngisdn_process_dat_ind(sngisdn_event);
389 break;
390 case SNGISDN_EVENT_SSHL_IND:
391 sngisdn_process_sshl_ind(sngisdn_event);
392 break;
393 case SNGISDN_EVENT_SSHL_CFM:
394 sngisdn_process_sshl_cfm(sngisdn_event);
395 break;
396 case SNGISDN_EVENT_RMRT_IND:
397 sngisdn_process_rmrt_ind(sngisdn_event);
398 break;
399 case SNGISDN_EVENT_RMRT_CFM:
400 sngisdn_process_rmrt_cfm(sngisdn_event);
401 break;
402 case SNGISDN_EVENT_FLC_IND:
403 sngisdn_process_flc_ind(sngisdn_event);
404 break;
405 case SNGISDN_EVENT_FAC_IND:
406 sngisdn_process_fac_ind(sngisdn_event);
407 break;
408 case SNGISDN_EVENT_STA_CFM:
409 sngisdn_process_sta_cfm(sngisdn_event);
410 break;
411 case SNGISDN_EVENT_SRV_IND:
412 sngisdn_process_srv_ind(sngisdn_event);
413 break;
414 case SNGISDN_EVENT_SRV_CFM:
415 sngisdn_process_srv_cfm(sngisdn_event);
416 break;
417 case SNGISDN_EVENT_RST_CFM:
418 sngisdn_process_rst_cfm(sngisdn_event);
419 break;
420 case SNGISDN_EVENT_RST_IND:
421 sngisdn_process_rst_ind(sngisdn_event);
422 break;
423 }
424 if(ftdmchan != NULL) {
425 ftdm_sangoma_isdn_advance_chan_states(ftdmchan);
426 ftdm_channel_unlock(ftdmchan);
427 }
428 }
429
430 static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
431 {
432 ftdm_sigmsg_t sigev;
433 ftdm_channel_state_t initial_state;
434 sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data;
435
436 memset(&sigev, 0, sizeof(sigev));
437
438 sigev.chan_id = ftdmchan->chan_id;
439 sigev.span_id = ftdmchan->span_id;
440 sigev.channel = ftdmchan;
441
442
443 ftdm_channel_lock(ftdmchan);
444
445 ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE);
446 #ifdef FTDM_DEBUG_CHAN_MEMORY
447 if (ftdmchan->state == FTDM_CHANNEL_STATE_DIALING) {
448 ftdm_assert(mprotect(ftdmchan, sizeof(*ftdmchan), PROT_READ)==0, "Failed to mprotect");
449 }
450 #endif
451
452
453 initial_state = ftdmchan->state;
454
455 ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "processing state change to %s\n", ftdm_channel_state2str(ftdmchan->state));
456
457 switch (ftdmchan->state) {
458 case FTDM_CHANNEL_STATE_COLLECT:
459 {
460
461 sngisdn_snd_setup_ack(ftdmchan);
462
463 }
464 break;
465 case FTDM_CHANNEL_STATE_GET_CALLERID:
466 {
467 sngisdn_set_flag(sngisdn_info, FLAG_SENT_PROCEED);
468 sngisdn_snd_proceed(ftdmchan);
469
470 }
471 break;
472 case FTDM_CHANNEL_STATE_RING:
473 {
474 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);
475
476
477 sigev.event_id = FTDM_SIGEVENT_START;
478 ftdm_span_send_signal(ftdmchan->span, &sigev);
479 }
480 break;
481 case FTDM_CHANNEL_STATE_DIALING:
482 {
483 sngisdn_snd_setup(ftdmchan);
484 }
485 break;
486 case FTDM_CHANNEL_STATE_PROGRESS:
487 {
488
489 if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
490
491 sigev.event_id = FTDM_SIGEVENT_PROGRESS;
492 ftdm_span_send_signal(ftdmchan->span, &sigev);
493 } else if (!sngisdn_test_flag(sngisdn_info, FLAG_SENT_PROCEED)) {
494 sngisdn_set_flag(sngisdn_info, FLAG_SENT_PROCEED);
495 sngisdn_snd_proceed(ftdmchan);
496 }
497 }
498 break;
499 case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
500 {
501 if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
502 sigev.event_id = FTDM_SIGEVENT_PROGRESS_MEDIA;
503 ftdm_span_send_signal(ftdmchan->span, &sigev);
504 } else {
505 sngisdn_snd_progress(ftdmchan);
506 }
507 }
508 break;
509 case FTDM_CHANNEL_STATE_UP:
510 {
511
512 if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
513
514 sigev.event_id = FTDM_SIGEVENT_UP;
515 ftdm_span_send_signal(ftdmchan->span, &sigev);
516
517 if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP &&
518 ((sngisdn_span_data_t*)ftdmchan->span->signal_data)->signalling == SNGISDN_SIGNALING_NET) {
519
520 sngisdn_snd_con_complete(ftdmchan);
521 }
522 } else {
523
524 sngisdn_snd_connect(ftdmchan);
525 }
526 }
527 break;
528 case FTDM_CHANNEL_STATE_CANCEL:
529 {
530 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Hanging up call before informing user!\n");
531
532
533 sngisdn_snd_release(ftdmchan, 0);
534
535 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
536 }
537 break;
538 case FTDM_CHANNEL_STATE_TERMINATING:
539 {
540
541 sigev.event_id = FTDM_SIGEVENT_STOP;
542 ftdm_span_send_signal(ftdmchan->span, &sigev);
543 }
544 break;
545 case FTDM_CHANNEL_STATE_HANGUP:
546 {
547 if (sngisdn_test_flag(sngisdn_info, FLAG_REMOTE_ABORT)) {
548 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Acknowledging remote abort\n");
549 } else if (sngisdn_test_flag(sngisdn_info, FLAG_REMOTE_REL)) {
550 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Acknowledging remote hangup\n");
551 sngisdn_snd_release(ftdmchan, 0);
552 } else if (sngisdn_test_flag(sngisdn_info, FLAG_LOCAL_ABORT)) {
553
554 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Clearing local states from local abort\n");
555 } else if (sngisdn_test_flag(sngisdn_info, FLAG_GLARE)) {
556
557
558 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Waiting for RELEASE on hungup glared call\n");
559 } else if (sngisdn_test_flag(sngisdn_info, FLAG_SEND_DISC)) {
560
561 sngisdn_snd_disconnect(ftdmchan);
562 } else {
563 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Hanging up call upon local request!\n");
564
565
566 sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_REL);
567
568
569 if (ftdmchan->last_state == FTDM_CHANNEL_STATE_RING ||
570 ftdmchan->last_state == FTDM_CHANNEL_STATE_DIALING) {
571
572 sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
573 sngisdn_snd_release(ftdmchan, 0);
574
575 if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) {
576 sng_isdn_set_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN);
577 }
578 } else {
579 sngisdn_snd_disconnect(ftdmchan);
580 }
581 }
582
583
584 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
585 }
586 break;
587 case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
588 {
589 if (sngisdn_test_flag(sngisdn_info, FLAG_REMOTE_ABORT) ||
590 sngisdn_test_flag(sngisdn_info, FLAG_LOCAL_ABORT)) {
591
592 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
593 } else {
594
595 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Waiting for release from stack\n");
596 }
597 }
598 break;
599 case FTDM_CHANNEL_STATE_DOWN:
600 {
601 uint8_t glare = 0;
602
603 glare = sngisdn_test_flag(sngisdn_info, FLAG_GLARE);
604
605 clear_call_data(sngisdn_info);
606
607
608
609 if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) {
610 ftdm_channel_t *close_chan = ftdmchan;
611
612 ftdm_channel_close(&close_chan);
613 }
614 if (glare) {
615
616 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Glare detected, processing saved call\n");
617
618
619
620
621 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);
622 }
623 }
624 break;
625 case FTDM_CHANNEL_STATE_RESTART:
626 {
627
628 }
629
630 break;
631 case FTDM_CHANNEL_STATE_SUSPENDED:
632 {
633
634 }
635 break;
636 default:
637 {
638 ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "unsupported sngisdn_rcvd state %s\n", ftdm_channel_state2str(ftdmchan->state));
639 }
640 break;
641 }
642
643 if (ftdmchan->state == initial_state) {
644 ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "state change flag is still set, but we did not change state\n");
645 }
646 #ifdef FTDM_DEBUG_CHAN_MEMORY
647 if (ftdmchan->state == FTDM_CHANNEL_STATE_DIALING) {
648 ftdm_assert(mprotect(ftdmchan, sizeof(*ftdmchan), PROT_READ|PROT_WRITE)==0, "Failed to mprotect");
649 }
650 #endif
651 ftdm_channel_unlock(ftdmchan);
652 return;
653 }
654
655 static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(ftdm_sangoma_isdn_outgoing_call)
656 {
657 sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data;
658 ftdm_status_t status = FTDM_FAIL;
659
660
661 ftdm_channel_lock(ftdmchan);
662
663 switch (ftdmchan->state) {
664
665 case FTDM_CHANNEL_STATE_DOWN:
666 {
667 if (sngisdn_test_flag(sngisdn_info, FLAG_GLARE)) {
668
669 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Glare detected - aborting outgoing call\n");
670
671 sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
672 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
673
674 status = FTDM_BREAK;
675 } else {
676 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DIALING);
677 status = FTDM_SUCCESS;
678 }
679 }
680 break;
681 default:
682 {
683
684 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Outgoing call requested channel in already in use\n");
685 status = FTDM_BREAK;
686 }
687 break;
688 }
689
690 ftdm_channel_unlock(ftdmchan);
691 return status;
692 }
693
694 static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(ftdm_sangoma_isdn_get_chan_sig_status)
695 {
696 if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) {
697 *status = FTDM_SIG_STATE_UP;
698 } else {
699 *status = FTDM_SIG_STATE_DOWN;
700 }
701
702 return FTDM_SUCCESS;
703 }
704
705 static FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(ftdm_sangoma_isdn_set_chan_sig_status)
706 {
707 ftdm_log(FTDM_LOG_ERROR,"Cannot set channel status in this module\n");
708 return FTDM_NOTIMPL;
709 }
710
711 static FIO_SPAN_GET_SIG_STATUS_FUNCTION(ftdm_sangoma_isdn_get_span_sig_status)
712 {
713 if (ftdm_test_flag(span->channels[1], FTDM_CHANNEL_SIG_UP)) {
714 *status = FTDM_SIG_STATE_UP;
715 } else {
716 *status = FTDM_SIG_STATE_DOWN;
717 }
718
719 return FTDM_SUCCESS;
720 }
721
722 static FIO_SPAN_SET_SIG_STATUS_FUNCTION(ftdm_sangoma_isdn_set_span_sig_status)
723 {
724 ftdm_log(FTDM_LOG_ERROR,"Cannot set span status in this module\n");
725 return FTDM_NOTIMPL;
726 }
727
728 static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span)
729 {
730 ftdm_log(FTDM_LOG_INFO,"Starting span %s:%u.\n",span->name,span->span_id);
731 if (sng_isdn_stack_start(span) != FTDM_SUCCESS) {
732 ftdm_log(FTDM_LOG_CRIT, "Failed to start span %s\n", span->name);
733 return FTDM_FAIL;
734 }
735
736 ftdm_clear_flag(span, FTDM_SPAN_STOP_THREAD);
737 ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD);
738
739
740 if (ftdm_thread_create_detached(ftdm_sangoma_isdn_run, span) != FTDM_SUCCESS) {
741 ftdm_log(FTDM_LOG_CRIT,"Failed to start Sangoma ISDN Span Monitor Thread!\n");
742 return FTDM_FAIL;
743 }
744
745 ftdm_log(FTDM_LOG_DEBUG,"Finished starting span %s\n", span->name);
746 return FTDM_SUCCESS;
747 }
748
749 static ftdm_status_t ftdm_sangoma_isdn_stop(ftdm_span_t *span)
750 {
751 ftdm_iterator_t *chaniter = NULL;
752 ftdm_iterator_t *curr = NULL;
753 ftdm_log(FTDM_LOG_INFO, "Stopping span %s\n", span->name);
754
755
756 ftdm_set_flag(span, FTDM_SPAN_STOP_THREAD);
757
758
759 while (ftdm_test_flag(span, FTDM_SPAN_IN_THREAD)) {
760 ftdm_log(FTDM_LOG_DEBUG, "Waiting for monitor thread to end for span %s\n", span->name);
761 ftdm_sleep(10);
762 }
763
764 if (sng_isdn_stack_stop(span) != FTDM_SUCCESS) {
765 ftdm_log(FTDM_LOG_CRIT, "Failed to stop span %s\n", span->name);
766 }
767
768 chaniter = ftdm_span_get_chan_iterator(span, NULL);
769 for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
770 ftdm_safe_free(((ftdm_channel_t*)ftdm_iterator_current(curr))->call_data);
771 ((ftdm_channel_t*)ftdm_iterator_current(curr))->call_data = NULL;
772 }
773 ftdm_iterator_free(chaniter);
774
775 ftdm_sched_destroy(&((sngisdn_span_data_t*)span->signal_data)->sched);
776 ftdm_queue_destroy(&((sngisdn_span_data_t*)span->signal_data)->event_queue);
777 ftdm_safe_free(span->signal_data);
778
779 ftdm_log(FTDM_LOG_DEBUG, "Finished stopping span %s\n", span->name);
780
781 return FTDM_SUCCESS;
782 }
783
784 static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config)
785 {
786 ftdm_iterator_t *chaniter = NULL;
787 ftdm_iterator_t *curr = NULL;
788
789 sngisdn_span_data_t *span_data;
790
791 ftdm_log(FTDM_LOG_INFO, "Configuring ftmod_sangoma_isdn span = %s\n", span->name);
792
793 span_data = ftdm_calloc(1, sizeof(sngisdn_span_data_t));
794 span_data->ftdm_span = span;
795 span->signal_data = span_data;
796
797 chaniter = ftdm_span_get_chan_iterator(span, NULL);
798 for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
799 sngisdn_chan_data_t *chan_data = ftdm_calloc(1, sizeof(sngisdn_chan_data_t));
800 chan_data->ftdmchan = ((ftdm_channel_t*)ftdm_iterator_current(curr));
801 ((ftdm_channel_t*)ftdm_iterator_current(curr))->call_data = chan_data;
802
803 }
804 ftdm_iterator_free(chaniter);
805
806 if (ftmod_isdn_parse_cfg(ftdm_parameters, span) != FTDM_SUCCESS) {
807 ftdm_log(FTDM_LOG_ERROR, "Failed to parse configuration\n");
808 return FTDM_FAIL;
809 }
810
811 if (sng_isdn_stack_cfg(span) != FTDM_SUCCESS) {
812 ftdm_log(FTDM_LOG_CRIT, "Sangoma ISDN Stack configuration failed\n");
813 return FTDM_FAIL;
814 }
815
816
817 span->start = ftdm_sangoma_isdn_start;
818 span->stop = ftdm_sangoma_isdn_stop;
819 span->signal_type = FTDM_SIGTYPE_ISDN;
820 span->outgoing_call = ftdm_sangoma_isdn_outgoing_call;
821 span->channel_request = NULL;
822 span->signal_cb = sig_cb;
823 span->get_channel_sig_status = ftdm_sangoma_isdn_get_chan_sig_status;
824 span->set_channel_sig_status = ftdm_sangoma_isdn_set_chan_sig_status;
825 span->get_span_sig_status = ftdm_sangoma_isdn_get_span_sig_status;
826 span->set_span_sig_status = ftdm_sangoma_isdn_set_span_sig_status;
827 span->state_map = &sangoma_isdn_state_map;
828 ftdm_set_flag(span, FTDM_SPAN_USE_CHAN_QUEUE);
829 ftdm_set_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE);
830
831 if (span->trunk_type == FTDM_TRUNK_BRI_PTMP ||
832 span->trunk_type == FTDM_TRUNK_BRI) {
833
834 ftdm_set_flag(span, FTDM_SPAN_USE_AV_RATE);
835 sng_isdn_set_avail_rate(span, SNGISDN_AVAIL_PWR_SAVING);
836 }
837
838
839 ftdm_assert(ftdm_sched_create(&((sngisdn_span_data_t*)span->signal_data)->sched, "sngisdn_schedule") == FTDM_SUCCESS, "Failed to create a new schedule!!");
840
841
842 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!!");
843
844 ftdm_log(FTDM_LOG_INFO, "Finished configuring ftmod_sangoma_isdn span = %s\n", span->name);
845 return FTDM_SUCCESS;
846 }
847
848 static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_isdn_init)
849 {
850 unsigned i;
851 ftdm_log(FTDM_LOG_INFO, "Loading ftmod_sangoma_isdn...\n");
852
853 memset(&g_sngisdn_data, 0, sizeof(g_sngisdn_data));
854
855
856 g_sngisdn_event_interface.cc.sng_con_ind = sngisdn_rcv_con_ind;
857 g_sngisdn_event_interface.cc.sng_con_cfm = sngisdn_rcv_con_cfm;
858 g_sngisdn_event_interface.cc.sng_cnst_ind = sngisdn_rcv_cnst_ind;
859 g_sngisdn_event_interface.cc.sng_disc_ind = sngisdn_rcv_disc_ind;
860 g_sngisdn_event_interface.cc.sng_rel_ind = sngisdn_rcv_rel_ind;
861 g_sngisdn_event_interface.cc.sng_dat_ind = sngisdn_rcv_dat_ind;
862 g_sngisdn_event_interface.cc.sng_sshl_ind = sngisdn_rcv_sshl_ind;
863 g_sngisdn_event_interface.cc.sng_sshl_cfm = sngisdn_rcv_sshl_cfm;
864 g_sngisdn_event_interface.cc.sng_rmrt_ind = sngisdn_rcv_rmrt_ind;
865 g_sngisdn_event_interface.cc.sng_rmrt_cfm = sngisdn_rcv_rmrt_cfm;
866 g_sngisdn_event_interface.cc.sng_flc_ind = sngisdn_rcv_flc_ind;
867 g_sngisdn_event_interface.cc.sng_fac_ind = sngisdn_rcv_fac_ind;
868 g_sngisdn_event_interface.cc.sng_sta_cfm = sngisdn_rcv_sta_cfm;
869 g_sngisdn_event_interface.cc.sng_srv_ind = sngisdn_rcv_srv_ind;
870 g_sngisdn_event_interface.cc.sng_srv_ind = sngisdn_rcv_srv_cfm;
871 g_sngisdn_event_interface.cc.sng_rst_ind = sngisdn_rcv_rst_cfm;
872 g_sngisdn_event_interface.cc.sng_rst_ind = sngisdn_rcv_rst_ind;
873 g_sngisdn_event_interface.cc.sng_rst_cfm = sngisdn_rcv_rst_cfm;
874
875 g_sngisdn_event_interface.lg.sng_log = sngisdn_rcv_sng_log;
876 g_sngisdn_event_interface.lg.sng_assert = sngisdn_rcv_sng_assert;
877
878 g_sngisdn_event_interface.sta.sng_phy_sta_ind = sngisdn_rcv_phy_ind;
879 g_sngisdn_event_interface.sta.sng_q921_sta_ind = sngisdn_rcv_q921_ind;
880 g_sngisdn_event_interface.sta.sng_q921_trc_ind = sngisdn_rcv_q921_trace;
881 g_sngisdn_event_interface.sta.sng_q931_sta_ind = sngisdn_rcv_q931_ind;
882 g_sngisdn_event_interface.sta.sng_q931_trc_ind = sngisdn_rcv_q931_trace;
883 g_sngisdn_event_interface.sta.sng_cc_sta_ind = sngisdn_rcv_cc_ind;
884
885 for(i=1;i<=MAX_VARIANTS;i++) {
886 ftdm_mutex_create(&g_sngisdn_data.ccs[i].mutex);
887 }
888
889
890 sng_isdn_init(&g_sngisdn_event_interface);
891 return FTDM_SUCCESS;
892 }
893
894 static FIO_SIG_UNLOAD_FUNCTION(ftdm_sangoma_isdn_unload)
895 {
896 unsigned i;
897 ftdm_log(FTDM_LOG_INFO, "Starting ftmod_sangoma_isdn unload...\n");
898
899 sng_isdn_free();
900
901 for(i=1;i<=MAX_VARIANTS;i++) {
902 ftdm_mutex_destroy(&g_sngisdn_data.ccs[i].mutex);
903 }
904
905 ftdm_log(FTDM_LOG_INFO, "Finished ftmod_sangoma_isdn unload!\n");
906 return FTDM_SUCCESS;
907 }
908
909 static FIO_API_FUNCTION(ftdm_sangoma_isdn_api)
910 {
911 ftdm_status_t status = FTDM_SUCCESS;
912 char *mycmd = NULL, *argv[10] = { 0 };
913 int argc = 0;
914
915 if (data) {
916 mycmd = ftdm_strdup(data);
917 argc = ftdm_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
918 }
919
920
921 if (argc <= 0) {
922 ftdm_log(FTDM_LOG_ERROR, "No parameters provided\n");
923 goto done;
924 }
925
926 if (!strcasecmp(argv[0], "trace")) {
927 char *trace_opt;
928
929 ftdm_span_t *span;
930
931 if (argc < 3) {
932 ftdm_log(FTDM_LOG_ERROR, "Usage: ftdm sangoma_isdn trace <q921|q931> <span name>\n");
933 status = FTDM_FAIL;
934 goto done;
935 }
936 trace_opt = argv[1];
937
938 status = ftdm_span_find_by_name(argv[2], &span);
939 if (FTDM_SUCCESS != status) {
940 stream->write_function(stream, "-ERR failed to find span by name %s\n", argv[2]);
941 goto done;
942 }
943 if (!strcasecmp(trace_opt, "q921")) {
944 sng_isdn_activate_trace(span, SNGISDN_TRACE_Q921);
945 } else if (!strcasecmp(trace_opt, "q931")) {
946 sng_isdn_activate_trace(span, SNGISDN_TRACE_Q931);
947 } else if (!strcasecmp(trace_opt, "disable")) {
948 sng_isdn_activate_trace(span, SNGISDN_TRACE_DISABLE);
949 } else {
950 stream->write_function(stream, "-ERR invalid trace option <q921|q931> <span name>\n");
951 }
952 }
953 if (!strcasecmp(argv[0], "l1_stats")) {
954 ftdm_span_t *span;
955 if (argc < 2) {
956 stream->write_function(stream, "Usage: ftdm sangoma_isdn l1_stats <span name>\n");
957 status = FTDM_FAIL;
958 goto done;
959 }
960 status = ftdm_span_find_by_name(argv[1], &span);
961 if (FTDM_SUCCESS != status) {
962 stream->write_function(stream, "-ERR failed to find span with name %s\n", argv[1]);
963
964 status = FTDM_SUCCESS;
965 goto done;
966 }
967 sngisdn_print_phy_stats(stream, span);
968 }
969
970 if (!strcasecmp(argv[0], "show_spans")) {
971 ftdm_span_t *span = NULL;
972 if (argc == 2) {
973 status = ftdm_span_find_by_name(argv[1], &span);
974 if (FTDM_SUCCESS != status) {
975 stream->write_function(stream, "-ERR failed to find span with name %s\n", argv[1]);
976
977 status = FTDM_SUCCESS;
978 goto done;
979 }
980 sngisdn_print_span(stream, span);
981 status = FTDM_SUCCESS;
982 goto done;
983 }
984 sngisdn_print_spans(stream);
985 }
986 if (!strcasecmp(argv[0], "check_ids")) {
987 sngisdn_check_free_ids();
988 }
989 done:
990 ftdm_safe_free(mycmd);
991 return status;
992 }
993
994 static FIO_IO_LOAD_FUNCTION(ftdm_sangoma_isdn_io_init)
995 {
996 memset(&g_sngisdn_io_interface, 0, sizeof(g_sngisdn_io_interface));
997
998 g_sngisdn_io_interface.name = "sangoma_isdn";
999 g_sngisdn_io_interface.api = ftdm_sangoma_isdn_api;
1000
1001 *fio = &g_sngisdn_io_interface;
1002
1003 return FTDM_SUCCESS;
1004 }
1005
1006 ftdm_module_t ftdm_module =
1007 {
1008 "sangoma_isdn",
1009 ftdm_sangoma_isdn_io_init,
1010 NULL,
1011 ftdm_sangoma_isdn_init,
1012 NULL,
1013 ftdm_sangoma_isdn_unload,
1014 ftdm_sangoma_isdn_span_config
1015 };
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031