This source file includes following definitions.
- interrupt_requested
- schedule_timer
- run_timers
- release_timers
- send_hangup
- send_answer
- send_progress
- FIO_SIGNAL_CB_FUNCTION
- place_call
- main
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
38
39
40
41 #ifndef __linux__
42 #define _CRT_SECURE_NO_WARNINGS 1
43 #endif
44
45 #include <signal.h>
46
47 #include "freetdm.h"
48 #include <stdlib.h>
49 #include <string.h>
50 #include <errno.h>
51
52
53
54 #define MAX_CALLS 255
55
56
57 #define PROGRESS_TIMER 1
58 #define ANSWER_TIMER 5
59 #define HANGUP_TIMER 15
60
61
62 static int app_running = 0;
63
64 typedef void (*expired_function_t)(ftdm_channel_t *channel);
65 typedef struct dummy_timer_s {
66 int time;
67 ftdm_channel_t *channel;
68 expired_function_t expired;
69 } dummy_timer_t;
70
71
72 static dummy_timer_t g_timers[MAX_CALLS];
73
74
75 static ftdm_mutex_t *g_schedule_mutex;
76
77
78 static ftdm_channel_t *g_outgoing_channel = NULL;
79
80 static void interrupt_requested(int signal)
81 {
82 app_running = 0;
83 }
84
85 static void schedule_timer(ftdm_channel_t *channel, int sec, expired_function_t expired)
86 {
87 int i;
88 ftdm_mutex_lock(g_schedule_mutex);
89 for (i = 0; i < sizeof(g_timers)/sizeof(g_timers[0]); i++) {
90
91 if (!g_timers[i].time) {
92 g_timers[i].time = sec;
93 g_timers[i].channel = channel;
94 g_timers[i].expired = expired;
95 ftdm_mutex_unlock(g_schedule_mutex);
96 return;
97 }
98 }
99 ftdm_log(FTDM_LOG_ERROR, "Failed to schedule timer\n");
100 ftdm_mutex_unlock(g_schedule_mutex);
101 }
102
103 static void run_timers(void)
104 {
105 int i;
106 void *channel;
107 expired_function_t expired_func = NULL;
108 ftdm_mutex_lock(g_schedule_mutex);
109 for (i = 0; i < sizeof(g_timers)/sizeof(g_timers[0]); i++) {
110
111 if (g_timers[i].time) {
112 g_timers[i].time--;
113 }
114
115
116 if (!g_timers[i].time && g_timers[i].expired) {
117 expired_func = g_timers[i].expired;
118 channel = g_timers[i].channel;
119 memset(&g_timers[i], 0, sizeof(g_timers[i]));
120 expired_func(channel);
121 }
122 }
123 ftdm_mutex_unlock(g_schedule_mutex);
124 }
125
126 static void release_timers(ftdm_channel_t *channel)
127 {
128 int i;
129 ftdm_mutex_lock(g_schedule_mutex);
130 for (i = 0; i < sizeof(g_timers)/sizeof(g_timers[0]); i++) {
131
132 if (g_timers[i].channel == channel) {
133 memset(&g_timers[i], 0, sizeof(g_timers[i]));
134 }
135 }
136 ftdm_mutex_unlock(g_schedule_mutex);
137 }
138
139
140 static void send_hangup(ftdm_channel_t *channel)
141 {
142 int spanid = ftdm_channel_get_span_id(channel);
143 int chanid = ftdm_channel_get_id(channel);
144 ftdm_log(FTDM_LOG_NOTICE, "-- Requesting hangup in channel %d:%d\n", spanid, chanid);
145 ftdm_channel_call_hangup(channel);
146 }
147
148
149 static void send_answer(ftdm_channel_t *channel)
150 {
151
152 int spanid = ftdm_channel_get_span_id(channel);
153 int chanid = ftdm_channel_get_id(channel);
154 ftdm_log(FTDM_LOG_NOTICE, "-- Requesting answer in channel %d:%d\n", spanid, chanid);
155 ftdm_channel_call_answer(channel);
156 schedule_timer(channel, HANGUP_TIMER, send_hangup);
157 }
158
159
160 static void send_progress(ftdm_channel_t *channel)
161 {
162
163 int spanid = ftdm_channel_get_span_id(channel);
164 int chanid = ftdm_channel_get_id(channel);
165 ftdm_log(FTDM_LOG_NOTICE, "-- Requesting progress\n", spanid, chanid);
166 ftdm_channel_call_indicate(channel, FTDM_CHANNEL_INDICATE_PROGRESS);
167 schedule_timer(channel, ANSWER_TIMER, send_answer);
168 }
169
170
171
172
173
174
175
176
177
178 static FIO_SIGNAL_CB_FUNCTION(on_signaling_event)
179 {
180 switch (sigmsg->event_id) {
181
182 case FTDM_SIGEVENT_START:
183 ftdm_log(FTDM_LOG_NOTICE, "Incoming call received in channel %d:%d\n", sigmsg->span_id, sigmsg->chan_id);
184 schedule_timer(sigmsg->channel, PROGRESS_TIMER, send_progress);
185 break;
186
187 case FTDM_SIGEVENT_PROGRESS_MEDIA:
188 ftdm_log(FTDM_LOG_NOTICE, "Progress message received in channel %d:%d\n", sigmsg->span_id, sigmsg->chan_id);
189 break;
190
191 case FTDM_SIGEVENT_UP:
192 ftdm_log(FTDM_LOG_NOTICE, "Answer received in channel %d:%d\n", sigmsg->span_id, sigmsg->chan_id);
193
194
195
196
197 break;
198
199 case FTDM_SIGEVENT_STOP:
200 ftdm_log(FTDM_LOG_NOTICE, "Hangup received in channel %d:%d\n", sigmsg->span_id, sigmsg->chan_id);
201 if (g_outgoing_channel == sigmsg->channel) {
202 g_outgoing_channel = NULL;
203 }
204
205 release_timers(sigmsg->channel);
206
207 ftdm_channel_call_hangup(sigmsg->channel);
208 break;
209 default:
210 ftdm_log(FTDM_LOG_WARNING, "Unhandled event %s in channel %d:%d\n", ftdm_signal_event2str(sigmsg->event_id),
211 sigmsg->span_id, sigmsg->chan_id);
212 break;
213 }
214 return FTDM_SUCCESS;
215 }
216
217 static void place_call(const ftdm_span_t *span, const char *number)
218 {
219 ftdm_channel_t *ftdmchan = NULL;
220 ftdm_caller_data_t caller_data = {{ 0 }};
221 ftdm_status_t status = FTDM_FAIL;
222
223
224 ftdm_set_string(caller_data.dnis.digits, number);
225
226
227 ftdm_set_string(caller_data.cid_name, "testsangomaboost");
228 ftdm_set_string(caller_data.cid_num.digits, "1234");
229
230
231
232
233
234 status = ftdm_channel_open_by_span(ftdm_span_get_id(span), FTDM_TOP_DOWN, &caller_data, &ftdmchan);
235 if (status != FTDM_SUCCESS) {
236 ftdm_log(FTDM_LOG_ERROR, "Failed to originate call\n");
237 return;
238 }
239
240 g_outgoing_channel = ftdmchan;
241
242
243 ftdm_channel_set_caller_data(ftdmchan, &caller_data);
244
245 status = ftdm_channel_call_place(ftdmchan);
246 if (status != FTDM_SUCCESS) {
247 ftdm_log(FTDM_LOG_ERROR, "Failed to originate call\n");
248 return;
249 }
250
251
252 ftdm_channel_init(ftdmchan);
253 }
254
255 #define ARRLEN(arr) (sizeof(arr)/sizeof(arr[0]))
256 int main(int argc, char *argv[])
257 {
258
259 int span_numbers[32];
260 char span_names[ARRLEN(span_numbers)][ARRLEN(span_numbers)];
261 const char *spanname = NULL;
262 char wpchans[25];
263 unsigned configured = 0;
264 int i, spanno;
265 int numspans = 0;
266 ftdm_status_t status;
267 ftdm_span_t *span_list[ARRLEN(span_numbers)];
268 ftdm_span_t *span;
269 ftdm_channel_config_t chan_config;
270 ftdm_conf_parameter_t parameters[20];
271 char *todial = NULL;
272 int32_t ticks = 0;
273
274
275 #ifdef _WIN64
276
277 if (signal(SIGINT, interrupt_requested) < 0) {
278 #else
279 if (signal(SIGINT, interrupt_requested) == SIG_ERR) {
280 #endif
281 fprintf(stderr, "Could not set the SIGINT signal handler: %s\n", strerror(errno));
282 exit(-1);
283 }
284
285 for (i = 1; i < argc; i++) {
286 if (argv[i][0] == '-' && argv[i][1] == 'd') {
287 i++;
288 if (i >= argc) {
289 fprintf(stderr, "Error, -d specified but no number to dial!\n");
290 exit(1);
291 }
292 todial = argv[i];
293 if (!strlen(todial)) {
294 todial = NULL;
295 }
296 printf("Number to dial: %s\n", todial);
297 continue;
298 }
299 spanno = atoi(argv[i]);
300 span_numbers[numspans] = spanno;
301 snprintf(span_names[numspans], sizeof(span_names[numspans]), "wanpipe%d", spanno);
302 numspans++;
303 }
304
305 if (!numspans) {
306 fprintf(stderr, "please specify a at least 1 wanpipe port number\n");
307 exit(-1);
308 }
309
310
311 memset(&g_timers, 0, sizeof(g_timers));
312
313
314 ftdm_global_set_default_logger(FTDM_LOG_LEVEL_DEBUG);
315
316
317 if (ftdm_global_init() != FTDM_SUCCESS) {
318 fprintf(stderr, "Error loading FreeTDM\n");
319 exit(-1);
320 }
321
322
323 ftdm_mutex_create(&g_schedule_mutex);
324
325
326 memset(&chan_config, 0, sizeof(chan_config));
327 strncpy(chan_config.group_name, "mygroup", sizeof(chan_config.group_name)-1);
328 chan_config.group_name[sizeof(chan_config.group_name)-1] = 0;
329 for (i = 0; i < numspans; i++) {
330 spanname = span_names[i];
331
332 ftdm_log(FTDM_LOG_NOTICE, "Creating span %s\n", spanname);
333 status = ftdm_span_create("wanpipe", spanname, &span_list[i]);
334 if (status != FTDM_SUCCESS) {
335 ftdm_log(FTDM_LOG_CRIT, "Failed to create span %s\n", spanname);
336 goto done;
337 }
338 span = span_list[i];
339 spanno = span_numbers[i];
340
341
342 ftdm_span_set_trunk_type(span_list[i], FTDM_TRUNK_T1);
343
344
345 chan_config.type = FTDM_CHAN_TYPE_B;
346 snprintf(wpchans, sizeof(wpchans), "%d:1-23", spanno);
347 ftdm_configure_span_channels(span, wpchans, &chan_config, &configured);
348 ftdm_log(FTDM_LOG_NOTICE, "registered %d b channels\n", configured);
349 }
350
351
352
353 ftdm_log(FTDM_LOG_NOTICE, "FreeTDM loaded ...\n");
354
355
356 for (i = 0; i < numspans; i++) {
357 spanname = span_names[i];
358
359
360 if (ftdm_span_find_by_name(spanname, &span) != FTDM_SUCCESS) {
361 ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM span %s\n", ftdm_span_get_name(span));
362 goto done;
363 }
364
365
366
367
368
369
370 parameters[0].var = "sigmod";
371 parameters[0].val = "sangoma_prid";
372
373
374 parameters[1].var = "switchtype";
375 parameters[1].val = "national";
376
377 parameters[2].var = "signalling";
378 parameters[2].val = "pri_cpe";
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393 parameters[3].var = NULL;
394
395
396 if (ftdm_configure_span_signaling(span, "sangoma_boost", on_signaling_event, parameters) != FTDM_SUCCESS) {
397 ftdm_log(FTDM_LOG_ERROR, "Error configuring sangoma_boost signaling abstraction in span %s\n", ftdm_span_get_name(span));
398 goto done;
399 }
400
401 }
402
403
404
405
406
407
408
409
410 for (i = 0; i < numspans; i++) {
411 spanname = span_names[i];
412
413 if (ftdm_span_find_by_name(spanname, &span) != FTDM_SUCCESS) {
414 ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM span %s\n", ftdm_span_get_name(span));
415 goto done;
416 }
417
418 if (ftdm_span_start(span) != FTDM_SUCCESS) {
419 ftdm_log(FTDM_LOG_ERROR, "Failing starting signaling on span %s\n", ftdm_span_get_name(span));
420 goto done;
421 }
422
423 }
424
425 app_running = 1;
426
427
428 if (ftdm_span_find(1, &span) != FTDM_SUCCESS) {
429 ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM span 1\n");
430 goto done;
431 }
432
433
434 while(ftdm_running() && app_running) {
435 ftdm_sleep(1000);
436 run_timers();
437 ticks++;
438 if (!(ticks % 10) && todial && !g_outgoing_channel) {
439 ftdm_log(FTDM_LOG_NOTICE, "Originating call to number %s\n", todial);
440 place_call(span, todial);
441 }
442 }
443
444 done:
445
446 ftdm_log(FTDM_LOG_NOTICE, "Shutting down FreeTDM ...\n");
447
448 ftdm_mutex_destroy(&g_schedule_mutex);
449
450
451 ftdm_global_destroy();
452
453 printf("Terminated!\n");
454
455 sleep(2);
456
457 exit(0);
458 }
459
460
461
462
463
464
465
466
467
468
469