This source file includes following definitions.
- gettimeofday
- strsep
- ftdm_r2_set_chan_sig_status
- ftdm_r2_cause_to_ftdm_cause
- ftdm_r2_ftdm_cause_to_openr2_cause
- ft_r2_clean_call
- ft_r2_accept_call
- ft_r2_answer_call
- ftdm_openr2_cpc_to_r2_ftdm_cpc
- ftdm_r2_ftdm_cpc_to_openr2_cpc
- FIO_CHANNEL_OUTGOING_CALL_FUNCTION
- ftdm_r2_start
- ftdm_r2_stop
- 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_r2_on_call_init
- ftdm_r2_on_call_offered
- clear_accept_pending
- dump_mf
- ftdm_r2_on_call_accepted
- ftdm_r2_on_call_answered
- ftdm_r2_on_call_disconnect
- ftdm_r2_on_call_end
- ftdm_r2_on_call_read
- ftdm_r2_on_hardware_alarm
- ftdm_r2_on_os_error
- ftdm_r2_recover_from_protocol_error
- ftdm_r2_on_protocol_error
- ftdm_r2_on_line_blocked
- ftdm_r2_on_line_idle
- ftdm_r2_write_log
- ftdm_r2_on_context_log
- ftdm_r2_on_chan_log
- ftdm_r2_on_dnis_digit_received
- ftdm_r2_on_ani_digit_received
- ftdm_r2_on_billing_pulse
- ftdm_r2_on_call_log_created
- ftdm_r2_on_call_proceed
- ftdm_r2_io_set_cas
- ftdm_r2_io_get_cas
- ftdm_r2_io_flush_write_buffers
- ftdm_r2_io_write
- ftdm_r2_io_read
- ftdm_r2_io_wait
- ftdm_r2_io_open
- ftdm_r2_io_close
- ftdm_r2_io_setup
- ftdm_r2_io_get_oob_event
- ftdm_r2_loglevel_from_string
- FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION
- ftdm_r2_state_advance
- ftdm_r2_run
- block_channel
- unblock_channel
- FIO_API_FUNCTION
- FIO_IO_LOAD_FUNCTION
- FIO_SIG_LOAD_FUNCTION
- FIO_SIG_UNLOAD_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
38
39
40 #ifdef __linux__
41 #ifndef _BSD_SOURCE
42 #define _BSD_SOURCE
43 #endif
44 #include <syscall.h>
45 #include <poll.h>
46 #include <string.h>
47 #endif
48 #include <stdio.h>
49 #include <openr2.h>
50 #include "freetdm.h"
51 #include "private/ftdm_core.h"
52
53
54
55
56
57 typedef enum {
58 FTDM_R2_RUNNING = (1 << 0),
59 FTDM_R2_SPAN_STARTED = (1 << 1),
60 } ftdm_r2_flag_t;
61
62
63
64
65
66 #define R2CALL(ftdmchan) ((ftdm_r2_call_t*)((ftdmchan)->call_data))
67 typedef struct ftdm_r2_call_t {
68 openr2_chan_t *r2chan;
69 int accepted:1;
70 int answer_pending:1;
71 int disconnect_rcvd:1;
72 int protocol_error:1;
73 ftdm_size_t dnis_index;
74 ftdm_size_t ani_index;
75 char logname[255];
76 char name[10];
77 ftdm_timer_id_t protocol_error_recovery_timer;
78 } ftdm_r2_call_t;
79
80
81 typedef struct ft_r2_conf_s {
82
83 openr2_variant_t variant;
84 openr2_calling_party_category_t category;
85 openr2_log_level_t loglevel;
86
87
88 char *logdir;
89 char *advanced_protocol_file;
90
91
92 int32_t max_ani;
93 int32_t max_dnis;
94 int32_t mfback_timeout;
95 int32_t metering_pulse_timeout;
96 ftdm_size_t mf_dump_size;
97
98
99 int immediate_accept;
100 int skip_category;
101 int get_ani_first;
102 int call_files;
103 int double_answer;
104 int charge_calls;
105 int forced_release;
106 int allow_collect_calls;
107 } ft_r2_conf_t;
108
109
110 typedef struct ftdm_r2_data_s {
111
112 ftdm_r2_flag_t flags;
113
114 openr2_context_t *r2context;
115
116 openr2_calling_party_category_t category;
117
118 int charge_calls:1;
119
120 int allow_collect_calls:1;
121
122 int forced_release:1;
123
124 int accept_on_offer:1;
125
126 ftdm_size_t mf_dump_size;
127
128 int32_t jobmax;
129
130 uint64_t total_loops;
131
132 uint64_t loops[11];
133
134 uint64_t total_sleeps;
135
136 uint64_t sleeps[11];
137
138 int32_t sleepmax;
139
140 uint32_t monitor_thread_id;
141
142 char logdir[512];
143
144 ftdm_sched_t *sched;
145 } ftdm_r2_data_t;
146
147
148
149 typedef struct ftdm_r2_span_pvt_s {
150 openr2_context_t *r2context;
151 ftdm_hash_t *r2calls;
152 ftdm_sched_t *sched;
153 } ftdm_r2_span_pvt_t;
154
155
156 static void *ftdm_r2_run(ftdm_thread_t *me, void *obj);
157
158
159
160
161
162 static ftdm_hash_t *g_mod_data_hash;
163
164
165 static ftdm_io_interface_t g_ftdm_r2_interface;
166
167 static ftdm_status_t ftdm_r2_state_advance(ftdm_channel_t *ftdmchan);
168
169
170 #define IS_ACCEPTING_PENDING(ftdmchan) \
171 ( (!ftdm_test_flag((ftdmchan), FTDM_CHANNEL_OUTBOUND)) && !R2CALL((ftdmchan))->accepted && \
172 ((ftdmchan)->state == FTDM_CHANNEL_STATE_PROGRESS || \
173 (ftdmchan)->state == FTDM_CHANNEL_STATE_PROGRESS_MEDIA || \
174 (ftdmchan)->state == FTDM_CHANNEL_STATE_UP) )
175
176
177 #ifdef WIN32
178 #include <mmsystem.h>
179
180 static __inline int gettimeofday(struct timeval *tp, void *nothing)
181 {
182 #ifdef WITHOUT_MM_LIB
183 SYSTEMTIME st;
184 time_t tt;
185 struct tm tmtm;
186
187 GetLocalTime (&st);
188 tmtm.tm_sec = st.wSecond;
189 tmtm.tm_min = st.wMinute;
190 tmtm.tm_hour = st.wHour;
191 tmtm.tm_mday = st.wDay;
192 tmtm.tm_mon = st.wMonth - 1;
193 tmtm.tm_year = st.wYear - 1900; tmtm.tm_isdst = -1;
194 tt = mktime (&tmtm);
195 tp->tv_sec = tt;
196 tp->tv_usec = st.wMilliseconds * 1000;
197 #else
198
199
200
201
202
203
204 unsigned long Ticks = 0;
205 unsigned long Sec =0;
206 unsigned long Usec = 0;
207 Ticks = timeGetTime();
208
209 Sec = Ticks/1000;
210 Usec = (Ticks - (Sec*1000))*1000;
211 tp->tv_sec = Sec;
212 tp->tv_usec = Usec;
213 #endif
214 (void)nothing;
215 return 0;
216 }
217
218 static char *strsep(char **stringp, const char *delim)
219 {
220 char *start = *stringp;
221 char *ptr;
222
223 if (!start)
224 return NULL;
225
226 if (!*delim)
227 ptr = start + strlen(start);
228 else {
229 ptr = strpbrk(start, delim);
230 if (!ptr) {
231 *stringp = NULL;
232 return start;
233 }
234 }
235
236 *ptr = '\0';
237 *stringp = ptr + 1;
238
239 return start;
240 }
241 #endif
242
243 static void ftdm_r2_set_chan_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status_t status)
244 {
245 ftdm_sigmsg_t sig;
246 ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Signalling link status changed to %s\n", ftdm_signaling_status2str(status));
247
248 memset(&sig, 0, sizeof(sig));
249 sig.chan_id = ftdmchan->chan_id;
250 sig.span_id = ftdmchan->span_id;
251 sig.channel = ftdmchan;
252 sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
253 sig.ev_data.sigstatus.status = status;
254 if (ftdm_span_send_signal(ftdmchan->span, &sig) != FTDM_SUCCESS) {
255 ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to change channel status to %s\n", ftdm_signaling_status2str(status));
256 }
257 return;
258 }
259
260 static ftdm_call_cause_t ftdm_r2_cause_to_ftdm_cause(ftdm_channel_t *fchan, openr2_call_disconnect_cause_t cause)
261 {
262 switch (cause) {
263
264 case OR2_CAUSE_NORMAL_CLEARING:
265 return FTDM_CAUSE_NORMAL_CLEARING;
266
267 case OR2_CAUSE_BUSY_NUMBER:
268 return FTDM_CAUSE_USER_BUSY;
269
270 case OR2_CAUSE_NETWORK_CONGESTION:
271 return FTDM_CAUSE_SWITCH_CONGESTION;
272
273 case OR2_CAUSE_UNALLOCATED_NUMBER:
274 return FTDM_CAUSE_NO_ROUTE_DESTINATION;
275
276 case OR2_CAUSE_NUMBER_CHANGED:
277 return FTDM_CAUSE_NUMBER_CHANGED;
278
279 case OR2_CAUSE_OUT_OF_ORDER:
280 return FTDM_CAUSE_NETWORK_OUT_OF_ORDER;
281
282 case OR2_CAUSE_NO_ANSWER:
283 return FTDM_CAUSE_NO_ANSWER;
284
285 case OR2_CAUSE_UNSPECIFIED:
286 return FTDM_CAUSE_NORMAL_UNSPECIFIED;
287
288 case OR2_CAUSE_COLLECT_CALL_REJECTED:
289 return FTDM_CAUSE_CALL_REJECTED;
290
291 case OR2_CAUSE_FORCED_RELEASE:
292 return FTDM_CAUSE_NORMAL_CLEARING;
293
294 case OR2_CAUSE_GLARE:
295 return FTDM_CAUSE_REQUESTED_CHAN_UNAVAIL;
296 }
297 ftdm_log_chan(fchan, FTDM_LOG_WARNING, "Mapping openr2 cause %d to unspecified\n", cause);
298 return FTDM_CAUSE_NORMAL_UNSPECIFIED;
299 }
300
301 static openr2_call_disconnect_cause_t ftdm_r2_ftdm_cause_to_openr2_cause(ftdm_channel_t *fchan)
302 {
303 switch (fchan->caller_data.hangup_cause) {
304
305 case FTDM_CAUSE_NORMAL_CLEARING:
306 return OR2_CAUSE_NORMAL_CLEARING;
307
308 case FTDM_CAUSE_USER_BUSY:
309 return OR2_CAUSE_BUSY_NUMBER;
310
311 case FTDM_CAUSE_SWITCH_CONGESTION:
312 return OR2_CAUSE_NETWORK_CONGESTION;
313
314 case FTDM_CAUSE_NO_ROUTE_DESTINATION:
315 return OR2_CAUSE_UNALLOCATED_NUMBER;
316
317 case FTDM_CAUSE_NUMBER_CHANGED:
318 return OR2_CAUSE_NUMBER_CHANGED;
319
320 case FTDM_CAUSE_NETWORK_OUT_OF_ORDER:
321 case FTDM_CAUSE_SERVICE_UNAVAILABLE:
322 case FTDM_CAUSE_PROTOCOL_ERROR:
323 return OR2_CAUSE_OUT_OF_ORDER;
324
325 case FTDM_CAUSE_NO_ANSWER:
326 case FTDM_CAUSE_NO_USER_RESPONSE:
327 return OR2_CAUSE_NO_ANSWER;
328
329 case FTDM_CAUSE_NORMAL_UNSPECIFIED:
330 return OR2_CAUSE_UNSPECIFIED;
331
332 case FTDM_CAUSE_REQUESTED_CHAN_UNAVAIL:
333 return OR2_CAUSE_GLARE;
334
335 }
336 ftdm_log_chan(fchan, FTDM_LOG_WARNING, "freetdm hangup cause %d mapped to openr2 cause %s\n",
337 fchan->caller_data.hangup_cause, openr2_proto_get_disconnect_string(OR2_CAUSE_UNSPECIFIED));
338 return OR2_CAUSE_UNSPECIFIED;
339 }
340
341 static void ft_r2_clean_call(ftdm_r2_call_t *call)
342 {
343 openr2_chan_t *r2chan = call->r2chan;
344
345
346
347 call->r2chan = r2chan;
348 call->accepted = 0;
349 call->answer_pending = 0;
350 call->disconnect_rcvd = 0;
351 call->protocol_error = 0;
352 call->dnis_index = 0;
353 call->ani_index = 0;
354 call->name[0] = 0;
355 call->protocol_error_recovery_timer = 0;
356 }
357
358 static void ft_r2_accept_call(ftdm_channel_t *ftdmchan)
359 {
360 openr2_chan_t *r2chan = R2CALL(ftdmchan)->r2chan;
361
362
363
364
365 openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
366 }
367
368 static void ft_r2_answer_call(ftdm_channel_t *ftdmchan)
369 {
370 openr2_chan_t *r2chan = R2CALL(ftdmchan)->r2chan;
371
372
373
374
375 openr2_chan_answer_call(r2chan);
376 R2CALL(ftdmchan)->answer_pending = 0;
377 }
378
379 static __inline__ ftdm_calling_party_category_t ftdm_openr2_cpc_to_r2_ftdm_cpc(openr2_calling_party_category_t cpc)
380 {
381 switch (cpc) {
382 case OR2_CALLING_PARTY_CATEGORY_UNKNOWN:
383 return FTDM_CPC_UNKNOWN;
384
385 case OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER:
386 return FTDM_CPC_ORDINARY;
387
388 case OR2_CALLING_PARTY_CATEGORY_NATIONAL_PRIORITY_SUBSCRIBER:
389 return FTDM_CPC_PRIORITY;
390
391 case OR2_CALLING_PARTY_CATEGORY_INTERNATIONAL_SUBSCRIBER:
392 return FTDM_CPC_UNKNOWN;
393
394 case OR2_CALLING_PARTY_CATEGORY_INTERNATIONAL_PRIORITY_SUBSCRIBER:
395 return FTDM_CPC_UNKNOWN;
396
397 case OR2_CALLING_PARTY_CATEGORY_TEST_EQUIPMENT:
398 return FTDM_CPC_TEST;
399
400 case OR2_CALLING_PARTY_CATEGORY_PAY_PHONE:
401 return FTDM_CPC_PAYPHONE;
402
403 case OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL:
404 return FTDM_CPC_OPERATOR;
405 }
406 return FTDM_CPC_INVALID;
407 }
408
409 static __inline openr2_calling_party_category_t ftdm_r2_ftdm_cpc_to_openr2_cpc(ftdm_calling_party_category_t cpc)
410 {
411 switch (cpc) {
412 case FTDM_CPC_UNKNOWN:
413 return OR2_CALLING_PARTY_CATEGORY_UNKNOWN;
414
415 case FTDM_CPC_OPERATOR:
416 return OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL;
417
418 case FTDM_CPC_ORDINARY:
419 return OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
420
421 case FTDM_CPC_PRIORITY:
422 return OR2_CALLING_PARTY_CATEGORY_NATIONAL_PRIORITY_SUBSCRIBER;
423
424 case FTDM_CPC_DATA:
425 return OR2_CALLING_PARTY_CATEGORY_UNKNOWN;
426
427 case FTDM_CPC_TEST:
428 return OR2_CALLING_PARTY_CATEGORY_TEST_EQUIPMENT;
429
430 case FTDM_CPC_PAYPHONE:
431 return OR2_CALLING_PARTY_CATEGORY_PAY_PHONE;
432
433 case FTDM_CPC_INVALID:
434 return OR2_CALLING_PARTY_CATEGORY_UNKNOWN;
435 }
436 return OR2_CALLING_PARTY_CATEGORY_UNKNOWN;
437 }
438
439
440 static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(r2_outgoing_call)
441 {
442 int ret;
443 ftdm_r2_data_t *r2data;
444 openr2_calling_party_category_t category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
445
446 r2data = ftdmchan->span->signal_data;
447
448 ft_r2_clean_call(ftdmchan->call_data);
449
450 if (ftdmchan->caller_data.cpc == FTDM_CPC_INVALID || ftdmchan->caller_data.cpc == FTDM_CPC_UNKNOWN) {
451 category = r2data->category;
452 } else {
453 category = ftdm_r2_ftdm_cpc_to_openr2_cpc(ftdmchan->caller_data.cpc);
454 }
455
456
457 if (r2data->mf_dump_size) {
458 ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_INPUT_DUMP, &r2data->mf_dump_size);
459 ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_OUTPUT_DUMP, &r2data->mf_dump_size);
460 }
461
462 ret = openr2_chan_make_call(R2CALL(ftdmchan)->r2chan,
463 ftdmchan->caller_data.cid_num.digits,
464 ftdmchan->caller_data.dnis.digits,
465 category,
466 ftdmchan->caller_data.pres == FTDM_PRES_ALLOWED ? 0 : 1);
467
468 if (ret) {
469 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to make call in R2 channel, openr2_chan_make_call failed\n");
470 return FTDM_FAIL;
471 }
472
473 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DIALING);
474
475 ftdm_channel_set_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS);
476 ftdm_channel_command(ftdmchan, FTDM_COMMAND_FLUSH_TX_BUFFERS, NULL);
477 ftdm_channel_command(ftdmchan, FTDM_COMMAND_FLUSH_RX_BUFFERS, NULL);
478
479 return FTDM_SUCCESS;
480 }
481
482 static ftdm_status_t ftdm_r2_start(ftdm_span_t *span)
483 {
484 ftdm_r2_data_t *r2_data = span->signal_data;
485 ftdm_set_flag(r2_data, FTDM_R2_SPAN_STARTED);
486 return ftdm_thread_create_detached(ftdm_r2_run, span);
487 }
488
489 static ftdm_status_t ftdm_r2_stop(ftdm_span_t *span)
490 {
491 ftdm_r2_data_t *r2_data = span->signal_data;
492 ftdm_clear_flag(r2_data, FTDM_R2_SPAN_STARTED);
493 while (ftdm_test_flag(r2_data, FTDM_R2_RUNNING)) {
494 ftdm_log(FTDM_LOG_DEBUG, "Waiting for R2 span %s\n", span->name);
495 ftdm_sleep(100);
496 }
497 return FTDM_SUCCESS;
498 }
499
500 static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(ftdm_r2_get_channel_sig_status)
501 {
502 if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) {
503 *status = FTDM_SIG_STATE_UP;
504 } else {
505 *status = FTDM_SIG_STATE_DOWN;
506 }
507
508 return FTDM_SUCCESS;
509 }
510
511 static FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(ftdm_r2_set_channel_sig_status)
512 {
513 openr2_chan_t *r2chan = R2CALL(ftdmchan)->r2chan;
514 openr2_cas_signal_t rxcas, txcas;
515
516
517 openr2_chan_get_cas(r2chan, &rxcas, &txcas);
518
519
520 if (status == FTDM_SIG_STATE_SUSPENDED && txcas == OR2_CAS_BLOCK) {
521 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Channel signaling status already in BLOCK state\n");
522 return FTDM_SUCCESS;
523 }
524 if (status == FTDM_SIG_STATE_UP && txcas == OR2_CAS_IDLE) {
525 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Channel signaling status already in IDLE state\n");
526 return FTDM_SUCCESS;
527 }
528
529
530
531 switch(status) {
532 case FTDM_SIG_STATE_SUSPENDED:
533 openr2_chan_set_blocked(r2chan);
534 if (rxcas == OR2_CAS_IDLE) {
535 ftdm_r2_set_chan_sig_status(ftdmchan, status);
536 }
537 break;
538 case FTDM_SIG_STATE_UP:
539 openr2_chan_set_idle(r2chan);
540 if (rxcas == OR2_CAS_IDLE) {
541 ftdm_r2_set_chan_sig_status(ftdmchan, status);
542 }
543 break;
544 default:
545 ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Cannot set signaling status to unknown value '%d'\n", status);
546 return FTDM_FAIL;
547 }
548 return FTDM_SUCCESS;
549 }
550
551 static FIO_SPAN_GET_SIG_STATUS_FUNCTION(ftdm_r2_get_span_sig_status)
552 {
553 ftdm_iterator_t *citer = NULL;
554 ftdm_iterator_t *chaniter = ftdm_span_get_chan_iterator(span, NULL);
555 if (!chaniter) {
556 ftdm_log(FTDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name);
557 return FTDM_FAIL;
558 }
559
560 *status = FTDM_SIG_STATE_SUSPENDED;
561 for (citer = chaniter; citer; citer = ftdm_iterator_next(citer)) {
562 ftdm_channel_t *fchan = ftdm_iterator_current(citer);
563 ftdm_channel_lock(fchan);
564 if (ftdm_test_flag(fchan, FTDM_CHANNEL_SIG_UP)) {
565 *status = FTDM_SIG_STATE_UP;
566 ftdm_channel_unlock(fchan);
567 break;
568 }
569 ftdm_channel_unlock(fchan);
570 }
571 ftdm_iterator_free(chaniter);
572 return FTDM_SUCCESS;
573 }
574
575 static FIO_SPAN_SET_SIG_STATUS_FUNCTION(ftdm_r2_set_span_sig_status)
576 {
577 ftdm_iterator_t *chaniter = NULL;
578 ftdm_iterator_t *citer = NULL;
579
580 chaniter = ftdm_span_get_chan_iterator(span, NULL);
581 if (!chaniter) {
582 ftdm_log(FTDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name);
583 return FTDM_FAIL;
584 }
585
586 for (citer = chaniter; citer; citer = ftdm_iterator_next(citer)) {
587 ftdm_channel_t *fchan = ftdm_iterator_current(citer);
588
589
590 ftdm_channel_lock(fchan);
591 if ((ftdm_r2_set_channel_sig_status(fchan, status)) != FTDM_SUCCESS) {
592 ftdm_log_chan(fchan, FTDM_LOG_ERROR, "Failed to set signaling status to %s\n", ftdm_signaling_status2str(status));
593 }
594 ftdm_channel_unlock(fchan);
595 }
596 ftdm_iterator_free(chaniter);
597 return FTDM_SUCCESS;
598 }
599
600
601 static void ftdm_r2_on_call_init(openr2_chan_t *r2chan)
602 {
603 ftdm_r2_call_t *r2call;
604 ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
605 ftdm_r2_data_t *r2data = ftdmchan->span->signal_data;
606
607 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Received request to start call\n");
608
609 if (ftdmchan->state == FTDM_CHANNEL_STATE_HANGUP) {
610 r2call = R2CALL(ftdmchan);
611 if (r2call->protocol_error) {
612
613
614 ftdm_sched_cancel_timer(r2data->sched, r2call->protocol_error_recovery_timer);
615 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Cancelled protocol error recovery timer\n");
616 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
617 ftdm_channel_advance_states(ftdmchan);
618 }
619 }
620
621 if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE)) {
622 ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Cannot start call when channel is in use (state = %s)\n", ftdm_channel_state2str(ftdmchan->state));
623 return;
624 }
625
626 if (ftdmchan->state != FTDM_CHANNEL_STATE_DOWN) {
627 ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Cannot handle request to start call in state %s\n", ftdm_channel_state2str(ftdmchan->state));
628 return;
629 }
630
631 if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) {
632 ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to open channel during incoming call! [%s]\n", ftdmchan->last_error);
633 return;
634 }
635
636
637 ftdm_channel_use(ftdmchan);
638
639 memset(ftdmchan->caller_data.dnis.digits, 0, sizeof(ftdmchan->caller_data.collected));
640 memset(ftdmchan->caller_data.ani.digits, 0, sizeof(ftdmchan->caller_data.collected));
641
642 ft_r2_clean_call(ftdmchan->call_data);
643 r2call = R2CALL(ftdmchan);
644
645
646 if (r2data->mf_dump_size) {
647 ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_INPUT_DUMP, &r2data->mf_dump_size);
648 ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_OUTPUT_DUMP, &r2data->mf_dump_size);
649 }
650
651 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_COLLECT);
652 ftdm_channel_set_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS);
653 ftdm_channel_command(ftdmchan, FTDM_COMMAND_FLUSH_TX_BUFFERS, NULL);
654 ftdm_channel_command(ftdmchan, FTDM_COMMAND_FLUSH_RX_BUFFERS, NULL);
655 }
656
657 static void dump_mf(openr2_chan_t *r2chan);
658
659 static void ftdm_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis,
660 openr2_calling_party_category_t category, int ani_restricted)
661 {
662 ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
663 ftdm_r2_data_t *r2data = ftdmchan->span->signal_data;
664
665 ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Call offered with ANI = %s, DNIS = %s, Category = %d, ANI restricted = %s\n",
666 ani, dnis, category, ani_restricted ? "Yes" : "No");
667
668
669 if (r2data->mf_dump_size) {
670 ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_INPUT_DUMP, NULL);
671 ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_OUTPUT_DUMP, NULL);
672 }
673
674
675 if (!r2data->allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
676 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Rejecting collect call\n");
677 openr2_chan_disconnect_call(r2chan, OR2_CAUSE_COLLECT_CALL_REJECTED);
678 } else {
679 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
680 }
681 ftdmchan->caller_data.cpc = ftdm_openr2_cpc_to_r2_ftdm_cpc(category);
682 ftdmchan->caller_data.pres = ani_restricted ? FTDM_PRES_RESTRICTED : FTDM_PRES_ALLOWED;
683 }
684
685
686
687
688
689
690
691
692
693
694
695
696
697 static void clear_accept_pending(ftdm_channel_t *fchan)
698 {
699 if (IS_ACCEPTING_PENDING(fchan)) {
700 ftdm_channel_complete_state(fchan);
701 } else if (ftdm_test_flag(fchan, FTDM_CHANNEL_STATE_CHANGE)) {
702 ftdm_log_chan(fchan, FTDM_LOG_CRIT, "State change flag set in state %s, last state = %s\n",
703 ftdm_channel_state2str(fchan->state), ftdm_channel_state2str(fchan->last_state));
704 ftdm_channel_complete_state(fchan);
705 }
706 }
707
708 static void dump_mf(openr2_chan_t *r2chan)
709 {
710 char dfile[512];
711 FILE *f = NULL;
712 ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
713 ftdm_r2_data_t *r2data = ftdmchan->span->signal_data;
714 if (r2data->mf_dump_size) {
715 char *logname = R2CALL(ftdmchan)->logname;
716
717 ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Dumping IO output in prefix %s\n", logname);
718 snprintf(dfile, sizeof(dfile), logname ? "%s.s%dc%d.input.alaw" : "%s/s%dc%d.input.alaw",
719 logname ? logname : r2data->logdir, ftdmchan->span_id, ftdmchan->chan_id);
720 f = fopen(dfile, "wb");
721 ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Dumping IO input in file %s\n", dfile);
722 ftdm_channel_command(ftdmchan, FTDM_COMMAND_DUMP_INPUT, f);
723 fclose(f);
724
725 snprintf(dfile, sizeof(dfile), logname ? "%s.s%dc%d.output.alaw" : "%s/s%dc%d.output.alaw",
726 logname ? logname : r2data->logdir, ftdmchan->span_id, ftdmchan->chan_id);
727 f = fopen(dfile, "wb");
728 ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Dumping IO output in file %s\n", dfile);
729 ftdm_channel_command(ftdmchan, FTDM_COMMAND_DUMP_OUTPUT, f);
730 fclose(f);
731 }
732 }
733
734 static void ftdm_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
735 {
736 ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
737 ftdm_r2_data_t *r2data = ftdmchan->span->signal_data;
738
739 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Call accepted\n");
740
741 clear_accept_pending(ftdmchan);
742
743
744 openr2_chan_disable_read(r2chan);
745
746
747
748 ftdm_channel_clear_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS);
749
750
751 R2CALL(ftdmchan)->accepted = 1;
752
753 if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
754 if (R2CALL(ftdmchan)->answer_pending) {
755 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Answer was pending, answering now.\n");
756 ft_r2_answer_call(ftdmchan);
757 R2CALL(ftdmchan)->answer_pending = 0;
758 return;
759 }
760 } else {
761
762 if (r2data->mf_dump_size) {
763 ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_INPUT_DUMP, NULL);
764 ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_OUTPUT_DUMP, NULL);
765 }
766 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
767 }
768 }
769
770 static void ftdm_r2_on_call_answered(openr2_chan_t *r2chan)
771 {
772 ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
773 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Call answered\n");
774
775 if (OR2_DIR_FORWARD == openr2_chan_get_direction(r2chan)) {
776 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP);
777 }
778 }
779
780
781 static void ftdm_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
782 {
783 ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
784
785 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Call disconnected\n");
786
787 clear_accept_pending(ftdmchan);
788
789 R2CALL(ftdmchan)->disconnect_rcvd = 1;
790
791 if (ftdmchan->state == FTDM_CHANNEL_STATE_HANGUP) {
792 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Call had been disconnected already by the user\n");
793
794 openr2_chan_disconnect_call(r2chan, OR2_CAUSE_NORMAL_CLEARING);
795 return;
796 }
797
798 ftdmchan->caller_data.hangup_cause = ftdm_r2_cause_to_ftdm_cause(ftdmchan, cause);
799 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
800 }
801
802 static void ftdm_r2_on_call_end(openr2_chan_t *r2chan)
803 {
804 ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
805 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Call finished\n");
806
807
808 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
809
810
811 ftdm_channel_advance_states(ftdmchan);
812 }
813
814 static void ftdm_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
815 {
816 #if 0
817 ftdm_log(FTDM_LOG_NOTICE, "Call read data on chan %d\n", openr2_chan_get_number(r2chan));
818 #endif
819 }
820
821 static void ftdm_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
822 {
823 ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
824 ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Alarm notification: %d\n", alarm);
825 }
826
827 static void ftdm_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
828 {
829 ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
830 ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "OS error: %s\n", strerror(errorcode));
831 }
832
833 static void ftdm_r2_recover_from_protocol_error(void *data)
834 {
835 openr2_chan_t *r2chan = data;
836 ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
837 ftdm_channel_lock(ftdmchan);
838 if (ftdmchan->state != FTDM_CHANNEL_STATE_HANGUP) {
839 ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Recovering from protocol error but state is %s!\n", ftdm_channel_state2str(ftdmchan->state));
840 goto done;
841 }
842 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
843 ftdm_channel_advance_states(ftdmchan);
844 done:
845 ftdm_channel_unlock(ftdmchan);
846 }
847
848 static void ftdm_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
849 {
850 ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
851
852 if (ftdmchan->state == FTDM_CHANNEL_STATE_DOWN) {
853 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Got protocol error when we're already down!\n");
854 return;
855 }
856
857 dump_mf(r2chan);
858
859 clear_accept_pending(ftdmchan);
860
861 R2CALL(ftdmchan)->disconnect_rcvd = 1;
862 R2CALL(ftdmchan)->protocol_error = 1;
863
864 if (ftdmchan->state == FTDM_CHANNEL_STATE_HANGUP) {
865 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "The user already hung up, finishing call in protocol error\n");
866 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
867 return;
868 }
869
870 ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_PROTOCOL_ERROR;
871 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
872 }
873
874 static void ftdm_r2_on_line_blocked(openr2_chan_t *r2chan)
875 {
876 ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
877 ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Far end blocked in state %s\n", ftdm_channel_state2str(ftdmchan->state));
878 ftdm_r2_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_SUSPENDED);
879 }
880
881 static void ftdm_r2_on_line_idle(openr2_chan_t *r2chan)
882 {
883 ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
884 ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Far end unblocked in state %s\n", ftdm_channel_state2str(ftdmchan->state));
885 ftdm_r2_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_UP);
886 }
887
888 static void ftdm_r2_write_log(openr2_log_level_t level, const char *file, const char *function, int line, const char *message)
889 {
890 switch (level) {
891 case OR2_LOG_NOTICE:
892 ftdm_log(file, function, line, FTDM_LOG_LEVEL_NOTICE, "%s", message);
893 break;
894 case OR2_LOG_WARNING:
895 ftdm_log(file, function, line, FTDM_LOG_LEVEL_WARNING, "%s", message);
896 break;
897 case OR2_LOG_ERROR:
898 ftdm_log(file, function, line, FTDM_LOG_LEVEL_ERROR, "%s", message);
899 break;
900 case OR2_LOG_STACK_TRACE:
901 case OR2_LOG_MF_TRACE:
902 case OR2_LOG_CAS_TRACE:
903 case OR2_LOG_DEBUG:
904 case OR2_LOG_EX_DEBUG:
905 ftdm_log(file, function, line, FTDM_LOG_LEVEL_DEBUG, "%s", message);
906 break;
907 default:
908 ftdm_log(FTDM_LOG_WARNING, "We should handle logging level %d here.\n", level);
909 ftdm_log(file, function, line, FTDM_LOG_LEVEL_DEBUG, "%s", message);
910 break;
911 }
912 }
913
914 static void ftdm_r2_on_context_log(openr2_context_t *r2context, const char *file, const char *function, unsigned int line,
915 openr2_log_level_t level, const char *fmt, va_list ap)
916 {
917 #define CONTEXT_TAG "Context -"
918 char logmsg[256];
919 char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
920 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
921 snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
922 ftdm_r2_write_log(level, file, function, line, completemsg);
923 #undef CONTEXT_TAG
924 }
925
926 static void ftdm_r2_on_chan_log(openr2_chan_t *r2chan, const char *file, const char *function, unsigned int line,
927 openr2_log_level_t level, const char *fmt, va_list ap)
928 {
929 ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
930 char logmsg[1024];
931 char completemsg[sizeof(logmsg)];
932 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
933 snprintf(completemsg, sizeof(completemsg), "[s%dc%d] [%d:%d] [%s] %s",
934 ftdmchan->span_id, ftdmchan->chan_id, ftdmchan->physical_span_id, ftdmchan->physical_chan_id,
935 ftdm_channel_state2str(ftdmchan->state), logmsg);
936 ftdm_r2_write_log(level, file, function, line, completemsg);
937 }
938
939 static int ftdm_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
940 {
941 ftdm_sigmsg_t sigev;
942 ftdm_r2_data_t *r2data;
943 ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
944 ftdm_size_t collected_len = R2CALL(ftdmchan)->dnis_index;
945
946 ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "DNIS digit %c received\n", digit);
947
948
949 ftdmchan->caller_data.dnis.digits[collected_len] = digit;
950 collected_len++;
951 ftdmchan->caller_data.dnis.digits[collected_len] = '\0';
952 R2CALL(ftdmchan)->dnis_index = collected_len;
953
954
955 memset(&sigev, 0, sizeof(sigev));
956 sigev.chan_id = ftdmchan->chan_id;
957 sigev.span_id = ftdmchan->span_id;
958 sigev.channel = ftdmchan;
959 sigev.event_id = FTDM_SIGEVENT_COLLECTED_DIGIT;
960 r2data = ftdmchan->span->signal_data;
961 if (ftdm_span_send_signal(ftdmchan->span, &sigev) == FTDM_BREAK) {
962 ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Requested to stop getting DNIS. Current DNIS = %s\n", ftdmchan->caller_data.dnis.digits);
963 return OR2_STOP_DNIS_REQUEST;
964 }
965
966
967 if (collected_len == (sizeof(ftdmchan->caller_data.dnis.digits) - 1)) {
968 ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "No more room for DNIS. Current DNIS = %s\n", ftdmchan->caller_data.dnis.digits);
969 return OR2_STOP_DNIS_REQUEST;
970 }
971
972 return OR2_CONTINUE_DNIS_REQUEST;
973 }
974
975 static void ftdm_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
976 {
977 ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
978 ftdm_size_t collected_len = R2CALL(ftdmchan)->ani_index;
979
980
981 if (collected_len == (sizeof(ftdmchan->caller_data.ani.digits) - 1)) {
982 ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "No more room for ANI, digit dropped: %c\n", digit);
983 return;
984 }
985 ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "ANI digit %c received\n", digit);
986
987
988 ftdmchan->caller_data.ani.digits[collected_len] = digit;
989 collected_len++;
990 ftdmchan->caller_data.ani.digits[collected_len] = '\0';
991 R2CALL(ftdmchan)->ani_index = collected_len;
992 }
993
994 static void ftdm_r2_on_billing_pulse(openr2_chan_t *r2chan) {}
995
996 static void ftdm_r2_on_call_log_created(openr2_chan_t *r2chan, const char *logname)
997 {
998 ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
999 ftdm_r2_call_t *r2call = R2CALL(ftdmchan);
1000
1001 snprintf(r2call->logname, sizeof(r2call->logname), "%s", logname);
1002 }
1003
1004 static void ftdm_r2_on_call_proceed(openr2_chan_t *r2chan)
1005 {
1006 ftdm_sigmsg_t sigev;
1007 ftdm_channel_t *fchan = openr2_chan_get_client_data(r2chan);
1008 memset(&sigev, 0, sizeof(sigev));
1009 sigev.event_id = FTDM_SIGEVENT_PROCEED;
1010 sigev.channel = fchan;
1011 ftdm_span_send_signal(fchan->span, &sigev);
1012 }
1013
1014 static openr2_event_interface_t ftdm_r2_event_iface = {
1015 ftdm_r2_on_call_init,
1016 ftdm_r2_on_call_proceed,
1017 ftdm_r2_on_call_offered,
1018 ftdm_r2_on_call_accepted,
1019 ftdm_r2_on_call_answered,
1020 ftdm_r2_on_call_disconnect,
1021 ftdm_r2_on_call_end,
1022 ftdm_r2_on_call_read,
1023 ftdm_r2_on_hardware_alarm,
1024 ftdm_r2_on_os_error,
1025 ftdm_r2_on_protocol_error,
1026 ftdm_r2_on_line_blocked,
1027 ftdm_r2_on_line_idle,
1028
1029
1030 (openr2_handle_context_logging_func)ftdm_r2_on_context_log,
1031 ftdm_r2_on_dnis_digit_received,
1032 ftdm_r2_on_ani_digit_received,
1033
1034
1035 ftdm_r2_on_billing_pulse,
1036 ftdm_r2_on_call_log_created,
1037 };
1038
1039 static int ftdm_r2_io_set_cas(openr2_chan_t *r2chan, int cas)
1040 {
1041 ftdm_channel_t *ftdm_chan = openr2_chan_get_fd(r2chan);
1042 ftdm_status_t status = ftdm_channel_command(ftdm_chan, FTDM_COMMAND_SET_CAS_BITS, &cas);
1043 if (FTDM_FAIL == status) {
1044 return -1;
1045 }
1046 return 0;
1047 }
1048
1049 static int ftdm_r2_io_get_cas(openr2_chan_t *r2chan, int *cas)
1050 {
1051 ftdm_channel_t *ftdm_chan = openr2_chan_get_fd(r2chan);
1052 ftdm_status_t status = ftdm_channel_command(ftdm_chan, FTDM_COMMAND_GET_CAS_BITS, cas);
1053 if (FTDM_FAIL == status) {
1054 return -1;
1055 }
1056 return 0;
1057 }
1058
1059 static int ftdm_r2_io_flush_write_buffers(openr2_chan_t *r2chan)
1060 {
1061 ftdm_channel_t *ftdm_chan = openr2_chan_get_fd(r2chan);
1062 ftdm_status_t status = ftdm_channel_command(ftdm_chan, FTDM_COMMAND_FLUSH_TX_BUFFERS, NULL);
1063 if (FTDM_FAIL == status) {
1064 return -1;
1065 }
1066 return 0;
1067 }
1068
1069 static int ftdm_r2_io_write(openr2_chan_t *r2chan, const void *buf, int size)
1070 {
1071 ftdm_channel_t *ftdm_chan = openr2_chan_get_fd(r2chan);
1072 ftdm_size_t outsize = size;
1073 ftdm_status_t status = ftdm_channel_write(ftdm_chan, (void *)buf, size, &outsize);
1074 if (FTDM_FAIL == status) {
1075 return -1;
1076 }
1077 return (int)outsize;
1078 }
1079
1080 static int ftdm_r2_io_read(openr2_chan_t *r2chan, const void *buf, int size)
1081 {
1082 ftdm_channel_t *ftdm_chan = openr2_chan_get_fd(r2chan);
1083 ftdm_size_t outsize = size;
1084 ftdm_status_t status = ftdm_channel_read(ftdm_chan, (void *)buf, &outsize);
1085 if (FTDM_FAIL == status) {
1086 return -1;
1087 }
1088 return (int)outsize;
1089 }
1090
1091 static int ftdm_r2_io_wait(openr2_chan_t *r2chan, int *flags, int block)
1092 {
1093 ftdm_status_t status;
1094 int32_t timeout;
1095 ftdm_wait_flag_t ftdmflags = 0;
1096
1097 ftdm_channel_t *fchan = openr2_chan_get_fd(r2chan);
1098 timeout = block ? -1 : 0;
1099
1100 if (*flags & OR2_IO_READ) {
1101 ftdmflags |= FTDM_READ;
1102 }
1103 if (*flags & OR2_IO_WRITE) {
1104 ftdmflags |= FTDM_WRITE;
1105 }
1106 if (*flags & OR2_IO_OOB_EVENT) {
1107 ftdmflags |= FTDM_EVENTS;
1108 }
1109
1110 status = ftdm_channel_wait(fchan, &ftdmflags, timeout);
1111
1112 if (FTDM_SUCCESS != status && FTDM_TIMEOUT != status) {
1113 ftdm_log_chan_msg(fchan, FTDM_LOG_ERROR, "Failed to wait for events on channel\n");
1114 return -1;
1115 }
1116
1117 *flags = 0;
1118 if (ftdmflags & FTDM_READ) {
1119 *flags |= OR2_IO_READ;
1120 }
1121 if (ftdmflags & FTDM_WRITE) {
1122 *flags |= OR2_IO_WRITE;
1123 }
1124 if (ftdmflags & FTDM_EVENTS) {
1125 *flags |= OR2_IO_OOB_EVENT;
1126 }
1127
1128 return 0;
1129 }
1130
1131
1132
1133 static openr2_io_fd_t ftdm_r2_io_open(openr2_context_t *r2context, int channo)
1134 {
1135 ftdm_log(FTDM_LOG_ERROR, "I should not be called (I/O open)!!\n");
1136 return NULL;
1137 }
1138
1139
1140 static int ftdm_r2_io_close(openr2_chan_t *r2chan)
1141 {
1142 ftdm_channel_t *fchan = openr2_chan_get_client_data(r2chan);
1143 ftdm_log_chan_msg(fchan, FTDM_LOG_ERROR, "I should not be called (I/O close)!!\n");
1144 return 0;
1145 }
1146
1147
1148 static int ftdm_r2_io_setup(openr2_chan_t *r2chan)
1149 {
1150 ftdm_channel_t *fchan = openr2_chan_get_client_data(r2chan);
1151 ftdm_log_chan_msg(fchan, FTDM_LOG_ERROR, "I should not be called (I/O Setup)!!\n");
1152 return 0;
1153 }
1154
1155 static int ftdm_r2_io_get_oob_event(openr2_chan_t *r2chan, openr2_oob_event_t *event)
1156 {
1157 ftdm_status_t status;
1158 ftdm_event_t *fevent = NULL;
1159 ftdm_channel_t *ftdmchan = openr2_chan_get_fd(r2chan);
1160
1161 *event = OR2_OOB_EVENT_NONE;
1162
1163 status = ftdm_channel_read_event(ftdmchan, &fevent);
1164
1165 if (status != FTDM_SUCCESS) {
1166 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "failed to retrieve freetdm event!\n");
1167 return -1;
1168 }
1169
1170 if (fevent->e_type != FTDM_EVENT_OOB) {
1171 return 0;
1172 }
1173
1174 switch (fevent->enum_id) {
1175 case FTDM_OOB_CAS_BITS_CHANGE:
1176 {
1177 *event = OR2_OOB_EVENT_CAS_CHANGE;
1178 }
1179 break;
1180 case FTDM_OOB_ALARM_TRAP:
1181 {
1182 *event = OR2_OOB_EVENT_ALARM_ON;
1183 }
1184 break;
1185 case FTDM_OOB_ALARM_CLEAR:
1186 {
1187 *event = OR2_OOB_EVENT_ALARM_OFF;
1188 }
1189 break;
1190 }
1191 return 0;
1192 }
1193
1194 static openr2_io_interface_t ftdm_r2_io_iface = {
1195 ftdm_r2_io_open,
1196 ftdm_r2_io_close,
1197 ftdm_r2_io_set_cas,
1198 ftdm_r2_io_get_cas,
1199 ftdm_r2_io_flush_write_buffers,
1200 ftdm_r2_io_write,
1201 ftdm_r2_io_read,
1202 ftdm_r2_io_setup,
1203 ftdm_r2_io_wait,
1204 ftdm_r2_io_get_oob_event
1205 };
1206
1207
1208 static openr2_log_level_t ftdm_r2_loglevel_from_string(const char *level)
1209 {
1210 openr2_log_level_t tmplevel;
1211 openr2_log_level_t newlevel = 0;
1212 char *clevel = NULL;
1213 char *logval = NULL;
1214
1215 logval = ftdm_malloc(strlen(level)+1);
1216 if (!logval) {
1217 ftdm_log(FTDM_LOG_WARNING, "Ignoring R2 logging parameter: '%s', failed to alloc memory\n", level);
1218 return newlevel;
1219 }
1220 strcpy(logval, level);
1221 while (logval) {
1222 clevel = strsep(&logval, ",");
1223 if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
1224 ftdm_log(FTDM_LOG_WARNING, "Ignoring invalid R2 logging level: '%s'\n", clevel);
1225 continue;
1226 }
1227 newlevel |= tmplevel;
1228 }
1229 ftdm_safe_free(logval);
1230 return newlevel;
1231 }
1232
1233 static ftdm_state_map_t r2_state_map = {
1234 {
1235 {
1236 ZSD_INBOUND,
1237 ZSM_UNACCEPTABLE,
1238 {FTDM_ANY_STATE, FTDM_END},
1239 {FTDM_CHANNEL_STATE_RESET, FTDM_END}
1240 },
1241 {
1242 ZSD_INBOUND,
1243 ZSM_UNACCEPTABLE,
1244 {FTDM_CHANNEL_STATE_RESET, FTDM_END},
1245 {FTDM_CHANNEL_STATE_DOWN, FTDM_END}
1246 },
1247 {
1248 ZSD_INBOUND,
1249 ZSM_UNACCEPTABLE,
1250 {FTDM_CHANNEL_STATE_DOWN, FTDM_END},
1251 {FTDM_CHANNEL_STATE_COLLECT, FTDM_END}
1252 },
1253 {
1254 ZSD_INBOUND,
1255 ZSM_UNACCEPTABLE,
1256 {FTDM_CHANNEL_STATE_COLLECT, FTDM_END},
1257 {FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}
1258 },
1259 {
1260 ZSD_INBOUND,
1261 ZSM_UNACCEPTABLE,
1262 {FTDM_CHANNEL_STATE_RING, FTDM_END},
1263 {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END}
1264 },
1265 {
1266 ZSD_INBOUND,
1267 ZSM_UNACCEPTABLE,
1268 {FTDM_CHANNEL_STATE_HANGUP, FTDM_END},
1269 {FTDM_CHANNEL_STATE_DOWN, FTDM_END},
1270 },
1271 {
1272 ZSD_INBOUND,
1273 ZSM_UNACCEPTABLE,
1274 {FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
1275 {FTDM_CHANNEL_STATE_HANGUP, FTDM_END},
1276 },
1277 {
1278 ZSD_INBOUND,
1279 ZSM_UNACCEPTABLE,
1280 {FTDM_CHANNEL_STATE_PROGRESS, FTDM_END},
1281 {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END},
1282 },
1283 {
1284 ZSD_INBOUND,
1285 ZSM_UNACCEPTABLE,
1286 {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END},
1287 {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_UP, FTDM_END},
1288 },
1289 {
1290 ZSD_INBOUND,
1291 ZSM_UNACCEPTABLE,
1292 {FTDM_CHANNEL_STATE_UP, FTDM_END},
1293 {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
1294 },
1295
1296
1297
1298 {
1299 ZSD_OUTBOUND,
1300 ZSM_UNACCEPTABLE,
1301 {FTDM_ANY_STATE, FTDM_END},
1302 {FTDM_CHANNEL_STATE_RESET, FTDM_END}
1303 },
1304
1305 {
1306 ZSD_OUTBOUND,
1307 ZSM_UNACCEPTABLE,
1308 {FTDM_CHANNEL_STATE_RESET, FTDM_END},
1309 {FTDM_CHANNEL_STATE_DOWN, FTDM_END}
1310 },
1311
1312 {
1313 ZSD_OUTBOUND,
1314 ZSM_UNACCEPTABLE,
1315 {FTDM_CHANNEL_STATE_DOWN, FTDM_END},
1316 {FTDM_CHANNEL_STATE_DIALING, FTDM_END}
1317 },
1318
1319 {
1320 ZSD_OUTBOUND,
1321 ZSM_UNACCEPTABLE,
1322 {FTDM_CHANNEL_STATE_DIALING, FTDM_END},
1323 {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END}
1324 },
1325
1326 {
1327 ZSD_OUTBOUND,
1328 ZSM_UNACCEPTABLE,
1329 {FTDM_CHANNEL_STATE_HANGUP, FTDM_END},
1330 {FTDM_CHANNEL_STATE_DOWN, FTDM_END}
1331 },
1332
1333 {
1334 ZSD_OUTBOUND,
1335 ZSM_UNACCEPTABLE,
1336 {FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
1337 {FTDM_CHANNEL_STATE_HANGUP, FTDM_END}
1338 },
1339
1340 {
1341 ZSD_OUTBOUND,
1342 ZSM_UNACCEPTABLE,
1343 {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END},
1344 {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_UP, FTDM_END}
1345 },
1346
1347 {
1348 ZSD_OUTBOUND,
1349 ZSM_UNACCEPTABLE,
1350 {FTDM_CHANNEL_STATE_UP, FTDM_END},
1351 {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}
1352 },
1353 }
1354 };
1355
1356 static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_r2_configure_span_signaling)
1357 {
1358 unsigned int i = 0;
1359 int conf_failure = 0;
1360 int intval = 0;
1361 char schedname[255];
1362 const char *var = NULL, *val = NULL;
1363 const char *log_level = "notice,warning,error";
1364 ftdm_r2_data_t *r2data = NULL;
1365 ftdm_r2_span_pvt_t *spanpvt = NULL;
1366 ftdm_r2_call_t *r2call = NULL;
1367 openr2_chan_t *r2chan = NULL;
1368 unsigned paramindex = 0;
1369
1370 ft_r2_conf_t r2conf =
1371 {
1372 OR2_VAR_ITU,
1373 OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER,
1374 OR2_LOG_ERROR | OR2_LOG_WARNING,
1375 #ifdef WIN32
1376 (char *)"c:\\",
1377 #else
1378 (char *)"/tmp",
1379 #endif
1380 NULL,
1381 10,
1382 4,
1383 -1,
1384 -1,
1385 0,
1386 -1,
1387 -1,
1388 -1,
1389 0,
1390 -1,
1391 -1,
1392 -1,
1393 -1
1394 };
1395
1396 ftdm_assert_return(sig_cb != NULL, FTDM_FAIL, "No signaling cb provided\n");
1397
1398 if (span->signal_type) {
1399 snprintf(span->last_error, sizeof(span->last_error), "Span is already configured for signalling.");
1400 return FTDM_FAIL;
1401 }
1402
1403 for (; ftdm_parameters[paramindex].var; paramindex++) {
1404 var = ftdm_parameters[paramindex].var;
1405 val = ftdm_parameters[paramindex].val;
1406 ftdm_log(FTDM_LOG_DEBUG, "Reading R2 parameter %s for span %d\n", var, span->span_id);
1407 if (!strcasecmp(var, "variant")) {
1408 if (!val) {
1409 break;
1410 }
1411 if (ftdm_strlen_zero_buf(val)) {
1412 ftdm_log(FTDM_LOG_NOTICE, "Ignoring empty R2 variant parameter\n");
1413 continue;
1414 }
1415 r2conf.variant = openr2_proto_get_variant(val);
1416 if (r2conf.variant == OR2_VAR_UNKNOWN) {
1417 ftdm_log(FTDM_LOG_ERROR, "Unknown R2 variant %s\n", val);
1418 conf_failure = 1;
1419 break;
1420 }
1421 ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d for variant %s\n", span->span_id, val);
1422 } else if (!strcasecmp(var, "category")) {
1423 if (!val) {
1424 break;
1425 }
1426 if (ftdm_strlen_zero_buf(val)) {
1427 ftdm_log(FTDM_LOG_NOTICE, "Ignoring empty R2 category parameter\n");
1428 continue;
1429 }
1430 r2conf.category = openr2_proto_get_category(val);
1431 if (r2conf.category == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
1432 ftdm_log(FTDM_LOG_ERROR, "Unknown R2 caller category %s\n", val);
1433 conf_failure = 1;
1434 break;
1435 }
1436 ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with default category %s\n", span->span_id, val);
1437 } else if (!strcasecmp(var, "logdir")) {
1438 if (!val) {
1439 break;
1440 }
1441 if (ftdm_strlen_zero_buf(val)) {
1442 ftdm_log(FTDM_LOG_NOTICE, "Ignoring empty R2 logdir parameter\n");
1443 continue;
1444 }
1445 r2conf.logdir = (char *)val;
1446 ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with logdir %s\n", span->span_id, val);
1447 } else if (!strcasecmp(var, "logging")) {
1448 if (!val) {
1449 break;
1450 }
1451 if (ftdm_strlen_zero_buf(val)) {
1452 ftdm_log(FTDM_LOG_NOTICE, "Ignoring empty R2 logging parameter\n");
1453 continue;
1454 }
1455 log_level = val;
1456 ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with loglevel %s\n", span->name, val);
1457 } else if (!strcasecmp(var, "advanced_protocol_file")) {
1458 if (!val) {
1459 break;
1460 }
1461 if (ftdm_strlen_zero_buf(val)) {
1462 ftdm_log(FTDM_LOG_NOTICE, "Ignoring empty R2 advanced_protocol_file parameter\n");
1463 continue;
1464 }
1465 r2conf.advanced_protocol_file = (char *)val;
1466 ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with advanced protocol file %s\n", span->name, val);
1467 } else if (!strcasecmp(var, "mf_dump_size")) {
1468 intval = atoi(val);
1469 if (intval < 0) {
1470 r2conf.mf_dump_size = FTDM_IO_DUMP_DEFAULT_BUFF_SIZE;
1471 ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with default mf_dump_size = %d bytes\n", span->name, r2conf.mf_dump_size);
1472 } else {
1473 r2conf.mf_dump_size = intval;
1474 ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with mf_dump_size = %d bytes\n", span->name, r2conf.mf_dump_size);
1475 }
1476 } else if (!strcasecmp(var, "allow_collect_calls")) {
1477 r2conf.allow_collect_calls = ftdm_true(val);
1478 ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with allow collect calls max ani = %d\n", span->name, r2conf.allow_collect_calls);
1479 } else if (!strcasecmp(var, "double_answer")) {
1480 r2conf.double_answer = ftdm_true(val);
1481 ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with double answer = %d\n", span->name, r2conf.double_answer);
1482 } else if (!strcasecmp(var, "immediate_accept")) {
1483 r2conf.immediate_accept = ftdm_true(val);
1484 ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with immediate accept = %d\n", span->name, r2conf.immediate_accept);
1485 } else if (!strcasecmp(var, "skip_category")) {
1486 r2conf.skip_category = ftdm_true(val);
1487 ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with skip category = %d\n", span->name, r2conf.skip_category);
1488 } else if (!strcasecmp(var, "forced_release")) {
1489 r2conf.forced_release = ftdm_true(val);
1490 ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with forced release = %d\n", span->name, r2conf.forced_release);
1491 } else if (!strcasecmp(var, "charge_calls")) {
1492 r2conf.charge_calls = ftdm_true(val);
1493 ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with charge calls = %d\n", span->name, r2conf.charge_calls);
1494 } else if (!strcasecmp(var, "get_ani_first")) {
1495 r2conf.get_ani_first = ftdm_true(val);
1496 ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with get ani first = %d\n", span->name, r2conf.get_ani_first);
1497 } else if (!strcasecmp(var, "call_files")) {
1498 r2conf.call_files = ftdm_true(val);
1499 ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with call files = %d\n", span->name, r2conf.call_files);
1500 } else if (!strcasecmp(var, "mfback_timeout")) {
1501 r2conf.mfback_timeout = atoi(val);
1502 ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with MF backward timeout = %dms\n", span->name, r2conf.mfback_timeout);
1503 } else if (!strcasecmp(var, "metering_pulse_timeout")) {
1504 r2conf.metering_pulse_timeout = atoi(val);
1505 ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with metering pulse timeout = %dms\n", span->name, r2conf.metering_pulse_timeout);
1506 } else if (!strcasecmp(var, "max_ani")) {
1507 r2conf.max_ani = atoi(val);
1508 ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with max ani = %d\n", span->name, r2conf.max_ani);
1509 } else if (!strcasecmp(var, "max_dnis")) {
1510 r2conf.max_dnis = atoi(val);
1511 ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with max dnis = %d\n", span->name, r2conf.max_dnis);
1512 } else {
1513 snprintf(span->last_error, sizeof(span->last_error), "Unknown R2 parameter [%s]", var);
1514 return FTDM_FAIL;
1515 }
1516 }
1517
1518 if (conf_failure) {
1519 snprintf(span->last_error, sizeof(span->last_error), "R2 configuration error");
1520 return FTDM_FAIL;
1521 }
1522
1523
1524 r2conf.loglevel = ftdm_r2_loglevel_from_string(log_level);
1525 ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with loglevel %s\n", span->span_id, log_level);
1526
1527 r2data = ftdm_malloc(sizeof(*r2data));
1528 if (!r2data) {
1529 snprintf(span->last_error, sizeof(span->last_error), "Failed to allocate R2 data.");
1530 return FTDM_FAIL;
1531 }
1532 memset(r2data, 0, sizeof(*r2data));
1533
1534 spanpvt = ftdm_malloc(sizeof(*spanpvt));
1535 if (!spanpvt) {
1536 snprintf(span->last_error, sizeof(span->last_error), "Failed to allocate private span data container.");
1537 goto fail;
1538 }
1539 memset(spanpvt, 0, sizeof(*spanpvt));
1540
1541 r2data->r2context = openr2_context_new(r2conf.variant, &ftdm_r2_event_iface, r2conf.max_ani, r2conf.max_dnis);
1542 if (!r2data->r2context) {
1543 snprintf(span->last_error, sizeof(span->last_error), "Cannot create openr2 context for span.");
1544 goto fail;
1545 }
1546 openr2_context_set_io_type(r2data->r2context, OR2_IO_CUSTOM, &ftdm_r2_io_iface);
1547 openr2_context_set_log_level(r2data->r2context, r2conf.loglevel);
1548 openr2_context_set_ani_first(r2data->r2context, r2conf.get_ani_first);
1549 openr2_context_set_skip_category_request(r2data->r2context, r2conf.skip_category);
1550 openr2_context_set_mf_back_timeout(r2data->r2context, r2conf.mfback_timeout);
1551 openr2_context_set_metering_pulse_timeout(r2data->r2context, r2conf.metering_pulse_timeout);
1552 openr2_context_set_double_answer(r2data->r2context, r2conf.double_answer);
1553 openr2_context_set_immediate_accept(r2data->r2context, r2conf.immediate_accept);
1554
1555 ftdm_log(FTDM_LOG_DEBUG, "Setting span %s logdir to %s\n", span->name, r2conf.logdir);
1556 openr2_context_set_log_directory(r2data->r2context, r2conf.logdir);
1557 snprintf(r2data->logdir, sizeof(r2data->logdir), "%s", r2conf.logdir);
1558
1559 if (r2conf.advanced_protocol_file) {
1560 openr2_context_configure_from_advanced_file(r2data->r2context, r2conf.advanced_protocol_file);
1561 }
1562
1563 spanpvt->r2calls = create_hashtable(FTDM_MAX_CHANNELS_SPAN, ftdm_hash_hashfromstring, ftdm_hash_equalkeys);
1564 if (!spanpvt->r2calls) {
1565 snprintf(span->last_error, sizeof(span->last_error), "Cannot create channel calls hash for span.");
1566 goto fail;
1567 }
1568
1569 for (i = 1; (i <= span->chan_count) && (i <= FTDM_MAX_CHANNELS_SPAN); i++) {
1570 r2chan = openr2_chan_new_from_fd(r2data->r2context, span->channels[i], span->channels[i]->chan_id);
1571 if (!r2chan) {
1572 snprintf(span->last_error, sizeof(span->last_error), "Cannot create all openr2 channels for span.");
1573 goto fail;
1574 }
1575 openr2_chan_set_log_level(r2chan, r2conf.loglevel);
1576 if (r2conf.call_files) {
1577 openr2_chan_enable_call_files(r2chan);
1578 }
1579
1580 r2call = ftdm_malloc(sizeof(*r2call));
1581 if (!r2call) {
1582 snprintf(span->last_error, sizeof(span->last_error), "Cannot create all R2 call data structures for the span.");
1583 ftdm_safe_free(r2chan);
1584 goto fail;
1585 }
1586 memset(r2call, 0, sizeof(*r2call));
1587 openr2_chan_set_logging_func(r2chan, ftdm_r2_on_chan_log);
1588 openr2_chan_set_client_data(r2chan, span->channels[i]);
1589 r2call->r2chan = r2chan;
1590 span->channels[i]->call_data = r2call;
1591
1592 snprintf(r2call->name, sizeof(r2call->name), "chancall%d", i);
1593 hashtable_insert(spanpvt->r2calls, (void *)r2call->name, r2call, HASHTABLE_FLAG_FREE_VALUE);
1594 }
1595 r2data->mf_dump_size = r2conf.mf_dump_size;
1596 r2data->category = r2conf.category;
1597 r2data->flags = 0;
1598 spanpvt->r2context = r2data->r2context;
1599
1600
1601 hashtable_insert(g_mod_data_hash, (void *)span->name, spanpvt, HASHTABLE_FLAG_FREE_VALUE);
1602
1603 span->start = ftdm_r2_start;
1604 span->stop = ftdm_r2_stop;
1605 span->sig_read = NULL;
1606 span->sig_write = NULL;
1607
1608 span->signal_cb = sig_cb;
1609 span->signal_type = FTDM_SIGTYPE_R2;
1610 span->signal_data = r2data;
1611 span->outgoing_call = r2_outgoing_call;
1612 span->get_span_sig_status = ftdm_r2_get_span_sig_status;
1613 span->set_span_sig_status = ftdm_r2_set_span_sig_status;
1614 span->get_channel_sig_status = ftdm_r2_get_channel_sig_status;
1615 span->set_channel_sig_status = ftdm_r2_set_channel_sig_status;
1616
1617 span->state_map = &r2_state_map;
1618 span->state_processor = ftdm_r2_state_advance;
1619
1620
1621 ftdm_set_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE);
1622
1623
1624 ftdm_set_flag(span, FTDM_SPAN_USE_SKIP_STATES);
1625
1626
1627 snprintf(schedname, sizeof(schedname), "ftmod_r2_%s", span->name);
1628 ftdm_assert(ftdm_sched_create(&r2data->sched, schedname) == FTDM_SUCCESS, "Failed to create schedule!\n");
1629 spanpvt->sched = r2data->sched;
1630
1631 return FTDM_SUCCESS;
1632
1633 fail:
1634
1635 if (r2data && r2data->r2context) {
1636 openr2_context_delete(r2data->r2context);
1637 }
1638 if (spanpvt && spanpvt->r2calls) {
1639 hashtable_destroy(spanpvt->r2calls);
1640 }
1641 ftdm_safe_free(r2data);
1642 ftdm_safe_free(spanpvt);
1643 return FTDM_FAIL;
1644
1645 }
1646
1647
1648 static ftdm_status_t ftdm_r2_state_advance(ftdm_channel_t *ftdmchan)
1649 {
1650 ftdm_sigmsg_t sigev;
1651 ftdm_status_t ret;
1652 ftdm_r2_call_t *r2call = R2CALL(ftdmchan);
1653 openr2_chan_t *r2chan = r2call->r2chan;
1654 ftdm_r2_data_t *r2data = ftdmchan->span->signal_data;
1655
1656 memset(&sigev, 0, sizeof(sigev));
1657 sigev.chan_id = ftdmchan->chan_id;
1658 sigev.span_id = ftdmchan->span_id;
1659 sigev.channel = ftdmchan;
1660
1661 ret = FTDM_SUCCESS;
1662
1663 ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Executing state handler for %s\n", ftdm_channel_state2str(ftdmchan->state));
1664
1665 if (IS_ACCEPTING_PENDING(ftdmchan)) {
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675 ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "State ack for state %s will have to wait a bit\n", ftdm_channel_state2str(ftdmchan->state));
1676 } else if (ftdmchan->state != FTDM_CHANNEL_STATE_DOWN){
1677 ftdm_channel_complete_state(ftdmchan);
1678 }
1679
1680 switch (ftdmchan->state) {
1681
1682
1683 case FTDM_CHANNEL_STATE_COLLECT:
1684 {
1685 uint32_t interval = 0;
1686 ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_INTERVAL, &interval);
1687 ftdm_assert(interval != 0, "Invalid interval!");
1688 ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Starting processing of incoming call with interval %d\n", interval);
1689 openr2_chan_enable_read(r2chan);
1690 }
1691 break;
1692
1693
1694 case FTDM_CHANNEL_STATE_DIALING:
1695 {
1696 uint32_t interval = 0;
1697 ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_INTERVAL, &interval);
1698 ftdm_assert(interval != 0, "Invalid interval!");
1699 ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Starting outgoing call with interval %d\n", interval);
1700 openr2_chan_enable_read(r2chan);
1701 }
1702 break;
1703
1704
1705 case FTDM_CHANNEL_STATE_RING:
1706
1707
1708 sigev.event_id = FTDM_SIGEVENT_START;
1709 ftdm_span_send_signal(ftdmchan->span, &sigev);
1710 break;
1711
1712
1713 case FTDM_CHANNEL_STATE_PROGRESS:
1714 case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
1715 {
1716 if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
1717 if (!r2call->accepted) {
1718 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Accepting call\n");
1719 ft_r2_accept_call(ftdmchan);
1720 }
1721 } else {
1722 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Notifying progress\n");
1723 sigev.event_id = FTDM_SIGEVENT_PROGRESS_MEDIA;
1724 ftdm_span_send_signal(ftdmchan->span, &sigev);
1725 }
1726 }
1727 break;
1728
1729
1730 case FTDM_CHANNEL_STATE_UP:
1731 {
1732 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Call was answered\n");
1733 if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
1734 if (!r2call->accepted) {
1735 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Call has not been accepted, need to accept first\n");
1736
1737 ft_r2_accept_call(ftdmchan);
1738 r2call->answer_pending = 1;
1739 } else {
1740 ft_r2_answer_call(ftdmchan);
1741 }
1742 } else {
1743 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Notifying of call answered\n");
1744 sigev.event_id = FTDM_SIGEVENT_UP;
1745 ftdm_span_send_signal(ftdmchan->span, &sigev);
1746 }
1747 }
1748 break;
1749
1750
1751 case FTDM_CHANNEL_STATE_HANGUP:
1752 {
1753 if (!r2call->disconnect_rcvd) {
1754 openr2_call_disconnect_cause_t disconnect_cause = ftdm_r2_ftdm_cause_to_openr2_cause(ftdmchan);
1755 ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Clearing call, cause = %s\n", openr2_proto_get_disconnect_string(disconnect_cause));
1756
1757 openr2_chan_disconnect_call(r2chan, disconnect_cause);
1758 } else if (!r2call->protocol_error) {
1759
1760 openr2_chan_disconnect_call(r2chan, OR2_CAUSE_NORMAL_CLEARING);
1761 } else {
1762 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Clearing call due to protocol error\n");
1763
1764 ftdm_sched_timer(r2data->sched, "protocolerr_recover", 100,
1765 ftdm_r2_recover_from_protocol_error, r2chan, &r2call->protocol_error_recovery_timer);
1766 }
1767 }
1768 break;
1769
1770 case FTDM_CHANNEL_STATE_TERMINATING:
1771 {
1772
1773 if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_CALL_STARTED)) {
1774 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
1775 } else {
1776 openr2_call_disconnect_cause_t disconnect_cause = ftdm_r2_ftdm_cause_to_openr2_cause(ftdmchan);
1777 ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Clearing call, cause = %s\n", openr2_proto_get_disconnect_string(disconnect_cause));
1778
1779 sigev.event_id = FTDM_SIGEVENT_STOP;
1780 ftdm_span_send_signal(ftdmchan->span, &sigev);
1781 }
1782 }
1783 break;
1784
1785
1786 case FTDM_CHANNEL_STATE_DOWN:
1787 {
1788 if (ftdmchan->last_state != FTDM_CHANNEL_STATE_RESET) {
1789 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "R2 Call is down\n");
1790 } else {
1791 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "R2 Reset Complete\n");
1792 }
1793 ret = FTDM_BREAK;
1794 }
1795 break;
1796
1797
1798 case FTDM_CHANNEL_STATE_RINGING:
1799 {
1800 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "RINGING indicated, ignoring it as it doesn't apply to MFC/R2\n");
1801 }
1802 break;
1803
1804
1805 case FTDM_CHANNEL_STATE_RESET:
1806 {
1807 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "RESET indicated, putting the R2 channel back to IDLE\n");
1808 openr2_chan_set_idle(r2chan);
1809 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
1810 }
1811 break;
1812
1813 default:
1814 {
1815 ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Unhandled channel state change: %s\n", ftdm_channel_state2str(ftdmchan->state));
1816 }
1817 break;
1818 }
1819
1820 if (ret == FTDM_BREAK) {
1821 ftdm_channel_t *closed_chan;
1822 closed_chan = ftdmchan;
1823 ftdm_channel_close(&closed_chan);
1824 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "State processing ended.\n");
1825 }
1826 return ret;
1827 }
1828
1829 static void *ftdm_r2_run(ftdm_thread_t *me, void *obj)
1830 {
1831 openr2_chan_t *r2chan = NULL;
1832 ftdm_channel_t *ftdmchan = NULL;
1833 ftdm_r2_call_t *call = NULL;
1834 ftdm_status_t status;
1835 ftdm_span_t *span = (ftdm_span_t *) obj;
1836 ftdm_r2_data_t *r2data = span->signal_data;
1837 int waitms = 20;
1838 unsigned int i;
1839 int res, ms;
1840 int index = 0;
1841 struct timeval start, end;
1842 ftdm_iterator_t *chaniter = NULL;
1843 ftdm_iterator_t *citer = NULL;
1844 uint32_t txqueue_size = 4;
1845 short *poll_events = ftdm_malloc(sizeof(short) * span->chan_count);
1846
1847
1848 ftdm_set_flag(r2data, FTDM_R2_RUNNING);
1849
1850 #ifdef __linux__
1851 r2data->monitor_thread_id = syscall(SYS_gettid);
1852 #endif
1853
1854 ftdm_log(FTDM_LOG_DEBUG, "OpenR2 monitor thread %lu started.\n", r2data->monitor_thread_id);
1855 r2chan = NULL;
1856 chaniter = ftdm_span_get_chan_iterator(span, NULL);
1857 if (!chaniter) {
1858 ftdm_log(FTDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name);
1859 goto done;
1860 }
1861 for (i = 1, citer = chaniter; citer; citer = ftdm_iterator_next(citer), i++) {
1862 ftdmchan = ftdm_iterator_current(citer);
1863 ftdm_channel_lock(ftdmchan);
1864 r2chan = R2CALL(ftdmchan)->r2chan;
1865 openr2_chan_set_span_id(r2chan, span->span_id);
1866 openr2_chan_set_idle(r2chan);
1867 openr2_chan_process_cas_signaling(r2chan);
1868 ftdm_channel_unlock(ftdmchan);
1869 ftdm_channel_command(ftdmchan, FTDM_COMMAND_SET_TX_QUEUE_SIZE, &txqueue_size);
1870 }
1871
1872 memset(&start, 0, sizeof(start));
1873 memset(&end, 0, sizeof(end));
1874 while (ftdm_running() && ftdm_test_flag(r2data, FTDM_R2_SPAN_STARTED)) {
1875 res = gettimeofday(&end, NULL);
1876 if (res) {
1877 ftdm_log(FTDM_LOG_CRIT, "Failure gettimeofday [%s]\n", strerror(errno));
1878 }
1879 if (start.tv_sec) {
1880 ms = ((end.tv_sec - start.tv_sec) * 1000)
1881 + ((( 1000000 + end.tv_usec - start.tv_usec) / 1000) - 1000);
1882 if (ms < 0) {
1883 ms = 0;
1884 }
1885 if (ms > r2data->jobmax) {
1886 r2data->jobmax = ms;
1887 }
1888 index = (ms / 10);
1889 index = (index > 10) ? 10 : index;
1890 r2data->loops[index]++;
1891 r2data->total_loops++;
1892 }
1893
1894
1895 ftdm_sched_run(r2data->sched);
1896
1897
1898 ftdm_span_trigger_signals(span);
1899
1900
1901
1902 memset(poll_events, 0, sizeof(short)*span->chan_count);
1903 citer = ftdm_span_get_chan_iterator(span, chaniter);
1904 if (!citer) {
1905 ftdm_log(FTDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name);
1906 goto done;
1907 }
1908 for (i = 0; citer; citer = ftdm_iterator_next(citer), i++) {
1909 ftdmchan = ftdm_iterator_current(citer);
1910 r2chan = R2CALL(ftdmchan)->r2chan;
1911 poll_events[i] = FTDM_EVENTS;
1912 if (openr2_chan_get_read_enabled(r2chan)) {
1913 poll_events[i] |= FTDM_READ;
1914 }
1915 }
1916 status = ftdm_span_poll_event(span, waitms, poll_events);
1917
1918
1919 ftdm_sched_run(r2data->sched);
1920
1921 res = gettimeofday(&start, NULL);
1922 if (res) {
1923 ftdm_log(FTDM_LOG_CRIT, "Failure gettimeofday [%s]\n", strerror(errno));
1924 }
1925
1926 if (FTDM_FAIL == status) {
1927 ftdm_log(FTDM_LOG_CRIT, "Failure waiting I/O! [%s]\n", span->channels[1]->last_error);
1928 continue;
1929 }
1930
1931 ms = ((start.tv_sec - end.tv_sec) * 1000)
1932 + ((( 1000000 + start.tv_usec - end.tv_usec) / 1000) - 1000);
1933 if (ms < 0) {
1934 ms = 0;
1935 }
1936 if (ms > r2data->sleepmax) {
1937 r2data->sleepmax = ms;
1938 }
1939 index = (ms / 15);
1940 index = (index > 10) ? 10 : index;
1941 r2data->sleeps[index]++;
1942 r2data->total_sleeps++;
1943
1944
1945
1946 citer = ftdm_span_get_chan_iterator(span, chaniter);
1947 for ( ; citer; citer = ftdm_iterator_next(citer)) {
1948 ftdmchan = ftdm_iterator_current(citer);
1949
1950 ftdm_channel_lock(ftdmchan);
1951
1952 call = R2CALL(ftdmchan);
1953
1954
1955
1956 ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_RX_DISABLED);
1957 ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_TX_DISABLED);
1958
1959 ftdm_channel_advance_states(ftdmchan);
1960
1961 r2chan = call->r2chan;
1962 openr2_chan_process_signaling(r2chan);
1963
1964 ftdm_channel_advance_states(ftdmchan);
1965
1966 if (!call->accepted) {
1967
1968 ftdm_set_flag(ftdmchan, FTDM_CHANNEL_RX_DISABLED);
1969 ftdm_set_flag(ftdmchan, FTDM_CHANNEL_TX_DISABLED);
1970 }
1971
1972 ftdm_channel_unlock(ftdmchan);
1973 }
1974 }
1975
1976 done:
1977 citer = ftdm_span_get_chan_iterator(span, chaniter);
1978 for ( ; citer; citer = ftdm_iterator_next(citer)) {
1979 ftdmchan = ftdm_iterator_current(citer);
1980 ftdm_channel_lock(ftdmchan);
1981 r2chan = R2CALL(ftdmchan)->r2chan;
1982 openr2_chan_set_blocked(r2chan);
1983 ftdm_channel_unlock(ftdmchan);
1984 }
1985
1986 ftdm_iterator_free(chaniter);
1987 ftdm_safe_free(poll_events);
1988
1989 ftdm_clear_flag(r2data, FTDM_R2_RUNNING);
1990 ftdm_log(FTDM_LOG_DEBUG, "R2 thread ending.\n");
1991
1992 return NULL;
1993 }
1994
1995 static void __inline__ block_channel(ftdm_channel_t *fchan, ftdm_stream_handle_t *stream)
1996 {
1997 openr2_chan_t *r2chan = R2CALL(fchan)->r2chan;
1998 ftdm_mutex_lock(fchan->mutex);
1999 if (fchan->state != FTDM_CHANNEL_STATE_DOWN) {
2000 stream->write_function(stream, "cannot block channel %d:%d because has a call in progress\n",
2001 fchan->span_id, fchan->chan_id);
2002 } else if (ftdm_test_flag(fchan, FTDM_CHANNEL_SUSPENDED)) {
2003 stream->write_function(stream, "cannot block channel %d:%d because is already blocked\n",
2004 fchan->span_id, fchan->chan_id);
2005 } else {
2006 if (!openr2_chan_set_blocked(r2chan)) {
2007 ftdm_set_flag(fchan, FTDM_CHANNEL_SUSPENDED);
2008 stream->write_function(stream, "blocked channel %d:%d\n",
2009 fchan->span_id, fchan->chan_id);
2010 } else {
2011 stream->write_function(stream, "failed to block channel %d:%d\n",
2012 fchan->span_id, fchan->chan_id);
2013 }
2014 }
2015 ftdm_mutex_unlock(fchan->mutex);
2016 }
2017
2018 static void __inline__ unblock_channel(ftdm_channel_t *fchan, ftdm_stream_handle_t *stream)
2019 {
2020 openr2_chan_t *r2chan = R2CALL(fchan)->r2chan;
2021 ftdm_mutex_lock(fchan->mutex);
2022 if (ftdm_test_flag(fchan, FTDM_CHANNEL_SUSPENDED)) {
2023 if (!openr2_chan_set_idle(r2chan)) {
2024 ftdm_clear_flag(fchan, FTDM_CHANNEL_SUSPENDED);
2025 stream->write_function(stream, "unblocked channel %d:%d\n",
2026 fchan->span_id, fchan->chan_id);
2027 } else {
2028 stream->write_function(stream, "failed to unblock channel %d:%d\n",
2029 fchan->span_id, fchan->chan_id);
2030 }
2031 } else {
2032 stream->write_function(stream, "cannot unblock channel %d:%d because is not blocked\n",
2033 fchan->span_id, fchan->chan_id);
2034 }
2035 ftdm_mutex_unlock(fchan->mutex);
2036 }
2037
2038 #define FT_SYNTAX "USAGE:\n" \
2039 "--------------------------------------------------------------------------------\n" \
2040 "ftdm r2 status <span_id|span_name>\n" \
2041 "ftdm r2 loopstats <span_id|span_name>\n" \
2042 "ftdm r2 block|unblock <span_id|span_name> [<chan_id>]\n" \
2043 "ftdm r2 version\n" \
2044 "ftdm r2 variants\n" \
2045 "--------------------------------------------------------------------------------\n"
2046 static FIO_API_FUNCTION(ftdm_r2_api)
2047 {
2048 ftdm_span_t *span = NULL;
2049 char *mycmd = NULL, *argv[10] = { 0 };
2050 int argc = 0;
2051 int span_id = 0;
2052 unsigned int chan_id = 0;
2053 unsigned int i = 0;
2054 ftdm_r2_data_t *r2data = NULL;
2055 openr2_chan_t *r2chan = NULL;
2056 openr2_context_t *r2context = NULL;
2057 openr2_variant_t r2variant;
2058
2059 if (data) {
2060 mycmd = ftdm_strdup(data);
2061 argc = ftdm_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
2062 }
2063
2064 if (argc >= 2) {
2065 if (!strcasecmp(argv[0], "block")) {
2066 int span_id = atoi(argv[1]);
2067
2068 if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS || ftdm_span_find(span_id, &span) == FTDM_SUCCESS) {
2069
2070 if (span->start != ftdm_r2_start) {
2071 stream->write_function(stream, "-ERR invalid span.\n");
2072 goto done;
2073 }
2074
2075 if (argc > 2) {
2076 chan_id = atoi(argv[2]);
2077 if (chan_id && chan_id <= span->chan_count) {
2078 block_channel(span->channels[chan_id], stream);
2079 } else {
2080 stream->write_function(stream, "-ERR invalid chan %d.\n", chan_id);
2081 }
2082 } else {
2083 for (i = 1; i <= span->chan_count; i++) {
2084 block_channel(span->channels[i], stream);
2085 }
2086 }
2087 stream->write_function(stream, "+OK blocked.\n");
2088 goto done;
2089 } else {
2090 stream->write_function(stream, "-ERR invalid span.\n");
2091 goto done;
2092 }
2093 }
2094
2095 if (!strcasecmp(argv[0], "unblock")) {
2096 span_id = atoi(argv[1]);
2097 if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS || ftdm_span_find(span_id, &span) == FTDM_SUCCESS) {
2098
2099 if (span->start != ftdm_r2_start) {
2100 stream->write_function(stream, "-ERR invalid span.\n");
2101 goto done;
2102 }
2103
2104 if (argc > 2) {
2105 chan_id = atoi(argv[2]);
2106 if (chan_id && chan_id <= span->chan_count) {
2107 unblock_channel(span->channels[chan_id], stream);
2108 } else {
2109 stream->write_function(stream, "-ERR invalid chan %d.\n", chan_id);
2110 }
2111 } else {
2112 for (i = 1; i <= span->chan_count; i++) {
2113 unblock_channel(span->channels[i], stream);
2114 }
2115 }
2116
2117 stream->write_function(stream, "+OK.\n");
2118 goto done;
2119 } else {
2120 stream->write_function(stream, "-ERR invalid span.\n");
2121 goto done;
2122 }
2123
2124 }
2125
2126 if (!strcasecmp(argv[0], "status")) {
2127
2128 span_id = atoi(argv[1]);
2129
2130 if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS || ftdm_span_find(span_id, &span) == FTDM_SUCCESS) {
2131 if (span->start != ftdm_r2_start) {
2132 stream->write_function(stream, "-ERR not an R2 span.\n");
2133 goto done;
2134 }
2135 if (!(r2data = span->signal_data)) {
2136 stream->write_function(stream, "-ERR invalid span. No R2 signal data in span.\n");
2137 goto done;
2138 }
2139 r2context = r2data->r2context;
2140 r2variant = openr2_context_get_variant(r2context);
2141 stream->write_function(stream,
2142 "Variant: %s\n"
2143 "Max ANI: %d\n"
2144 "Max DNIS: %d\n"
2145 "ANI First: %s\n"
2146 "Immediate Accept: %s\n"
2147 "Job Thread: %u\n"
2148 "Job Max ms: %d\n"
2149 "Job Loops: %lu\n",
2150 openr2_proto_get_variant_string(r2variant),
2151 openr2_context_get_max_ani(r2context),
2152 openr2_context_get_max_dnis(r2context),
2153 openr2_context_get_ani_first(r2context) ? "Yes" : "No",
2154 openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
2155 r2data->monitor_thread_id,
2156 r2data->jobmax,
2157 r2data->total_loops);
2158 stream->write_function(stream, "\n");
2159 stream->write_function(stream, "%4s %-12.12s %-12.12s\n", "Channel", "Tx CAS", "Rx CAS");
2160 for (i = 1; i <= span->chan_count; i++) {
2161 r2chan = R2CALL(span->channels[i])->r2chan;
2162 stream->write_function(stream, "%4d %-12.12s %-12.12s\n",
2163 span->channels[i]->chan_id,
2164 openr2_chan_get_tx_cas_string(r2chan),
2165 openr2_chan_get_rx_cas_string(r2chan));
2166 }
2167 stream->write_function(stream, "\n");
2168 stream->write_function(stream, "+OK.\n");
2169 goto done;
2170 } else {
2171 stream->write_function(stream, "-ERR invalid span.\n");
2172 goto done;
2173 }
2174 }
2175
2176 if (!strcasecmp(argv[0], "loopstats")) {
2177 int range;
2178 float pct;
2179 span_id = atoi(argv[1]);
2180
2181 if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS || ftdm_span_find(span_id, &span) == FTDM_SUCCESS) {
2182 if (span->start != ftdm_r2_start) {
2183 stream->write_function(stream, "-ERR not an R2 span.\n");
2184 goto done;
2185 }
2186 if (!(r2data = span->signal_data)) {
2187 stream->write_function(stream, "-ERR invalid span. No R2 signal data in span.\n");
2188 goto done;
2189 }
2190 stream->write_function(stream, "-- Working --\n");
2191 stream->write_function(stream, "Total loops: %llu\n", r2data->total_loops);
2192 range = 0;
2193 for (i = 0; i < ftdm_array_len(r2data->loops); i++) {
2194 pct = 100*(float)r2data->loops[i]/r2data->total_loops;
2195 if ((i + 1) == ftdm_array_len(r2data->loops)) {
2196 stream->write_function(stream, ">= %dms: %llu - %.03lf%%\n", range, r2data->loops[i], pct);
2197 } else {
2198 stream->write_function(stream, "%d-%dms: %llu - %.03lf%%\n", range, range + 9, r2data->loops[i], pct);
2199 }
2200 range += 10;
2201 }
2202 stream->write_function(stream, "\n");
2203
2204 stream->write_function(stream, "-- Sleeping --\n");
2205 stream->write_function(stream, "Total sleeps: %llu\n", r2data->total_sleeps);
2206 range = 0;
2207 for (i = 0; i < ftdm_array_len(r2data->sleeps); i++) {
2208 pct = 100*(float)r2data->sleeps[i]/r2data->total_sleeps;
2209 if ((i + 1) == ftdm_array_len(r2data->sleeps)) {
2210 stream->write_function(stream, ">= %dms: %llu - %.03lf%%\n", range, r2data->sleeps[i], pct);
2211 } else {
2212 stream->write_function(stream, "%d-%dms: %llu - %.03lf%%\n", range, range + 14, r2data->sleeps[i], pct);
2213 }
2214 range += 15;
2215 }
2216 stream->write_function(stream, "\n");
2217
2218 stream->write_function(stream, "+OK.\n");
2219 goto done;
2220 } else {
2221 stream->write_function(stream, "-ERR invalid span.\n");
2222 goto done;
2223 }
2224 }
2225
2226 }
2227
2228 if (argc == 1) {
2229 if (!strcasecmp(argv[0], "version")) {
2230 stream->write_function(stream, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
2231 stream->write_function(stream, "+OK.\n");
2232 goto done;
2233 }
2234
2235 if (!strcasecmp(argv[0], "variants")) {
2236 int32_t numvariants = 0;
2237 const openr2_variant_entry_t *variants = openr2_proto_get_variant_list(&numvariants);
2238 if (!variants) {
2239 stream->write_function(stream, "-ERR failed to retrieve openr2 variant list.\n");
2240 goto done;
2241 }
2242 #define VARIANT_FORMAT "%4s %40s\n"
2243 stream->write_function(stream, VARIANT_FORMAT, "Variant Code", "Country");
2244 numvariants--;
2245 for (; numvariants; numvariants--) {
2246 stream->write_function(stream, VARIANT_FORMAT, variants[numvariants].name, variants[numvariants].country);
2247 }
2248 stream->write_function(stream, "+OK.\n");
2249 #undef VARIANT_FORMAT
2250 goto done;
2251 }
2252 }
2253
2254 stream->write_function(stream, "%s", FT_SYNTAX);
2255
2256 done:
2257
2258 ftdm_safe_free(mycmd);
2259
2260 return FTDM_SUCCESS;
2261
2262 }
2263
2264 static FIO_IO_LOAD_FUNCTION(ftdm_r2_io_init)
2265 {
2266 assert(fio != NULL);
2267 memset(&g_ftdm_r2_interface, 0, sizeof(g_ftdm_r2_interface));
2268
2269 g_ftdm_r2_interface.name = "r2";
2270 g_ftdm_r2_interface.api = ftdm_r2_api;
2271
2272 *fio = &g_ftdm_r2_interface;
2273
2274 return FTDM_SUCCESS;
2275 }
2276
2277 static FIO_SIG_LOAD_FUNCTION(ftdm_r2_init)
2278 {
2279 g_mod_data_hash = create_hashtable(10, ftdm_hash_hashfromstring, ftdm_hash_equalkeys);
2280 if (!g_mod_data_hash) {
2281 return FTDM_FAIL;
2282 }
2283 return FTDM_SUCCESS;
2284 }
2285
2286 static FIO_SIG_UNLOAD_FUNCTION(ftdm_r2_destroy)
2287 {
2288 ftdm_hash_iterator_t *i = NULL;
2289 ftdm_r2_span_pvt_t *spanpvt = NULL;
2290 const void *key = NULL;
2291 void *val = NULL;
2292 for (i = hashtable_first(g_mod_data_hash); i; i = hashtable_next(i)) {
2293 hashtable_this(i, &key, NULL, &val);
2294 if (key && val) {
2295 spanpvt = val;
2296 openr2_context_delete(spanpvt->r2context);
2297 hashtable_destroy(spanpvt->r2calls);
2298 ftdm_sched_destroy(&spanpvt->sched);
2299 }
2300 }
2301 hashtable_destroy(g_mod_data_hash);
2302 return FTDM_SUCCESS;
2303 }
2304
2305 EX_DECLARE_DATA ftdm_module_t ftdm_module = {
2306 "r2",
2307 ftdm_r2_io_init,
2308 NULL,
2309 ftdm_r2_init,
2310 NULL,
2311 ftdm_r2_destroy,
2312 ftdm_r2_configure_span_signaling
2313 };
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325