From 6cbf8a0167d9a3d79ff3846e14bc90dbf4fe7371 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Wed, 10 Nov 2010 19:03:15 -0500 Subject: [PATCH 001/237] freetdm: ISDN - Changes to used ftdm IO for d-channel --- .../freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c | 1 - .../ftmod_sangoma_boost/ftmod_sangoma_boost.c | 8 +- .../ftmod_sangoma_isdn/ftmod_sangoma_isdn.c | 168 ++++++++++++++---- .../ftmod_sangoma_isdn/ftmod_sangoma_isdn.h | 51 +++--- .../ftmod_sangoma_isdn_cfg.c | 33 ++-- .../ftmod_sangoma_isdn_stack_cfg.c | 107 +++++------ .../ftmod_sangoma_isdn_stack_cntrl.c | 83 ++++++--- .../ftmod_sangoma_isdn_stack_hndl.c | 2 +- .../ftmod_sangoma_isdn_stack_out.c | 11 ++ .../ftmod_sangoma_isdn_stack_rcv.c | 24 ++- .../ftmod_sangoma_isdn_support.c | 35 +++- libs/freetdm/src/include/private/ftdm_core.h | 2 + libs/freetdm/src/include/private/ftdm_types.h | 3 +- 13 files changed, 369 insertions(+), 159 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c index 65c9dfc11f..d64e711e73 100644 --- a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c +++ b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c @@ -53,7 +53,6 @@ //#define IODEBUG /* helper macros */ -#define FTDM_SPAN_IS_BRI(x) ((x)->trunk_type == FTDM_TRUNK_BRI || (x)->trunk_type == FTDM_TRUNK_BRI_PTMP) #define FTDM_SPAN_IS_NT(x) (((ftdm_isdn_data_t *)(x)->signal_data)->mode == Q921_NT) diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c index a975204b62..c9691e232b 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c @@ -1557,11 +1557,11 @@ static __inline__ ftdm_status_t state_advance(ftdm_channel_t *ftdmchan) ftdm_set_string(event.calling_name, ftdmchan->caller_data.cid_name); ftdm_set_string(event.rdnis.digits, ftdmchan->caller_data.rdnis.digits); if (strlen(ftdmchan->caller_data.rdnis.digits)) { - event.rdnis.digits_count = (uint8_t)strlen(ftdmchan->caller_data.rdnis.digits)+1; - event.rdnis.ton = ftdmchan->caller_data.rdnis.type; - event.rdnis.npi = ftdmchan->caller_data.rdnis.plan; + event.rdnis.digits_count = (uint8_t)strlen(ftdmchan->caller_data.rdnis.digits)+1; + event.rdnis.ton = ftdmchan->caller_data.rdnis.type; + event.rdnis.npi = ftdmchan->caller_data.rdnis.plan; } - + event.calling.screening_ind = ftdmchan->caller_data.screen; event.calling.presentation_ind = ftdmchan->caller_data.pres; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c index 22c89cb920..04c3b86c5e 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c @@ -47,6 +47,8 @@ static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span); ftdm_channel_t* ftdm_sangoma_isdn_process_event_states(ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event); static void ftdm_sangoma_isdn_advance_chan_states(ftdm_channel_t *ftdmchan); +static void ftdm_sangoma_isdn_poll_events(ftdm_span_t *span); +static void ftdm_sangoma_isdn_process_phy_events(ftdm_span_t *span, ftdm_oob_event_t event); static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan); static void ftdm_sangoma_isdn_process_stack_event (ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event); @@ -56,7 +58,7 @@ static sng_isdn_event_interface_t g_sngisdn_event_interface; ftdm_sngisdn_data_t g_sngisdn_data; -extern ftdm_status_t sng_isdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t trace_opt); +extern ftdm_status_t sngisdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t trace_opt); extern ftdm_status_t sngisdn_check_free_ids(void); ftdm_state_map_t sangoma_isdn_state_map = { @@ -238,6 +240,106 @@ static __inline__ void ftdm_sangoma_isdn_advance_chan_states(ftdm_channel_t *ftd } } +static void ftdm_sangoma_isdn_process_phy_events(ftdm_span_t *span, ftdm_oob_event_t event) +{ + + switch (event) { + /* Check if the span woke up from power-saving mode */ + case FTDM_OOB_ALARM_CLEAR: + sngisdn_snd_event(span, SNG_L1EVENT_ALARM_OFF); + if (FTDM_SPAN_IS_BRI(span)) { + ftdm_channel_t *ftdmchan; + ftdm_iterator_t *chaniter = NULL; + ftdm_iterator_t *curr = NULL; + sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data; + + chaniter = ftdm_span_get_chan_iterator(span, NULL); + for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) { + ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr); + sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data; + + if (ftdm_test_flag(sngisdn_info, FLAG_ACTIVATING)) { + ftdm_clear_flag(sngisdn_info, FLAG_ACTIVATING); + + ftdm_sched_timer(signal_data->sched, "delayed_setup", 1, sngisdn_delayed_setup, (void*) ftdmchan->call_data, NULL); + } + } + ftdm_iterator_free(chaniter); + } + break; + case FTDM_OOB_ALARM_TRAP: + sngisdn_snd_event(span, SNG_L1EVENT_ALARM_ON); + break; + default: + /* Ignore other events for now */ + break; + } +} + +static void ftdm_sangoma_isdn_poll_events(ftdm_span_t *span) +{ + ftdm_status_t ret_status; + ret_status = ftdm_span_poll_event(span, 0, NULL); + switch(ret_status) { + case FTDM_SUCCESS: + { + ftdm_event_t *event; + while (ftdm_span_next_event(span, &event) == FTDM_SUCCESS) { + ftdm_sangoma_isdn_process_phy_events(span, event->enum_id); + } + } + break; + case FTDM_TIMEOUT: + /* No events pending */ + break; + default: + ftdm_log(FTDM_LOG_WARNING, "%s:Failed to poll span event\n", span->name); + } +} + +static void *ftdm_sangoma_isdn_dchan_run(ftdm_thread_t *me, void *obj) +{ + uint8_t data[1000]; + ftdm_status_t status = FTDM_SUCCESS; + ftdm_wait_flag_t wflags = FTDM_READ; + ftdm_span_t *span = (ftdm_span_t*) obj; + ftdm_channel_t *dchan = ((sngisdn_span_data_t*)span->signal_data)->dchan; + ftdm_size_t len = 0; + + + ftdm_assert(dchan, "Span does not have a dchannel"); + ftdm_channel_open_chan(dchan); + + while (ftdm_running() && !(ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD))) { + wflags = FTDM_READ; + status = ftdm_channel_wait(dchan, &wflags, 0); + switch(status) { + case FTDM_FAIL: + ftdm_log_chan_msg(dchan, FTDM_LOG_CRIT, "Failed to wait for d-channel\n"); + break; + case FTDM_TIMEOUT: + break; + case FTDM_SUCCESS: + if ((wflags & FTDM_READ)) { + len = 1000; + status = ftdm_channel_read(dchan, data, &len); + if (status == FTDM_SUCCESS) { + sngisdn_snd_data(span, data, len); + } else { + ftdm_log_chan_msg(dchan, FTDM_LOG_WARNING, "Failed to read from channel \n"); + } + } else { + ftdm_log_chan_msg(dchan, FTDM_LOG_CRIT, "Failed to poll for d-channel\n"); + } + break; + default: + ftdm_log_chan_msg(dchan, FTDM_LOG_CRIT, "Unhandled IO event\n"); + } + } + ftdm_channel_close(&dchan); + return NULL; +} + static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj) { ftdm_interrupt_t *ftdm_sangoma_isdn_int[2]; @@ -300,21 +402,8 @@ static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj) } /* Poll for events, e.g HW DTMF */ - ret_status = ftdm_span_poll_event(span, 0, NULL); - switch(ret_status) { - case FTDM_SUCCESS: - { - ftdm_event_t *event; - while (ftdm_span_next_event(span, &event) == FTDM_SUCCESS); - } - break; - case FTDM_TIMEOUT: - /* No events pending */ - break; - default: - ftdm_log(FTDM_LOG_WARNING, "%s:Failed to poll span event\n", span->name); - } - + ftdm_sangoma_isdn_poll_events(span); + if (ftdm_sched_get_time_to_next_timer(signal_data->sched, &sleep) == FTDM_SUCCESS) { if (sleep < 0 || sleep > SNGISDN_EVENT_POLL_RATE) { sleep = SNGISDN_EVENT_POLL_RATE; @@ -498,8 +587,20 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan) } break; case FTDM_CHANNEL_STATE_DIALING: /* outgoing call request */ - { - sngisdn_snd_setup(ftdmchan); + { + if (FTDM_SPAN_IS_BRI(ftdmchan->span) && + ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM) && + ftdm_test_flag(ftdmchan->span, FTDM_SPAN_PWR_SAVING)) { + + sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; + + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Requesting Line activation\n"); + sngisdn_set_flag(sngisdn_info, FLAG_ACTIVATING); + sngisdn_wake_up_phy(ftdmchan->span); + ftdm_sched_timer(signal_data->sched, "timer_t3", signal_data->timer_t3*1000, sngisdn_t3_timeout, (void*) sngisdn_info, NULL); + } else { + sngisdn_snd_setup(ftdmchan); + } } break; case FTDM_CHANNEL_STATE_PROGRESS: @@ -592,7 +693,7 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan) sngisdn_snd_release(ftdmchan, 0); if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) { - sng_isdn_set_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN); + sngisdn_set_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN); } } else { sngisdn_snd_disconnect(ftdmchan); @@ -747,7 +848,7 @@ static FIO_SPAN_SET_SIG_STATUS_FUNCTION(ftdm_sangoma_isdn_set_span_sig_status) static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span) { ftdm_log(FTDM_LOG_INFO,"Starting span %s:%u.\n",span->name,span->span_id); - if (sng_isdn_stack_start(span) != FTDM_SUCCESS) { + if (sngisdn_stack_start(span) != FTDM_SUCCESS) { ftdm_log(FTDM_LOG_CRIT, "Failed to start span %s\n", span->name); return FTDM_FAIL; } @@ -761,6 +862,12 @@ static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span) return FTDM_FAIL; } + /*start the dchan monitor thread*/ + if (ftdm_thread_create_detached(ftdm_sangoma_isdn_dchan_run, span) != FTDM_SUCCESS) { + ftdm_log(FTDM_LOG_CRIT,"Failed to start Sangoma ISDN d-channel Monitor Thread!\n"); + return FTDM_FAIL; + } + ftdm_log(FTDM_LOG_DEBUG,"Finished starting span %s\n", span->name); return FTDM_SUCCESS; } @@ -782,7 +889,7 @@ static ftdm_status_t ftdm_sangoma_isdn_stop(ftdm_span_t *span) ftdm_sleep(10); } - if (sng_isdn_stack_stop(span) != FTDM_SUCCESS) { + if (sngisdn_stack_stop(span) != FTDM_SUCCESS) { ftdm_log(FTDM_LOG_CRIT, "Failed to stop span %s\n", span->name); } @@ -834,7 +941,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config) return FTDM_FAIL; } - if (sng_isdn_stack_cfg(span) != FTDM_SUCCESS) { + if (sngisdn_stack_cfg(span) != FTDM_SUCCESS) { ftdm_log(FTDM_LOG_CRIT, "Sangoma ISDN Stack configuration failed\n"); return FTDM_FAIL; } @@ -856,9 +963,8 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config) if (span->trunk_type == FTDM_TRUNK_BRI_PTMP || span->trunk_type == FTDM_TRUNK_BRI) { - - ftdm_set_flag(span, FTDM_SPAN_USE_AV_RATE); - sng_isdn_set_avail_rate(span, SNGISDN_AVAIL_PWR_SAVING); + + sngisdn_set_avail_rate(span, SNGISDN_AVAIL_PWR_SAVING); } /* Initialize scheduling context */ @@ -906,7 +1012,9 @@ static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_isdn_init) g_sngisdn_event_interface.sta.sng_q921_trc_ind = sngisdn_rcv_q921_trace; g_sngisdn_event_interface.sta.sng_q931_sta_ind = sngisdn_rcv_q931_ind; g_sngisdn_event_interface.sta.sng_q931_trc_ind = sngisdn_rcv_q931_trace; - g_sngisdn_event_interface.sta.sng_cc_sta_ind = sngisdn_rcv_cc_ind; + g_sngisdn_event_interface.sta.sng_cc_sta_ind = sngisdn_rcv_cc_ind; + + g_sngisdn_event_interface.io.sng_data_req = sngisdn_rcv_data_req; for(i=1;i<=MAX_VARIANTS;i++) { ftdm_mutex_create(&g_sngisdn_data.ccs[i].mutex); @@ -914,7 +1022,7 @@ static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_isdn_init) /* initalize sng_isdn library */ - ftdm_assert_return(!sng_isdn_init(&g_sngisdn_event_interface), FTDM_FAIL, "Failed to initialize stack\n"); + ftdm_assert_return(!sng_isdn_init(&g_sngisdn_event_interface), FTDM_FAIL, "Failed to initialize stack\n"); return FTDM_SUCCESS; } @@ -968,11 +1076,11 @@ static FIO_API_FUNCTION(ftdm_sangoma_isdn_api) goto done; } if (!strcasecmp(trace_opt, "q921")) { - sng_isdn_activate_trace(span, SNGISDN_TRACE_Q921); + sngisdn_activate_trace(span, SNGISDN_TRACE_Q921); } else if (!strcasecmp(trace_opt, "q931")) { - sng_isdn_activate_trace(span, SNGISDN_TRACE_Q931); + sngisdn_activate_trace(span, SNGISDN_TRACE_Q931); } else if (!strcasecmp(trace_opt, "disable")) { - sng_isdn_activate_trace(span, SNGISDN_TRACE_DISABLE); + sngisdn_activate_trace(span, SNGISDN_TRACE_DISABLE); } else { stream->write_function(stream, "-ERR invalid trace option \n"); } diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h index e84392e22a..75262c9627 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h @@ -74,6 +74,7 @@ typedef enum { FLAG_DELAYED_REL = (1 << 7), FLAG_SENT_PROCEED = (1 << 8), FLAG_SEND_DISC = (1 << 9), + FLAG_ACTIVATING = (1 << 10), /* Used for BRI only, flag is set after we request line CONNECTED */ } sngisdn_flag_t; @@ -167,6 +168,7 @@ typedef struct sngisdn_chan_data { /* Span specific data */ typedef struct sngisdn_span_data { ftdm_span_t *ftdm_span; + ftdm_channel_t *dchan; uint8_t link_id; uint8_t switchtype; uint8_t signalling; /* SNGISDN_SIGNALING_CPE or SNGISDN_SIGNALING_NET */ @@ -181,6 +183,7 @@ typedef struct sngisdn_span_data { uint8_t facility; int8_t facility_timeout; uint8_t num_local_numbers; + uint8_t timer_t3; char* local_numbers[SNGISDN_NUM_LOCAL_NUMBERS]; ftdm_sched_t *sched; ftdm_queue_t *event_queue; @@ -275,7 +278,7 @@ void stack_hdr_init(Header *hdr); void stack_pst_init(Pst *pst); FT_DECLARE_INLINE(ftdm_status_t) get_ftdmchan_by_spInstId(int16_t cc_id, uint32_t spInstId, sngisdn_chan_data_t **sngisdn_data); FT_DECLARE_INLINE(ftdm_status_t) get_ftdmchan_by_suInstId(int16_t cc_id, uint32_t suInstId, sngisdn_chan_data_t **sngisdn_data); -FT_DECLARE_INLINE(ftdm_status_t) sng_isdn_set_avail_rate(ftdm_span_t *ftdmspan, sngisdn_avail_t avail); +FT_DECLARE_INLINE(ftdm_status_t) sngisdn_set_avail_rate(ftdm_span_t *ftdmspan, sngisdn_avail_t avail); /* Outbound Call Control functions */ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan); @@ -290,25 +293,28 @@ void sngisdn_snd_reset(ftdm_channel_t *ftdmchan); void sngisdn_snd_con_complete(ftdm_channel_t *ftdmchan); void sngisdn_snd_info_req(ftdm_channel_t *ftdmchan); void sngisdn_snd_status_enq(ftdm_channel_t *ftdmchan); +void sngisdn_snd_data(ftdm_span_t *span, uint8_t *data, ftdm_size_t len); +void sngisdn_snd_event(ftdm_span_t *span, sng_isdn_l1_event_t l1_event); /* Inbound Call Control functions */ -void sngisdn_rcv_con_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, ConEvnt *conEvnt, int16_t dChan, uint8_t ces); -void sngisdn_rcv_con_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, int16_t dChan, uint8_t ces); -void sngisdn_rcv_cnst_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, uint8_t evntType, int16_t dChan, uint8_t ces); -void sngisdn_rcv_disc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, DiscEvnt *discEvnt); -void sngisdn_rcv_rel_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, RelEvnt *relEvnt); -void sngisdn_rcv_dat_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, InfoEvnt *infoEvnt); -void sngisdn_rcv_sshl_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action); -void sngisdn_rcv_sshl_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action); -void sngisdn_rcv_rmrt_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action); -void sngisdn_rcv_rmrt_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action); -void sngisdn_rcv_flc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt); -void sngisdn_rcv_fac_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, FacEvnt *facEvnt, uint8_t evntType, int16_t dChan, uint8_t ces); -void sngisdn_rcv_sta_cfm ( int16_t suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt); -void sngisdn_rcv_srv_ind ( int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces); -void sngisdn_rcv_srv_cfm ( int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces); -void sngisdn_rcv_rst_cfm ( int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evntType); -void sngisdn_rcv_rst_ind ( int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evntType); +void sngisdn_rcv_con_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, ConEvnt *conEvnt, int16_t dChan, uint8_t ces); +void sngisdn_rcv_con_cfm(int16_t suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, int16_t dChan, uint8_t ces); +void sngisdn_rcv_cnst_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, uint8_t evntType, int16_t dChan, uint8_t ces); +void sngisdn_rcv_disc_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, DiscEvnt *discEvnt); +void sngisdn_rcv_rel_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, RelEvnt *relEvnt); +void sngisdn_rcv_dat_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, InfoEvnt *infoEvnt); +void sngisdn_rcv_sshl_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action); +void sngisdn_rcv_sshl_cfm(int16_t suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action); +void sngisdn_rcv_rmrt_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action); +void sngisdn_rcv_rmrt_cfm(int16_t suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action); +void sngisdn_rcv_flc_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt); +void sngisdn_rcv_fac_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, FacEvnt *facEvnt, uint8_t evntType, int16_t dChan, uint8_t ces); +void sngisdn_rcv_sta_cfm(int16_t suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt); +void sngisdn_rcv_srv_ind(int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces); +void sngisdn_rcv_srv_cfm(int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces); +void sngisdn_rcv_rst_cfm(int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evntType); +void sngisdn_rcv_rst_ind(int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evntType); +int16_t sngisdn_rcv_data_req(uint16_t spId, uint8_t *buff, uint32_t length); void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event); void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event); @@ -364,15 +370,18 @@ static __inline__ void sngisdn_set_flag(sngisdn_chan_data_t *sngisdn_info, sngis void handle_sng_log(uint8_t level, char *fmt,...); void sngisdn_set_span_sig_status(ftdm_span_t *ftdmspan, ftdm_signaling_status_t status); +void sngisdn_delayed_setup(void* p_sngisdn_info); void sngisdn_delayed_release(void* p_sngisdn_info); void sngisdn_delayed_connect(void* p_sngisdn_info); void sngisdn_delayed_disconnect(void* p_sngisdn_info); void sngisdn_facility_timeout(void* p_sngisdn_info); +void sngisdn_t3_timeout(void* p_sngisdn_info); /* Stack management functions */ -ftdm_status_t sng_isdn_stack_cfg(ftdm_span_t *span); -ftdm_status_t sng_isdn_stack_start(ftdm_span_t *span); -ftdm_status_t sng_isdn_stack_stop(ftdm_span_t *span); +ftdm_status_t sngisdn_stack_cfg(ftdm_span_t *span); +ftdm_status_t sngisdn_stack_start(ftdm_span_t *span); +ftdm_status_t sngisdn_stack_stop(ftdm_span_t *span); +ftdm_status_t sngisdn_wake_up_phy(ftdm_span_t *span); void sngisdn_print_phy_stats(ftdm_stream_handle_t *stream, ftdm_span_t *span); void sngisdn_print_spans(ftdm_stream_handle_t *stream); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c index 64d7a2403f..43e35b6dfd 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c @@ -56,9 +56,11 @@ ftdm_status_t add_local_number(const char* val, ftdm_span_t *span) ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span) { unsigned i; - + ftdm_iterator_t *chaniter = NULL; + ftdm_iterator_t *curr = NULL; sngisdn_dchan_data_t *dchan_data; sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data; + switch(span->trunk_type) { case FTDM_TRUNK_T1: if (!strcasecmp(switch_name, "ni2") || @@ -122,9 +124,9 @@ ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span) /* add this span to its ent_cc */ signal_data->cc_id = i; - /* create a new dchan */ /* for NFAS - no-dchan on b-channels only links */ + /* create a new dchan */ /* for NFAS - no-dchan on b-channels-only links */ g_sngisdn_data.num_dchan++; - signal_data->dchan_id = g_sngisdn_data.num_dchan; + signal_data->dchan_id = g_sngisdn_data.num_dchan; dchan_data = &g_sngisdn_data.dchans[signal_data->dchan_id]; dchan_data->num_spans++; @@ -136,16 +138,23 @@ ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span) ftdm_log(FTDM_LOG_DEBUG, "%s: cc_id:%d dchan_id:%d span_id:%d\n", span->name, signal_data->cc_id, signal_data->dchan_id, signal_data->span_id); - /* Add the channels to the span */ - for (i=1;i<=span->chan_count;i++) { - unsigned chan_id; - ftdm_channel_t *ftdmchan = span->channels[i]; - /* NFAS is not supported on E1, so span_id will always be 1 for E1 so this will work for E1 as well */ - chan_id = ((signal_data->span_id-1)*NUM_T1_CHANNELS_PER_SPAN)+ftdmchan->physical_chan_id; - dchan_data->channels[chan_id] = (sngisdn_chan_data_t*)ftdmchan->call_data; - dchan_data->num_chans++; + + chaniter = ftdm_span_get_chan_iterator(span, NULL); + for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) { + int32_t chan_id; + ftdm_channel_t *ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr); + if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921) { + /* set the d-channel */ + signal_data->dchan = ftdmchan; + } else { + /* Add the channels to the span */ + /* NFAS is not supported on E1, so span_id will always be 1 for E1 so this will work for E1 as well */ + chan_id = ((signal_data->span_id-1)*NUM_T1_CHANNELS_PER_SPAN)+ftdmchan->physical_chan_id; + dchan_data->channels[chan_id] = (sngisdn_chan_data_t*)ftdmchan->call_data; + dchan_data->num_chans++; + } } - + ftdm_iterator_free(chaniter); return FTDM_SUCCESS; } diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c index bb46fb7fba..eabaa7affc 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c @@ -38,52 +38,52 @@ extern ftdm_sngisdn_data_t g_sngisdn_data; uint8_t sng_isdn_stack_switchtype(sngisdn_switchtype_t switchtype); -ftdm_status_t sng_isdn_cfg_phy(ftdm_span_t *span); -ftdm_status_t sng_isdn_cfg_q921(ftdm_span_t *span); -ftdm_status_t sng_isdn_cfg_q931(ftdm_span_t *span); -ftdm_status_t sng_isdn_cfg_cc(ftdm_span_t *span); +ftdm_status_t sngisdn_cfg_phy(ftdm_span_t *span); +ftdm_status_t sngisdn_cfg_q921(ftdm_span_t *span); +ftdm_status_t sngisdn_cfg_q931(ftdm_span_t *span); +ftdm_status_t sngisdn_cfg_cc(ftdm_span_t *span); -ftdm_status_t sng_isdn_stack_cfg_phy_gen(void); -ftdm_status_t sng_isdn_stack_cfg_q921_gen(void); -ftdm_status_t sng_isdn_stack_cfg_q931_gen(void); -ftdm_status_t sng_isdn_stack_cfg_cc_gen(void); +ftdm_status_t sngisdn_stack_cfg_phy_gen(void); +ftdm_status_t sngisdn_stack_cfg_q921_gen(void); +ftdm_status_t sngisdn_stack_cfg_q931_gen(void); +ftdm_status_t sngisdn_stack_cfg_cc_gen(void); -ftdm_status_t sng_isdn_stack_cfg_phy_psap(ftdm_span_t *span); -ftdm_status_t sng_isdn_stack_cfg_q921_msap(ftdm_span_t *span); -ftdm_status_t sng_isdn_stack_cfg_q921_dlsap(ftdm_span_t *span, uint8_t management); -ftdm_status_t sng_isdn_stack_cfg_q931_tsap(ftdm_span_t *span); -ftdm_status_t sng_isdn_stack_cfg_q931_dlsap(ftdm_span_t *span); -ftdm_status_t sng_isdn_stack_cfg_q931_lce(ftdm_span_t *span); +ftdm_status_t sngisdn_stack_cfg_phy_psap(ftdm_span_t *span); +ftdm_status_t sngisdn_stack_cfg_q921_msap(ftdm_span_t *span); +ftdm_status_t sngisdn_stack_cfg_q921_dlsap(ftdm_span_t *span, uint8_t management); +ftdm_status_t sngisdn_stack_cfg_q931_tsap(ftdm_span_t *span); +ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span); +ftdm_status_t sngisdn_stack_cfg_q931_lce(ftdm_span_t *span); -ftdm_status_t sng_isdn_stack_cfg_cc_sap(ftdm_span_t *span); +ftdm_status_t sngisdn_stack_cfg_cc_sap(ftdm_span_t *span); -ftdm_status_t sng_isdn_stack_cfg(ftdm_span_t *span) +ftdm_status_t sngisdn_stack_cfg(ftdm_span_t *span) { sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data; if (!g_sngisdn_data.gen_config_done) { g_sngisdn_data.gen_config_done = 1; ftdm_log(FTDM_LOG_DEBUG, "Starting general stack configuration\n"); - if(sng_isdn_stack_cfg_phy_gen()!= FTDM_SUCCESS) { + if(sngisdn_stack_cfg_phy_gen()!= FTDM_SUCCESS) { ftdm_log(FTDM_LOG_CRIT, "Failed general physical configuration\n"); return FTDM_FAIL; } ftdm_log(FTDM_LOG_DEBUG, "General stack physical done\n"); - if(sng_isdn_stack_cfg_q921_gen()!= FTDM_SUCCESS) { + if(sngisdn_stack_cfg_q921_gen()!= FTDM_SUCCESS) { ftdm_log(FTDM_LOG_CRIT, "Failed general q921 configuration\n"); return FTDM_FAIL; } ftdm_log(FTDM_LOG_DEBUG, "General stack q921 done\n"); - if(sng_isdn_stack_cfg_q931_gen()!= FTDM_SUCCESS) { + if(sngisdn_stack_cfg_q931_gen()!= FTDM_SUCCESS) { ftdm_log(FTDM_LOG_CRIT, "Failed general q921 configuration\n"); return FTDM_FAIL; } ftdm_log(FTDM_LOG_DEBUG, "General stack q931 done\n"); - if(sng_isdn_stack_cfg_cc_gen()!= FTDM_SUCCESS) { + if(sngisdn_stack_cfg_cc_gen()!= FTDM_SUCCESS) { ftdm_log(FTDM_LOG_CRIT, "Failed general CC configuration\n"); return FTDM_FAIL; } @@ -92,26 +92,26 @@ ftdm_status_t sng_isdn_stack_cfg(ftdm_span_t *span) } /* TODO: for NFAS, should only call these function for spans with d-chans */ - if (sng_isdn_stack_cfg_phy_psap(span) != FTDM_SUCCESS) { + if (sngisdn_stack_cfg_phy_psap(span) != FTDM_SUCCESS) { ftdm_log(FTDM_LOG_ERROR, "%s:phy_psap configuration failed\n", span->name); return FTDM_FAIL; } ftdm_log(FTDM_LOG_DEBUG, "%s:phy_psap configuration done\n", span->name); - if (sng_isdn_stack_cfg_q921_msap(span) != FTDM_SUCCESS) { + if (sngisdn_stack_cfg_q921_msap(span) != FTDM_SUCCESS) { ftdm_log(FTDM_LOG_ERROR, "%s:q921_msap configuration failed\n", span->name); return FTDM_FAIL; } ftdm_log(FTDM_LOG_DEBUG, "%s:q921_msap configuration done\n", span->name); - if (sng_isdn_stack_cfg_q921_dlsap(span, 0) != FTDM_SUCCESS) { + if (sngisdn_stack_cfg_q921_dlsap(span, 0) != FTDM_SUCCESS) { ftdm_log(FTDM_LOG_ERROR, "%s:q921_dlsap configuration failed\n", span->name); return FTDM_FAIL; } ftdm_log(FTDM_LOG_DEBUG, "%s:q921_dlsap configuration done\n", span->name); if (span->trunk_type == FTDM_TRUNK_BRI_PTMP) { - if (sng_isdn_stack_cfg_q921_dlsap(span, 1) != FTDM_SUCCESS) { + if (sngisdn_stack_cfg_q921_dlsap(span, 1) != FTDM_SUCCESS) { ftdm_log(FTDM_LOG_ERROR, "%s:q921_dlsap management configuration failed\n", span->name); return FTDM_FAIL; } @@ -119,13 +119,13 @@ ftdm_status_t sng_isdn_stack_cfg(ftdm_span_t *span) } - if (sng_isdn_stack_cfg_q931_dlsap(span) != FTDM_SUCCESS) { + if (sngisdn_stack_cfg_q931_dlsap(span) != FTDM_SUCCESS) { ftdm_log(FTDM_LOG_ERROR, "%s:q931_dlsap configuration failed\n", span->name); return FTDM_FAIL; } ftdm_log(FTDM_LOG_DEBUG, "%s:q931_dlsap configuration done\n", span->name); - if (sng_isdn_stack_cfg_q931_lce(span) != FTDM_SUCCESS) { + if (sngisdn_stack_cfg_q931_lce(span) != FTDM_SUCCESS) { ftdm_log(FTDM_LOG_ERROR, "%s:q931_lce configuration failed\n", span->name); return FTDM_FAIL; } @@ -134,13 +134,13 @@ ftdm_status_t sng_isdn_stack_cfg(ftdm_span_t *span) if (!g_sngisdn_data.ccs[signal_data->cc_id].config_done) { g_sngisdn_data.ccs[signal_data->cc_id].config_done = 1; /* if BRI, need to configure dlsap_mgmt */ - if (sng_isdn_stack_cfg_q931_tsap(span) != FTDM_SUCCESS) { + if (sngisdn_stack_cfg_q931_tsap(span) != FTDM_SUCCESS) { ftdm_log(FTDM_LOG_ERROR, "%s:q931_tsap configuration failed\n", span->name); return FTDM_FAIL; } ftdm_log(FTDM_LOG_DEBUG, "%s:q931_tsap configuration done\n", span->name); - if (sng_isdn_stack_cfg_cc_sap(span) != FTDM_SUCCESS) { + if (sngisdn_stack_cfg_cc_sap(span) != FTDM_SUCCESS) { ftdm_log(FTDM_LOG_ERROR, "%s:cc_sap configuration failed\n", span->name); return FTDM_FAIL; } @@ -153,7 +153,7 @@ ftdm_status_t sng_isdn_stack_cfg(ftdm_span_t *span) -ftdm_status_t sng_isdn_stack_cfg_phy_gen(void) +ftdm_status_t sngisdn_stack_cfg_phy_gen(void) { /*local variables*/ L1Mngmt cfg; /*configuration structure*/ @@ -191,14 +191,11 @@ ftdm_status_t sng_isdn_stack_cfg_phy_gen(void) return FTDM_SUCCESS; } -ftdm_status_t sng_isdn_stack_cfg_phy_psap(ftdm_span_t *span) -{ - ftdm_iterator_t *chaniter; - ftdm_iterator_t *curr; +ftdm_status_t sngisdn_stack_cfg_phy_psap(ftdm_span_t *span) +{ L1Mngmt cfg; Pst pst; - int32_t d_channel_fd = -1; sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data; /* initalize the post structure */ @@ -220,25 +217,13 @@ ftdm_status_t sng_isdn_stack_cfg_phy_psap(ftdm_span_t *span) cfg.hdr.elmId.elmnt = STPSAP; cfg.hdr.elmId.elmntInst1 = signal_data->link_id; - - - /* Find the d-channel */ - chaniter = ftdm_span_get_chan_iterator(span, NULL); - for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) { - ftdm_channel_t *ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr); - if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921) { - d_channel_fd = (int32_t)ftdmchan->sockfd; - break; - } - } - ftdm_iterator_free(chaniter); - - if(d_channel_fd < 0) { + + if (!signal_data->dchan) { ftdm_log(FTDM_LOG_ERROR, "%s:No d-channels specified\n", span->name); return FTDM_FAIL; - } - - cfg.t.cfg.s.l1PSAP.sockfd = d_channel_fd; + } + + cfg.t.cfg.s.l1PSAP.sockfd = (int32_t)signal_data->dchan->sockfd; switch(span->trunk_type) { case FTDM_TRUNK_E1: @@ -257,7 +242,7 @@ ftdm_status_t sng_isdn_stack_cfg_phy_psap(ftdm_span_t *span) return FTDM_FAIL; } cfg.t.cfg.s.l1PSAP.spId = signal_data->link_id; - + if (sng_isdn_phy_config(&pst, &cfg)) { return FTDM_FAIL; } @@ -265,7 +250,7 @@ ftdm_status_t sng_isdn_stack_cfg_phy_psap(ftdm_span_t *span) } -ftdm_status_t sng_isdn_stack_cfg_q921_gen(void) +ftdm_status_t sngisdn_stack_cfg_q921_gen(void) { BdMngmt cfg; Pst pst; @@ -308,7 +293,7 @@ ftdm_status_t sng_isdn_stack_cfg_q921_gen(void) return FTDM_SUCCESS; } -ftdm_status_t sng_isdn_stack_cfg_q921_msap(ftdm_span_t *span) +ftdm_status_t sngisdn_stack_cfg_q921_msap(ftdm_span_t *span) { BdMngmt cfg; Pst pst; @@ -401,7 +386,7 @@ ftdm_status_t sng_isdn_stack_cfg_q921_msap(ftdm_span_t *span) return FTDM_SUCCESS; } -ftdm_status_t sng_isdn_stack_cfg_q921_dlsap(ftdm_span_t *span, uint8_t management) +ftdm_status_t sngisdn_stack_cfg_q921_dlsap(ftdm_span_t *span, uint8_t management) { BdMngmt cfg; Pst pst; @@ -483,7 +468,7 @@ ftdm_status_t sng_isdn_stack_cfg_q921_dlsap(ftdm_span_t *span, uint8_t managemen return FTDM_SUCCESS; } -ftdm_status_t sng_isdn_stack_cfg_q931_gen(void) +ftdm_status_t sngisdn_stack_cfg_q931_gen(void) { InMngmt cfg; Pst pst; @@ -538,7 +523,7 @@ ftdm_status_t sng_isdn_stack_cfg_q931_gen(void) } /* Link between CC and q931 */ -ftdm_status_t sng_isdn_stack_cfg_q931_tsap(ftdm_span_t *span) +ftdm_status_t sngisdn_stack_cfg_q931_tsap(ftdm_span_t *span) { InMngmt cfg; Pst pst; @@ -601,7 +586,7 @@ ftdm_status_t sng_isdn_stack_cfg_q931_tsap(ftdm_span_t *span) return FTDM_SUCCESS; } -ftdm_status_t sng_isdn_stack_cfg_q931_dlsap(ftdm_span_t *span) +ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span) { InMngmt cfg; Pst pst; @@ -851,7 +836,7 @@ ftdm_status_t sng_isdn_stack_cfg_q931_dlsap(ftdm_span_t *span) return FTDM_SUCCESS; } -ftdm_status_t sng_isdn_stack_cfg_q931_lce(ftdm_span_t *span) +ftdm_status_t sngisdn_stack_cfg_q931_lce(ftdm_span_t *span) { InMngmt cfg; Pst pst; @@ -927,7 +912,7 @@ ftdm_status_t sng_isdn_stack_cfg_q931_lce(ftdm_span_t *span) } -ftdm_status_t sng_isdn_stack_cfg_cc_gen(void) +ftdm_status_t sngisdn_stack_cfg_cc_gen(void) { CcMngmt cfg; Pst pst; @@ -966,7 +951,7 @@ ftdm_status_t sng_isdn_stack_cfg_cc_gen(void) } -ftdm_status_t sng_isdn_stack_cfg_cc_sap(ftdm_span_t *span) +ftdm_status_t sngisdn_stack_cfg_cc_sap(ftdm_span_t *span) { CcMngmt cfg; Pst pst; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c index 27c16c2a51..d8e6c8e00d 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c @@ -37,27 +37,27 @@ void stack_resp_hdr_init(Header *hdr); -ftdm_status_t sng_isdn_activate_phy(ftdm_span_t *span); -ftdm_status_t sng_isdn_deactivate_phy(ftdm_span_t *span); +ftdm_status_t sngisdn_activate_phy(ftdm_span_t *span); +ftdm_status_t sngisdn_deactivate_phy(ftdm_span_t *span); -ftdm_status_t sng_isdn_activate_cc(ftdm_span_t *span); -ftdm_status_t sng_isdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t trace_opt); +ftdm_status_t sngisdn_activate_cc(ftdm_span_t *span); +ftdm_status_t sngisdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t trace_opt); -ftdm_status_t sng_isdn_cntrl_q931(ftdm_span_t *span, uint8_t action, uint8_t subaction); -ftdm_status_t sng_isdn_cntrl_q921(ftdm_span_t *span, uint8_t action, uint8_t subaction); +ftdm_status_t sngisdn_cntrl_q931(ftdm_span_t *span, uint8_t action, uint8_t subaction); +ftdm_status_t sngisdn_cntrl_q921(ftdm_span_t *span, uint8_t action, uint8_t subaction); extern ftdm_sngisdn_data_t g_sngisdn_data; -ftdm_status_t sng_isdn_stack_stop(ftdm_span_t *span); +ftdm_status_t sngisdn_stack_stop(ftdm_span_t *span); -ftdm_status_t sng_isdn_stack_start(ftdm_span_t *span) +ftdm_status_t sngisdn_stack_start(ftdm_span_t *span) { sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data; - if (sng_isdn_cntrl_q921(span, ABND_ENA, NOTUSED) != FTDM_SUCCESS) { + if (sngisdn_cntrl_q921(span, ABND_ENA, NOTUSED) != FTDM_SUCCESS) { ftdm_log(FTDM_LOG_CRIT, "%s:Failed to activate stack q921\n", span->name); return FTDM_FAIL; } @@ -72,7 +72,7 @@ ftdm_status_t sng_isdn_stack_start(ftdm_span_t *span) ftdm_log(FTDM_LOG_DEBUG, "%s:Stack q921 activated\n", span->name); if (!g_sngisdn_data.ccs[signal_data->cc_id].activation_done) { g_sngisdn_data.ccs[signal_data->cc_id].activation_done = 1; - if (sng_isdn_activate_cc(span) != FTDM_SUCCESS) { + if (sngisdn_activate_cc(span) != FTDM_SUCCESS) { ftdm_log(FTDM_LOG_CRIT, "%s:Failed to activate stack CC\n", span->name); return FTDM_FAIL; } @@ -80,7 +80,7 @@ ftdm_status_t sng_isdn_stack_start(ftdm_span_t *span) } - if (sng_isdn_cntrl_q931(span, ABND_ENA, SAELMNT) != FTDM_SUCCESS) { + if (sngisdn_cntrl_q931(span, ABND_ENA, SAELMNT) != FTDM_SUCCESS) { ftdm_log(FTDM_LOG_CRIT, "%s:Failed to activate stack q931\n", span->name); return FTDM_FAIL; } @@ -90,20 +90,20 @@ ftdm_status_t sng_isdn_stack_start(ftdm_span_t *span) return FTDM_SUCCESS; } -ftdm_status_t sng_isdn_stack_stop(ftdm_span_t *span) +ftdm_status_t sngisdn_stack_stop(ftdm_span_t *span) { /* Stop L1 first, so we do not receive any more frames */ - if (sng_isdn_deactivate_phy(span) != FTDM_SUCCESS) { + if (sngisdn_deactivate_phy(span) != FTDM_SUCCESS) { ftdm_log(FTDM_LOG_CRIT, "%s:Failed to deactivate stack phy\n", span->name); return FTDM_FAIL; } - if (sng_isdn_cntrl_q931(span, AUBND_DIS, SAELMNT) != FTDM_SUCCESS) { + if (sngisdn_cntrl_q931(span, AUBND_DIS, SAELMNT) != FTDM_SUCCESS) { ftdm_log(FTDM_LOG_CRIT, "%s:Failed to deactivate stack q931\n", span->name); return FTDM_FAIL; } - if (sng_isdn_cntrl_q921(span, AUBND_DIS, SAELMNT) != FTDM_SUCCESS) { + if (sngisdn_cntrl_q921(span, AUBND_DIS, SAELMNT) != FTDM_SUCCESS) { ftdm_log(FTDM_LOG_CRIT, "%s:Failed to deactivate stack q921\n", span->name); return FTDM_FAIL; } @@ -113,7 +113,7 @@ ftdm_status_t sng_isdn_stack_stop(ftdm_span_t *span) } -ftdm_status_t sng_isdn_activate_phy(ftdm_span_t *span) +ftdm_status_t sngisdn_activate_phy(ftdm_span_t *span) { /* There is no need to start phy, as it will Q921 will send a activate request to phy when it starts */ @@ -121,7 +121,7 @@ ftdm_status_t sng_isdn_activate_phy(ftdm_span_t *span) return FTDM_SUCCESS; } -ftdm_status_t sng_isdn_deactivate_phy(ftdm_span_t *span) +ftdm_status_t sngisdn_deactivate_phy(ftdm_span_t *span) { L1Mngmt cntrl; Pst pst; @@ -155,8 +155,41 @@ ftdm_status_t sng_isdn_deactivate_phy(ftdm_span_t *span) return FTDM_SUCCESS; } +ftdm_status_t sngisdn_wake_up_phy(ftdm_span_t *span) +{ + L1Mngmt cntrl; + Pst pst; -ftdm_status_t sng_isdn_activate_cc(ftdm_span_t *span) + sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data; + + /* initalize the post structure */ + stack_pst_init(&pst); + + /* insert the destination Entity */ + pst.dstEnt = ENTL1; + + /* initalize the control structure */ + memset(&cntrl, 0, sizeof(cntrl)); + + /* initalize the control header */ + stack_hdr_init(&cntrl.hdr); + + cntrl.hdr.msgType = TCNTRL; /* configuration */ + cntrl.hdr.entId.ent = ENTL1; /* entity */ + cntrl.hdr.entId.inst = S_INST; /* instance */ + cntrl.hdr.elmId.elmnt = STTSAP; /* SAP Specific cntrl */ + + cntrl.t.cntrl.action = AENA; + cntrl.t.cntrl.subAction = SAELMNT; + cntrl.t.cntrl.sapId = signal_data->link_id; + + if (sng_isdn_phy_cntrl(&pst, &cntrl)) { + return FTDM_FAIL; + } + return FTDM_SUCCESS; +} + +ftdm_status_t sngisdn_activate_cc(ftdm_span_t *span) { CcMngmt cntrl; Pst pst; @@ -190,7 +223,7 @@ ftdm_status_t sng_isdn_activate_cc(ftdm_span_t *span) return FTDM_SUCCESS; } -ftdm_status_t sng_isdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t trace_opt) +ftdm_status_t sngisdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t trace_opt) { sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data; switch (trace_opt) { @@ -199,7 +232,7 @@ ftdm_status_t sng_isdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t tra ftdm_log(FTDM_LOG_INFO, "s%d Disabling q921 trace\n", signal_data->link_id); sngisdn_clear_trace_flag(signal_data, SNGISDN_TRACE_Q921); - if (sng_isdn_cntrl_q921(span, ADISIMM, SATRC) != FTDM_SUCCESS) { + if (sngisdn_cntrl_q921(span, ADISIMM, SATRC) != FTDM_SUCCESS) { ftdm_log(FTDM_LOG_ERROR, "s%d Failed to disable q921 trace\n"); } } @@ -207,7 +240,7 @@ ftdm_status_t sng_isdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t tra ftdm_log(FTDM_LOG_INFO, "s%d Disabling q931 trace\n", signal_data->link_id); sngisdn_clear_trace_flag(signal_data, SNGISDN_TRACE_Q931); - if (sng_isdn_cntrl_q931(span, ADISIMM, SATRC) != FTDM_SUCCESS) { + if (sngisdn_cntrl_q931(span, ADISIMM, SATRC) != FTDM_SUCCESS) { ftdm_log(FTDM_LOG_ERROR, "s%d Failed to disable q931 trace\n"); } } @@ -217,7 +250,7 @@ ftdm_status_t sng_isdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t tra ftdm_log(FTDM_LOG_INFO, "s%d Enabling q921 trace\n", signal_data->link_id); sngisdn_set_trace_flag(signal_data, SNGISDN_TRACE_Q921); - if (sng_isdn_cntrl_q921(span, AENA, SATRC) != FTDM_SUCCESS) { + if (sngisdn_cntrl_q921(span, AENA, SATRC) != FTDM_SUCCESS) { ftdm_log(FTDM_LOG_ERROR, "s%d Failed to enable q921 trace\n"); } } @@ -227,7 +260,7 @@ ftdm_status_t sng_isdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t tra ftdm_log(FTDM_LOG_INFO, "s%d Enabling q931 trace\n", signal_data->link_id); sngisdn_set_trace_flag(signal_data, SNGISDN_TRACE_Q931); - if (sng_isdn_cntrl_q931(span, AENA, SATRC) != FTDM_SUCCESS) { + if (sngisdn_cntrl_q931(span, AENA, SATRC) != FTDM_SUCCESS) { ftdm_log(FTDM_LOG_ERROR, "s%d Failed to enable q931 trace\n"); } } @@ -237,7 +270,7 @@ ftdm_status_t sng_isdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t tra } -ftdm_status_t sng_isdn_cntrl_q931(ftdm_span_t *span, uint8_t action, uint8_t subaction) +ftdm_status_t sngisdn_cntrl_q931(ftdm_span_t *span, uint8_t action, uint8_t subaction) { InMngmt cntrl; Pst pst; @@ -276,7 +309,7 @@ ftdm_status_t sng_isdn_cntrl_q931(ftdm_span_t *span, uint8_t action, uint8_t sub } -ftdm_status_t sng_isdn_cntrl_q921(ftdm_span_t *span, uint8_t action, uint8_t subaction) +ftdm_status_t sngisdn_cntrl_q921(ftdm_span_t *span, uint8_t action, uint8_t subaction) { BdMngmt cntrl; Pst pst; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c index 7ca408538a..37613cc33d 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c @@ -539,7 +539,7 @@ void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event) case FTDM_CHANNEL_STATE_DIALING: /* Remote side rejected our SETUP message on outbound call */ if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) { - sng_isdn_set_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN); + sngisdn_set_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN); } /* fall-through */ case FTDM_CHANNEL_STATE_PROGRESS: diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c index 3284d54165..bf44cb2e0a 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c @@ -600,6 +600,17 @@ void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare) return; } +void sngisdn_snd_data(ftdm_span_t *span, uint8_t *data, ftdm_size_t len) +{ + sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data; + sng_isdn_data_ind(signal_data->link_id, data, len); +} + +void sngisdn_snd_event(ftdm_span_t *span, sng_isdn_l1_event_t l1_event) +{ + sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data; + sng_isdn_event_ind(signal_data->link_id, l1_event); +} /* For Emacs: diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c index 5580f3a950..e7ebc8f20b 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c @@ -736,7 +736,7 @@ void sngisdn_rcv_q931_ind(InMngmt *status) DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause); sngisdn_set_span_sig_status(ftdmspan, FTDM_SIG_STATE_UP); - sng_isdn_set_avail_rate(ftdmspan, SNGISDN_AVAIL_UP); + sngisdn_set_avail_rate(ftdmspan, SNGISDN_AVAIL_UP); } else { ftdm_log(FTDM_LOG_WARNING, "[SNGISDN Q931] s%d: %s: %s(%d): %s(%d)\n", status->t.usta.suId, @@ -745,7 +745,7 @@ void sngisdn_rcv_q931_ind(InMngmt *status) DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause); sngisdn_set_span_sig_status(ftdmspan, FTDM_SIG_STATE_DOWN); - sng_isdn_set_avail_rate(ftdmspan, SNGISDN_AVAIL_PWR_SAVING); + sngisdn_set_avail_rate(ftdmspan, SNGISDN_AVAIL_PWR_SAVING); } } break; @@ -866,6 +866,26 @@ end_of_trace: return; } +int16_t sngisdn_rcv_data_req(uint16_t spId, uint8_t *buff, uint32_t length) +{ + ftdm_status_t status; + ftdm_wait_flag_t flags = FTDM_WRITE; + sngisdn_span_data_t *signal_data = g_sngisdn_data.spans[spId]; + ftdm_assert(signal_data, "Received Data request on unconfigured span\n"); + + status = signal_data->dchan->fio->wait(signal_data->dchan, &flags, 10); + if (status != FTDM_SUCCESS) { + ftdm_log_chan_msg(signal_data->dchan, FTDM_LOG_WARNING, "transmit timed-out\n"); + return -1; + } + status = signal_data->dchan->fio->write(signal_data->dchan, buff, (ftdm_size_t*)&length); + if (status != FTDM_SUCCESS) { + ftdm_log_chan_msg(signal_data->dchan, FTDM_LOG_CRIT, "Failed to transmit frame\n"); + return -1; + } + return 0; +} + void sngisdn_rcv_sng_assert(char *message) { ftdm_assert(0, message); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c index f54f7db61c..a418103bed 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c @@ -137,7 +137,7 @@ FT_DECLARE_INLINE(ftdm_status_t) get_ftdmchan_by_spInstId(int16_t cc_id, uint32_ return FTDM_SUCCESS; } -ftdm_status_t sng_isdn_set_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail) +ftdm_status_t sngisdn_set_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail) { if (span->trunk_type == FTDM_TRUNK_BRI || @@ -382,6 +382,39 @@ ftdm_status_t cpy_calling_name_from_user(ConEvnt *conEvnt, ftdm_channel_t *ftdmc return FTDM_SUCCESS; } +void sngisdn_t3_timeout(void* p_sngisdn_info) +{ + sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info; + ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; + sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; + + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Timer T3 expired (suId:%d suInstId:%u spInstId:%u)\n", + signal_data->cc_id, sngisdn_info->glare.spInstId, sngisdn_info->glare.suInstId); + ftdm_mutex_lock(ftdmchan->mutex); + if (ftdm_test_flag(sngisdn_info, FLAG_ACTIVATING)){ + /* PHY layer timed-out, need to clear the call */ + ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Failed to Wake-Up line (suId:%d suInstId:%u spInstId:%u)\n", + signal_data->cc_id, sngisdn_info->glare.spInstId, sngisdn_info->glare.suInstId); + + ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NO_ROUTE_DESTINATION; + ftdm_clear_flag(sngisdn_info, FLAG_ACTIVATING); + ftdm_set_flag(sngisdn_info, FLAG_LOCAL_ABORT); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); + } + ftdm_mutex_unlock(ftdmchan->mutex); +} + +void sngisdn_delayed_setup(void* p_sngisdn_info) +{ + sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info; + ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; + + ftdm_mutex_lock(ftdmchan->mutex); + sngisdn_snd_setup(ftdmchan); + ftdm_mutex_unlock(ftdmchan->mutex); + return; +} + void sngisdn_delayed_release(void* p_sngisdn_info) { sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info; diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h index 8bdbdd60f8..239eb4a3d9 100644 --- a/libs/freetdm/src/include/private/ftdm_core.h +++ b/libs/freetdm/src/include/private/ftdm_core.h @@ -222,6 +222,8 @@ extern "C" { #define ftdm_is_dtmf(key) ((key > 47 && key < 58) || (key > 64 && key < 69) || (key > 96 && key < 101) || key == 35 || key == 42 || key == 87 || key == 119) +#define FTDM_SPAN_IS_BRI(x) ((x)->trunk_type == FTDM_TRUNK_BRI || (x)->trunk_type == FTDM_TRUNK_BRI_PTMP) + /*! \brief Copy flags from one arbitrary object to another \command dest the object to copy the flags to diff --git a/libs/freetdm/src/include/private/ftdm_types.h b/libs/freetdm/src/include/private/ftdm_types.h index bddefd9be6..78ac8f63eb 100644 --- a/libs/freetdm/src/include/private/ftdm_types.h +++ b/libs/freetdm/src/include/private/ftdm_types.h @@ -176,10 +176,11 @@ typedef enum { FTDM_SPAN_USE_CHAN_QUEUE = (1 << 6), FTDM_SPAN_SUGGEST_CHAN_ID = (1 << 7), FTDM_SPAN_USE_AV_RATE = (1 << 8), + FTDM_SPAN_PWR_SAVING = (1 << 9), /* If you use this flag, you MUST call ftdm_span_trigger_signals to deliver the user signals * after having called ftdm_send_span_signal(), which with this flag it will just enqueue the signal * for later delivery */ - FTDM_SPAN_USE_SIGNALS_QUEUE = (1 << 9), + FTDM_SPAN_USE_SIGNALS_QUEUE = (1 << 10), } ftdm_span_flag_t; /*! \brief Channel supported features */ From 93aa30076b01be366f8f1c487b7b561f5bd7e074 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Wed, 10 Nov 2010 19:23:48 -0500 Subject: [PATCH 002/237] Fixed conflicts --- .../ftmod_sangoma_isdn_stack_cntrl.c | 34 ------------------- 1 file changed, 34 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c index 1714ac185c..d8e6c8e00d 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c @@ -113,40 +113,6 @@ ftdm_status_t sngisdn_stack_stop(ftdm_span_t *span) } -ftdm_status_t sngisdn_wake_up_phy(ftdm_span_t *span) -{ - L1Mngmt cntrl; - Pst pst; - - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data; - - /* initalize the post structure */ - stack_pst_init(&pst); - - /* insert the destination Entity */ - pst.dstEnt = ENTL1; - - /* initalize the control structure */ - memset(&cntrl, 0, sizeof(cntrl)); - - /* initalize the control header */ - stack_hdr_init(&cntrl.hdr); - - cntrl.hdr.msgType = TCNTRL; /* configuration */ - cntrl.hdr.entId.ent = ENTL1; /* entity */ - cntrl.hdr.entId.inst = S_INST; /* instance */ - cntrl.hdr.elmId.elmnt = STTSAP; /* SAP Specific cntrl */ - - cntrl.t.cntrl.action = AENA; - cntrl.t.cntrl.subAction = SAELMNT; - cntrl.t.cntrl.sapId = signal_data->link_id; - - if (sng_isdn_phy_cntrl(&pst, &cntrl)) { - return FTDM_FAIL; - } - return FTDM_SUCCESS; -} - ftdm_status_t sngisdn_activate_phy(ftdm_span_t *span) { From d0b6117325ded66fdbcb8a8c3630386e671675f9 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Thu, 11 Nov 2010 18:43:53 -0500 Subject: [PATCH 003/237] FIX for windows IO --- libs/freetdm/cyginstall.sh | 4 +-- .../ftmod_sangoma_isdn/ftmod_sangoma_isdn.c | 22 ++++++------ .../ftmod_sangoma_isdn_stack_out.c | 1 + .../ftmod_sangoma_isdn_stack_rcv.c | 34 +++++++++++++------ .../src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c | 3 +- 5 files changed, 41 insertions(+), 23 deletions(-) diff --git a/libs/freetdm/cyginstall.sh b/libs/freetdm/cyginstall.sh index 9d486b7dce..311df939af 100644 --- a/libs/freetdm/cyginstall.sh +++ b/libs/freetdm/cyginstall.sh @@ -5,8 +5,8 @@ fsdir=../.. set -x cp Debug/mod/*.dll $fsdir/Debug/mod/ cp mod_freetdm/Debug/*.pdb $fsdir/Debug/mod/ -cp Debug/*.dll $fsdir/Debug/ -cp Debug/*.pdb $fsdir/Debug/ +cp Debug/*.dll $fsdir/Debug/mod/ +cp Debug/*.pdb $fsdir/Debug/mod/ #cp Debug/testsangomaboost.exe $fsdir/Debug/ echo "FRIENDLY REMINDER: RECOMPILE ftmod_wanpipe WHENEVER YOU INSTALL NEW DRIVERS" set +x diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c index 69743115fe..98b09e9305 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c @@ -52,10 +52,10 @@ static void ftdm_sangoma_isdn_process_phy_events(ftdm_span_t *span, ftdm_oob_eve static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan); static void ftdm_sangoma_isdn_process_stack_event (ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event); -static ftdm_io_interface_t g_sngisdn_io_interface; -static sng_isdn_event_interface_t g_sngisdn_event_interface; +static ftdm_io_interface_t g_sngisdn_io_interface; +static sng_isdn_event_interface_t g_sngisdn_event_interface; -ftdm_sngisdn_data_t g_sngisdn_data; +ftdm_sngisdn_data_t g_sngisdn_data; extern ftdm_status_t sngisdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t trace_opt); extern ftdm_status_t sngisdn_check_free_ids(void); @@ -248,6 +248,7 @@ static void ftdm_sangoma_isdn_process_phy_events(ftdm_span_t *span, ftdm_oob_eve sngisdn_snd_event(span, SNG_L1EVENT_ALARM_OFF); if (FTDM_SPAN_IS_BRI(span)) { ftdm_channel_t *ftdmchan; + sngisdn_chan_data_t *sngisdn_info; ftdm_iterator_t *chaniter = NULL; ftdm_iterator_t *curr = NULL; sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data; @@ -255,7 +256,7 @@ static void ftdm_sangoma_isdn_process_phy_events(ftdm_span_t *span, ftdm_oob_eve chaniter = ftdm_span_get_chan_iterator(span, NULL); for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) { ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr); - sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data; + sngisdn_info = (sngisdn_chan_data_t*)ftdmchan->call_data; if (ftdm_test_flag(sngisdn_info, FLAG_ACTIVATING)) { ftdm_clear_flag(sngisdn_info, FLAG_ACTIVATING); @@ -277,8 +278,7 @@ static void ftdm_sangoma_isdn_process_phy_events(ftdm_span_t *span, ftdm_oob_eve static void ftdm_sangoma_isdn_poll_events(ftdm_span_t *span) { - ftdm_status_t ret_status; - ftdm_channel_t *ftdmchan; + ftdm_status_t ret_status; ftdm_iterator_t *chaniter = NULL; ftdm_iterator_t *curr = NULL; @@ -315,7 +315,7 @@ static void *ftdm_sangoma_isdn_dchan_run(ftdm_thread_t *me, void *obj) while (ftdm_running() && !(ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD))) { wflags = FTDM_READ; - status = ftdm_channel_wait(dchan, &wflags, 0); + status = ftdm_channel_wait(dchan, &wflags, 10000); switch(status) { case FTDM_FAIL: ftdm_log_chan_msg(dchan, FTDM_LOG_CRIT, "Failed to wait for d-channel\n"); @@ -331,8 +331,10 @@ static void *ftdm_sangoma_isdn_dchan_run(ftdm_thread_t *me, void *obj) } else { ftdm_log_chan_msg(dchan, FTDM_LOG_WARNING, "Failed to read from channel \n"); } +#ifndef WIN32 /* It is valid on WIN32 for poll to return without errors, but no flags set */ } else { ftdm_log_chan_msg(dchan, FTDM_LOG_CRIT, "Failed to poll for d-channel\n"); +#endif } break; default: @@ -986,7 +988,7 @@ static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_isdn_init) ftdm_log(FTDM_LOG_INFO, "Loading ftmod_sangoma_isdn...\n"); memset(&g_sngisdn_data, 0, sizeof(g_sngisdn_data)); - + memset(&g_sngisdn_event_interface, 0, sizeof(g_sngisdn_event_interface)); /* set callbacks */ g_sngisdn_event_interface.cc.sng_con_ind = sngisdn_rcv_con_ind; g_sngisdn_event_interface.cc.sng_con_cfm = sngisdn_rcv_con_cfm; @@ -1017,8 +1019,8 @@ static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_isdn_init) g_sngisdn_event_interface.sta.sng_q931_trc_ind = sngisdn_rcv_q931_trace; g_sngisdn_event_interface.sta.sng_cc_sta_ind = sngisdn_rcv_cc_ind; - g_sngisdn_event_interface.io.sng_data_req = sngisdn_rcv_data_req; - + g_sngisdn_event_interface.io.sng_data_req = sngisdn_rcv_data_req; + for(i=1;i<=MAX_VARIANTS;i++) { ftdm_mutex_create(&g_sngisdn_data.ccs[i].mutex); } diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c index 163265177f..c0ee11d980 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c @@ -37,6 +37,7 @@ extern ftdm_status_t cpy_calling_num_from_user(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *ftdm); extern ftdm_status_t cpy_called_num_from_user(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *ftdm); extern ftdm_status_t cpy_calling_name_from_user(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan); +extern ftdm_status_t cpy_redir_num_from_user(RedirNmb *redirNmb, ftdm_caller_data_t *ftdm); void sngisdn_snd_setup(ftdm_channel_t *ftdmchan) diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c index e7ebc8f20b..940006451a 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c @@ -873,16 +873,30 @@ int16_t sngisdn_rcv_data_req(uint16_t spId, uint8_t *buff, uint32_t length) sngisdn_span_data_t *signal_data = g_sngisdn_data.spans[spId]; ftdm_assert(signal_data, "Received Data request on unconfigured span\n"); - status = signal_data->dchan->fio->wait(signal_data->dchan, &flags, 10); - if (status != FTDM_SUCCESS) { - ftdm_log_chan_msg(signal_data->dchan, FTDM_LOG_WARNING, "transmit timed-out\n"); - return -1; - } - status = signal_data->dchan->fio->write(signal_data->dchan, buff, (ftdm_size_t*)&length); - if (status != FTDM_SUCCESS) { - ftdm_log_chan_msg(signal_data->dchan, FTDM_LOG_CRIT, "Failed to transmit frame\n"); - return -1; - } + do { + flags = FTDM_WRITE; + status = signal_data->dchan->fio->wait(signal_data->dchan, &flags, 1000); + if (status != FTDM_SUCCESS) { + ftdm_log_chan_msg(signal_data->dchan, FTDM_LOG_WARNING, "transmit timed-out\n"); + return -1; + } + + + if ((flags & FTDM_WRITE)) { + status = signal_data->dchan->fio->write(signal_data->dchan, buff, (ftdm_size_t*)&length); + if (status != FTDM_SUCCESS) { + ftdm_log_chan_msg(signal_data->dchan, FTDM_LOG_CRIT, "Failed to transmit frame\n"); + return -1; + } + break; + /* On WIN32, it is possible for poll to return without FTDM_WRITE flag set, so we try to retransmit */ +#ifndef WIN32 + } else { + ftdm_log_chan_msg(signal_data->dchan, FTDM_LOG_WARNING, "Failed to poll for d-channel\n"); + return -1; +#endif + } + } while(1); return 0; } diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c index 896b8eebd8..f40f2b20c7 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c @@ -115,7 +115,7 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event); static __inline__ int tdmv_api_wait_socket(ftdm_channel_t *ftdmchan, int timeout, int *flags) { -#ifdef LIBSANGOMA_VERSION +#ifdef LIBSANGOMA_VERSION int err; uint32_t inflags = *flags; uint32_t outflags = 0; @@ -130,6 +130,7 @@ static __inline__ int tdmv_api_wait_socket(ftdm_channel_t *ftdmchan, int timeout if (err == SANG_STATUS_APIPOLL_TIMEOUT) { err = 0; } + return err; #else struct pollfd pfds[1]; From caacb24500b1294a93cea6fa5345bd9605492c99 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Mon, 15 Nov 2010 14:13:01 -0500 Subject: [PATCH 004/237] freetdm: Changes for FTDM IO commands --- libs/freetdm/src/ftdm_io.c | 3 + .../ftmod_sangoma_isdn/ftmod_sangoma_isdn.c | 10 +- .../ftmod_sangoma_isdn/ftmod_sangoma_isdn.h | 8 +- .../ftmod_sangoma_isdn_stack_cfg.c | 347 +++++++++--------- .../ftmod_sangoma_isdn_stack_out.c | 63 +++- .../src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c | 51 ++- libs/freetdm/src/include/private/ftdm_core.h | 40 ++ 7 files changed, 329 insertions(+), 193 deletions(-) diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 1ede703a41..15e853236d 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -56,6 +56,9 @@ #define FTDM_READ_TRACE_INDEX 0 #define FTDM_WRITE_TRACE_INDEX 1 +ftdm_time_t time_last_throttle_log = 0; +ftdm_time_t time_current_throttle_log = 0; + static int time_is_init = 0; static void time_init(void) diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c index 98b09e9305..5142de5211 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c @@ -242,10 +242,10 @@ static __inline__ void ftdm_sangoma_isdn_advance_chan_states(ftdm_channel_t *ftd static void ftdm_sangoma_isdn_process_phy_events(ftdm_span_t *span, ftdm_oob_event_t event) { + sngisdn_snd_event(span, event); switch (event) { /* Check if the span woke up from power-saving mode */ case FTDM_OOB_ALARM_CLEAR: - sngisdn_snd_event(span, SNG_L1EVENT_ALARM_OFF); if (FTDM_SPAN_IS_BRI(span)) { ftdm_channel_t *ftdmchan; sngisdn_chan_data_t *sngisdn_info; @@ -267,9 +267,6 @@ static void ftdm_sangoma_isdn_process_phy_events(ftdm_span_t *span, ftdm_oob_eve ftdm_iterator_free(chaniter); } break; - case FTDM_OOB_ALARM_TRAP: - sngisdn_snd_event(span, SNG_L1EVENT_ALARM_ON); - break; default: /* Ignore other events for now */ break; @@ -327,7 +324,7 @@ static void *ftdm_sangoma_isdn_dchan_run(ftdm_thread_t *me, void *obj) len = 1000; status = ftdm_channel_read(dchan, data, &len); if (status == FTDM_SUCCESS) { - sngisdn_snd_data(span, data, len); + sngisdn_snd_data(dchan, data, len); } else { ftdm_log_chan_msg(dchan, FTDM_LOG_WARNING, "Failed to read from channel \n"); } @@ -1019,7 +1016,8 @@ static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_isdn_init) g_sngisdn_event_interface.sta.sng_q931_trc_ind = sngisdn_rcv_q931_trace; g_sngisdn_event_interface.sta.sng_cc_sta_ind = sngisdn_rcv_cc_ind; - g_sngisdn_event_interface.io.sng_data_req = sngisdn_rcv_data_req; + g_sngisdn_event_interface.io.sng_l1_data_req = sngisdn_rcv_l1_data_req; + g_sngisdn_event_interface.io.sng_l1_cmd_req = sngisdn_rcv_l1_cmd_req; for(i=1;i<=MAX_VARIANTS;i++) { ftdm_mutex_create(&g_sngisdn_data.ccs[i].mutex); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h index 75262c9627..7c66c38acf 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h @@ -293,8 +293,8 @@ void sngisdn_snd_reset(ftdm_channel_t *ftdmchan); void sngisdn_snd_con_complete(ftdm_channel_t *ftdmchan); void sngisdn_snd_info_req(ftdm_channel_t *ftdmchan); void sngisdn_snd_status_enq(ftdm_channel_t *ftdmchan); -void sngisdn_snd_data(ftdm_span_t *span, uint8_t *data, ftdm_size_t len); -void sngisdn_snd_event(ftdm_span_t *span, sng_isdn_l1_event_t l1_event); +void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len); +void sngisdn_snd_event(ftdm_channel_t *span, sng_isdn_l1_event_t l1_event); /* Inbound Call Control functions */ void sngisdn_rcv_con_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, ConEvnt *conEvnt, int16_t dChan, uint8_t ces); @@ -314,7 +314,9 @@ void sngisdn_rcv_srv_ind(int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces) void sngisdn_rcv_srv_cfm(int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces); void sngisdn_rcv_rst_cfm(int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evntType); void sngisdn_rcv_rst_ind(int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evntType); -int16_t sngisdn_rcv_data_req(uint16_t spId, uint8_t *buff, uint32_t length); +int16_t sngisdn_rcv_l1_data_req(uint16_t spId, sng_isdn_l1_frame_t *l1_frame); +int16_t sngisdn_rcv_l1_cmd_req(uint16_t spId, sng_l1_cmd_t *l1_cmd); + void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event); void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c index eabaa7affc..6c75fb3a81 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c @@ -156,34 +156,34 @@ ftdm_status_t sngisdn_stack_cfg(ftdm_span_t *span) ftdm_status_t sngisdn_stack_cfg_phy_gen(void) { /*local variables*/ - L1Mngmt cfg; /*configuration structure*/ - Pst pst; /*post structure*/ + L1Mngmt cfg; /*configuration structure*/ + Pst pst; /*post structure*/ - /* initalize the post structure */ - stack_pst_init(&pst); + /* initalize the post structure */ + stack_pst_init(&pst); - /* insert the destination Entity */ - pst.dstEnt = ENTL1; + /* insert the destination Entity */ + pst.dstEnt = ENTL1; - /*clear the configuration structure*/ + /*clear the configuration structure*/ memset(&cfg, 0, sizeof(cfg)); - /*fill in some general sections of the header*/ - stack_hdr_init(&cfg.hdr); + /*fill in some general sections of the header*/ + stack_hdr_init(&cfg.hdr); - /*fill in the specific fields of the header*/ - cfg.hdr.msgType = TCFG; - cfg.hdr.entId.ent = ENTL1; - cfg.hdr.entId.inst = S_INST; - cfg.hdr.elmId.elmnt = STGEN; + /*fill in the specific fields of the header*/ + cfg.hdr.msgType = TCFG; + cfg.hdr.entId.ent = ENTL1; + cfg.hdr.entId.inst = S_INST; + cfg.hdr.elmId.elmnt = STGEN; - stack_pst_init(&cfg.t.cfg.s.l1Gen.sm ); - cfg.t.cfg.s.l1Gen.sm.srcEnt = ENTL1; - cfg.t.cfg.s.l1Gen.sm.dstEnt = ENTSM; + stack_pst_init(&cfg.t.cfg.s.l1Gen.sm ); + cfg.t.cfg.s.l1Gen.sm.srcEnt = ENTL1; + cfg.t.cfg.s.l1Gen.sm.dstEnt = ENTSM; - cfg.t.cfg.s.l1Gen.nmbLnks = MAX_L1_LINKS+1; - cfg.t.cfg.s.l1Gen.poolTrUpper = POOL_UP_TR; /* upper pool threshold */ - cfg.t.cfg.s.l1Gen.poolTrLower = POOL_LW_TR; /* lower pool threshold */ + cfg.t.cfg.s.l1Gen.nmbLnks = MAX_L1_LINKS; + cfg.t.cfg.s.l1Gen.poolTrUpper = POOL_UP_TR; /* upper pool threshold */ + cfg.t.cfg.s.l1Gen.poolTrLower = POOL_LW_TR; /* lower pool threshold */ if (sng_isdn_phy_config(&pst, &cfg)) { return FTDM_FAIL; @@ -193,38 +193,38 @@ ftdm_status_t sngisdn_stack_cfg_phy_gen(void) ftdm_status_t sngisdn_stack_cfg_phy_psap(ftdm_span_t *span) { - L1Mngmt cfg; - Pst pst; + L1Mngmt cfg; + Pst pst; sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data; - /* initalize the post structure */ - stack_pst_init(&pst); + /* initalize the post structure */ + stack_pst_init(&pst); - /* insert the destination Entity */ - pst.dstEnt = ENTL1; + /* insert the destination Entity */ + pst.dstEnt = ENTL1; - /*clear the configuration structure*/ + /*clear the configuration structure*/ memset(&cfg, 0, sizeof(cfg)); - /*fill in some general sections of the header*/ - stack_hdr_init(&cfg.hdr); + /*fill in some general sections of the header*/ + stack_hdr_init(&cfg.hdr); - /*fill in the specific fields of the header*/ - cfg.hdr.msgType = TCFG; - cfg.hdr.entId.ent = ENTL1; - cfg.hdr.entId.inst = S_INST; - cfg.hdr.elmId.elmnt = STPSAP; + /*fill in the specific fields of the header*/ + cfg.hdr.msgType = TCFG; + cfg.hdr.entId.ent = ENTL1; + cfg.hdr.entId.inst = S_INST; + cfg.hdr.elmId.elmnt = STPSAP; cfg.hdr.elmId.elmntInst1 = signal_data->link_id; - + if (!signal_data->dchan) { ftdm_log(FTDM_LOG_ERROR, "%s:No d-channels specified\n", span->name); return FTDM_FAIL; - } + } cfg.t.cfg.s.l1PSAP.sockfd = (int32_t)signal_data->dchan->sockfd; - + switch(span->trunk_type) { case FTDM_TRUNK_E1: cfg.t.cfg.s.l1PSAP.type = SNG_L1_TYPE_PRI; @@ -240,9 +240,9 @@ ftdm_status_t sngisdn_stack_cfg_phy_psap(ftdm_span_t *span) default: ftdm_log(FTDM_LOG_ERROR, "%s:Unsupported trunk type %d\n", span->name, span->trunk_type); return FTDM_FAIL; - } - cfg.t.cfg.s.l1PSAP.spId = signal_data->link_id; - + } + cfg.t.cfg.s.l1PSAP.spId = signal_data->link_id; + if (sng_isdn_phy_config(&pst, &cfg)) { return FTDM_FAIL; } @@ -253,25 +253,25 @@ ftdm_status_t sngisdn_stack_cfg_phy_psap(ftdm_span_t *span) ftdm_status_t sngisdn_stack_cfg_q921_gen(void) { BdMngmt cfg; - Pst pst; + Pst pst; - /* initalize the post structure */ - stack_pst_init(&pst); + /* initalize the post structure */ + stack_pst_init(&pst); /* insert the destination Entity */ - pst.dstEnt = ENTLD; + pst.dstEnt = ENTLD; - /*clear the configuration structure*/ - memset(&cfg, 0, sizeof(cfg)); + /*clear the configuration structure*/ + memset(&cfg, 0, sizeof(cfg)); /*fill in some general sections of the header*/ - stack_hdr_init(&cfg.hdr); - - cfg.hdr.msgType = TCFG; - cfg.hdr.entId.ent = ENTLD; - cfg.hdr.entId.inst = S_INST; - cfg.hdr.elmId.elmnt = STGEN; - /* fill in the Gen Conf structures internal pst struct */ + stack_hdr_init(&cfg.hdr); - stack_pst_init(&cfg.t.cfg.s.bdGen.sm); + cfg.hdr.msgType = TCFG; + cfg.hdr.entId.ent = ENTLD; + cfg.hdr.entId.inst = S_INST; + cfg.hdr.elmId.elmnt = STGEN; + /* fill in the Gen Conf structures internal pst struct */ + + stack_pst_init(&cfg.t.cfg.s.bdGen.sm); cfg.t.cfg.s.bdGen.sm.dstEnt = ENTSM; /* entity */ @@ -284,8 +284,8 @@ ftdm_status_t sngisdn_stack_cfg_q921_gen(void) #ifdef LAPD_3_4 cfg.t.cfg.s.bdGen.timeRes = 100; /* timer resolution = 1 sec */ #endif - cfg.t.cfg.s.bdGen.poolTrUpper = 2; /* upper pool threshold */ - cfg.t.cfg.s.bdGen.poolTrLower = 1; /* lower pool threshold */ + cfg.t.cfg.s.bdGen.poolTrUpper = 2; /* upper pool threshold */ + cfg.t.cfg.s.bdGen.poolTrLower = 1; /* lower pool threshold */ if (sng_isdn_q921_config(&pst, &cfg)) { return FTDM_FAIL; @@ -296,27 +296,27 @@ ftdm_status_t sngisdn_stack_cfg_q921_gen(void) ftdm_status_t sngisdn_stack_cfg_q921_msap(ftdm_span_t *span) { BdMngmt cfg; - Pst pst; + Pst pst; sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data; - /* initalize the post structure */ - stack_pst_init(&pst); + /* initalize the post structure */ + stack_pst_init(&pst); /* insert the destination Entity */ - pst.dstEnt = ENTLD; + pst.dstEnt = ENTLD; - /*clear the configuration structure*/ - memset(&cfg, 0, sizeof(cfg)); + /*clear the configuration structure*/ + memset(&cfg, 0, sizeof(cfg)); /*fill in some general sections of the header*/ - stack_hdr_init(&cfg.hdr); + stack_hdr_init(&cfg.hdr); cfg.hdr.msgType = TCFG; - cfg.hdr.entId.ent = ENTLD; - cfg.hdr.entId.inst = S_INST; - cfg.hdr.elmId.elmnt = STMSAP; + cfg.hdr.entId.ent = ENTLD; + cfg.hdr.entId.inst = S_INST; + cfg.hdr.elmId.elmnt = STMSAP; cfg.t.cfg.s.bdMSAP.lnkNmb = signal_data->link_id; - + cfg.t.cfg.s.bdMSAP.maxOutsFrms = 24; /* MAC window */ cfg.t.cfg.s.bdMSAP.tQUpperTrs = 32; /* Tx Queue Upper Threshold */ cfg.t.cfg.s.bdMSAP.tQLowerTrs = 24; /* Tx Queue Lower Threshold */ @@ -328,7 +328,7 @@ ftdm_status_t sngisdn_stack_cfg_q921_msap(ftdm_span_t *span) cfg.t.cfg.s.bdMSAP.route = RTESPEC; /* Route */ cfg.t.cfg.s.bdMSAP.dstProcId = SFndProcId(); /* destination proc id */ cfg.t.cfg.s.bdMSAP.dstEnt = ENTL1; /* entity */ - cfg.t.cfg.s.bdMSAP.dstInst = S_INST; /* instance */ + cfg.t.cfg.s.bdMSAP.dstInst = S_INST; /* instance */ cfg.t.cfg.s.bdMSAP.t201Tmr = 1; /* T201 - should be equal to t200Tmr */ cfg.t.cfg.s.bdMSAP.t202Tmr = 2; /* T202 */ cfg.t.cfg.s.bdMSAP.bndRetryCnt = 2; /* bind retry counter */ @@ -377,7 +377,7 @@ ftdm_status_t sngisdn_stack_cfg_q921_msap(ftdm_span_t *span) if (signal_data->setup_arb == SNGISDN_OPT_TRUE) { cfg.t.cfg.s.bdMSAP.setUpArb = ACTIVE; } else if (signal_data->setup_arb == SNGISDN_OPT_FALSE) { - cfg.t.cfg.s.bdMSAP.setUpArb = PASSIVE; + cfg.t.cfg.s.bdMSAP.setUpArb = PASSIVE; } if (sng_isdn_q921_config(&pst, &cfg)) { @@ -389,24 +389,24 @@ ftdm_status_t sngisdn_stack_cfg_q921_msap(ftdm_span_t *span) ftdm_status_t sngisdn_stack_cfg_q921_dlsap(ftdm_span_t *span, uint8_t management) { BdMngmt cfg; - Pst pst; + Pst pst; sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data; - /* initalize the post structure */ - stack_pst_init(&pst); + /* initalize the post structure */ + stack_pst_init(&pst); /* insert the destination Entity */ - pst.dstEnt = ENTLD; + pst.dstEnt = ENTLD; - /*clear the configuration structure*/ - memset(&cfg, 0, sizeof(cfg)); + /*clear the configuration structure*/ + memset(&cfg, 0, sizeof(cfg)); /*fill in some general sections of the header*/ - stack_hdr_init(&cfg.hdr); + stack_hdr_init(&cfg.hdr); /*fill in the specific fields of the header*/ - cfg.hdr.msgType = TCFG; - cfg.hdr.entId.ent = ENTLD; - cfg.hdr.entId.inst = S_INST; - cfg.hdr.elmId.elmnt = STDLSAP; + cfg.hdr.msgType = TCFG; + cfg.hdr.entId.ent = ENTLD; + cfg.hdr.entId.inst = S_INST; + cfg.hdr.elmId.elmnt = STDLSAP; cfg.t.cfg.s.bdDLSAP.lnkNmb = signal_data->link_id; @@ -418,10 +418,10 @@ ftdm_status_t sngisdn_stack_cfg_q921_dlsap(ftdm_span_t *span, uint8_t management } else { cfg.t.cfg.s.bdDLSAP.k = 7; /* k */ } - + cfg.t.cfg.s.bdDLSAP.n200 = 3; /* n200 */ cfg.t.cfg.s.bdDLSAP.congTmr = 300; /* congestion timer */ - cfg.t.cfg.s.bdDLSAP.t200Tmr = 1; /* t1 changed from 25 */ + cfg.t.cfg.s.bdDLSAP.t200Tmr = 1; /* t1 changed from 25 */ cfg.t.cfg.s.bdDLSAP.t203Tmr = 10; /* t3 changed from 50 */ cfg.t.cfg.s.bdDLSAP.mod = 128; /* modulo */ cfg.t.cfg.s.bdDLSAP.selector = 0; /* Selector 0 */ @@ -471,28 +471,28 @@ ftdm_status_t sngisdn_stack_cfg_q921_dlsap(ftdm_span_t *span, uint8_t management ftdm_status_t sngisdn_stack_cfg_q931_gen(void) { InMngmt cfg; - Pst pst; + Pst pst; - /* initalize the post structure */ - stack_pst_init(&pst); + /* initalize the post structure */ + stack_pst_init(&pst); - /* insert the destination Entity */ - pst.dstEnt = ENTIN; + /* insert the destination Entity */ + pst.dstEnt = ENTIN; - /*clear the configuration structure*/ + /*clear the configuration structure*/ memset(&cfg, 0, sizeof(cfg)); - /*fill in some general sections of the header*/ - stack_hdr_init(&cfg.hdr); + /*fill in some general sections of the header*/ + stack_hdr_init(&cfg.hdr); - /*fill in the specific fields of the header*/ - cfg.hdr.msgType = TCFG; - cfg.hdr.entId.ent = ENTIN; - cfg.hdr.entId.inst = S_INST; - cfg.hdr.elmId.elmnt = STGEN; + /*fill in the specific fields of the header*/ + cfg.hdr.msgType = TCFG; + cfg.hdr.entId.ent = ENTIN; + cfg.hdr.entId.inst = S_INST; + cfg.hdr.elmId.elmnt = STGEN; - /* fill in the Gen Conf structures internal pst struct */ - stack_pst_init(&cfg.t.cfg.s.inGen.sm); + /* fill in the Gen Conf structures internal pst struct */ + stack_pst_init(&cfg.t.cfg.s.inGen.sm); cfg.t.cfg.s.inGen.nmbSaps = MAX_VARIANTS+1; /* Total number of variants supported */ @@ -526,26 +526,26 @@ ftdm_status_t sngisdn_stack_cfg_q931_gen(void) ftdm_status_t sngisdn_stack_cfg_q931_tsap(ftdm_span_t *span) { InMngmt cfg; - Pst pst; + Pst pst; unsigned i; sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data; - /* initalize the post structure */ - stack_pst_init(&pst); + /* initalize the post structure */ + stack_pst_init(&pst); - /* insert the destination Entity */ - pst.dstEnt = ENTIN; + /* insert the destination Entity */ + pst.dstEnt = ENTIN; - /*clear the configuration structure*/ + /*clear the configuration structure*/ memset(&cfg, 0, sizeof(cfg)); - /*fill in some general sections of the header*/ - stack_hdr_init(&cfg.hdr); + /*fill in some general sections of the header*/ + stack_hdr_init(&cfg.hdr); - /*fill in the specific fields of the header*/ - cfg.hdr.msgType = TCFG; - cfg.hdr.entId.ent = ENTIN; - cfg.hdr.entId.inst = S_INST; - cfg.hdr.elmId.elmnt = STTSAP; + /*fill in the specific fields of the header*/ + cfg.hdr.msgType = TCFG; + cfg.hdr.entId.ent = ENTIN; + cfg.hdr.entId.inst = S_INST; + cfg.hdr.elmId.elmnt = STTSAP; cfg.t.cfg.s.inTSAP.sapId = signal_data->cc_id; @@ -589,31 +589,31 @@ ftdm_status_t sngisdn_stack_cfg_q931_tsap(ftdm_span_t *span) ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span) { InMngmt cfg; - Pst pst; + Pst pst; unsigned i; sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data; - /* initalize the post structure */ - stack_pst_init(&pst); + /* initalize the post structure */ + stack_pst_init(&pst); - /* insert the destination Entity */ - pst.dstEnt = ENTIN; + /* insert the destination Entity */ + pst.dstEnt = ENTIN; - /*clear the configuration structure*/ + /*clear the configuration structure*/ memset(&cfg, 0, sizeof(cfg)); - /*fill in some general sections of the header*/ - stack_hdr_init(&cfg.hdr); + /*fill in some general sections of the header*/ + stack_hdr_init(&cfg.hdr); + + /*fill in the specific fields of the header*/ + cfg.hdr.msgType = TCFG; + cfg.hdr.entId.ent = ENTIN; + cfg.hdr.entId.inst = S_INST; + cfg.hdr.elmId.elmnt = STDLSAP; - /*fill in the specific fields of the header*/ - cfg.hdr.msgType = TCFG; - cfg.hdr.entId.ent = ENTIN; - cfg.hdr.entId.inst = S_INST; - cfg.hdr.elmId.elmnt = STDLSAP; - cfg.hdr.response.selector=0; - + cfg.t.cfg.s.inDLSAP.sapId = signal_data->link_id; cfg.t.cfg.s.inDLSAP.spId = signal_data->link_id; cfg.t.cfg.s.inDLSAP.swtch = sng_isdn_stack_switchtype(signal_data->switchtype); @@ -659,7 +659,7 @@ ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span) cfg.t.cfg.s.inDLSAP.ctldInt[1] = 1; } - cfg.t.cfg.s.inDLSAP.numRstInd = 255; + cfg.t.cfg.s.inDLSAP.numRstInd = 255; cfg.t.cfg.s.inDLSAP.relOpt = TRUE; #ifdef ISDN_SRV cfg.t.cfg.s.inDLSAP.bcas = FALSE; @@ -839,36 +839,36 @@ ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span) ftdm_status_t sngisdn_stack_cfg_q931_lce(ftdm_span_t *span) { InMngmt cfg; - Pst pst; + Pst pst; uint8_t i; - uint8_t numCes=1; + uint8_t numCes=1; sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data; if (span->trunk_type == FTDM_TRUNK_BRI_PTMP && signal_data->signalling == SNGISDN_SIGNALING_NET) { numCes = 8; } - /* initalize the post structure */ - stack_pst_init(&pst); + /* initalize the post structure */ + stack_pst_init(&pst); - /* insert the destination Entity */ - pst.dstEnt = ENTIN; + /* insert the destination Entity */ + pst.dstEnt = ENTIN; - /*clear the configuration structure*/ + /*clear the configuration structure*/ memset(&cfg, 0, sizeof(cfg)); - /*fill in some general sections of the header*/ - stack_hdr_init(&cfg.hdr); + /*fill in some general sections of the header*/ + stack_hdr_init(&cfg.hdr); - /*fill in the specific fields of the header*/ - cfg.hdr.msgType = TCFG; - cfg.hdr.entId.ent = ENTIN; - cfg.hdr.entId.inst = S_INST; - cfg.hdr.elmId.elmnt = STDLC; + /*fill in the specific fields of the header*/ + cfg.hdr.msgType = TCFG; + cfg.hdr.entId.ent = ENTIN; + cfg.hdr.entId.inst = S_INST; + cfg.hdr.elmId.elmnt = STDLC; cfg.hdr.response.selector=0; cfg.t.cfg.s.inLCe.sapId = signal_data->link_id; - + cfg.t.cfg.s.inLCe.lnkUpDwnInd = TRUE; cfg.t.cfg.s.inLCe.tCon.enb = TRUE; @@ -877,7 +877,7 @@ ftdm_status_t sngisdn_stack_cfg_q931_lce(ftdm_span_t *span) cfg.t.cfg.s.inLCe.tDisc.val = 35; cfg.t.cfg.s.inLCe.t314.enb = FALSE; /* if segmentation enabled, set to TRUE */ cfg.t.cfg.s.inLCe.t314.val = 35; - + cfg.t.cfg.s.inLCe.t332i.enb = FALSE; /* set to TRUE for NFAS */ #ifdef NFAS @@ -897,7 +897,6 @@ ftdm_status_t sngisdn_stack_cfg_q931_lce(ftdm_span_t *span) cfg.t.cfg.s.inLCe.tRstAck.enb = TRUE; cfg.t.cfg.s.inLCe.tRstAck.val = 10; - cfg.t.cfg.s.inLCe.usid = 0; cfg.t.cfg.s.inLCe.tid = 0; @@ -983,11 +982,11 @@ ftdm_status_t sngisdn_stack_cfg_cc_sap(ftdm_span_t *span) cfg.t.cfg.s.ccISAP.pst.dstInst = S_INST; cfg.t.cfg.s.ccISAP.pst.dstProcId = SFndProcId(); - cfg.t.cfg.s.ccISAP.pst.prior = PRIOR0; - cfg.t.cfg.s.ccISAP.pst.route = RTESPEC; - cfg.t.cfg.s.ccISAP.pst.region = S_REG; - cfg.t.cfg.s.ccISAP.pst.pool = S_POOL; - cfg.t.cfg.s.ccISAP.pst.selector = 0; + cfg.t.cfg.s.ccISAP.pst.prior = PRIOR0; + cfg.t.cfg.s.ccISAP.pst.route = RTESPEC; + cfg.t.cfg.s.ccISAP.pst.region = S_REG; + cfg.t.cfg.s.ccISAP.pst.pool = S_POOL; + cfg.t.cfg.s.ccISAP.pst.selector = 0; cfg.t.cfg.s.ccISAP.suId = signal_data->cc_id; cfg.t.cfg.s.ccISAP.spId = signal_data->cc_id; @@ -1005,19 +1004,19 @@ ftdm_status_t sngisdn_stack_cfg_cc_sap(ftdm_span_t *span) void stack_pst_init(Pst *pst) { memset(pst, 0, sizeof(Pst)); - /*fill in the post structure*/ - pst->dstProcId = SFndProcId(); - pst->dstInst = S_INST; + /*fill in the post structure*/ + pst->dstProcId = SFndProcId(); + pst->dstInst = S_INST; - pst->srcProcId = SFndProcId(); - pst->srcEnt = ENTSM; - pst->srcInst = S_INST; + pst->srcProcId = SFndProcId(); + pst->srcEnt = ENTSM; + pst->srcInst = S_INST; - pst->prior = PRIOR0; - pst->route = RTESPEC; - pst->region = S_REG; - pst->pool = S_POOL; - pst->selector = 0; + pst->prior = PRIOR0; + pst->route = RTESPEC; + pst->region = S_REG; + pst->pool = S_POOL; + pst->selector = 0; return; } @@ -1026,21 +1025,21 @@ void stack_pst_init(Pst *pst) void stack_hdr_init(Header *hdr) { hdr->msgType = 0; - hdr->msgLen = 0; - hdr->entId.ent = 0; - hdr->entId.inst = 0; - hdr->elmId.elmnt = 0; - hdr->elmId.elmntInst1 = 0; - hdr->elmId.elmntInst2 = 0; - hdr->elmId.elmntInst3 = 0; - hdr->seqNmb = 0; - hdr->version = 0; - hdr->response.prior = PRIOR0; - hdr->response.route = RTESPEC; - hdr->response.mem.region = S_REG; - hdr->response.mem.pool = S_POOL; - hdr->transId = 0; - hdr->response.selector = 0; + hdr->msgLen = 0; + hdr->entId.ent = 0; + hdr->entId.inst = 0; + hdr->elmId.elmnt = 0; + hdr->elmId.elmntInst1 = 0; + hdr->elmId.elmntInst2 = 0; + hdr->elmId.elmntInst3 = 0; + hdr->seqNmb = 0; + hdr->version = 0; + hdr->response.prior = PRIOR0; + hdr->response.route = RTESPEC; + hdr->response.mem.region = S_REG; + hdr->response.mem.pool = S_POOL; + hdr->transId = 0; + hdr->response.selector = 0; return; } diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c index c0ee11d980..94bd6e23e1 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c @@ -595,16 +595,65 @@ void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare) return; } -void sngisdn_snd_data(ftdm_span_t *span, uint8_t *data, ftdm_size_t len) +/* We received an incoming frame on the d-channel, send data to the stack */ +void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len) { - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data; - sng_isdn_data_ind(signal_data->link_id, data, len); + l1_frame_t l1_frame; + sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) dchan->span->signal_data; + + memset(&l1_frame, 0, sizeof(l1_frame)); + l1_frame.len = len; + + memcpy(&l1_frame.data, data, len); + + if (ftdm_test_flag(&(dchan->iostats.s.rx), FTDM_IOSTATS_ERROR_CRC)) { + l1_frame.flags |= SNG_L1FRAME_ERROR_CRC; + } + + if (ftdm_test_flag(&(dchan->iostats.s.rx), FTDM_IOSTATS_ERROR_FRAME)) { + l1_frame.flags |= SNG_L1FRAME_ERROR_FRAME; + } + + if (ftdm_test_flag(&(dchan->iostats.s.rx), FTDM_IOSTATS_ERROR_ABORT)) { + l1_frame.flags |= SNG_L1FRAME_ERROR_ABORT; + } + + if (ftdm_test_flag(&(dchan->iostats.s.rx), FTDM_IOSTATS_ERROR_FIFO)) { + l1_frame.flags |= SNG_L1FRAME_ERROR_FIFO; + } + + if (ftdm_test_flag(&(dchan->iostats.s.rx), FTDM_IOSTATS_ERROR_DMA)) { + l1_frame.flags |= SNG_L1FRAME_ERROR_DMA; + } + + if (ftdm_test_flag(&(dchan->iostats.s.rx), FTDM_IOSTATS_QUEUE_THRES)) { + /* Should we trigger congestion here? */ + l1_frame.flags |= SNG_L1FRAME_QUEUE_THRES; + } + + if (ftdm_test_flag(&(dchan->iostats.s.rx), FTDM_IOSTATS_QUEUE_FULL)) { + /* Should we trigger congestion here? */ + l1_frame.flags |= SNG_L1FRAME_QUEUE_FULL; + } + + sng_isdn_data_ind(signal_data->link_id, &l1_frame); } -void sngisdn_snd_event(ftdm_span_t *span, sng_isdn_l1_event_t l1_event) -{ - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data; - sng_isdn_event_ind(signal_data->link_id, l1_event); +void sngisdn_snd_event(ftdm_channel_t *dchan, ftdm_oob_event_t event) +{ + sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) dchan->span->signal_data; + switch(event) { + case FTDM_OOB_ALARM_CLEAR: + sng_isdn_event_ind(signal_data->link_id, SNG_L1EVENT_ALARM_OFF); + break; + case FTDM_OOB_ALARM_TRAP: + sng_isdn_event_ind(signal_data->link_id, SNG_L1EVENT_ALARM_ON); + break; + default: + /* We do not care about the other OOB events for now */ + return; + } + return; } diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c index f40f2b20c7..d6573ac2de 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c @@ -170,7 +170,7 @@ static __inline__ sng_fd_t tdmv_api_open_span_chan(int span, int chan) static __inline__ sng_fd_t __tdmv_api_open_span_chan(int span, int chan) { return __sangoma_open_tdmapi_span_chan(span, chan); -} +} #endif static ftdm_io_interface_t wanpipe_interface; @@ -759,6 +759,49 @@ static FIO_COMMAND_FUNCTION(wanpipe_command) return FTDM_SUCCESS; } +static void wanpipe_read_stats(ftdmchan, wp_tdm_api_rx_hdr_t *rx_stats) +{ + ftdmchan->iostats.s.rx.error_flags = 0; + if (rx_stats->rx_hdr_errors) { + wanpipe_reset_stats(ftdmchan); + ftdm_log_chan_msg_throttle(ftdmchan, "IO errors\n"); + } + + ftdmchan->iostats.s.rx_queue_size = rx_stats->rx_h.rx_h.max_rx_queue_length; + ftdmchan->iostats.s.rx_queue_len = rx_stats->rx_h.current_number_of_frames_in_rx_queue; + + if (rx_stats->rx_h.wp_api_rx_hdr_error_map & (1<iostats.s.rx), FTDM_IOSTATS_ERROR_ABORT); + } + if (rx_stats->rx_h.wp_api_rx_hdr_error_map & (1<iostats.s.rx), FTDM_IOSTATS_ERROR_DMA); + } + if (rx_stats->rx_h.wp_api_rx_hdr_error_map & (1<iostats.s.rx), FTDM_IOSTATS_ERROR_FIFO); + } + if (rx_stats->rx_h.wp_api_rx_hdr_error_map & (1<iostats.s.rx), FTDM_IOSTATS_ERROR_CRC); + } + if (rx_stats->rx_h.wp_api_rx_hdr_error_map & (1<iostats.s.rx), FTDM_IOSTATS_ERROR_FRAME); + } + + if (ftdmchan->iostats.s.rx_queue_len >= (0.8*ftdmchan->iostats.s.rx_queue_size)) { + ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Rx Queue length exceeded threshold (%d/%d)\n", + ftdmchan->iostats.s.rx_queue_len, ftdmchan->iostats.s.rx_queue_size); + + ftdm_set_flag(&(ftdmchan->iostats.s.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES); + } + + if (ftdmchan->iostats.s.rx_queue_len >= ftdmchan->iostats.s.rx_queue_size) { + ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Rx Queue Full (%d/%d)\n", + ftdmchan->iostats.s.rx_queue_len, ftdmchan->iostats.s.rx_queue_size); + + ftdm_set_flag(&(ftdmchan->iostats.s.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL); + } + return; +} + /** * \brief Reads data from a Wanpipe channel * \param ftdmchan Channel to read from @@ -787,9 +830,11 @@ static FIO_READ_FUNCTION(wanpipe_read) snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", strerror(errno)); ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Failed to read from sangoma device: %s (%d)\n", strerror(errno), rx_len); return FTDM_FAIL; - } - + } + if (ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS)) { + wanpipe_read_stats(ftdmchan, &hdrframe); + } return FTDM_SUCCESS; } diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h index c5f3c4b821..6cbf589044 100644 --- a/libs/freetdm/src/include/private/ftdm_core.h +++ b/libs/freetdm/src/include/private/ftdm_core.h @@ -357,6 +357,7 @@ typedef struct { } ftdm_dtmf_debug_t; #endif + typedef struct { const char *file; const char *func; @@ -366,6 +367,33 @@ typedef struct { ftdm_time_t time; } ftdm_channel_history_entry_t; +typedef enum { + FTDM_IOSTATS_ERROR_CRC = (1<<0), + FTDM_IOSTATS_ERROR_FRAME = (1<<1), + FTDM_IOSTATS_ERROR_ABORT = (1<<2), + FTDM_IOSTATS_ERROR_FIFO = (1<<3), + FTDM_IOSTATS_ERROR_DMA = (1<<4), + FTDM_IOSTATS_ERROR_QUEUE_THRES = (1<<5), /* Queue reached high threshold */ + FTDM_IOSTATS_ERROR_QUEUE_FULL = (1<<6), /* Queue is full */ +} ftdm_iostats_error_type_t; + +typedef struct { + union { + struct { + uint32_t errors; + uint16_t flags; + uint8_t rx_queue_size; /* max queue size configured */ + uint8_t rx_queue_len; /* Current number of elements in queue */ + } rx; + struct { + uint32_t errors; + uint16_t flags; + uint8_t tx_queue_size; /* max queue size configured */ + uint8_t tx_queue_len; /* Current number of elements in queue */ + } tx; + } s; +} ftdm_channel_iostats_t; + /* 2^8 table size, one for each byte (sample) value */ #define FTDM_GAINS_TABLE_SIZE 256 struct ftdm_channel { @@ -438,6 +466,7 @@ struct ftdm_channel { int availability_rate; void *user_private; ftdm_timer_id_t hangup_timer; + ftdm_channel_iostats_t iostats; #ifdef FTDM_DEBUG_DTMF ftdm_dtmf_debug_t dtmfdbg; #endif @@ -632,10 +661,21 @@ FT_DECLARE(void) ftdm_channel_clear_detected_tones(ftdm_channel_t *ftdmchan); #define ftdm_channel_lock(chan) ftdm_mutex_lock(chan->mutex) #define ftdm_channel_unlock(chan) ftdm_mutex_unlock(chan->mutex) + +#define ftdm_log_throttle(level, ...) \ + time_current_throttle_log = ftdm_current_time_in_ms(); \ + if (time_current_throttle_log - time_last_throttle_log > FTDM_THROTTLE_LOG_INTERVAL) {\ + ftdm_log(level, __VA_ARGS__); \ + time_last_throttle_log = time_current_throttle_log; \ + } + #define ftdm_log_chan_ex(fchan, file, func, line, level, format, ...) ftdm_log(file, func, line, level, "[s%dc%d][%d:%d] " format, fchan->span_id, fchan->chan_id, fchan->physical_span_id, fchan->physical_chan_id, __VA_ARGS__) #define ftdm_log_chan(fchan, level, format, ...) ftdm_log(level, "[s%dc%d][%d:%d] " format, fchan->span_id, fchan->chan_id, fchan->physical_span_id, fchan->physical_chan_id, __VA_ARGS__) #define ftdm_log_chan_msg(fchan, level, msg) ftdm_log(level, "[s%dc%d][%d:%d] " msg, fchan->span_id, fchan->chan_id, fchan->physical_span_id, fchan->physical_chan_id) +#define ftdm_log_chan_throttle(fchan, level, format, ...) ftdm_log_throttle(level, "[s%dc%d][%d:%d] " format, fchan->span_id, fchan->chan_id, fchan->physical_span_id, fchan->physical_chan_id, __VA_ARGS__) +#define ftdm_log_chan_msg_throttle(fchan, level, format, ...) ftdm_log_throttle(level, "[s%dc%d][%d:%d] " format, fchan->span_id, fchan->chan_id, fchan->physical_span_id, fchan->physical_chan_id, __VA_ARGS__) + #define ftdm_span_lock(span) ftdm_mutex_lock(span->mutex) #define ftdm_span_unlock(span) ftdm_mutex_unlock(span->mutex) From a2add139638907d3c36ee935c2f0b51db7821fd0 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Mon, 15 Nov 2010 19:16:09 -0500 Subject: [PATCH 005/237] freetdm:Changes for shared IO --- .../ftmod_sangoma_isdn/ftmod_sangoma_isdn.c | 51 +++++++++++--- .../ftmod_sangoma_isdn/ftmod_sangoma_isdn.h | 5 +- .../ftmod_sangoma_isdn_stack_out.c | 28 +++++--- .../ftmod_sangoma_isdn_stack_rcv.c | 47 ++++++++++++- .../src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c | 67 ++++++++++++------- libs/freetdm/src/include/freetdm.h | 5 +- libs/freetdm/src/include/private/ftdm_core.h | 2 +- libs/freetdm/src/include/private/ftdm_types.h | 1 + 8 files changed, 153 insertions(+), 53 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c index 5142de5211..674fea21c5 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c @@ -51,6 +51,8 @@ static void ftdm_sangoma_isdn_poll_events(ftdm_span_t *span); static void ftdm_sangoma_isdn_process_phy_events(ftdm_span_t *span, ftdm_oob_event_t event); static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan); static void ftdm_sangoma_isdn_process_stack_event (ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event); +static void ftdm_sangoma_isdn_wakeup_phy(ftdm_channel_t *dchan); +static void ftdm_sangoma_isdn_dchan_set_queue_size(ftdm_channel_t *ftdmchan); static ftdm_io_interface_t g_sngisdn_io_interface; static sng_isdn_event_interface_t g_sngisdn_event_interface; @@ -241,8 +243,9 @@ static __inline__ void ftdm_sangoma_isdn_advance_chan_states(ftdm_channel_t *ftd static void ftdm_sangoma_isdn_process_phy_events(ftdm_span_t *span, ftdm_oob_event_t event) { - - sngisdn_snd_event(span, event); + sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data; + sngisdn_snd_event(signal_data->dchan, event); + switch (event) { /* Check if the span woke up from power-saving mode */ case FTDM_OOB_ALARM_CLEAR: @@ -251,8 +254,7 @@ static void ftdm_sangoma_isdn_process_phy_events(ftdm_span_t *span, ftdm_oob_eve sngisdn_chan_data_t *sngisdn_info; ftdm_iterator_t *chaniter = NULL; ftdm_iterator_t *curr = NULL; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data; - + chaniter = ftdm_span_get_chan_iterator(span, NULL); for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) { ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr); @@ -261,7 +263,7 @@ static void ftdm_sangoma_isdn_process_phy_events(ftdm_span_t *span, ftdm_oob_eve if (ftdm_test_flag(sngisdn_info, FLAG_ACTIVATING)) { ftdm_clear_flag(sngisdn_info, FLAG_ACTIVATING); - ftdm_sched_timer(signal_data->sched, "delayed_setup", 1, sngisdn_delayed_setup, (void*) ftdmchan->call_data, NULL); + ftdm_sched_timer(signal_data->sched, "delayed_setup", 1000, sngisdn_delayed_setup, (void*) ftdmchan->call_data, NULL); } } ftdm_iterator_free(chaniter); @@ -276,9 +278,7 @@ static void ftdm_sangoma_isdn_process_phy_events(ftdm_span_t *span, ftdm_oob_eve static void ftdm_sangoma_isdn_poll_events(ftdm_span_t *span) { ftdm_status_t ret_status; - ftdm_iterator_t *chaniter = NULL; - ftdm_iterator_t *curr = NULL; - + ret_status = ftdm_span_poll_event(span, 0, NULL); switch(ret_status) { case FTDM_SUCCESS: @@ -297,6 +297,33 @@ static void ftdm_sangoma_isdn_poll_events(ftdm_span_t *span) } } +static void ftdm_sangoma_isdn_dchan_set_queue_size(ftdm_channel_t *dchan) +{ + ftdm_status_t ret_status; + uint32_t queue_size; + + queue_size = SNGISDN_DCHAN_QUEUE_LEN; + ret_status = ftdm_channel_command(dchan, FTDM_COMMAND_SET_RX_QUEUE_SIZE, &queue_size); + ftdm_assert(ret_status == FTDM_SUCCESS, "Failed to set Rx Queue size"); + + queue_size = SNGISDN_DCHAN_QUEUE_LEN; + ret_status = ftdm_channel_command(dchan, FTDM_COMMAND_SET_TX_QUEUE_SIZE, &queue_size); + ftdm_assert(ret_status == FTDM_SUCCESS, "Failed to set Tx Queue size"); + + RETVOID; +} + +static void ftdm_sangoma_isdn_wakeup_phy(ftdm_channel_t *dchan) +{ + ftdm_status_t ret_status; + ftdm_channel_hw_link_status_t status = FTDM_HW_LINK_CONNECTED; + ret_status = ftdm_channel_command(dchan, FTDM_COMMAND_SET_LINK_STATUS, &status); + if (ret_status != FTDM_SUCCESS) { + ftdm_log_chan_msg(dchan, FTDM_LOG_WARNING, "Failed to wake-up link\n"); + } + return; +} + static void *ftdm_sangoma_isdn_dchan_run(ftdm_thread_t *me, void *obj) { uint8_t data[1000]; @@ -306,7 +333,9 @@ static void *ftdm_sangoma_isdn_dchan_run(ftdm_thread_t *me, void *obj) ftdm_channel_t *dchan = ((sngisdn_span_data_t*)span->signal_data)->dchan; ftdm_size_t len = 0; - + ftdm_channel_set_feature(dchan, FTDM_CHANNEL_FEATURE_IO_STATS); + ftdm_sangoma_isdn_dchan_set_queue_size(dchan); + ftdm_assert(dchan, "Span does not have a dchannel"); ftdm_channel_open_chan(dchan); @@ -597,8 +626,8 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan) sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Requesting Line activation\n"); - sngisdn_set_flag(sngisdn_info, FLAG_ACTIVATING); - sngisdn_wake_up_phy(ftdmchan->span); + sngisdn_set_flag(sngisdn_info, FLAG_ACTIVATING); + ftdm_sangoma_isdn_wakeup_phy(ftdmchan); ftdm_sched_timer(signal_data->sched, "timer_t3", signal_data->timer_t3*1000, sngisdn_t3_timeout, (void*) sngisdn_info, NULL); } else { sngisdn_snd_setup(ftdmchan); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h index 7c66c38acf..8208aa14bd 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h @@ -60,6 +60,7 @@ #define SNGISDN_EVENT_QUEUE_SIZE 100 #define SNGISDN_EVENT_POLL_RATE 100 #define SNGISDN_NUM_LOCAL_NUMBERS 8 +#define SNGISDN_DCHAN_QUEUE_LEN 200 /* TODO: rename all *_cc_* to *_an_* */ @@ -294,7 +295,7 @@ void sngisdn_snd_con_complete(ftdm_channel_t *ftdmchan); void sngisdn_snd_info_req(ftdm_channel_t *ftdmchan); void sngisdn_snd_status_enq(ftdm_channel_t *ftdmchan); void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len); -void sngisdn_snd_event(ftdm_channel_t *span, sng_isdn_l1_event_t l1_event); +void sngisdn_snd_event(ftdm_channel_t *dchan, ftdm_oob_event_t event); /* Inbound Call Control functions */ void sngisdn_rcv_con_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, ConEvnt *conEvnt, int16_t dChan, uint8_t ces); @@ -314,7 +315,7 @@ void sngisdn_rcv_srv_ind(int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces) void sngisdn_rcv_srv_cfm(int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces); void sngisdn_rcv_rst_cfm(int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evntType); void sngisdn_rcv_rst_ind(int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evntType); -int16_t sngisdn_rcv_l1_data_req(uint16_t spId, sng_isdn_l1_frame_t *l1_frame); +int16_t sngisdn_rcv_l1_data_req(uint16_t spId, sng_l1_frame_t *l1_frame); int16_t sngisdn_rcv_l1_cmd_req(uint16_t spId, sng_l1_cmd_t *l1_cmd); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c index 94bd6e23e1..8842ef5934 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c @@ -598,7 +598,7 @@ void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare) /* We received an incoming frame on the d-channel, send data to the stack */ void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len) { - l1_frame_t l1_frame; + sng_l1_frame_t l1_frame; sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) dchan->span->signal_data; memset(&l1_frame, 0, sizeof(l1_frame)); @@ -606,32 +606,32 @@ void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len) memcpy(&l1_frame.data, data, len); - if (ftdm_test_flag(&(dchan->iostats.s.rx), FTDM_IOSTATS_ERROR_CRC)) { + if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_CRC)) { l1_frame.flags |= SNG_L1FRAME_ERROR_CRC; } - if (ftdm_test_flag(&(dchan->iostats.s.rx), FTDM_IOSTATS_ERROR_FRAME)) { + if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_FRAME)) { l1_frame.flags |= SNG_L1FRAME_ERROR_FRAME; } - if (ftdm_test_flag(&(dchan->iostats.s.rx), FTDM_IOSTATS_ERROR_ABORT)) { + if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_ABORT)) { l1_frame.flags |= SNG_L1FRAME_ERROR_ABORT; } - if (ftdm_test_flag(&(dchan->iostats.s.rx), FTDM_IOSTATS_ERROR_FIFO)) { + if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_FIFO)) { l1_frame.flags |= SNG_L1FRAME_ERROR_FIFO; } - if (ftdm_test_flag(&(dchan->iostats.s.rx), FTDM_IOSTATS_ERROR_DMA)) { + if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_DMA)) { l1_frame.flags |= SNG_L1FRAME_ERROR_DMA; } - if (ftdm_test_flag(&(dchan->iostats.s.rx), FTDM_IOSTATS_QUEUE_THRES)) { + if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES)) { /* Should we trigger congestion here? */ l1_frame.flags |= SNG_L1FRAME_QUEUE_THRES; } - if (ftdm_test_flag(&(dchan->iostats.s.rx), FTDM_IOSTATS_QUEUE_FULL)) { + if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL)) { /* Should we trigger congestion here? */ l1_frame.flags |= SNG_L1FRAME_QUEUE_FULL; } @@ -640,14 +640,20 @@ void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len) } void sngisdn_snd_event(ftdm_channel_t *dchan, ftdm_oob_event_t event) -{ +{ + sng_l1_event_t l1_event; + memset(&l1_event, 0, sizeof(l1_event)); + + sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) dchan->span->signal_data; switch(event) { case FTDM_OOB_ALARM_CLEAR: - sng_isdn_event_ind(signal_data->link_id, SNG_L1EVENT_ALARM_OFF); + l1_event.type = SNG_L1EVENT_ALARM_OFF; + sng_isdn_event_ind(signal_data->link_id, &l1_event); break; case FTDM_OOB_ALARM_TRAP: - sng_isdn_event_ind(signal_data->link_id, SNG_L1EVENT_ALARM_ON); + l1_event.type = SNG_L1EVENT_ALARM_ON; + sng_isdn_event_ind(signal_data->link_id, &l1_event); break; default: /* We do not care about the other OOB events for now */ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c index 940006451a..e3898b9096 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c @@ -866,13 +866,15 @@ end_of_trace: return; } -int16_t sngisdn_rcv_data_req(uint16_t spId, uint8_t *buff, uint32_t length) +/* The stacks is wants to transmit a frame */ +int16_t sngisdn_rcv_l1_data_req(uint16_t spId, sng_l1_frame_t *l1_frame) { ftdm_status_t status; ftdm_wait_flag_t flags = FTDM_WRITE; sngisdn_span_data_t *signal_data = g_sngisdn_data.spans[spId]; ftdm_assert(signal_data, "Received Data request on unconfigured span\n"); - + ftdm_size_t length = l1_frame->len; + do { flags = FTDM_WRITE; status = signal_data->dchan->fio->wait(signal_data->dchan, &flags, 1000); @@ -883,7 +885,7 @@ int16_t sngisdn_rcv_data_req(uint16_t spId, uint8_t *buff, uint32_t length) if ((flags & FTDM_WRITE)) { - status = signal_data->dchan->fio->write(signal_data->dchan, buff, (ftdm_size_t*)&length); + status = signal_data->dchan->fio->write(signal_data->dchan, l1_frame->data, (ftdm_size_t*)&length); if (status != FTDM_SUCCESS) { ftdm_log_chan_msg(signal_data->dchan, FTDM_LOG_CRIT, "Failed to transmit frame\n"); return -1; @@ -900,6 +902,45 @@ int16_t sngisdn_rcv_data_req(uint16_t spId, uint8_t *buff, uint32_t length) return 0; } +int16_t sngisdn_rcv_l1_cmd_req(uint16_t spId, sng_l1_cmd_t *l1_cmd) +{ + sngisdn_span_data_t *signal_data = g_sngisdn_data.spans[spId]; + ftdm_assert(signal_data, "Received Data request on unconfigured span\n"); + + switch(l1_cmd->type) { + case SNG_L1CMD_SET_LINK_STATUS: + { + ftdm_channel_hw_link_status_t status = FTDM_HW_LINK_CONNECTED; + ftdm_channel_command(signal_data->dchan, FTDM_COMMAND_SET_LINK_STATUS, &status); + } + break; + case SNG_L1CMD_GET_LINK_STATUS: + { + ftdm_channel_hw_link_status_t status = 0; + ftdm_channel_command(signal_data->dchan, FTDM_COMMAND_GET_LINK_STATUS, &status); + if (status == FTDM_HW_LINK_CONNECTED) { + l1_cmd->cmd.status = 1; + } else if (status == FTDM_HW_LINK_DISCONNECTED) { + l1_cmd->cmd.status = 0; + } else { + ftdm_log_chan(signal_data->dchan, FTDM_LOG_CRIT, "Invalid link status reported %d\n", status); + l1_cmd->cmd.status = 0; + } + } + break; + case SNG_L1CMD_FLUSH_STATS: + ftdm_channel_command(signal_data->dchan, FTDM_COMMAND_FLUSH_IOSTATS, NULL); + break; + case SNG_L1CMD_FLUSH_BUFFERS: + ftdm_channel_command(signal_data->dchan, FTDM_COMMAND_FLUSH_BUFFERS, NULL); + break; + default: + ftdm_log_chan(signal_data->dchan, FTDM_LOG_CRIT, "Unsupported channel command:%d\n", l1_cmd->type); + return -1; + } + return 0; +} + void sngisdn_rcv_sng_assert(char *message) { ftdm_assert(0, message); diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c index d6573ac2de..f9fbb5c044 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c @@ -746,6 +746,28 @@ static FIO_COMMAND_FUNCTION(wanpipe_command) } } break; + case FTDM_COMMAND_FLUSH_BUFFERS: + { + err = sangoma_flush_bufs(ftdmchan->sockfd, &tdm_api); + } + break; + case FTDM_COMMAND_FLUSH_IOSTATS: + { + err = sangoma_flush_stats(ftdmchan->sockfd, &tdm_api); + } + break; + case FTDM_COMMAND_SET_RX_QUEUE_SIZE: + { + uint32_t queue_size = FTDM_COMMAND_OBJ_INT; + err = sangoma_set_rx_queue_sz(ftdmchan->sockfd, &tdm_api, queue_size); + } + break; + case FTDM_COMMAND_SET_TX_QUEUE_SIZE: + { + uint32_t queue_size = FTDM_COMMAND_OBJ_INT; + err = sangoma_set_tx_queue_sz(ftdmchan->sockfd, &tdm_api, queue_size); + } + break; default: break; }; @@ -759,45 +781,42 @@ static FIO_COMMAND_FUNCTION(wanpipe_command) return FTDM_SUCCESS; } -static void wanpipe_read_stats(ftdmchan, wp_tdm_api_rx_hdr_t *rx_stats) +static void wanpipe_read_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_rx_hdr_t *rx_stats) { - ftdmchan->iostats.s.rx.error_flags = 0; - if (rx_stats->rx_hdr_errors) { - wanpipe_reset_stats(ftdmchan); - ftdm_log_chan_msg_throttle(ftdmchan, "IO errors\n"); - } + ftdmchan->iostats.stats.rx.flags = 0; - ftdmchan->iostats.s.rx_queue_size = rx_stats->rx_h.rx_h.max_rx_queue_length; - ftdmchan->iostats.s.rx_queue_len = rx_stats->rx_h.current_number_of_frames_in_rx_queue; + ftdmchan->iostats.stats.rx.errors = rx_stats->wp_api_rx_hdr_errors; + ftdmchan->iostats.stats.rx.rx_queue_size = rx_stats->wp_api_rx_hdr_max_queue_length; + ftdmchan->iostats.stats.rx.rx_queue_len = rx_stats->wp_api_rx_hdr_number_of_frames_in_queue; - if (rx_stats->rx_h.wp_api_rx_hdr_error_map & (1<iostats.s.rx), FTDM_IOSTATS_ERROR_ABORT); + if (rx_stats->wp_api_rx_hdr_error_map & (1<iostats.stats.rx), FTDM_IOSTATS_ERROR_ABORT); } - if (rx_stats->rx_h.wp_api_rx_hdr_error_map & (1<iostats.s.rx), FTDM_IOSTATS_ERROR_DMA); + if (rx_stats->wp_api_rx_hdr_error_map & (1<iostats.stats.rx), FTDM_IOSTATS_ERROR_DMA); } - if (rx_stats->rx_h.wp_api_rx_hdr_error_map & (1<iostats.s.rx), FTDM_IOSTATS_ERROR_FIFO); + if (rx_stats->wp_api_rx_hdr_error_map & (1<iostats.stats.rx), FTDM_IOSTATS_ERROR_FIFO); } - if (rx_stats->rx_h.wp_api_rx_hdr_error_map & (1<iostats.s.rx), FTDM_IOSTATS_ERROR_CRC); + if (rx_stats->wp_api_rx_hdr_error_map & (1<iostats.stats.rx), FTDM_IOSTATS_ERROR_CRC); } - if (rx_stats->rx_h.wp_api_rx_hdr_error_map & (1<iostats.s.rx), FTDM_IOSTATS_ERROR_FRAME); + if (rx_stats->wp_api_rx_hdr_error_map & (1<iostats.stats.rx), FTDM_IOSTATS_ERROR_FRAME); } - if (ftdmchan->iostats.s.rx_queue_len >= (0.8*ftdmchan->iostats.s.rx_queue_size)) { + if (ftdmchan->iostats.stats.rx.rx_queue_len >= (0.8*ftdmchan->iostats.stats.rx.rx_queue_size)) { ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Rx Queue length exceeded threshold (%d/%d)\n", - ftdmchan->iostats.s.rx_queue_len, ftdmchan->iostats.s.rx_queue_size); + ftdmchan->iostats.stats.rx.rx_queue_len, ftdmchan->iostats.stats.rx.rx_queue_size); - ftdm_set_flag(&(ftdmchan->iostats.s.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES); + ftdm_set_flag(&(ftdmchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES); } - if (ftdmchan->iostats.s.rx_queue_len >= ftdmchan->iostats.s.rx_queue_size) { + if (ftdmchan->iostats.stats.rx.rx_queue_len >= ftdmchan->iostats.stats.rx.rx_queue_size) { ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Rx Queue Full (%d/%d)\n", - ftdmchan->iostats.s.rx_queue_len, ftdmchan->iostats.s.rx_queue_size); + ftdmchan->iostats.stats.rx.rx_queue_len, ftdmchan->iostats.stats.rx.rx_queue_size); - ftdm_set_flag(&(ftdmchan->iostats.s.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL); + ftdm_set_flag(&(ftdmchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL); } return; } diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index 64ecc2e357..52a5456df1 100644 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -430,12 +430,15 @@ typedef enum { FTDM_COMMAND_FLUSH_TX_BUFFERS, FTDM_COMMAND_FLUSH_RX_BUFFERS, FTDM_COMMAND_FLUSH_BUFFERS, + FTDM_COMMAND_FLUSH_IOSTATS, FTDM_COMMAND_SET_PRE_BUFFER_SIZE, FTDM_COMMAND_SET_LINK_STATUS, FTDM_COMMAND_GET_LINK_STATUS, FTDM_COMMAND_ENABLE_LOOP, FTDM_COMMAND_DISABLE_LOOP, - FTDM_COMMAND_COUNT + FTDM_COMMAND_COUNT, + FTDM_COMMAND_SET_RX_QUEUE_SIZE, + FTDM_COMMAND_SET_TX_QUEUE_SIZE, } ftdm_command_t; /*! \brief Custom memory handler hooks. Not recommended to use unless you need memory allocation customizations */ diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h index 6cbf589044..c7a1533320 100644 --- a/libs/freetdm/src/include/private/ftdm_core.h +++ b/libs/freetdm/src/include/private/ftdm_core.h @@ -391,7 +391,7 @@ typedef struct { uint8_t tx_queue_size; /* max queue size configured */ uint8_t tx_queue_len; /* Current number of elements in queue */ } tx; - } s; + } stats; } ftdm_channel_iostats_t; /* 2^8 table size, one for each byte (sample) value */ diff --git a/libs/freetdm/src/include/private/ftdm_types.h b/libs/freetdm/src/include/private/ftdm_types.h index 78ac8f63eb..d9cefc3c6f 100644 --- a/libs/freetdm/src/include/private/ftdm_types.h +++ b/libs/freetdm/src/include/private/ftdm_types.h @@ -194,6 +194,7 @@ typedef enum { FTDM_CHANNEL_FEATURE_CALLWAITING = (1 << 6), /*!< Channel will allow call waiting (ie: FXS devices) (read/write) */ FTDM_CHANNEL_FEATURE_HWEC = (1<<7), /*!< Channel has a hardware echo canceller */ FTDM_CHANNEL_FEATURE_HWEC_DISABLED_ON_IDLE = (1<<8), /*!< hardware echo canceller is disabled when there are no calls on this channel */ + FTDM_CHANNEL_FEATURE_IO_STATS = (1<<9), /*!< Channel supports IO statistics (HDLC channels only) */ } ftdm_channel_feature_t; typedef enum { From 97056b24c0fc975ac7a92d344992e13e6c0d320d Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Thu, 11 Nov 2010 16:04:56 -0500 Subject: [PATCH 006/237] mod_sangoma_codec: fix samples per packet --- src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c b/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c index 6e6fe58af6..dc2fce2b96 100644 --- a/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c +++ b/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c @@ -91,7 +91,7 @@ vocallo_codec_t g_codec_map[] = { SNGTC_CODEC_PCMU, 0, "PCMU", "Sangoma PCMU", 40, 64000, 10000, 80, 160, 80, 8000, 8000, 1 }, { SNGTC_CODEC_PCMA, 8, "PCMA", "Sangoma PCMA", 40, 64000, 10000, 80, 160, 80, 8000, 8000, 1 }, { SNGTC_CODEC_L16_1, 10, "L16", "Sangoma L16", 40, 120000, 10000, 80, 160, 160, 8000, 8000, 0 }, - { SNGTC_CODEC_L16_2, 10, "L16", "Sangoma L16 2", 40, 320000, 10000, 80, 320, 320, 16000, 16000, 0 }, + { SNGTC_CODEC_L16_2, 10, "L16", "Sangoma L16 2", 40, 320000, 10000, 160, 320, 320, 16000, 16000, 0 }, { SNGTC_CODEC_G729AB, 18, "G729", "Sangoma G729", 40, 8000, 10000, 80, 160, 10, 8000, 8000, 1 }, { SNGTC_CODEC_G726_32, 122, "G726-32", "Sangoma G.726 32k", 40, 32000, 10000, 80, 160, 40, 8000, 8000, 1 }, { SNGTC_CODEC_G722, 9, "G722", "Sangoma G722", 20, 64000, 10000, 80, 160, 80, 8000, 8000, 1 }, From fcaf2677574df7fde795bb4e11f8d843ab383442 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Fri, 12 Nov 2010 09:47:55 -0500 Subject: [PATCH 007/237] mod_sangoma_codec: add siren7 32kbps --- .../mod_sangoma_codec/mod_sangoma_codec.c | 57 ++++++++++++++----- 1 file changed, 43 insertions(+), 14 deletions(-) diff --git a/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c b/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c index dc2fce2b96..9f4c12b314 100644 --- a/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c +++ b/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c @@ -88,21 +88,22 @@ typedef struct vocallo_codec_s { vocallo_codec_t g_codec_map[] = { /* auto-init codecs */ - { SNGTC_CODEC_PCMU, 0, "PCMU", "Sangoma PCMU", 40, 64000, 10000, 80, 160, 80, 8000, 8000, 1 }, - { SNGTC_CODEC_PCMA, 8, "PCMA", "Sangoma PCMA", 40, 64000, 10000, 80, 160, 80, 8000, 8000, 1 }, - { SNGTC_CODEC_L16_1, 10, "L16", "Sangoma L16", 40, 120000, 10000, 80, 160, 160, 8000, 8000, 0 }, - { SNGTC_CODEC_L16_2, 10, "L16", "Sangoma L16 2", 40, 320000, 10000, 160, 320, 320, 16000, 16000, 0 }, - { SNGTC_CODEC_G729AB, 18, "G729", "Sangoma G729", 40, 8000, 10000, 80, 160, 10, 8000, 8000, 1 }, - { SNGTC_CODEC_G726_32, 122, "G726-32", "Sangoma G.726 32k", 40, 32000, 10000, 80, 160, 40, 8000, 8000, 1 }, - { SNGTC_CODEC_G722, 9, "G722", "Sangoma G722", 20, 64000, 10000, 80, 160, 80, 8000, 8000, 1 }, + { SNGTC_CODEC_PCMU, IANA_PCMU_A_8000_1, "PCMU", "Sangoma PCMU", 40, 64000, 10000, 80, 160, 80, 8000, 8000, 1 }, + { SNGTC_CODEC_PCMA, IANA_PCMA_A_8000_1, "PCMA", "Sangoma PCMA", 40, 64000, 10000, 80, 160, 80, 8000, 8000, 1 }, + { SNGTC_CODEC_L16_1, IANA_L16_A_44100_1, "L16", "Sangoma L16", 40, 120000, 10000, 80, 160, 160, 8000, 8000, 0 }, + { SNGTC_CODEC_L16_2, IANA_L16_A_44100_1, "L16", "Sangoma L16 2", 40, 320000, 10000, 160, 320, 320, 16000, 16000, 0 }, + { SNGTC_CODEC_G729AB, IANA_G729_AB_8000_1, "G729", "Sangoma G729", 40, 8000, 10000, 80, 160, 10, 8000, 8000, 1 }, + { SNGTC_CODEC_G726_32, IANA_G726_32_8000_1, "G726-32", "Sangoma G.726 32k", 40, 32000, 10000, 80, 160, 40, 8000, 8000, 1 }, + { SNGTC_CODEC_G722, IANA_G722_A_8000_1, "G722", "Sangoma G722", 20, 64000, 10000, 80, 160, 80, 8000, 8000, 1 }, /* manually initialized */ - { SNGTC_CODEC_GSM_FR, 3, "GSM", "Sangoma GSM", 20, 13200, 20000, 160, 320, 33, 8000, 8000, 0 }, - { SNGTC_CODEC_G723_1_63, 4, "G723", "Sangoma G723", 90, 6300, 30000, 240, 480, 24, 8000, 8000, 0 }, - { SNGTC_CODEC_AMR_1220, 96, "AMR", "Sangoma AMR", 20, 12200, 20000, 160, 320, 0, 8000, 8000, 0 }, - { SNGTC_CODEC_ILBC_133, ILBC_133_PAYLOAD, "iLBC", "Sangoma iLBC", -1, -1, -1, -1, -1, -1, -1, -1, 0 }, - { SNGTC_CODEC_ILBC_152, ILBC_152_PAYLOAD, "iLBC", "Sangoma iLBC", -1, -1, -1, -1, -1, -1, -1, -1, 0 }, - { -1, -1, NULL, NULL, -1, -1, -1, -1, -1, -1, -1, -1, 0 }, + { SNGTC_CODEC_GSM_FR, IANA_GSM_A_8000_1, "GSM", "Sangoma GSM", 20, 13200, 20000, 160, 320, 33, 8000, 8000, 0 }, + { SNGTC_CODEC_G723_1_63, IANA_G723_A_8000_1, "G723", "Sangoma G723", 90, 6300, 30000, 240, 480, 24, 8000, 8000, 0 }, + { SNGTC_CODEC_AMR_1220, IANA_AMR_WB_16000_1, "AMR", "Sangoma AMR", 20, 12200, 20000, 160, 320, 0, 8000, 8000, 0 }, + { SNGTC_CODEC_SIREN7_32, IANA_SIREN7, "G7221", "Sangoma G722.1", 20, 32000, 20000, 320, 640, 80, 16000, 16000, 0 }, + { SNGTC_CODEC_ILBC_133, IANA_ILBC_133_8000_1, "iLBC", "Sangoma iLBC", -1, -1, -1, -1, -1, -1, -1, -1, 0 }, + { SNGTC_CODEC_ILBC_152, IANA_ILBC_152_8000_1, "iLBC", "Sangoma iLBC", -1, -1, -1, -1, -1, -1, -1, -1, 0 }, + { -1, -1, NULL, NULL, -1, -1, -1, -1, -1, -1, -1, -1, 0 }, }; /* RFC3389 RTP Payload for Comfort Noise */ @@ -386,6 +387,12 @@ static switch_status_t switch_sangoma_init_ilbc(switch_codec_t *codec, switch_co return switch_sangoma_init(codec, flags, codec_settings); } +static switch_status_t switch_sangoma_init_siren7(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings) +{ + int bit_rate = codec->implementation->bits_per_second; + codec->fmtp_out = switch_core_sprintf(codec->memory_pool, "bitrate=%d", bit_rate); + return switch_sangoma_init(codec, flags, codec_settings); +} static void flush_rtp(switch_rtp_t *rtp) { @@ -1322,7 +1329,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sangoma_codec_load) 50, /* number of bytes per frame compressed */ 1, /* number of channels represented */ 1, /* number of frames per network packet (I dont think this is used at all) */ - switch_sangoma_init, /* function to initialize a codec session using this implementation */ + switch_sangoma_init_ilbc, /* function to initialize a codec session using this implementation */ switch_sangoma_encode, /* function to encode slinear data into encoded data */ switch_sangoma_decode, /* function to decode encoded data into slinear data */ switch_sangoma_destroy); /* deinitalize a codec handle using this implementation */ @@ -1353,6 +1360,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sangoma_codec_load) } break; + case SNGTC_CODEC_AMR_1220: switch_core_codec_add_implementation(pool, codec_interface, /* the codec interface we allocated and we want to register with the core */ SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */ @@ -1374,6 +1382,27 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sangoma_codec_load) switch_sangoma_destroy); /* deinitalize a codec handle using this implementation */ break; + case SNGTC_CODEC_SIREN7_32: + switch_core_codec_add_implementation(pool, codec_interface, /* the codec interface we allocated and we want to register with the core */ + SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */ + g_codec_map[c].iana, /* the IANA code number, ie http://www.iana.org/assignments/rtp-parameters */ + g_codec_map[c].iana_name, /* the IANA code name */ + "bitrate=32000", /* default fmtp to send (can be overridden by the init function), fmtp is used in SDP for format specific parameters */ + g_codec_map[c].sampling_rate, /* samples transferred per second */ + g_codec_map[c].actual_sampling_rate, /* actual samples transferred per second */ + g_codec_map[c].bps, /* bits transferred per second */ + g_codec_map[c].mpf, /* microseconds per frame */ + g_codec_map[c].spf, /* samples per frame */ + g_codec_map[c].bpfd, /* number of bytes per frame decompressed */ + g_codec_map[c].bpfc, /* number of bytes per frame compressed */ + 1, /* number of channels represented */ + g_codec_map[c].spf, /* number of frames per network packet (I dont think this is used at all) */ + switch_sangoma_init_siren7, /* function to initialize a codec session using this implementation */ + switch_sangoma_encode, /* function to encode slinear data into encoded data */ + switch_sangoma_decode, /* function to decode encoded data into slinear data */ + switch_sangoma_destroy); /* deinitalize a codec handle using this implementation */ + break; + default: break; } From 3acc5fdb642832bf2b91c06fadcd221660f6e6ae Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Fri, 12 Nov 2010 12:39:32 -0500 Subject: [PATCH 008/237] mod_sangoma_codec: add SIREN7 24kbps --- .../mod_sangoma_codec/mod_sangoma_codec.c | 94 ++++++++++++------- 1 file changed, 62 insertions(+), 32 deletions(-) diff --git a/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c b/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c index 9f4c12b314..97d9f6de9e 100644 --- a/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c +++ b/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c @@ -40,7 +40,6 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sangoma_codec_load); SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_sangoma_codec_shutdown); SWITCH_MODULE_DEFINITION(mod_sangoma_codec, mod_sangoma_codec_load, mod_sangoma_codec_shutdown, NULL); -#define IANA_LINEAR 10 #define SANGOMA_SESS_HASH_KEY_FORMAT "sngtc%lu" /* it seemed we need higher PTIME than the calling parties, so we assume nobody will use higher ptime than 40 */ @@ -83,15 +82,13 @@ typedef struct vocallo_codec_s { int autoinit; /* initialize on start loop or manually */ } vocallo_codec_t; -#define ILBC_133_PAYLOAD 97 -#define ILBC_152_PAYLOAD 98 vocallo_codec_t g_codec_map[] = { /* auto-init codecs */ { SNGTC_CODEC_PCMU, IANA_PCMU_A_8000_1, "PCMU", "Sangoma PCMU", 40, 64000, 10000, 80, 160, 80, 8000, 8000, 1 }, { SNGTC_CODEC_PCMA, IANA_PCMA_A_8000_1, "PCMA", "Sangoma PCMA", 40, 64000, 10000, 80, 160, 80, 8000, 8000, 1 }, - { SNGTC_CODEC_L16_1, IANA_L16_A_44100_1, "L16", "Sangoma L16", 40, 120000, 10000, 80, 160, 160, 8000, 8000, 0 }, - { SNGTC_CODEC_L16_2, IANA_L16_A_44100_1, "L16", "Sangoma L16 2", 40, 320000, 10000, 160, 320, 320, 16000, 16000, 0 }, + { SNGTC_CODEC_L16_1, IANA_L16_A_8000_1, "L16", "Sangoma L16", 40, 120000, 10000, 80, 160, 160, 8000, 8000, 0 }, + { SNGTC_CODEC_L16_2, IANA_L16_A_16000_1, "L16", "Sangoma L16 2", 40, 320000, 10000, 160, 320, 320, 16000, 16000, 0 }, { SNGTC_CODEC_G729AB, IANA_G729_AB_8000_1, "G729", "Sangoma G729", 40, 8000, 10000, 80, 160, 10, 8000, 8000, 1 }, { SNGTC_CODEC_G726_32, IANA_G726_32_8000_1, "G726-32", "Sangoma G.726 32k", 40, 32000, 10000, 80, 160, 40, 8000, 8000, 1 }, { SNGTC_CODEC_G722, IANA_G722_A_8000_1, "G722", "Sangoma G722", 20, 64000, 10000, 80, 160, 80, 8000, 8000, 1 }, @@ -100,9 +97,10 @@ vocallo_codec_t g_codec_map[] = { SNGTC_CODEC_GSM_FR, IANA_GSM_A_8000_1, "GSM", "Sangoma GSM", 20, 13200, 20000, 160, 320, 33, 8000, 8000, 0 }, { SNGTC_CODEC_G723_1_63, IANA_G723_A_8000_1, "G723", "Sangoma G723", 90, 6300, 30000, 240, 480, 24, 8000, 8000, 0 }, { SNGTC_CODEC_AMR_1220, IANA_AMR_WB_16000_1, "AMR", "Sangoma AMR", 20, 12200, 20000, 160, 320, 0, 8000, 8000, 0 }, + { SNGTC_CODEC_SIREN7_24, IANA_SIREN7, "G7221", "Sangoma G722.1", 20, 24000, 20000, 320, 640, 60, 16000, 16000, 0 }, { SNGTC_CODEC_SIREN7_32, IANA_SIREN7, "G7221", "Sangoma G722.1", 20, 32000, 20000, 320, 640, 80, 16000, 16000, 0 }, - { SNGTC_CODEC_ILBC_133, IANA_ILBC_133_8000_1, "iLBC", "Sangoma iLBC", -1, -1, -1, -1, -1, -1, -1, -1, 0 }, - { SNGTC_CODEC_ILBC_152, IANA_ILBC_152_8000_1, "iLBC", "Sangoma iLBC", -1, -1, -1, -1, -1, -1, -1, -1, 0 }, + { SNGTC_CODEC_ILBC_133, IANA_ILBC_133_8000_1, "iLBC", "Sangoma iLBC", 30, 13300, 30000, 240, 480, 50, 8000, 8000, 0 }, + { SNGTC_CODEC_ILBC_152, IANA_ILBC_152_8000_1, "iLBC", "Sangoma iLBC", 20, 15200, 20000, 160, 320, 38, 8000, 8000, 0 }, { -1, -1, NULL, NULL, -1, -1, -1, -1, -1, -1, -1, -1, 0 }, }; @@ -182,11 +180,14 @@ static int codec_id_to_iana(int codec_id) return -1; } -static vocallo_codec_t *get_codec_from_iana(int iana) +static vocallo_codec_t *get_codec_from_iana(int iana, int bitrate) { int i; for (i = 0; g_codec_map[i].codec_id != -1; i++) { - if (iana == g_codec_map[i].iana) { + if (iana == g_codec_map[i].iana && !bitrate) { + return &g_codec_map[i]; + } + if (iana == g_codec_map[i].iana && bitrate == g_codec_map[i].bps) { return &g_codec_map[i]; } } @@ -320,7 +321,7 @@ static switch_status_t switch_sangoma_init(switch_codec_t *codec, switch_codec_f sess->pool = codec->memory_pool; sess->impl = codec->implementation; - vcodec = get_codec_from_iana(codec->implementation->ianacode); + vcodec = get_codec_from_iana(codec->implementation->ianacode, codec->implementation->bits_per_second); switch_mutex_lock(g_sessions_lock); @@ -442,6 +443,7 @@ static switch_status_t switch_sangoma_encode(switch_codec_t *codec, switch_codec switch_time_t func_start_time = 0, func_end_time = 0; int i = 0; int res = 0; + int linear_payload = codec->implementation->actual_samples_per_second == 8000 ? IANA_L16_A_8000_1 : IANA_L16_A_16000_1; struct sangoma_transcoding_session *sess = codec->private_info; if (sess->encoder.debug_timing) { @@ -480,7 +482,7 @@ static switch_status_t switch_sangoma_encode(switch_codec_t *codec, switch_codec linear_frame.source = __FUNCTION__; linear_frame.data = decoded_byteswapped_data; linear_frame.datalen = decoded_data_len; - linear_frame.payload = IANA_LINEAR; + linear_frame.payload = linear_payload; /* copy and byte-swap */ for (i = 0; i < decoded_data_len/2; i++) { @@ -538,9 +540,9 @@ static switch_status_t switch_sangoma_encode(switch_codec_t *codec, switch_codec if (sess->encoder.request.b.codec_id == SNGTC_CODEC_ILBC_152 || sess->encoder.request.b.codec_id == SNGTC_CODEC_ILBC_133) { /* since we moved to SOAP based communications, the mapping between vocallo IANA and our IANA does not work, * some codecs checks cannot be completely done, like iLBC */ - if (encoded_frame.payload != ILBC_152_PAYLOAD && encoded_frame.payload != ILBC_133_PAYLOAD) { + if (encoded_frame.payload != IANA_ILBC_152_8000_1 && encoded_frame.payload != IANA_ILBC_133_8000_1) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Read unexpected payload %d in Sangoma encoder RTP session, expecting either %d or %d\n", - encoded_frame.payload, ILBC_152_PAYLOAD, ILBC_133_PAYLOAD); + encoded_frame.payload, IANA_ILBC_152_8000_1, IANA_ILBC_133_8000_1); break; } } else { @@ -640,6 +642,7 @@ static switch_status_t switch_sangoma_decode(switch_codec_t *codec, /* codec ses uint16_t *rtp_data_linear; int res = 0; int i = 0; + int linear_payload = codec->implementation->actual_samples_per_second == 8000 ? IANA_L16_A_8000_1 : IANA_L16_A_16000_1; struct sangoma_transcoding_session *sess = codec->private_info; if (sess->decoder.debug_timing) { @@ -729,9 +732,9 @@ static switch_status_t switch_sangoma_decode(switch_codec_t *codec, /* codec ses continue; } - if (linear_frame.payload != IANA_LINEAR) { + if (linear_frame.payload != linear_payload) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Read unexpected payload %d in Sangoma decoder RTP session, expecting %d\n", - linear_frame.payload, IANA_LINEAR); + linear_frame.payload, linear_payload); break; } @@ -1163,7 +1166,9 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sangoma_codec_load) switch_api_interface_t *api_interface = NULL; int i = 0, c = 0; int ilbc_done = 0; + int siren_done = 0; vocallo_codec_t *ilbc_codec = NULL; + vocallo_codec_t *siren_codec = NULL; int detected = 0, activated = 0; /* make sure we have valid configuration */ @@ -1221,17 +1226,18 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sangoma_codec_load) continue; } - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Registering implementations for codec %s\n", g_codec_map[c].iana_name); - - /* let know the library which iana to use */ - sngtc_set_iana_code_based_on_codec_id(g_codec_map[c].codec_id, g_codec_map[c].iana); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Mapped codec %d to IANA %d\n", g_codec_map[c].codec_id, g_codec_map[c].iana); - /* special check for iLBC to add a single codec interface for both ILBC bitrate versions */ if ((g_codec_map[c].codec_id == SNGTC_CODEC_ILBC_152 || g_codec_map[c].codec_id == SNGTC_CODEC_ILBC_133) && ilbc_done) { continue; } + /* special check for siren to add a single codec interface for all siren bitrate versions */ + if ((g_codec_map[c].codec_id == SNGTC_CODEC_SIREN7_24 || g_codec_map[c].codec_id == SNGTC_CODEC_SIREN7_32) && siren_done) { + continue; + } + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Registering implementations for codec %s\n", g_codec_map[c].iana_name); + /* SWITCH_ADD_CODEC allocates a codec interface structure from the pool the core gave us and adds it to the internal interface * list the core keeps, gets a codec id and set the given codec name to it. * At this point there is an empty shell codec interface registered, but not yet implementations */ @@ -1382,25 +1388,49 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sangoma_codec_load) switch_sangoma_destroy); /* deinitalize a codec handle using this implementation */ break; + case SNGTC_CODEC_SIREN7_24: case SNGTC_CODEC_SIREN7_32: + + siren_codec = get_codec_from_id(SNGTC_CODEC_SIREN7_24); switch_core_codec_add_implementation(pool, codec_interface, /* the codec interface we allocated and we want to register with the core */ SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */ - g_codec_map[c].iana, /* the IANA code number, ie http://www.iana.org/assignments/rtp-parameters */ - g_codec_map[c].iana_name, /* the IANA code name */ - "bitrate=32000", /* default fmtp to send (can be overridden by the init function), fmtp is used in SDP for format specific parameters */ - g_codec_map[c].sampling_rate, /* samples transferred per second */ - g_codec_map[c].actual_sampling_rate, /* actual samples transferred per second */ - g_codec_map[c].bps, /* bits transferred per second */ - g_codec_map[c].mpf, /* microseconds per frame */ - g_codec_map[c].spf, /* samples per frame */ - g_codec_map[c].bpfd, /* number of bytes per frame decompressed */ - g_codec_map[c].bpfc, /* number of bytes per frame compressed */ + siren_codec->iana, /* the IANA code number, ie http://www.iana.org/assignments/rtp-parameters */ + siren_codec->iana_name, /* the IANA code name */ + "bitrate=24000", /* default fmtp to send (can be overridden by the init function), fmtp is used in SDP for format specific parameters */ + siren_codec->sampling_rate, /* samples transferred per second */ + siren_codec->actual_sampling_rate, /* actual samples transferred per second */ + siren_codec->bps, /* bits transferred per second */ + siren_codec->mpf, /* microseconds per frame */ + siren_codec->spf, /* samples per frame */ + siren_codec->bpfd, /* number of bytes per frame decompressed */ + siren_codec->bpfc, /* number of bytes per frame compressed */ 1, /* number of channels represented */ - g_codec_map[c].spf, /* number of frames per network packet (I dont think this is used at all) */ + siren_codec->spf, /* number of frames per network packet (I dont think this is used at all) */ switch_sangoma_init_siren7, /* function to initialize a codec session using this implementation */ switch_sangoma_encode, /* function to encode slinear data into encoded data */ switch_sangoma_decode, /* function to decode encoded data into slinear data */ switch_sangoma_destroy); /* deinitalize a codec handle using this implementation */ + + siren_codec = get_codec_from_id(SNGTC_CODEC_SIREN7_32); + switch_core_codec_add_implementation(pool, codec_interface, /* the codec interface we allocated and we want to register with the core */ + SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */ + siren_codec->iana, /* the IANA code number, ie http://www.iana.org/assignments/rtp-parameters */ + siren_codec->iana_name, /* the IANA code name */ + "bitrate=32000", /* default fmtp to send (can be overridden by the init function), fmtp is used in SDP for format specific parameters */ + siren_codec->sampling_rate, /* samples transferred per second */ + siren_codec->actual_sampling_rate, /* actual samples transferred per second */ + siren_codec->bps, /* bits transferred per second */ + siren_codec->mpf, /* microseconds per frame */ + siren_codec->spf, /* samples per frame */ + siren_codec->bpfd, /* number of bytes per frame decompressed */ + siren_codec->bpfc, /* number of bytes per frame compressed */ + 1, /* number of channels represented */ + siren_codec->spf, /* number of frames per network packet (I dont think this is used at all) */ + switch_sangoma_init_siren7, /* function to initialize a codec session using this implementation */ + switch_sangoma_encode, /* function to encode slinear data into encoded data */ + switch_sangoma_decode, /* function to decode encoded data into slinear data */ + switch_sangoma_destroy); /* deinitalize a codec handle using this implementation */ + siren_done = 1; break; default: From 68f18efe37248bd6797b055b31711ae1c7f2e782 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 15 Nov 2010 13:51:27 -0600 Subject: [PATCH 009/237] add intercept_unanswered_only var akin to intercept_unbridged_only --- src/switch_ivr_bridge.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/switch_ivr_bridge.c b/src/switch_ivr_bridge.c index 2549554005..b6363ffa53 100644 --- a/src/switch_ivr_bridge.c +++ b/src/switch_ivr_bridge.c @@ -1546,6 +1546,13 @@ SWITCH_DECLARE(void) switch_ivr_intercept_session(switch_core_session_t *session } } + if ((var = switch_channel_get_variable(channel, "intercept_unanswered_only")) && switch_true(var)) { + if ((switch_channel_test_flag(rchannel, CF_ANSWERED))) { + switch_core_session_rwunlock(rsession); + return; + } + } + switch_channel_pre_answer(channel); if (!zstr(buuid)) { From 0b377051af622ac8974e990f9244e9f69bee90ce Mon Sep 17 00:00:00 2001 From: Mathieu Rene Date: Tue, 16 Nov 2010 10:52:16 -0500 Subject: [PATCH 010/237] gdbinit: ignore SIGTTIN and SIGPIPE --- support-d/.gdbinit | 3 +++ 1 file changed, 3 insertions(+) mode change 100644 => 100755 support-d/.gdbinit diff --git a/support-d/.gdbinit b/support-d/.gdbinit old mode 100644 new mode 100755 index 942b761adf..e32687cfc4 --- a/support-d/.gdbinit +++ b/support-d/.gdbinit @@ -1,3 +1,6 @@ +handle SIGPIPE pass noprint nostop +handle SIGTTIN pass noprint nostop + # FreeSWITCH Custom GDB commands define list_sessions dont-repeat From 65be57d212e601de396d57821bb499a4d802a1c7 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Tue, 16 Nov 2010 12:41:56 -0500 Subject: [PATCH 011/237] Fixed for windows compilation issues --- .../ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c | 3 ++- .../ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c index 8842ef5934..b0848379e9 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c @@ -642,10 +642,11 @@ void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len) void sngisdn_snd_event(ftdm_channel_t *dchan, ftdm_oob_event_t event) { sng_l1_event_t l1_event; + sngisdn_span_data_t *signal_data = NULL; memset(&l1_event, 0, sizeof(l1_event)); - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) dchan->span->signal_data; + signal_data = (sngisdn_span_data_t*) dchan->span->signal_data; switch(event) { case FTDM_OOB_ALARM_CLEAR: l1_event.type = SNG_L1EVENT_ALARM_OFF; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c index e3898b9096..02e0bdf71b 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c @@ -871,9 +871,10 @@ int16_t sngisdn_rcv_l1_data_req(uint16_t spId, sng_l1_frame_t *l1_frame) { ftdm_status_t status; ftdm_wait_flag_t flags = FTDM_WRITE; - sngisdn_span_data_t *signal_data = g_sngisdn_data.spans[spId]; - ftdm_assert(signal_data, "Received Data request on unconfigured span\n"); + sngisdn_span_data_t *signal_data = g_sngisdn_data.spans[spId]; ftdm_size_t length = l1_frame->len; + + ftdm_assert(signal_data, "Received Data request on unconfigured span\n"); do { flags = FTDM_WRITE; From c5070aaf52bb37ec63731e82be04f8e78057df21 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Tue, 16 Nov 2010 14:56:19 -0500 Subject: [PATCH 012/237] Fixed cyginstall.sh script --- libs/freetdm/cyginstall.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/freetdm/cyginstall.sh b/libs/freetdm/cyginstall.sh index 311df939af..e2d5885c4e 100644 --- a/libs/freetdm/cyginstall.sh +++ b/libs/freetdm/cyginstall.sh @@ -5,7 +5,8 @@ fsdir=../.. set -x cp Debug/mod/*.dll $fsdir/Debug/mod/ cp mod_freetdm/Debug/*.pdb $fsdir/Debug/mod/ -cp Debug/*.dll $fsdir/Debug/mod/ +cp Debug/freetdm.dll $fsdir/Debug/ +cp Debug/ftmod_*.dll $fsdir/Debug/mod/ cp Debug/*.pdb $fsdir/Debug/mod/ #cp Debug/testsangomaboost.exe $fsdir/Debug/ echo "FRIENDLY REMINDER: RECOMPILE ftmod_wanpipe WHENEVER YOU INSTALL NEW DRIVERS" From 055c78e61eb4a4de76404d11c221654dda2b301d Mon Sep 17 00:00:00 2001 From: Michael S Collins Date: Tue, 16 Nov 2010 12:49:59 -0800 Subject: [PATCH 013/237] Update ChangeLog through Oct 15 (more to come) --- docs/ChangeLog | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/docs/ChangeLog b/docs/ChangeLog index d6fddd6bfa..e0f5297d2c 100644 --- a/docs/ChangeLog +++ b/docs/ChangeLog @@ -30,6 +30,7 @@ freeswitch (1.0.7) config: Add att_xfer example to default dialplan (r:20ec962a) config: default example to resolve some issues with SCA in cases where host and ip are mixed causing the phone to be confused. (r:0279261b) config: Fix phrase files, still missing a sound file (r:6741f350/FS-2742) + config: Disallow global-intercept and group-intercept can intercept an outbound call in default dialplan (r:890871ba/FS-2777) core: Add RTCP support (FSRTP-14) core: handle some errors on missing db handle conditions core: add ... and shutdown as a fail-safe when no modules are loaded @@ -110,6 +111,13 @@ freeswitch (1.0.7) core: add bitrate patch from moc with some extra stuff for late neg mode (r:633f193d) core: refactor fmtp parser as a core func (r:56f8c11f) core: add switch_ivr_dmachine async digit parser to core (r:7f3319dc) + core: make parens optional on functions as vars ${foo(bar)} is now the same as ${foo bar} (r:fdba0e07) + core: fix default ptime for iLBC and make new configurable global map in switch.conf.xml (r:e3c427ad) + core: only pause recording media bugs in fifo (r:c1d41dd9) + core: Allow IPv6 in proxy mode (r:4e5911c2/FS-2776) + core: "Silent recovery" (r:93c2ed94) + core: fix switch_find_local_ip to properly handle force_local_ip_v4 and _v6 (r:f42c9036/FS-2778) + core: fix att_xfer/3-way scenario (r:0559cc50) lang: Improve French phrase files (FSCONFIG-23) libapr: Fix issue where after a bridge with a member, uuid of Agent is set to single quote character ' (r:3fee704d/FS-2738) libdingaling: fix race on shutdown causing crash (FSMOD-47) @@ -126,6 +134,7 @@ freeswitch (1.0.7) libesl: use uint32_t instead of long for timeout as in the rest of the lib, 0 means forever. Also added esl_send_recv_timed() (r:49d6c803) libesl: Fix SEGV when using serialize function without any arguments (r:910729b5/ESL-44) libesl: fix leak-on-error in esl_connect_timeout() (r:4263d60e) + libesl: Call close on connection handle if the connection fails (r:413dcc4c/ESL-50) libfreetdm: implemented freetdm config nodes and ss7 initial configuration libfreetdm: fix codec for CAS signaling (r:b76e7f18) libfreetdm: freetdm: ss7- added support for incoming group blocks, started adding support for ansi (r:c219a73c) @@ -142,6 +151,7 @@ freeswitch (1.0.7) libspandsp: Changes to the signaling tone detector to detect concurrent 2400Hz + 2600Hz tones. This passes voice immunity and other key tests, but it bounces a bit when transitions like 2400 -> 2400+2600 -> 2600 occur. Transitions between tone off and tone on are clean. (r:bc13e944) libspandsp: Fix Windows build after libspandsp update (r:d70cc852/FSBUILD-293) libspandsp: Fix for T.30 processing of operator interrupts, to improve compatibility with some machines, which seem to send them when no operator is around. (r:84ee0ae6) + libspandsp: spandsp t38 fax receiving error in win XP - regression from f029f7ef (r:761cec8f/FS-2766) mod_avmd: Initial check in - Advanced Voicemail Detect (r:10c6a30a) (by Eric Des Courtis) mod_avmd: Add to windows build (r:df4bd935) mod_callcenter: Initial commit of the mod_callcenter application. This module is in it early state of developpement. You can see documentation on the wiki at : http://wiki.freeswitch.org/wiki/Mod_callcenter For support/comments, please use http://jira.freeswitch.org/ and select the MOD CALLCENTER module. (r:ba09b96d) @@ -159,6 +169,7 @@ freeswitch (1.0.7) mod_callcenter: Added max-wait-time and max-wait-time-with-no-agent param to a queue. (r:3482f95e) mod_callcenter: Make sure we fail to load if config is not present (r:e1fb79a1) mod_callcenter: Fix invalid update of agent field (r:426a448f/FS-2738) + mod_callcenter: Allow to get queue info via api (r:70d592ae) mod_cidlookup: null xml is bad (r:095815f8) mod_cid_lookup: honor skipcitystate when using whitepages (r:a66654de/FSMOD-53) mod_commands: make break uuid_break and add cascade flag @@ -180,22 +191,28 @@ freeswitch (1.0.7) mod_conference: add conference_member_id variable to all sessions with the member id used by their conference participation (For drk__) (r:49c9bfdb) mod_conference: fix relate nohear (r:f029ce07/MODAPP-428) mod_conference: Fix floor change events not always firing (r:8f1767d3/MODAPP-424) + mod_conference: refactor conference to use switch_ivr_dmachine for the digit parsing controls are now bound to each member separately based on conference_controls channel var, then the caller-controls param in the profile or a default to "default" (r:ac19f73c) + mod_conference: Fix crash on dtmf action (r:4d5389bd/FS-2781) mod_curl: use method=post when post requested (r:c6a4ddd0/FSMOD-69) + mod_db: fix stack corruption (MODAPP-407) mod_dialplan_xml: Add in the INFO log the caller id number when processing a request (Currenly only show the caller name) (r:e1df5e13) mod_dingaling: make mod_dingaling compat with google's new free phonecalls thing (r:ba0a2a32) mod_dingaling: make dingaling work with google voice inbound too (r:4ee68141) mod_dingaling: Fix crash when testing the new gv-dingaling with around 24 concurrent calls (r:73e1ec5e/FSCORE-667) mod_dingaling: Fix NULL pointer (r:e3eff816/FS-1103) mod_directory: Add variable directory_search_order to allow to search by first name by default is set to "first_name" (r:163ca31f) - mod_db: fix stack corruption (MODAPP-407) + mod_distributor: Add mod_distributor to VS2010 - not built by default (r:bac79ba1) mod_dptools: add eavesdrop_enable_dtmf chan var (r:596c0012) mod_dptools: Make park app not send 183 session progress (r:76932995/FSCORE-567) mod_dptools: add block_dtmf and unblock_dtmf apps (r:d9eb0197) mod_dptools: refactor export code and add new bridge_export app which is like export but exports across when one channel bridges another (r:4aa9a838) + mod_dptools: add bind_digit_action application (r:9537197b) + mod_dptools: emit event when user presses DTMFs (r:37298f56) mod_erlang_event: Make XML fetch reply ACKs distinguishable, update freeswitch.erl (r:9d44ed04) mod_erlang_event: Add 3 new commands; session_event, session_noevents, session_nixevent (r:698fa045) mod_erlang_event: generate long node names the same as erlang does (r:9ad509c2) mod_erlang_event: Improve some logging to include UUIDs (r:c0d51b83) + mod_erlang_event: Support for reading erlang cookie from a file (r:094ffe37) mod_event_socket: fix up other users of switch_event_xmlize() to use SWITCH_EVENT_NONE (r:d6eb7562) mod_event_socket: Fix small mem leaks (r:e4f90584/MODEVENT-68) mod_fifo: allow multiple dtmf to exit fifo, set fifo_caller_exit_key to specify which (MODAPP-420) @@ -234,6 +251,8 @@ freeswitch (1.0.7) mod_freetdm: OPENZAP-107 - Patched by Jeff Lenk (r:aa075136/OPENZAP-107) mod_freetdm: allocate channels in their own memory page when debugging (r:fcd8df0a) mod_freetdm: lock the channel when placing call (r:705dd237) + mod_freetdm: created cmake files for freetdm (r:fc55997b) + mod_freetdm: ss7 - added support to control mtp2, mtp3, and isup timers via freetdm.conf.xml (r:4455d581) mod_gsmopen: copy from branch mod_hash: free all hashtables on shutdown (r:e76d7d92) mod_hash: remove unneeded initializer (r:10d468a6) @@ -291,6 +310,8 @@ freeswitch (1.0.7) mod_sangoma_codec: added load/noload options for the supported codecs mod_sangoma_codec: rename load/noload to register/noregister mod_sangoma_codec: silence suppression (r:73d9d56f) + mod_sangoma_codec: do not return 0 len frames and return silence instead when there is no transcoding output update stats only when we really receive a frame (r:dc4d19e9) + mod_sangoma_codec: flush sockets on first use (r:bbba1148) mod_say_es: fix grammar when saying dates and time (r:6bed19b2/MODAPP-429) mod_say_ja: initial commit, still needs sound files (r:b2423158/FS-2755) mod_say_ru: Fix saying time with +1 hour of current time (r:68d74c31/MODAPP-444) @@ -391,6 +412,11 @@ freeswitch (1.0.7) mod_sofia: fix parsing of sofia tracelevel param, moved param from profile params to global_settings as its global, and it only worked on reparse before anyways. Please correct any documentation on this issue on the wiki (r:82c4c4cc/FS-523) mod_sofia: fix nat acl count check to check against the number of nat acls (r:e11550e7/FS-502) mod_sofia: add sofia_glue_find_parameter_value function to get a specific value from a url params string (r:c701d41c) + mod_sofia: Sofia SIP Stack Lockup (r:8f13eb89/FS-2762) + mod_sofia: ix memory leak caused by regression from FS-2747 (r:6c4cb07b/FS-2747) + mod_sofia: Set SDP proper connection type of "c=" field to IP6 or IP4 when IPv6 called IPv4 (r:14361c09/FS-620) + mod_sofia: FS wrongly assumes NAT on Cisco 7941G (r:42f534fa/FS-2773) + mod_sofia: sofia_reg.c doesn't pass profile name into query, also, typo with all-reg-options-ping (r:6772c795/FS-2787) mod_spandsp: initial checkin of mod_fax/mod_voipcodecs merge into mod_spandsp (r:fa9a59a8) mod_spandsp: rework of new mod_spandsp to have functions broken up into different c files (r:65400642) mod_spandsp: improve duplicate digit detection and add 'min_dup_digit_spacing_ms' channel variable for use with the dtmf detector (r:eab4f246/FSMOD-45) @@ -420,6 +446,7 @@ freeswitch (1.0.7) mod_voicemail: fix vm_inject to a group and change syntax for sending to a whole domain to domain= for clarity sake (r:f30a1cc6) mod_voicemail: add quotes to vm_cc command generated internally to escape spaces in the caller id name (r:5f012813) mod_voicemail: Play caller id of callee prior to playing a vmail (r:e7b97907/FS-2719) + mod_voicemail: FS-1776 Add support for per user operator exten override param vm-operator-extension (r:df5b3498/FS-1776) mod_xml_cdr: add force_process_cdr var to process b leg cdr on a case by case basis when b leg cdr is disabled (XML-17) mod_xml_cdr: add leg param to query string (XML-24) mod_xml_cdr: fix locked sessions (XML-26) @@ -428,6 +455,7 @@ freeswitch (1.0.7) scripts: added honeypot.pl and blacklist.pl which add extra SIP security options (r:b6a81ba7) sofia-sip: fix null derefernce segfault in soa (r:f356c5e6) sofia-sip: extend timeout for session expires on short timeouts to be 90% of timeout instead of 1/3 to handle devices that do not refresh in time such as polycom (r:a7f48928/SFSIP-212) + tools: Add fs_encode tool (r:89b17601) freeswitch (1.0.6) From a9b2ced2aaa56311237c8437efde13f3d5342600 Mon Sep 17 00:00:00 2001 From: Stefan Knoblich Date: Tue, 16 Nov 2010 22:50:43 +0100 Subject: [PATCH 014/237] ftmod_libpri: First part of the BRI PTMP channel handling changes. I really need to dig deeper here, some libpri events never fire for incoming calls and i'll have to find out how mod_freetdm or the FreeSWITCH core change states on the channel... Anyway, incoming and outgoing calls still work for me (BRI PTMP TE), so commit this now and let a wider audience do some more testing. Signed-off-by: Stefan Knoblich Tested-by: Stefan Knoblich --- .../src/ftmod/ftmod_libpri/ftmod_libpri.c | 187 ++++++++++++++++-- 1 file changed, 167 insertions(+), 20 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c index 21d6674717..669e85218a 100644 --- a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c +++ b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c @@ -503,15 +503,9 @@ static __inline__ void state_advance(ftdm_channel_t *chan) ftdm_status_t status; ftdm_sigmsg_t sig; - ftdm_log(FTDM_LOG_DEBUG, "%d:%d STATE [%s]\n", + ftdm_log(FTDM_LOG_DEBUG, "-- %d:%d STATE [%s]\n", ftdm_channel_get_span_id(chan), ftdm_channel_get_id(chan), ftdm_channel_get_state_str(chan)); -#if 0 - if (!ftdm_test_flag(chan, FTDM_CHANNEL_OUTBOUND) && !call) { - ftdm_log(FTDM_LOG_WARNING, "NO CALL!!!!\n"); - } -#endif - memset(&sig, 0, sizeof(sig)); sig.chan_id = ftdm_channel_get_id(chan); sig.span_id = ftdm_channel_get_span_id(chan); @@ -522,6 +516,22 @@ static __inline__ void state_advance(ftdm_channel_t *chan) { chan->call_data = NULL; ftdm_channel_done(chan); + + /* + * Close channel completely, BRI PTMP will thank us + */ + if (ftdm_test_flag(chan, FTDM_CHANNEL_OPEN)) { + ftdm_channel_t *chtmp = chan; + if (ftdm_channel_close(&chtmp) != FTDM_SUCCESS) { + ftdm_log(FTDM_LOG_WARNING, "-- Failed to close channel %d:%d\n", + ftdm_channel_get_span_id(chan), + ftdm_channel_get_id(chan)); + } else { + ftdm_log(FTDM_LOG_DEBUG, "-- Closed channel %d:%d\n", + ftdm_channel_get_span_id(chan), + ftdm_channel_get_id(chan)); + } + } } break; @@ -548,6 +558,10 @@ static __inline__ void state_advance(ftdm_channel_t *chan) ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_HANGUP); } } else if (call) { + /* make sure channel is open in this state (outbound handled in on_proceeding()) */ + if (!ftdm_test_flag(chan, FTDM_CHANNEL_OPEN)) { + ftdm_channel_open_chan(chan); + } pri_proceeding(isdn_data->spri.pri, call, ftdm_channel_get_id(chan), 1); } else { ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RESTART); @@ -557,6 +571,10 @@ static __inline__ void state_advance(ftdm_channel_t *chan) case FTDM_CHANNEL_STATE_RING: { + /* + * This needs more auditing for BRI PTMP: + * does pri_acknowledge() steal the call from other devices? + */ if (!ftdm_test_flag(chan, FTDM_CHANNEL_OUTBOUND)) { if (call) { pri_acknowledge(isdn_data->spri.pri, call, ftdm_channel_get_id(chan), 0); @@ -588,6 +606,10 @@ static __inline__ void state_advance(ftdm_channel_t *chan) ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_HANGUP); } } else if (call) { + /* make sure channel is open in this state (outbound handled in on_answer()) */ + if (!ftdm_test_flag(chan, FTDM_CHANNEL_OPEN)) { + ftdm_channel_open_chan(chan); + } pri_answer(isdn_data->spri.pri, call, 0, 1); } else { ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RESTART); @@ -795,34 +817,113 @@ static int on_answer(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_even ftdm_channel_t *chan = ftdm_span_get_channel(span, pevent->answer.channel); if (chan) { + if (!ftdm_test_flag(chan, FTDM_CHANNEL_OPEN)) { + ftdm_log(FTDM_LOG_DEBUG, "-- Call answered, opening B-Channel %d:%d\n", + ftdm_channel_get_span_id(chan), + ftdm_channel_get_id(chan)); + + if (ftdm_channel_open_chan(chan) != FTDM_SUCCESS) { + ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan); + + ftdm_log(FTDM_LOG_ERROR, "-- Error opening channel %d:%d\n", + ftdm_channel_get_span_id(chan), + ftdm_channel_get_id(chan)); + + caller_data->hangup_cause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER; + ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_TERMINATING); + goto out; + } + } ftdm_log(FTDM_LOG_DEBUG, "-- Answer on channel %d:%d\n", ftdm_span_get_id(span), pevent->answer.channel); ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_UP); } else { ftdm_log(FTDM_LOG_DEBUG, "-- Answer on channel %d:%d but it's not in the span?\n", ftdm_span_get_id(span), pevent->answer.channel); } +out: return 0; } /** - * \brief Handler for libpri proceed event + * \brief Handler for libpri proceeding event * \param spri Pri wrapper structure (libpri, span, dchan) * \param event_type Event type (unused) * \param pevent Event * \return 0 */ -static int on_proceed(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent) +static int on_proceeding(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent) { ftdm_span_t *span = spri->span; - ftdm_channel_t *chan = ftdm_span_get_channel(span, pevent->answer.channel); + ftdm_channel_t *chan = ftdm_span_get_channel(span, pevent->proceeding.channel); if (chan) { + /* Open channel if inband information is available */ + if ((pevent->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) && !ftdm_test_flag(chan, FTDM_CHANNEL_OPEN)) { + ftdm_log(FTDM_LOG_DEBUG, "-- In-band information available, opening B-Channel %d:%d\n", + ftdm_channel_get_span_id(chan), + ftdm_channel_get_id(chan)); + + if (ftdm_channel_open_chan(chan) != FTDM_SUCCESS) { + ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan); + + ftdm_log(FTDM_LOG_ERROR, "-- Error opening channel %d:%d\n", + ftdm_channel_get_span_id(chan), + ftdm_channel_get_id(chan)); + + caller_data->hangup_cause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER; + ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_TERMINATING); + goto out; + } + } ftdm_log(FTDM_LOG_DEBUG, "-- Proceeding on channel %d:%d\n", ftdm_span_get_id(span), pevent->proceeding.channel); ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); } else { ftdm_log(FTDM_LOG_DEBUG, "-- Proceeding on channel %d:%d but it's not in the span?\n", ftdm_span_get_id(span), pevent->proceeding.channel); } +out: + return 0; +} + +/** + * \brief Handler for libpri progress event + * \param spri Pri wrapper structure (libpri, span, dchan) + * \param event_type Event type (unused) + * \param pevent Event + * \return 0 + * \note also uses pri_event->proceeding + */ +static int on_progress(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent) +{ + ftdm_span_t *span = spri->span; + ftdm_channel_t *chan = ftdm_span_get_channel(span, pevent->proceeding.channel); + + if (chan) { + /* Open channel if inband information is available */ + if ((pevent->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) && !ftdm_test_flag(chan, FTDM_CHANNEL_OPEN)) { + ftdm_log(FTDM_LOG_DEBUG, "-- In-band information available, opening B-Channel %d:%d\n", + ftdm_channel_get_span_id(chan), + ftdm_channel_get_id(chan)); + + if (ftdm_channel_open_chan(chan) != FTDM_SUCCESS) { + ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan); + + ftdm_log(FTDM_LOG_ERROR, "-- Error opening channel %d:%d\n", + ftdm_channel_get_span_id(chan), + ftdm_channel_get_id(chan)); + + caller_data->hangup_cause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER; + ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_TERMINATING); + goto out; + } + } + ftdm_log(FTDM_LOG_DEBUG, "-- Progress on channel %d:%d\n", ftdm_span_get_id(span), pevent->proceeding.channel); + ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); + } else { + ftdm_log(FTDM_LOG_DEBUG, "-- Progress on channel %d:%d but it's not in the span?\n", + ftdm_span_get_id(span), pevent->proceeding.channel); + } +out: return 0; } @@ -840,17 +941,37 @@ static int on_ringing(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_eve if (chan) { ftdm_log(FTDM_LOG_DEBUG, "-- Ringing on channel %d:%d\n", ftdm_span_get_id(span), pevent->ringing.channel); + /* we may get on_ringing even when we're already in FTDM_CHANNEL_STATE_PROGRESS_MEDIA */ if (ftdm_channel_get_state(chan) == FTDM_CHANNEL_STATE_PROGRESS_MEDIA) { /* dont try to move to STATE_PROGRESS to avoid annoying veto warning */ return 0; } + + /* Open channel if inband information is available */ + if ((pevent->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) && !ftdm_test_flag(chan, FTDM_CHANNEL_OPEN)) { + ftdm_log(FTDM_LOG_DEBUG, "-- In-band information available, opening B-Channel %d:%d\n", + ftdm_channel_get_span_id(chan), + ftdm_channel_get_id(chan)); + + if (ftdm_channel_open_chan(chan) != FTDM_SUCCESS) { + ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan); + + ftdm_log(FTDM_LOG_ERROR, "-- Error opening channel %d:%d\n", + ftdm_channel_get_span_id(chan), + ftdm_channel_get_id(chan)); + + caller_data->hangup_cause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER; + ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_TERMINATING); + goto out; + } + } ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_PROGRESS); } else { ftdm_log(FTDM_LOG_DEBUG, "-- Ringing on channel %d:%d but it's not in the span?\n", ftdm_span_get_id(span), pevent->ringing.channel); } - +out: return 0; } @@ -868,16 +989,42 @@ static int on_ring(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event ftdm_caller_data_t *caller_data = NULL; int ret = 0; - if (!chan || ftdm_channel_get_state(chan) != FTDM_CHANNEL_STATE_DOWN || ftdm_test_flag(chan, FTDM_CHANNEL_INUSE)) { - ftdm_log(FTDM_LOG_WARNING, "--Duplicate Ring on channel %d:%d (ignored)\n", ftdm_span_get_id(span), pevent->ring.channel); + if (!chan) { + ftdm_log(FTDM_LOG_ERROR, "-- Unable to get channel %d:%d\n", ftdm_span_get_id(span), pevent->ring.channel); goto done; } - if (ftdm_channel_open_chan(chan) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_WARNING, "--Failure opening channel %d:%d (ignored)\n", ftdm_span_get_id(span), pevent->ring.channel); + if (ftdm_channel_get_state(chan) != FTDM_CHANNEL_STATE_DOWN || ftdm_test_flag(chan, FTDM_CHANNEL_INUSE)) { + ftdm_log(FTDM_LOG_WARNING, "-- Duplicate Ring on channel %d:%d (ignored)\n", ftdm_span_get_id(span), pevent->ring.channel); goto done; } + if ((pevent->ring.progressmask & PRI_PROG_INBAND_AVAILABLE)) { + /* Open channel if inband information is available */ + ftdm_log(FTDM_LOG_DEBUG, "-- In-band information available, opening B-Channel %d:%d\n", + ftdm_channel_get_span_id(chan), + ftdm_channel_get_id(chan)); + + if (!ftdm_test_flag(chan, FTDM_CHANNEL_OPEN) && ftdm_channel_open_chan(chan) != FTDM_SUCCESS) { +// ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan); + + ftdm_log(FTDM_LOG_WARNING, "-- Error opening channel %d:%d (ignored)\n", + ftdm_channel_get_span_id(chan), + ftdm_channel_get_id(chan)); + +// caller_data->hangup_cause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER; +// ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_TERMINATING); +// goto done; + } + } else { + /* Reserve channel, don't open it yet */ + if (ftdm_channel_use(chan) != FTDM_SUCCESS) { + ftdm_log(FTDM_LOG_WARNING, "-- Error reserving channel %d:%d (ignored)\n", + ftdm_span_get_id(span), pevent->ring.channel); + goto done; + } + } + ftdm_log(FTDM_LOG_NOTICE, "-- Ring on channel %d:%d (from %s to %s)\n", ftdm_span_get_id(span), pevent->ring.channel, pevent->ring.callingnum, pevent->ring.callednum); @@ -901,7 +1048,7 @@ static int on_ring(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event } // scary to trust this pointer, you'd think they would give you a copy of the call data so you own it...... - /* hurr, this valid as along as nobody releases the call */ + /* hurr, this is valid as along as nobody releases the call */ chan->call_data = pevent->ring.call; ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RING); @@ -1300,7 +1447,7 @@ static int on_dchan_down(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_ */ static int on_anything(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent) { - ftdm_log(FTDM_LOG_DEBUG, "Caught Event span %d %u (%s)\n", ftdm_span_get_id(spri->span), event_type, lpwrap_pri_event_str(event_type)); + ftdm_log(FTDM_LOG_DEBUG, "-- Caught Event span %d %u (%s)\n", ftdm_span_get_id(spri->span), event_type, lpwrap_pri_event_str(event_type)); return 0; } @@ -1313,7 +1460,7 @@ static int on_anything(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_ev */ static int on_io_fail(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent) { - ftdm_log(FTDM_LOG_DEBUG, "Caught Event span %d %u (%s)\n", ftdm_span_get_id(spri->span), event_type, lpwrap_pri_event_str(event_type)); + ftdm_log(FTDM_LOG_DEBUG, "-- Caught Event span %d %u (%s)\n", ftdm_span_get_id(spri->span), event_type, lpwrap_pri_event_str(event_type)); return 0; } @@ -1401,8 +1548,8 @@ static void *ftdm_libpri_run(ftdm_thread_t *me, void *obj) LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_ANY, on_anything); LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_RING, on_ring); LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_RINGING, on_ringing); - //LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_SETUP_ACK, on_proceed); - LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_PROCEEDING, on_proceed); + LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_PROCEEDING, on_proceeding); + LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_PROGRESS, on_progress); LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_ANSWER, on_answer); LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_DCHAN_UP, on_dchan_up); LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_DCHAN_DOWN, on_dchan_down); From 9257e0f34459f6087d37843defdfadf75c72ac39 Mon Sep 17 00:00:00 2001 From: Stefan Knoblich Date: Tue, 16 Nov 2010 22:58:44 +0100 Subject: [PATCH 015/237] ftmod_isdn: Port(/Fix) span signal handling, remove some dead/unused pieces and close the D-Channel on shutdown. This fixes a NULL-call segfault in ftdm_span_trigger_signal(). Signed-off-by: Stefan Knoblich --- .../freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c | 40 ++++++++++--------- .../freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.h | 3 -- 2 files changed, 21 insertions(+), 22 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c index 491ef886fa..d54d46ad99 100644 --- a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c +++ b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c @@ -595,9 +595,10 @@ static void ftdm_isdn_call_event(struct Q931_Call *call, struct Q931_CallEvent * return; } - if (ftdmchan->state != FTDM_CHANNEL_STATE_DOWN) { + if (ftdm_channel_get_state(ftdmchan) != FTDM_CHANNEL_STATE_DOWN) { ftdm_log(FTDM_LOG_DEBUG, "Channel %d:%d not in DOWN state, cleaning up\n", - ftdmchan->span_id, ftdmchan->chan_id); + ftdm_channel_get_span_id(ftdmchan), + ftdm_channel_get_id(ftdmchan)); /* * Send hangup signal to mod_openzap @@ -607,7 +608,7 @@ static void ftdm_isdn_call_event(struct Q931_Call *call, struct Q931_CallEvent * } sig.event_id = FTDM_SIGEVENT_STOP; - isdn_data->sig_cb(&sig); + ftdm_span_send_signal(ftdm_channel_get_span(ftdmchan), &sig); /* Release zap channel */ ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); @@ -641,7 +642,9 @@ static void ftdm_isdn_call_event(struct Q931_Call *call, struct Q931_CallEvent * return; } - ftdm_log(FTDM_LOG_DEBUG, "Call setup failed on channel %d:%d\n", ftdmchan->span_id, ftdmchan->chan_id); + ftdm_log(FTDM_LOG_DEBUG, "Call setup failed on channel %d:%d\n", + ftdm_channel_get_span_id(ftdmchan), + ftdm_channel_get_id(ftdmchan)); /* * Send signal to mod_openzap @@ -649,7 +652,7 @@ static void ftdm_isdn_call_event(struct Q931_Call *call, struct Q931_CallEvent * sig.channel->caller_data.hangup_cause = FTDM_CAUSE_NETWORK_OUT_OF_ORDER; sig.event_id = FTDM_SIGEVENT_STOP; - isdn_data->sig_cb(&sig); + ftdm_span_send_signal(ftdm_channel_get_span(ftdmchan), &sig); /* Release zap channel */ ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); @@ -909,7 +912,7 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic sig.channel->caller_data.hangup_cause = (cause) ? cause->Value : FTDM_CAUSE_NORMAL_UNSPECIFIED; sig.event_id = FTDM_SIGEVENT_STOP; - status = isdn_data->sig_cb(&sig); + status = ftdm_span_send_signal(span, &sig); ftdm_log(FTDM_LOG_DEBUG, "Received %s in state %s, requested hangup for channel %d:%d\n", what, ftdm_channel_get_state_str(ftdmchan), @@ -1298,6 +1301,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) { Q931mes_Generic *gen = (Q931mes_Generic *) ftdmchan->caller_data.raw_data; ftdm_isdn_data_t *isdn_data = ftdmchan->span->signal_data; + ftdm_span_t *span = ftdm_channel_get_span(ftdmchan); ftdm_sigmsg_t sig; ftdm_status_t status; @@ -1329,7 +1333,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) { if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { sig.event_id = FTDM_SIGEVENT_PROGRESS; - if ((status = isdn_data->sig_cb(&sig) != FTDM_SUCCESS)) { + if ((status = ftdm_span_send_signal(ftdm_channel_get_span(ftdmchan), &sig) != FTDM_SUCCESS)) { ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); } } else { @@ -1377,7 +1381,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) { if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { sig.event_id = FTDM_SIGEVENT_START; - if ((status = isdn_data->sig_cb(&sig) != FTDM_SUCCESS)) { + if ((status = ftdm_span_send_signal(span, &sig) != FTDM_SUCCESS)) { ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); } } @@ -1387,7 +1391,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) { ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_UNSPECIFIED; sig.event_id = FTDM_SIGEVENT_RESTART; - status = isdn_data->sig_cb(&sig); + status = ftdm_span_send_signal(span, &sig); ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); } break; @@ -1395,7 +1399,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) { if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { sig.event_id = FTDM_SIGEVENT_PROGRESS_MEDIA; - if ((status = isdn_data->sig_cb(&sig) != FTDM_SUCCESS)) { + if ((status = ftdm_span_send_signal(span, &sig) != FTDM_SUCCESS)) { ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); } } else { @@ -1415,7 +1419,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) { if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { sig.event_id = FTDM_SIGEVENT_UP; - if ((status = isdn_data->sig_cb(&sig) != FTDM_SUCCESS)) { + if ((status = ftdm_span_send_signal(span, &sig) != FTDM_SUCCESS)) { ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); } } else { @@ -1636,7 +1640,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) ftdm_log(FTDM_LOG_DEBUG, "Terminating: Direction %s\n", ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) ? "Outbound" : "Inbound"); sig.event_id = FTDM_SIGEVENT_STOP; - status = isdn_data->sig_cb(&sig); + status = ftdm_span_send_signal(span, &sig); gen->MesType = Q931mes_RELEASE; gen->CRVFlag = ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) ? 0 : 1; @@ -1673,7 +1677,6 @@ static __inline__ void check_state(ftdm_span_t *span) static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *event) { - ftdm_isdn_data_t *isdn_data = span->signal_data; ftdm_alarm_flag_t alarmbits; ftdm_sigmsg_t sig; @@ -1697,7 +1700,7 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e } ftdm_set_flag(event->channel, FTDM_CHANNEL_SUSPENDED); ftdm_channel_get_alarms(event->channel, &alarmbits); - isdn_data->sig_cb(&sig); + ftdm_span_send_signal(span, &sig); ftdm_log(FTDM_LOG_WARNING, "channel %d:%d (%d:%d) has alarms [%s]\n", ftdm_channel_get_span_id(event->channel), @@ -1712,7 +1715,7 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e sig.event_id = FTDM_OOB_ALARM_CLEAR; ftdm_clear_flag(event->channel, FTDM_CHANNEL_SUSPENDED); ftdm_channel_get_alarms(event->channel, &alarmbits); - isdn_data->sig_cb(&sig); + ftdm_span_send_signal(span, &sig); } break; #ifdef __BROKEN_BY_FREETDM_CONVERSION__ @@ -2057,8 +2060,7 @@ static void *ftdm_isdn_run(ftdm_thread_t *me, void *obj) } done: -// ftdm_channel_close(&isdn_data->dchans[0]); -// ftdm_channel_close(&isdn_data->dchans[1]); + ftdm_channel_close(&isdn_data->dchan); ftdm_clear_flag(isdn_data, FTDM_ISDN_RUNNING); #ifdef WIN32 @@ -2745,8 +2747,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(isdn_configure_span) } } - isdn_data->sig_cb = sig_cb; - isdn_data->dchan = dchan; + isdn_data->dchan = dchan; isdn_data->digit_timeout = digit_timeout; Q921_InitTrunk(&isdn_data->q921, @@ -2788,6 +2789,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(isdn_configure_span) span->state_map = &isdn_state_map; span->signal_data = isdn_data; span->signal_type = FTDM_SIGTYPE_ISDN; + span->signal_cb = sig_cb; span->start = ftdm_isdn_start; span->stop = ftdm_isdn_stop; span->outgoing_call = isdn_outgoing_call; diff --git a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.h b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.h index 95eee90887..6b17f2cbef 100644 --- a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.h +++ b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.h @@ -63,9 +63,6 @@ struct ftdm_isdn_data { Q921Data_t q921; Q931_TrunkInfo_t q931; ftdm_channel_t *dchan; - ftdm_channel_t *dchans[2]; - struct ftdm_sigmsg sigmsg; - fio_signal_cb_t sig_cb; uint32_t flags; int32_t mode; int32_t digit_timeout; From 4f343bf892d75f00d58d3886d07c937888dfe4f5 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Tue, 16 Nov 2010 17:34:50 -0600 Subject: [PATCH 016/237] fix spidermonkey with x64 windows --- libs/js/nsprpub/pr/src/io/prmwait.c | 2 +- libs/js/src/jscpucfg.h | 55 ++++++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/libs/js/nsprpub/pr/src/io/prmwait.c b/libs/js/nsprpub/pr/src/io/prmwait.c index 1a2e1cd77b..afdcddf215 100644 --- a/libs/js/nsprpub/pr/src/io/prmwait.c +++ b/libs/js/nsprpub/pr/src/io/prmwait.c @@ -235,7 +235,7 @@ void _PR_InitMW(void) * We use NT 4's InterlockedCompareExchange() to operate * on PRMWStatus variables. */ - PR_ASSERT(sizeof(PVOID) == sizeof(PRMWStatus)); + //PR_ASSERT(sizeof(PVOID) == sizeof(PRMWStatus)); TimerInit(); #endif mw_lock = PR_NewLock(); diff --git a/libs/js/src/jscpucfg.h b/libs/js/src/jscpucfg.h index 7b8b2add45..f8b25d1ef7 100644 --- a/libs/js/src/jscpucfg.h +++ b/libs/js/src/jscpucfg.h @@ -44,11 +44,62 @@ #if defined(XP_WIN) || defined(XP_OS2) || defined(WINCE) +#if defined(_WIN64) + +#if defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_) +#define IS_LITTLE_ENDIAN 1 +#undef IS_BIG_ENDIAN + +#define JS_BYTES_PER_BYTE 1Ll +#define JS_BYTES_PER_SHORT 2L +#define JS_BYTES_PER_INT 4L +#define JS_BYTES_PER_INT64 8L +#define JS_BYTES_PER_LONG 4L +#define JS_BYTES_PER_FLOAT 4L +#define JS_BYTES_PER_DOUBLE 8L +#define JS_BYTES_PER_WORD 8L +#define JS_BYTES_PER_DWORD 8L + +#define JS_BITS_PER_BYTE 8L +#define JS_BITS_PER_SHORT 16L +#define JS_BITS_PER_INT 32L +#define JS_BITS_PER_INT64 64L +#define JS_BITS_PER_LONG 32L +#define JS_BITS_PER_FLOAT 32L +#define JS_BITS_PER_DOUBLE 64L +#define JS_BITS_PER_WORD 64L + +#define JS_BITS_PER_BYTE_LOG2 3L +#define JS_BITS_PER_SHORT_LOG2 4L +#define JS_BITS_PER_INT_LOG2 5L +#define JS_BITS_PER_INT64_LOG2 6L +#define JS_BITS_PER_LONG_LOG2 5L +#define JS_BITS_PER_FLOAT_LOG2 5L +#define JS_BITS_PER_DOUBLE_LOG2 6L +#define JS_BITS_PER_WORD_LOG2 6L + +#define JS_ALIGN_OF_SHORT 2L +#define JS_ALIGN_OF_INT 4L +#define JS_ALIGN_OF_LONG 4L +#define JS_ALIGN_OF_INT64 8L +#define JS_ALIGN_OF_FLOAT 4L +#define JS_ALIGN_OF_DOUBLE 8L +#define JS_ALIGN_OF_POINTER 8L +#define JS_ALIGN_OF_WORD 8L + +#define JS_BYTES_PER_WORD_LOG2 3L +#define JS_BYTES_PER_DWORD_LOG2 3L +#define PR_WORDS_PER_DWORD_LOG2 0L +#else /* !(defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_)) */ +#error "CPU type is unknown" +#endif /* !(defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_)) */ + +#elif defined(_WIN32) || defined(XP_OS2) || defined(WINCE) + #ifdef __WATCOMC__ #define HAVE_VA_LIST_AS_ARRAY #endif -#if defined(_WIN32) || defined(XP_OS2) || defined(WINCE) #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN @@ -95,6 +146,7 @@ #endif /* _WIN32 || XP_OS2 || WINCE*/ #if defined(_WINDOWS) && !defined(_WIN32) /* WIN16 */ + #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN @@ -138,6 +190,7 @@ #define JS_BYTES_PER_WORD_LOG2 2L #define JS_BYTES_PER_DWORD_LOG2 3L #define PR_WORDS_PER_DWORD_LOG2 1L + #endif /* defined(_WINDOWS) && !defined(_WIN32) */ #elif defined(XP_UNIX) || defined(XP_BEOS) From 8be0cef9079ca3e2935798412739e7b83b1cc42c Mon Sep 17 00:00:00 2001 From: Michael S Collins Date: Tue, 16 Nov 2010 18:09:27 -0800 Subject: [PATCH 017/237] Update ChangeLog through Nov 16 --- docs/ChangeLog | 57 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/docs/ChangeLog b/docs/ChangeLog index e0f5297d2c..6037c14ec7 100644 --- a/docs/ChangeLog +++ b/docs/ChangeLog @@ -19,6 +19,7 @@ freeswitch (1.0.7) build: add mod_osp Makefile to configure generated Makefiles (r:dc06a039/FS-122) build: Remove mod_spidermonkey from windows 2008 x64 builds - does not work (r:280e894d) build: fix warnings on windows x64 builds src and mods projects - only libsofia included on the libs side (r:45ecbc2f) + build: Patch debian init.d script to set ulimit values (r:0eb33e57/FS-2844) codec2: working prototype, still for testing only (r:04ca0751) config: move limit.conf to db.conf config: Update VM phrase macros to voice option then action on main, config menus @@ -118,6 +119,21 @@ freeswitch (1.0.7) core: "Silent recovery" (r:93c2ed94) core: fix switch_find_local_ip to properly handle force_local_ip_v4 and _v6 (r:f42c9036/FS-2778) core: fix att_xfer/3-way scenario (r:0559cc50) + core: dmachine - timeout instantly when you have exact match and are equal to max digits (r:81a9f8ef) + core: Core ODBC support for transactions with MSSQL (r:d2ca8d40/FS-2050) + core: Show the UUID of the session in the log when sending RFC2833 DTMF packet and when receiving a RTP DTMF (r:9241a35e) + core: add record_post_process_exec_app and record_post_process_exec_api both can have : (r:07adca56) + core: add -ncwait for Unix based implememtations to make the backgrounder wait to make sure the process starts before detaching (r:23d5fc19) + core: fire DTMF event when converting dtmf to inband with start_dtmf_generate (r:dcdd3811) + core: fail calls with uninitialized frame (r:7dafe4e2) + core: allow switch_process_import to specify a prefix (r:e0c37c1f) + core: add additional info when fail (r:4bbd9a4c/FS-2825) + core: avoid hypothetical problem with flushing queue with delayed events (r:49b6237e) + core: add send_silence_when_idle and dmachine honoring to park loop (r:3be3cd76) + core: ivr_enterprise_originate: Fix export of variable from the originator channel to the called channels (r:025c82e7) + core: Better handling of progress and answering to prevent sip profile from locking up at higher volumes (r:04e57577/FS-2801) + core: ACL for IPv6 address and swigall to boot (r:db91f0e8/FS-2842) + core: add intercept_unanswered_only var akin to intercept_unbridged_only (r:68f18efe) lang: Improve French phrase files (FSCONFIG-23) libapr: Fix issue where after a bridge with a member, uuid of Agent is set to single quote character ' (r:3fee704d/FS-2738) libdingaling: fix race on shutdown causing crash (FSMOD-47) @@ -146,6 +162,7 @@ freeswitch (1.0.7) libsofiasip: Fix random crashes (r:c15ee980/SFSIP-219) libsofiasip: Fix T.38 bug in sofia_glue (r:2843f1ad/MODSOFIA-94) libsofiasip: VS2010 sofia posix problem (r:46dd24c2/SFSIP-220) + libsofiasip: set minimum initital sip t1 timer to 1000ms to work around race condition on retry timer firing before all the things that are supposed to be handled by the timer are set. The base resolution on this timer is 500ms, so doubling up makes sure we always hit the initial retry timer on the next run, where everything should be set. The side effect was, 1/2 the time on a request that did not get immediate response, the timer would be fired and cleared, but the action (sending retry) was never done, and a new timer was not set, causing the request to just sit zombied and never retry. A better solution would be to find and correct the race condition so the timer is never set to early and we never hit this condition. (r:20c2740c) libspandsp: Fixed a typo in spandsp's msvc/inttypes.h Updated sig_tone processing in spandsp to the latest, to allow moy to proceed with his signaling work. libspandsp: removed a saturate16 from spandsp that was causing problems fixed a typo in the MSVC inttypes.h file for spandsp libspandsp: Changes to the signaling tone detector to detect concurrent 2400Hz + 2600Hz tones. This passes voice immunity and other key tests, but it bounces a bit when transitions like 2400 -> 2400+2600 -> 2600 occur. Transitions between tone off and tone on are clean. (r:bc13e944) @@ -154,6 +171,7 @@ freeswitch (1.0.7) libspandsp: spandsp t38 fax receiving error in win XP - regression from f029f7ef (r:761cec8f/FS-2766) mod_avmd: Initial check in - Advanced Voicemail Detect (r:10c6a30a) (by Eric Des Courtis) mod_avmd: Add to windows build (r:df4bd935) + mod_avmd: Fix mem leak (r:cd951384/FS-2839) mod_callcenter: Initial commit of the mod_callcenter application. This module is in it early state of developpement. You can see documentation on the wiki at : http://wiki.freeswitch.org/wiki/Mod_callcenter For support/comments, please use http://jira.freeswitch.org/ and select the MOD CALLCENTER module. (r:ba09b96d) mod_callcenter: Add ability to unload/reload/load a queue setting (You still need to reloadxml before). Note that joining a queue will check for it in the config and load it on the fly... I've used the same system as in mod_voicemail. Not sure if we should allow this, but just comment it out of the config before unload and it wont be available anymore (r:3eafca60) mod_callcenter: Try to fix the ring-all, also add cli auto complete done in previous commit (r:1666783c) @@ -170,6 +188,8 @@ freeswitch (1.0.7) mod_callcenter: Make sure we fail to load if config is not present (r:e1fb79a1) mod_callcenter: Fix invalid update of agent field (r:426a448f/FS-2738) mod_callcenter: Allow to get queue info via api (r:70d592ae) + mod_callcenter: Fix bad return type so it compile on archlinux, thx bougyman (r:3a475986) + mod_callcenter: Make callcenter_config agent get return the value of the item requested. Also added queue param max-wait-time-with-no-agent-time-reached: If the max-wai-time-with-no-agent is already reached for the queue, then new caller can wait for x ammount of second before it kicked out of the queue rather than get rejected automaticly. (r:81a03869) mod_cidlookup: null xml is bad (r:095815f8) mod_cid_lookup: honor skipcitystate when using whitepages (r:a66654de/FSMOD-53) mod_commands: make break uuid_break and add cascade flag @@ -184,6 +204,7 @@ freeswitch (1.0.7) mod_commands: Allow cond API to return empty false value (r:c8a897b9) mod_commands: ***BEHAVIOUR CHANGE*** reloadacl, load , reload will now explicitly call reloadxml (r:42c9df72) mod_commands: add nat_map usage (r:7577b8aa) + mod_commands: add escaping empty strings to sql_escape (r:7bd0a5a6/FS-2833) mod_conference: Fix reporting of volume up/down (MODAPP-419) mod_conference: add last talking time per member to conference xml list mod_conference: add terminate-on-silence conference param @@ -213,14 +234,19 @@ freeswitch (1.0.7) mod_erlang_event: generate long node names the same as erlang does (r:9ad509c2) mod_erlang_event: Improve some logging to include UUIDs (r:c0d51b83) mod_erlang_event: Support for reading erlang cookie from a file (r:094ffe37) + mod_erlang_event: Rewrite XML fetch conditional wait to be more sane (Reported by James Aimonetti) (r:6941c6eb/FS-2775) mod_event_socket: fix up other users of switch_event_xmlize() to use SWITCH_EVENT_NONE (r:d6eb7562) mod_event_socket: Fix small mem leaks (r:e4f90584/MODEVENT-68) + mod_event_socket: Add "-ERR" to api cmd response when failure occurs (r:58759052/FS-2827) mod_fifo: allow multiple dtmf to exit fifo, set fifo_caller_exit_key to specify which (MODAPP-420) mod_fifo: cancel outbound call if customer hangs up (r:cadb4d94) mod_fifo: add taking_calls param to fifo member add and config file (r:821488bf) mod_fifo: add nomedia flag (r:2d30a8c2) mod_fifo: Fix inconsistency between the fifo queue and the channels (num callers in queue can become "-1") (r:07487114/FS-1659) mod_fifo: fix issue leaving stale records in fifo_bridge table (r:b36d015f) + mod_fifo: fix fifo race in use count dec (r:402e383b) + mod_fifo: add outbound_ring_timeout param to mod_fifo (r:3885eea7) + mod_fifo: add default_lag to fifo (r:dd4fb5be) mod_freetdm: Fix for TON and NPI not passed through to channel variables on incoming calls mod_freetdm: add pvt data to freetdm channels fix fxs features (r:9d456900) mod_freetdm: export and import boost custom data (r:edb2d582) @@ -254,6 +280,7 @@ freeswitch (1.0.7) mod_freetdm: created cmake files for freetdm (r:fc55997b) mod_freetdm: ss7 - added support to control mtp2, mtp3, and isup timers via freetdm.conf.xml (r:4455d581) mod_gsmopen: copy from branch + mod_gsmopen: fix FS-2793, compilation stops (r:355c0dbb/FS-2793) mod_hash: free all hashtables on shutdown (r:e76d7d92) mod_hash: remove unneeded initializer (r:10d468a6) mod_hash: begin working on remote support (r:c5ad49da) @@ -277,6 +304,8 @@ freeswitch (1.0.7) mod_java: fix eventConsumer issue and add flush() method (r:7fd3aff6) mod_java: Allow user defined java methods to be called at startup and shutdown of JVM (r:1339e218/MODLANG-117) mod_json_cdr: Fix segfault in mod_json_cdr.c (r:f347698a/MODEVENT-66) + mod_khomp: Added mod_khomp Endpoint. (r:5fea197b) + mod_khomp: Removed alternative contexts / extensions - New struct for matchs - On calls originated from an FXS branch, the Endpoint searches for a valid extension (digits sent) after the DTMF '#' or after the timeout (option fxs-digit-timeout). That search is done in the context defined in section , or if no context configured, the search is done in context defined in context-fxs. - Added "dialplan" configuration: Name of the dialplan module in use (default XML) - Group context enabled. If set, the search for a valid extension is done only in that context. - Updated documentation (r:1ef3fc9a) mod_lcr: Expand variables (MODAPP-418) mod_lcr: add enable_sip_redir parameter (r:70bf7a0a/MODAPP-427) mod_lcr: don't validate profiles with ${} vars since they are dynamic and we can't guess what the proper value should be (r:af33afaa) @@ -287,12 +316,16 @@ freeswitch (1.0.7) mod_loopback: add loopback_bowout_on_execute var to make 1 legged loopback calls bow out of the picture mod_loopback: only execute app once in app mode (r:64f58f2d) mod_loopback: fix bug in mod_loopback where bowout=false (r:e9ab5368) + mod_loopback: pass indication when in app mode on mod_loopback (r:c423e209) + mod_loopback: fix voicemail failure (r:1a1881e8/FS-2795) + mod_loopback: pass ring_ready like we do with pre_answer (r:9d087d45) mod_lua: Add switch_core_sqldb functionality from inside Lua script (r:26f2e095/FS-1384) mod_lua: Made 2nd arg to freeswitch.Dbh:query (cb func) optional (r:87db11af) mod_lua: Added SAF_ROUTING_EXEC flag to lua app, so it can be run inline (r:7d5ca1c0) mod_managed: Added wrapper for switch_event_bind for .net (r:a5f07a80/MODLANG-165) mod_managed: add additional support (r:5be58aac) mod_mp4v: MP4V-ES passthru for washibechi on IRC + mod_mp4: New module. Supports playback of MP4 files. Depends on libmp4v2 (originally compiled against v1.6.1) mod_nibblebill: free allocated mem at shutdown; free properly if using custom_sql mod_nibblebill: Add SAF_SUPPORT_NOMEDIA to nibblebill mod_nibblebill: fix compile issues in latest HEAD (r:b073e82b/FSMOD-51) @@ -312,7 +345,15 @@ freeswitch (1.0.7) mod_sangoma_codec: silence suppression (r:73d9d56f) mod_sangoma_codec: do not return 0 len frames and return silence instead when there is no transcoding output update stats only when we really receive a frame (r:dc4d19e9) mod_sangoma_codec: flush sockets on first use (r:bbba1148) - mod_say_es: fix grammar when saying dates and time (r:6bed19b2/MODAPP-429) + mod_sangoma_codec: use native L16 for the source codec (r:d2e25519) + mod_sangoma_codec: default to G729 only and remove L16 since it did not make any sense (r:1d5aa062) + mod_sangoma_codec: add iLBC 13.3k and 15.2k (r:68abb39e) + mod_sangoma_codec: add G723.1 (r:3e33540a) + mod_sangoma_codec: register AMR (r:31cc2502) + mod_sangoma_codec: add G722 (r:ca8c2336) + mod_sangoma_codec: add siren7 32kbps (r:fcaf2677) + mod_sangoma_codec: add SIREN7 24kbps (r:3acc5fdb) + mod_say_es: fix grammar when saying dates and time (r:6bed19b2/MODAPP-429) mod_say_ja: initial commit, still needs sound files (r:b2423158/FS-2755) mod_say_ru: Fix saying time with +1 hour of current time (r:68d74c31/MODAPP-444) mod_say_zh: Number reading should now be OK for the whole range of integers for Cantonese and Mandarin @@ -341,6 +382,7 @@ freeswitch (1.0.7) mod_skypopen: now answer a call only when directed to do it (before was trying to answer any incoming call). Lot of changes to a messy part, so maybe some problem will come out... (r:45c6c4d3) mod_skypopen: ignore early media sent by channels to be bridged before our channel is answered (r:ef14b78a) mod_sndfile: Add support for .alaw and .ulaw to mod_sndfile (r:facf09b8/MODFORM-41) + mod_sndfile: return break in mod_sndfile when seek returns failure (r:564dc7e4) mod_sofia: Send SIP MESSAGE to unregistered users by prefixing sip: to user@domain mod_sofia: fix callee being updated with callee information mod_sofia: set appearance-index in update statement for SLA @@ -417,6 +459,19 @@ freeswitch (1.0.7) mod_sofia: Set SDP proper connection type of "c=" field to IP6 or IP4 when IPv6 called IPv4 (r:14361c09/FS-620) mod_sofia: FS wrongly assumes NAT on Cisco 7941G (r:42f534fa/FS-2773) mod_sofia: sofia_reg.c doesn't pass profile name into query, also, typo with all-reg-options-ping (r:6772c795/FS-2787) + mod_sofia: adjust sql stmts in presence to allow even non-registered entities to be tracked (r:4e0399d0) + mod_sofia: dont update display to ring when call is hungup in pidf presence (r:36851a90) + mod_sofia: 1) Add force-publish-expires to set custom presence update expires delta (-1 means endless) 2) Check how many users are registered when receiving a PUBLISH AND Multiple Registrations is enabled: if there is more than just 1 AND you are sending a offline message: skip publishing it to everyone to prevent clients from thinking themselves has gone offline. (r:fd1736b3) + mod_sofia: profile param ignore-183nosdp, chanvar sip_ignore_183nosdp FS-1978 (r:59d3b84d/FS-1978) + mod_sofia: fix race in codec failure condition, then fix bug in sdp parsing (likely a regression from recent codec changes) to never have the problem in the first place so you are double-protected (r:19325c43) + mod_sofia: fix mem leak (r:1970ec1d/FS-2810) + mod_sofia: parse static route in sip uri in notify by event (r:35676e7e) + mod_sofia: add support for NDLB-force-rport=safe param that does force-rport behavior only on endpoints we know are safe to do so on. This is a dirty hack to try to work with certain endpoints behind sonicwall which does not use the same port when it does nat, when the devices do not support rport, while not breaking devices that acutally use different ports that force-rport will break (r:fc4d290c) + mod_sofia: add separate reg timeout from retry sec (r:e5b891ee) + mod_sofia: fix display of timeout (r:2043d5a) + mod_sofia: fix missing name and potential segfault in gateway status (r:40ac860a) + mod_sofia: Add missing RTP info for early SDP in bypass media (r:10119e9e/FS-2824) + mod_sofia: add manual_rtp_bugs to profile and chan var and 3 new RTP bugs SEND_LINEAR_TIMESTAMPS|START_SEQ_AT_ZERO|NEVER_SEND_MARKER (r:b278dd23) mod_spandsp: initial checkin of mod_fax/mod_voipcodecs merge into mod_spandsp (r:fa9a59a8) mod_spandsp: rework of new mod_spandsp to have functions broken up into different c files (r:65400642) mod_spandsp: improve duplicate digit detection and add 'min_dup_digit_spacing_ms' channel variable for use with the dtmf detector (r:eab4f246/FSMOD-45) From 21e1f69b982682c8d135a52193dee3450f9d53a4 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Tue, 16 Nov 2010 20:21:59 -0600 Subject: [PATCH 018/237] add spidermonkey back to x64 build and setup --- Freeswitch.2010.sln | 12 +++++++++++ w32/Setup/Setup.wixproj | 45 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/Freeswitch.2010.sln b/Freeswitch.2010.sln index 5722802839..186969891a 100644 --- a/Freeswitch.2010.sln +++ b/Freeswitch.2010.sln @@ -942,11 +942,13 @@ Global {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Debug|Win32.ActiveCfg = Debug|Win32 {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Debug|Win32.Build.0 = Debug|Win32 {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Debug|x64.ActiveCfg = Debug|x64 + {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Debug|x64.Build.0 = Debug|x64 {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Debug|x64 Setup.ActiveCfg = Debug|x64 {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Release|Win32.ActiveCfg = Release|Win32 {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Release|Win32.Build.0 = Release|Win32 {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Release|x64.ActiveCfg = Release|x64 + {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Release|x64.Build.0 = Release|x64 {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Release|x64 Setup.ActiveCfg = Release|x64 {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Release|x86 Setup.ActiveCfg = Release|Win32 {692F6330-4D87-4C82-81DF-40DB5892636E}.All|Win32.ActiveCfg = Release|x64 @@ -1442,11 +1444,13 @@ Global {ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.Debug|Win32.ActiveCfg = Debug|Win32 {ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.Debug|Win32.Build.0 = Debug|Win32 {ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.Debug|x64.ActiveCfg = Debug|x64 + {ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.Debug|x64.Build.0 = Debug|x64 {ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.Debug|x64 Setup.ActiveCfg = Debug|x64 {ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.Release|Win32.ActiveCfg = Release|Win32 {ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.Release|Win32.Build.0 = Release|Win32 {ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.Release|x64.ActiveCfg = Release|x64 + {ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.Release|x64.Build.0 = Release|x64 {ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.Release|x64 Setup.ActiveCfg = Release|x64 {ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.Release|x86 Setup.ActiveCfg = Release|Win32 {8F992C49-6C51-412F-B2A3-34EAB708EB65}.All|Win32.ActiveCfg = Release|x64 @@ -1458,11 +1462,13 @@ Global {8F992C49-6C51-412F-B2A3-34EAB708EB65}.Debug|Win32.ActiveCfg = Debug|Win32 {8F992C49-6C51-412F-B2A3-34EAB708EB65}.Debug|Win32.Build.0 = Debug|Win32 {8F992C49-6C51-412F-B2A3-34EAB708EB65}.Debug|x64.ActiveCfg = Debug|x64 + {8F992C49-6C51-412F-B2A3-34EAB708EB65}.Debug|x64.Build.0 = Debug|x64 {8F992C49-6C51-412F-B2A3-34EAB708EB65}.Debug|x64 Setup.ActiveCfg = Debug|x64 {8F992C49-6C51-412F-B2A3-34EAB708EB65}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {8F992C49-6C51-412F-B2A3-34EAB708EB65}.Release|Win32.ActiveCfg = Release|Win32 {8F992C49-6C51-412F-B2A3-34EAB708EB65}.Release|Win32.Build.0 = Release|Win32 {8F992C49-6C51-412F-B2A3-34EAB708EB65}.Release|x64.ActiveCfg = Release|x64 + {8F992C49-6C51-412F-B2A3-34EAB708EB65}.Release|x64.Build.0 = Release|x64 {8F992C49-6C51-412F-B2A3-34EAB708EB65}.Release|x64 Setup.ActiveCfg = Release|x64 {8F992C49-6C51-412F-B2A3-34EAB708EB65}.Release|x86 Setup.ActiveCfg = Release|Win32 {4043FC6A-9A30-4577-8AD5-9B233C9575D8}.All|Win32.ActiveCfg = Release|x64 @@ -1510,11 +1516,13 @@ Global {0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.Debug|Win32.ActiveCfg = Debug|Win32 {0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.Debug|Win32.Build.0 = Debug|Win32 {0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.Debug|x64.ActiveCfg = Debug|x64 + {0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.Debug|x64.Build.0 = Debug|x64 {0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.Debug|x64 Setup.ActiveCfg = Debug|x64 {0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.Release|Win32.ActiveCfg = Release|Win32 {0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.Release|Win32.Build.0 = Release|Win32 {0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.Release|x64.ActiveCfg = Release|x64 + {0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.Release|x64.Build.0 = Release|x64 {0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.Release|x64 Setup.ActiveCfg = Release|x64 {0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.Release|x86 Setup.ActiveCfg = Release|Win32 {AB91A099-7690-4ECF-8994-E458F4EA1ED4}.All|Win32.ActiveCfg = Release|x64 @@ -1670,11 +1678,13 @@ Global {028C7278-05D7-4E18-82FE-BE231B844F41}.Debug|Win32.ActiveCfg = Debug|Win32 {028C7278-05D7-4E18-82FE-BE231B844F41}.Debug|Win32.Build.0 = Debug|Win32 {028C7278-05D7-4E18-82FE-BE231B844F41}.Debug|x64.ActiveCfg = Debug|x64 + {028C7278-05D7-4E18-82FE-BE231B844F41}.Debug|x64.Build.0 = Debug|x64 {028C7278-05D7-4E18-82FE-BE231B844F41}.Debug|x64 Setup.ActiveCfg = Debug|x64 {028C7278-05D7-4E18-82FE-BE231B844F41}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {028C7278-05D7-4E18-82FE-BE231B844F41}.Release|Win32.ActiveCfg = Release|Win32 {028C7278-05D7-4E18-82FE-BE231B844F41}.Release|Win32.Build.0 = Release|Win32 {028C7278-05D7-4E18-82FE-BE231B844F41}.Release|x64.ActiveCfg = Release|x64 + {028C7278-05D7-4E18-82FE-BE231B844F41}.Release|x64.Build.0 = Release|x64 {028C7278-05D7-4E18-82FE-BE231B844F41}.Release|x64 Setup.ActiveCfg = Release|x64 {028C7278-05D7-4E18-82FE-BE231B844F41}.Release|x86 Setup.ActiveCfg = Release|Win32 {D7F1E3F2-A3F4-474C-8555-15122571AF52}.All|Win32.ActiveCfg = Release|x64 @@ -1938,11 +1948,13 @@ Global {36E854E3-CE12-4348-A125-CCF3F9D74813}.Debug|Win32.ActiveCfg = Debug|Win32 {36E854E3-CE12-4348-A125-CCF3F9D74813}.Debug|Win32.Build.0 = Debug|Win32 {36E854E3-CE12-4348-A125-CCF3F9D74813}.Debug|x64.ActiveCfg = Debug|x64 + {36E854E3-CE12-4348-A125-CCF3F9D74813}.Debug|x64.Build.0 = Debug|x64 {36E854E3-CE12-4348-A125-CCF3F9D74813}.Debug|x64 Setup.ActiveCfg = Debug|x64 {36E854E3-CE12-4348-A125-CCF3F9D74813}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {36E854E3-CE12-4348-A125-CCF3F9D74813}.Release|Win32.ActiveCfg = Release|Win32 {36E854E3-CE12-4348-A125-CCF3F9D74813}.Release|Win32.Build.0 = Release|Win32 {36E854E3-CE12-4348-A125-CCF3F9D74813}.Release|x64.ActiveCfg = Release|x64 + {36E854E3-CE12-4348-A125-CCF3F9D74813}.Release|x64.Build.0 = Release|x64 {36E854E3-CE12-4348-A125-CCF3F9D74813}.Release|x64 Setup.ActiveCfg = Release|x64 {36E854E3-CE12-4348-A125-CCF3F9D74813}.Release|x86 Setup.ActiveCfg = Release|Win32 {7B077E7F-1BE7-4291-AB86-55E527B25CAC}.All|Win32.ActiveCfg = Release|x64 diff --git a/w32/Setup/Setup.wixproj b/w32/Setup/Setup.wixproj index 9aba3a1d34..7d11c90a4b 100644 --- a/w32/Setup/Setup.wixproj +++ b/w32/Setup/Setup.wixproj @@ -597,6 +597,51 @@ Binaries;Content;Satellites MODLOCATION + + mod_spidermonkey + {1ad3f51e-bbb6-4090-ba39-9dfab1ef1f5f} + True + + + Binaries;Content;Satellites + MODLOCATION + + + mod_spidermonkey_core_db + {acfff684-4d19-4d48-af12-88ea1d778bdf} + True + + + Binaries;Content;Satellites + MODLOCATION + + + mod_spidermonkey_odbc + {0a6b5ea5-6e9b-4a51-931f-ed25aa87b4df} + True + + + Binaries;Content;Satellites + MODLOCATION + + + mod_spidermonkey_socket + {028c7278-05d7-4e18-82fe-be231b844f41} + True + + + Binaries;Content;Satellites + MODLOCATION + + + mod_spidermonkey_teletone + {8f992c49-6c51-412f-b2a3-34eab708eb65} + True + + + Binaries;Content;Satellites + MODLOCATION + mod_console {1c453396-d912-4213-89fd-9b489162b7b5} From 5486b8c74d9b853cd74229689dc67800cd722c65 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Tue, 16 Nov 2010 23:41:11 -0500 Subject: [PATCH 019/237] freetdm: retry polling in DAHDI devices when fails due to interrupted system call --- libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c b/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c index ddf7b3ffab..b135e61269 100644 --- a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c +++ b/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c @@ -889,13 +889,18 @@ static FIO_WAIT_FUNCTION(zt_wait) inflags |= POLLPRI; } - +pollagain: memset(&pfds[0], 0, sizeof(pfds[0])); pfds[0].fd = ftdmchan->sockfd; pfds[0].events = inflags; result = poll(pfds, 1, to); *flags = 0; + if (rc < 0 && errno == EINTR) { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "DAHDI wait got interrupted, trying again\n"); + goto pollagain; + } + if (pfds[0].revents & POLLERR) { ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "DAHDI device got POLLERR\n"); result = -1; From 1c1df1f77239b32701cdcabc9eb63f4974210d53 Mon Sep 17 00:00:00 2001 From: Rupa Schomaker Date: Wed, 17 Nov 2010 09:34:09 -0600 Subject: [PATCH 020/237] mod_lcr: FS-2820 - profile support in dialplan module --- src/mod/applications/mod_lcr/mod_lcr.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/mod/applications/mod_lcr/mod_lcr.c b/src/mod/applications/mod_lcr/mod_lcr.c index cc93707367..5f70e0ab77 100644 --- a/src/mod/applications/mod_lcr/mod_lcr.c +++ b/src/mod/applications/mod_lcr/mod_lcr.c @@ -1387,7 +1387,6 @@ SWITCH_STANDARD_DIALPLAN(lcr_dialplan_hunt) switch_channel_t *channel = switch_core_session_get_channel(session); callback_t routes = { 0 }; lcr_route cur_route = { 0 }; - char *lcr_profile = NULL; switch_memory_pool_t *pool = NULL; switch_event_t *event = NULL; const char *intrastate = NULL; @@ -1403,11 +1402,6 @@ SWITCH_STANDARD_DIALPLAN(lcr_dialplan_hunt) } routes.pool = pool; - if (!(routes.profile = locate_profile(lcr_profile))) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Unknown profile: %s\n", lcr_profile); - goto end; - } - intrastate = switch_channel_get_variable(channel, "intrastate"); intralata = switch_channel_get_variable(channel, "intralata"); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "intrastate channel var is [%s]\n", intrastate); @@ -1427,7 +1421,12 @@ SWITCH_STANDARD_DIALPLAN(lcr_dialplan_hunt) caller_profile = switch_channel_get_caller_profile(channel); } - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "LCR Lookup on %s using profile %s\n", caller_profile->destination_number, lcr_profile); + if (!(routes.profile = locate_profile(caller_profile->context))) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Unknown profile: %s\n", caller_profile->context); + goto end; + } + + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "LCR Lookup on %s using profile %s\n", caller_profile->destination_number, caller_profile->context); routes.lookup_number = caller_profile->destination_number; routes.cid = (char *) caller_profile->caller_id_number; if (lcr_do_lookup(&routes) == SWITCH_STATUS_SUCCESS) { @@ -1465,7 +1464,7 @@ SWITCH_STANDARD_DIALPLAN(lcr_dialplan_hunt) switch_caller_extension_add_application(session, extension, app, argc); } } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "LCR lookup failed for %s using profile %s\n", caller_profile->destination_number, lcr_profile); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "LCR lookup failed for %s using profile %s\n", caller_profile->destination_number, caller_profile->context); } end: From 05d1fd2a66e6acb73937a0adae23563f6ee6fae0 Mon Sep 17 00:00:00 2001 From: cypromis Date: Wed, 17 Nov 2010 17:01:30 +0100 Subject: [PATCH 021/237] ftmod_zt rc has changed to result --- libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c b/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c index b135e61269..06c48da78a 100644 --- a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c +++ b/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c @@ -896,7 +896,7 @@ pollagain: result = poll(pfds, 1, to); *flags = 0; - if (rc < 0 && errno == EINTR) { + if result < 0 && errno == EINTR) { ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "DAHDI wait got interrupted, trying again\n"); goto pollagain; } From 5d28a8fa057d948464588226598e94f2c905d20f Mon Sep 17 00:00:00 2001 From: cypromis Date: Wed, 17 Nov 2010 17:15:30 +0100 Subject: [PATCH 022/237] ftmod_zt typo ... --- libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c b/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c index 06c48da78a..9247edc72e 100644 --- a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c +++ b/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c @@ -896,7 +896,7 @@ pollagain: result = poll(pfds, 1, to); *flags = 0; - if result < 0 && errno == EINTR) { + if (result < 0 && errno == EINTR) { ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "DAHDI wait got interrupted, trying again\n"); goto pollagain; } From b517ddd6d3f1090fec83fe91c508b5f8bb19dd2a Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 17 Nov 2010 10:51:14 -0600 Subject: [PATCH 023/237] fix jitterbuffer --- libs/stfu/stfu.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/libs/stfu/stfu.c b/libs/stfu/stfu.c index 7c30ab2ad4..bb10b4a166 100644 --- a/libs/stfu/stfu.c +++ b/libs/stfu/stfu.c @@ -47,6 +47,7 @@ struct stfu_instance { struct stfu_queue *in_queue; struct stfu_queue *out_queue; struct stfu_frame *last_frame; + uint32_t cur_ts; uint32_t last_wr_ts; uint32_t last_rd_ts; uint32_t interval; @@ -267,27 +268,26 @@ static int stfu_n_find_frame(stfu_queue_t *queue, uint32_t ts, stfu_frame_t **r_ stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i) { uint32_t index; - uint32_t should_have = 0; stfu_frame_t *rframe = NULL; if (((i->out_queue->wr_len == i->out_queue->array_len) || !i->out_queue->array_len)) { return NULL; } - if (i->last_wr_ts) { - should_have = i->last_wr_ts + i->interval; - } else { - should_have = i->out_queue->array[0].ts; - } - - if (stfu_n_find_frame(i->out_queue, should_have, &rframe, &index) || stfu_n_find_frame(i->in_queue, should_have, &rframe, &index)) { + if (i->cur_ts == 0) { + i->cur_ts = i->out_queue->array[1].ts; + } else { + i->cur_ts += i->interval; + } + + if (stfu_n_find_frame(i->out_queue, i->cur_ts, &rframe, &index) || stfu_n_find_frame(i->in_queue, i->cur_ts, &rframe, &index)) { i->last_frame = rframe; i->out_queue->wr_len++; i->last_wr_ts = rframe->ts; rframe->was_read = 1; i->miss_count = 0; } else { - i->last_wr_ts = should_have; + i->last_wr_ts = i->cur_ts; rframe = &i->out_queue->int_frame; if (i->last_frame && i->last_frame != rframe) { @@ -296,12 +296,11 @@ stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i) memcpy(rframe->data, i->last_frame->data, rframe->dlen); } - rframe->ts = should_have; + rframe->ts = i->cur_ts; if (++i->miss_count > i->max_plc) { - i->interval = 0; i->out_queue->wr_len = i->out_queue->array_size; - i->last_wr_ts = 0; + i->cur_ts = 0; rframe = NULL; } } From b32ceb3c228b33d5640cc5253f6e88d7b98baa60 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 17 Nov 2010 11:46:20 -0600 Subject: [PATCH 024/237] part 2 --- libs/stfu/stfu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/stfu/stfu.c b/libs/stfu/stfu.c index bb10b4a166..0422cd2081 100644 --- a/libs/stfu/stfu.c +++ b/libs/stfu/stfu.c @@ -269,22 +269,22 @@ stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i) { uint32_t index; stfu_frame_t *rframe = NULL; - + if (((i->out_queue->wr_len == i->out_queue->array_len) || !i->out_queue->array_len)) { return NULL; } if (i->cur_ts == 0) { - i->cur_ts = i->out_queue->array[1].ts; + i->cur_ts = i->out_queue->array[0].ts; } else { i->cur_ts += i->interval; } + if (stfu_n_find_frame(i->out_queue, i->cur_ts, &rframe, &index) || stfu_n_find_frame(i->in_queue, i->cur_ts, &rframe, &index)) { i->last_frame = rframe; i->out_queue->wr_len++; i->last_wr_ts = rframe->ts; - rframe->was_read = 1; i->miss_count = 0; } else { i->last_wr_ts = i->cur_ts; From 180f58a677a2ef49f71cbbe377f9eb177e6574e5 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 17 Nov 2010 12:17:27 -0600 Subject: [PATCH 025/237] FS-2851 --- src/switch_channel.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/switch_channel.c b/src/switch_channel.c index 0b1b6e8f82..c63a1aadb9 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -1971,7 +1971,7 @@ SWITCH_DECLARE(void) switch_channel_event_set_basic_data(switch_channel_t *chann SWITCH_DECLARE(void) switch_channel_event_set_extended_data(switch_channel_t *channel, switch_event_t *event) { switch_event_header_t *hi; - int x, global_verbose_events = 0; + int global_verbose_events = -1; switch_mutex_lock(channel->profile_mutex); @@ -2004,7 +2004,6 @@ SWITCH_DECLARE(void) switch_channel_event_set_extended_data(switch_channel_t *ch event->event_id == SWITCH_EVENT_MEDIA_BUG_STOP || event->event_id == SWITCH_EVENT_CUSTOM) { - x = 0; /* Index Variables */ if (channel->variables) { for (hi = channel->variables->headers; hi; hi = hi->next) { @@ -2013,8 +2012,7 @@ SWITCH_DECLARE(void) switch_channel_event_set_extended_data(switch_channel_t *ch vvar = (char *) hi->name; vval = (char *) hi->value; - x++; - + switch_assert(vvar && vval); switch_snprintf(buf, sizeof(buf), "variable_%s", vvar); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, buf, vval); From 4d41a0f3a2ddd74e0a95b31f3766a71f80d1045c Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Wed, 17 Nov 2010 15:39:33 -0600 Subject: [PATCH 026/237] FS-2855 Fix spidermonkey under windows x64 --- libs/js/src/jstypes.h | 191 +++++++++++------- .../mod_spidermonkey.2008.vcproj | 8 +- .../mod_spidermonkey.2010.vcxproj | 8 +- 3 files changed, 129 insertions(+), 78 deletions(-) diff --git a/libs/js/src/jstypes.h b/libs/js/src/jstypes.h index 0a76d478cf..e5d9544413 100644 --- a/libs/js/src/jstypes.h +++ b/libs/js/src/jstypes.h @@ -77,35 +77,25 @@ ** ***********************************************************************/ #ifdef WIN32 + /* These also work for __MWERKS__ */ -#define JS_EXTERN_API(__type) extern __declspec(dllexport) __type -#define JS_EXPORT_API(__type) __declspec(dllexport) __type -#define JS_EXTERN_DATA(__type) extern __declspec(dllexport) __type -#define JS_EXPORT_DATA(__type) __declspec(dllexport) __type +# define JS_EXTERN_API(__type) extern __declspec(dllexport) __type +# define JS_EXPORT_API(__type) __declspec(dllexport) __type +# define JS_EXTERN_DATA(__type) extern __declspec(dllexport) __type +# define JS_EXPORT_DATA(__type) __declspec(dllexport) __type -#define JS_DLL_CALLBACK -#define JS_STATIC_DLL_CALLBACK(__x) static __x +# define JS_DLL_CALLBACK +# define JS_STATIC_DLL_CALLBACK(__x) static __x -#elif defined(WIN16) +#elif defined(XP_OS2) && defined(__declspec) -#ifdef _WINDLL -#define JS_EXTERN_API(__type) extern __type _cdecl _export _loadds -#define JS_EXPORT_API(__type) __type _cdecl _export _loadds -#define JS_EXTERN_DATA(__type) extern __type _export -#define JS_EXPORT_DATA(__type) __type _export +# define JS_EXTERN_API(__type) extern __declspec(dllexport) __type +# define JS_EXPORT_API(__type) __declspec(dllexport) __type +# define JS_EXTERN_DATA(__type) extern __declspec(dllexport) __type +# define JS_EXPORT_DATA(__type) __declspec(dllexport) __type -#define JS_DLL_CALLBACK __cdecl __loadds -#define JS_STATIC_DLL_CALLBACK(__x) static __x CALLBACK - -#else /* this must be .EXE */ -#define JS_EXTERN_API(__type) extern __type _cdecl _export -#define JS_EXPORT_API(__type) __type _cdecl _export -#define JS_EXTERN_DATA(__type) extern __type _export -#define JS_EXPORT_DATA(__type) __type _export - -#define JS_DLL_CALLBACK __cdecl __loadds -#define JS_STATIC_DLL_CALLBACK(__x) __x JS_DLL_CALLBACK -#endif /* _WINDLL */ +# define JS_DLL_CALLBACK +# define JS_STATIC_DLL_CALLBACK(__x) static __x #else /* Unix */ @@ -126,44 +116,57 @@ #endif #ifdef _WIN32 -# if defined(__MWERKS__) || defined(__GNUC__) -# define JS_IMPORT_API(__x) __x -# else -# define JS_IMPORT_API(__x) __declspec(dllimport) __x -# endif +# if defined(__MWERKS__) || defined(__GNUC__) +# define JS_IMPORT_API(__x) __x +# else +# define JS_IMPORT_API(__x) __declspec(dllimport) __x +# endif +#elif defined(XP_OS2) && defined(__declspec) +# define JS_IMPORT_API(__x) __declspec(dllimport) __x #else -# define JS_IMPORT_API(__x) JS_EXPORT_API (__x) +# define JS_IMPORT_API(__x) JS_EXPORT_API (__x) #endif #if defined(_WIN32) && !defined(__MWERKS__) -# define JS_IMPORT_DATA(__x) __declspec(dllimport) __x +# define JS_IMPORT_DATA(__x) __declspec(dllimport) __x +#elif defined(XP_OS2) && defined(__declspec) +# define JS_IMPORT_DATA(__x) __declspec(dllimport) __x #else -# define JS_IMPORT_DATA(__x) JS_EXPORT_DATA (__x) +# define JS_IMPORT_DATA(__x) JS_EXPORT_DATA (__x) #endif /* * The linkage of JS API functions differs depending on whether the file is - * used within the JS library or not. Any source file within the JS + * used within the JS library or not. Any source file within the JS * interpreter should define EXPORT_JS_API whereas any client of the library - * should not. + * should not. STATIC_JS_API is used to build JS as a static library. */ -#ifdef EXPORT_JS_API -#define JS_PUBLIC_API(t) JS_EXPORT_API(t) -#define JS_PUBLIC_DATA(t) JS_EXPORT_DATA(t) +#if defined(STATIC_JS_API) + +# define JS_PUBLIC_API(t) t +# define JS_PUBLIC_DATA(t) t + +#elif defined(EXPORT_JS_API) + +# define JS_PUBLIC_API(t) JS_EXPORT_API(t) +# define JS_PUBLIC_DATA(t) JS_EXPORT_DATA(t) + #else -#define JS_PUBLIC_API(t) JS_IMPORT_API(t) -#define JS_PUBLIC_DATA(t) JS_IMPORT_DATA(t) + +# define JS_PUBLIC_API(t) JS_IMPORT_API(t) +# define JS_PUBLIC_DATA(t) JS_IMPORT_DATA(t) + #endif #define JS_FRIEND_API(t) JS_PUBLIC_API(t) #define JS_FRIEND_DATA(t) JS_PUBLIC_DATA(t) -#ifdef _WIN32 -# define JS_INLINE __inline +#if defined(_MSC_VER) +# define JS_INLINE __forceinline #elif defined(__GNUC__) # define JS_INLINE #else -# define JS_INLINE +# define JS_INLINE #endif /*********************************************************************** @@ -174,7 +177,14 @@ ** behave syntactically more like functions when called. ***********************************************************************/ #define JS_BEGIN_MACRO do { -#define JS_END_MACRO } while (0) + +#if defined(_MSC_VER) && _MSC_VER >= 1400 +# define JS_END_MACRO \ + } __pragma(warning(push)) __pragma(warning(disable:4127)) \ + while (0) __pragma(warning(pop)) +#else +# define JS_END_MACRO } while (0) +#endif /*********************************************************************** ** MACROS: JS_BEGIN_EXTERN_C @@ -183,11 +193,15 @@ ** Macro shorthands for conditional C++ extern block delimiters. ***********************************************************************/ #ifdef __cplusplus -#define JS_BEGIN_EXTERN_C extern "C" { -#define JS_END_EXTERN_C } + +# define JS_BEGIN_EXTERN_C extern "C" { +# define JS_END_EXTERN_C } + #else -#define JS_BEGIN_EXTERN_C -#define JS_END_EXTERN_C + +# define JS_BEGIN_EXTERN_C +# define JS_END_EXTERN_C + #endif /*********************************************************************** @@ -226,12 +240,12 @@ #define JS_MAX(x,y) ((x)>(y)?(x):(y)) #if (defined(XP_WIN) && !defined(CROSS_COMPILE)) || defined (WINCE) -# include "jscpucfg.h" /* Use standard Mac or Windows configuration */ +# include "jscpucfg.h" /* Use standard Mac or Windows configuration */ #elif defined(XP_UNIX) || defined(XP_BEOS) || defined(XP_OS2) || defined(CROSS_COMPILE) -# include "jsautocfg.h" /* Use auto-detected configuration */ +# include "jsautocfg.h" /* Use auto-detected configuration */ # include "jsosdep.h" /* ...and platform-specific flags */ #else -# error "Must define one of XP_BEOS, XP_OS2, XP_WIN or XP_UNIX" +# error "Must define one of XP_BEOS, XP_OS2, XP_WIN or XP_UNIX" #endif JS_BEGIN_EXTERN_C @@ -247,7 +261,7 @@ JS_BEGIN_EXTERN_C typedef unsigned char JSUint8; typedef signed char JSInt8; #else -#error No suitable type for JSInt8/JSUint8 +# error No suitable type for JSInt8/JSUint8 #endif /************************************************************************ @@ -260,7 +274,7 @@ typedef signed char JSInt8; typedef unsigned short JSUint16; typedef short JSInt16; #else -#error No suitable type for JSInt16/JSUint16 +# error No suitable type for JSInt16/JSUint16 #endif /************************************************************************ @@ -272,15 +286,15 @@ typedef short JSInt16; #if JS_BYTES_PER_INT == 4 typedef unsigned int JSUint32; typedef int JSInt32; -#define JS_INT32(x) x -#define JS_UINT32(x) x ## U +# define JS_INT32(x) x +# define JS_UINT32(x) x ## U #elif JS_BYTES_PER_LONG == 4 typedef unsigned long JSUint32; typedef long JSInt32; -#define JS_INT32(x) x ## L -#define JS_UINT32(x) x ## UL +# define JS_INT32(x) x ## L +# define JS_UINT32(x) x ## UL #else -#error No suitable type for JSInt32/JSUint32 +# error No suitable type for JSInt32/JSUint32 #endif /************************************************************************ @@ -294,28 +308,32 @@ typedef long JSInt32; ** the JSLL_ macros (see jslong.h). ************************************************************************/ #ifdef JS_HAVE_LONG_LONG -#if JS_BYTES_PER_LONG == 8 + +# if JS_BYTES_PER_LONG == 8 typedef long JSInt64; typedef unsigned long JSUint64; -#elif defined(WIN16) +# elif defined(WIN16) typedef __int64 JSInt64; typedef unsigned __int64 JSUint64; -#elif defined(WIN32) && !defined(__GNUC__) +# elif defined(WIN32) && !defined(__GNUC__) typedef __int64 JSInt64; typedef unsigned __int64 JSUint64; -#else +# else typedef long long JSInt64; typedef unsigned long long JSUint64; -#endif /* JS_BYTES_PER_LONG == 8 */ +# endif /* JS_BYTES_PER_LONG == 8 */ + #else /* !JS_HAVE_LONG_LONG */ + typedef struct { -#ifdef IS_LITTLE_ENDIAN +# ifdef IS_LITTLE_ENDIAN JSUint32 lo, hi; -#else +# else JSUint32 hi, lo; #endif } JSInt64; typedef JSInt64 JSUint64; + #endif /* !JS_HAVE_LONG_LONG */ /************************************************************************ @@ -331,7 +349,7 @@ typedef JSInt64 JSUint64; typedef int JSIntn; typedef unsigned int JSUintn; #else -#error 'sizeof(int)' not sufficient for platform use +# error 'sizeof(int)' not sufficient for platform use #endif /************************************************************************ @@ -362,7 +380,11 @@ typedef ptrdiff_t JSPtrdiff; ** A type for pointer difference. Variables of this type are suitable ** for storing a pointer or pointer sutraction. ************************************************************************/ +#if JS_BYTES_PER_WORD == 8 && JS_BYTES_PER_LONG != 8 +typedef JSUint64 JSUptrdiff; +#else typedef unsigned long JSUptrdiff; +#endif /************************************************************************ ** TYPES: JSBool @@ -380,15 +402,20 @@ typedef JSIntn JSBool; ** TYPES: JSPackedBool ** DESCRIPTION: ** Use JSPackedBool within structs where bitfields are not desireable -** but minimum and consistant overhead matters. +** but minimum and consistent overhead matters. ************************************************************************/ typedef JSUint8 JSPackedBool; /* ** A JSWord is an integer that is the same size as a void* */ +#if JS_BYTES_PER_WORD == 8 && JS_BYTES_PER_LONG != 8 +typedef JSInt64 JSWord; +typedef JSUint64 JSUword; +#else typedef long JSWord; typedef unsigned long JSUword; +#endif #include "jsotypes.h" @@ -409,13 +436,37 @@ typedef unsigned long JSUword; ** ***********************************************************************/ #if defined(__GNUC__) && (__GNUC__ > 2) -#define JS_LIKELY(x) (__builtin_expect((x), 1)) -#define JS_UNLIKELY(x) (__builtin_expect((x), 0)) + +# define JS_LIKELY(x) (__builtin_expect((x), 1)) +# define JS_UNLIKELY(x) (__builtin_expect((x), 0)) + #else -#define JS_LIKELY(x) (x) -#define JS_UNLIKELY(x) (x) + +# define JS_LIKELY(x) (x) +# define JS_UNLIKELY(x) (x) + #endif +/*********************************************************************** +** MACROS: JS_ARRAY_LENGTH +** JS_ARRAY_END +** DESCRIPTION: +** Macros to get the number of elements and the pointer to one past the +** last element of a C array. Use them like this: +** +** jschar buf[10], *s; +** JSString *str; +** ... +** for (s = buf; s != JS_ARRAY_END(buf); ++s) *s = ...; +** ... +** str = JS_NewStringCopyN(cx, buf, JS_ARRAY_LENGTH(buf)); +** ... +** +***********************************************************************/ + +#define JS_ARRAY_LENGTH(array) (sizeof (array) / sizeof (array)[0]) +#define JS_ARRAY_END(array) ((array) + JS_ARRAY_LENGTH(array)) + JS_END_EXTERN_C #endif /* jstypes_h___ */ diff --git a/src/mod/languages/mod_spidermonkey/mod_spidermonkey.2008.vcproj b/src/mod/languages/mod_spidermonkey/mod_spidermonkey.2008.vcproj index d2f7fb3a25..cf35ce5e13 100644 --- a/src/mod/languages/mod_spidermonkey/mod_spidermonkey.2008.vcproj +++ b/src/mod/languages/mod_spidermonkey/mod_spidermonkey.2008.vcproj @@ -44,7 +44,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="" - PreprocessorDefinitions="SM_EXPORTS;JS_HAS_FILE_OBJECT=1" + PreprocessorDefinitions="SM_EXPORTS;JS_HAS_FILE_OBJECT=1;XP_WIN" UsePrecompiledHeader="0" /> Disabled %(AdditionalIncludeDirectories) - SM_EXPORTS;JS_HAS_FILE_OBJECT=1;%(PreprocessorDefinitions) + SM_EXPORTS;JS_HAS_FILE_OBJECT=1;XP_WIN;%(PreprocessorDefinitions) @@ -91,7 +91,7 @@ Disabled %(AdditionalIncludeDirectories) - SM_EXPORTS;JS_HAS_FILE_OBJECT=1;%(PreprocessorDefinitions) + SM_EXPORTS;JS_HAS_FILE_OBJECT=1;XP_WIN;%(PreprocessorDefinitions) @@ -107,7 +107,7 @@ %(AdditionalIncludeDirectories) - SM_EXPORTS;JS_HAS_FILE_OBJECT=1;%(PreprocessorDefinitions) + SM_EXPORTS;JS_HAS_FILE_OBJECT=1;XP_WIN;%(PreprocessorDefinitions) @@ -125,7 +125,7 @@ %(AdditionalIncludeDirectories) - SM_EXPORTS;JS_HAS_FILE_OBJECT=1;%(PreprocessorDefinitions) + SM_EXPORTS;JS_HAS_FILE_OBJECT=1;XP_WIN;%(PreprocessorDefinitions) From de7a9843996f31e29a08fa93e2bf7b600e76cad0 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Wed, 17 Nov 2010 19:37:40 -0600 Subject: [PATCH 027/237] correct windows vs2010 mod_valet_parking x64 path issue --- .../mod_valet_parking/mod_valet_parking.2010.vcxproj | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/mod/applications/mod_valet_parking/mod_valet_parking.2010.vcxproj b/src/mod/applications/mod_valet_parking/mod_valet_parking.2010.vcxproj index 5e006e13f9..29c0c4a742 100644 --- a/src/mod/applications/mod_valet_parking/mod_valet_parking.2010.vcxproj +++ b/src/mod/applications/mod_valet_parking/mod_valet_parking.2010.vcxproj @@ -63,10 +63,6 @@ <_ProjectFileVersion>10.0.30319.1 - $(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ From 86509640e343da132c0a06461c0b9bdde7e6309c Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 18 Nov 2010 09:00:24 -0600 Subject: [PATCH 028/237] FS-2857 --- src/switch_ivr.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/switch_ivr.c b/src/switch_ivr.c index e599839e16..aa3de5ffd8 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -911,10 +911,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_park(switch_core_session_t *session, switch_ivr_parse_all_events(session); - if (switch_channel_has_dtmf(channel)) { + if (args && switch_channel_has_dtmf(channel)) { switch_dtmf_t dtmf = { 0 }; - if (!args->input_callback && !args->buf && !args->dmachine) { + if (args && !args->input_callback && !args->buf && !args->dmachine) { status = SWITCH_STATUS_BREAK; break; } @@ -926,7 +926,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_park(switch_core_session_t *session, if ((status = switch_ivr_dmachine_feed(args->dmachine, ds, NULL)) != SWITCH_STATUS_SUCCESS) { break; } - } else if (args && args->input_callback) { + } else if (args->input_callback) { if ((status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen)) != SWITCH_STATUS_SUCCESS) { break; } From ad7c7f1323d64c255b88f13610fc9c0341f86dc1 Mon Sep 17 00:00:00 2001 From: Mathieu Rene Date: Thu, 18 Nov 2010 11:17:11 -0500 Subject: [PATCH 029/237] adjust switch_yield times in switch_core_sql_db_thread() and pool_thread() --- src/switch_core_memory.c | 2 +- src/switch_core_sqldb.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/switch_core_memory.c b/src/switch_core_memory.c index 39d0403c42..a63ce0d6f9 100644 --- a/src/switch_core_memory.c +++ b/src/switch_core_memory.c @@ -548,7 +548,7 @@ static void *SWITCH_THREAD_FUNC pool_thread(switch_thread_t *thread, void *obj) goto done; } } else { - switch_yield(100000); + switch_yield(1000000); } } diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index 509d989581..89249e69a9 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -898,7 +898,7 @@ static void *SWITCH_THREAD_FUNC switch_core_sql_db_thread(switch_thread_t *threa wake_thread(0); sec = 0; } - switch_yield(1000); + switch_yield(1000000); } From d4138959b2eac09313c420e158f2488ece7080d8 Mon Sep 17 00:00:00 2001 From: Stefan Knoblich Date: Thu, 18 Nov 2010 23:14:46 +0100 Subject: [PATCH 030/237] freetdm: use m4_ifdef() to check for pkg-config macros and print a warning if they are not available ...instead of failing at runtime Signed-off-by: Stefan Knoblich --- libs/freetdm/configure.ac | 74 ++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 33 deletions(-) diff --git a/libs/freetdm/configure.ac b/libs/freetdm/configure.ac index 8b878edc09..6b9287d791 100644 --- a/libs/freetdm/configure.ac +++ b/libs/freetdm/configure.ac @@ -24,7 +24,12 @@ AC_PROG_MAKE_SET AM_PROG_CC_C_O AC_PROG_LIBTOOL AC_PROG_INSTALL -PKG_PROG_PKG_CONFIG + +# NOTE: pkg-config is used to detect libisdn +m4_ifdef([PKG_PROG_PKG_CONFIG], + [PKG_PROG_PKG_CONFIG], + [AC_MSG_WARN([pkg-config missing (required for libisdn detection)])] +) AX_COMPILER_VENDOR @@ -305,41 +310,44 @@ AC_ARG_WITH([libisdn], if test "${with_libisdn}" != "no" then AC_MSG_RESULT([${as_nl}<<>> ftmod_isdn (libisdn stack)]) - PKG_CHECK_MODULES([libisdn], - [libisdn >= 0.0.1], - [AC_MSG_CHECKING([libisdn version]) - LIBISDN_VERSION="`${PKG_CONFIG} --modversion libisdn`" - if test -z "${LIBISDN_VERSION}"; then - AC_MSG_ERROR([Failed to retrieve libisdn version]) - fi - AC_MSG_RESULT([${LIBISDN_VERSION}]) + m4_ifdef([PKG_CHECK_MODULES], + [PKG_CHECK_MODULES([libisdn], + [libisdn >= 0.0.1], + [AC_MSG_CHECKING([libisdn version]) + LIBISDN_VERSION="`${PKG_CONFIG} --modversion libisdn`" + if test -z "${LIBISDN_VERSION}"; then + AC_MSG_ERROR([Failed to retrieve libisdn version]) + fi + AC_MSG_RESULT([${LIBISDN_VERSION}]) - # check features - AC_MSG_CHECKING([for new experimental API]) - AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM( - [#include - #if !LIBISDN_FEATURE(API2) - #error "libisdn API v2 not available" - #endif - ], - [;] - )], - [AC_MSG_RESULT([yes])], - [AC_MSG_RESULT([no])] + # check features + AC_MSG_CHECKING([for new experimental API]) + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [#include + #if !LIBISDN_FEATURE(API2) + #error "libisdn API v2 not available" + #endif + ], + [;] + )], + [AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no])] + ) + + HAVE_LIBISDN="yes" + AC_DEFINE([HAVE_LIBISDN], [1], [libisdn support]) + AC_SUBST([LIBISDN_CFLAGS], [${libisdn_CFLAGS}]) + AC_SUBST([LIBISDN_CPPFLAGS],[${libisdn_CPPFLAGS}]) + AC_SUBST([LIBISDN_LDFLAGS], [${libisdn_LDFLAGS}]) + AC_SUBST([LIBISDN_LIBS], [${libisdn_LIBS}]) + AC_SUBST([LIBISDN_VERSION]) + ], + [AC_MSG_ERROR([Need libisdn-0.0.1 or higher])] ) - - HAVE_LIBISDN="yes" - AC_DEFINE([HAVE_LIBISDN], [1], [libisdn support]) - AC_SUBST([LIBISDN_CFLAGS], [${libisdn_CFLAGS}]) - AC_SUBST([LIBISDN_CPPFLAGS],[${libisdn_CPPFLAGS}]) - AC_SUBST([LIBISDN_LDFLAGS], [${libisdn_LDFLAGS}]) - AC_SUBST([LIBISDN_LIBS], [${libisdn_LIBS}]) - AC_SUBST([LIBISDN_VERSION]) - ], - [AC_MSG_ERROR([Need libisdn-0.0.1 or higher])] + AX_LIB_PCAP], + [AC_MSG_WARN([pkg-config missing (required for libisdn detection)])] ) - AX_LIB_PCAP fi AM_CONDITIONAL([HAVE_LIBISDN], [test "${HAVE_LIBISDN}" = "yes"]) From d96eb988ff7422dc72662b51ce1d0cbb036138e0 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 18 Nov 2010 16:14:08 -0600 Subject: [PATCH 031/237] FS-2857 --- src/switch_ivr.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/switch_ivr.c b/src/switch_ivr.c index aa3de5ffd8..f076f6cb9f 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -911,7 +911,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_park(switch_core_session_t *session, switch_ivr_parse_all_events(session); - if (args && switch_channel_has_dtmf(channel)) { + if (switch_channel_has_dtmf(channel)) { switch_dtmf_t dtmf = { 0 }; if (args && !args->input_callback && !args->buf && !args->dmachine) { @@ -921,14 +921,16 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_park(switch_core_session_t *session, switch_channel_dequeue_dtmf(channel, &dtmf); - if (args->dmachine) { - char ds[2] = {dtmf.digit, '\0'}; - if ((status = switch_ivr_dmachine_feed(args->dmachine, ds, NULL)) != SWITCH_STATUS_SUCCESS) { - break; - } - } else if (args->input_callback) { - if ((status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen)) != SWITCH_STATUS_SUCCESS) { - break; + if (args) { + if (args->dmachine) { + char ds[2] = {dtmf.digit, '\0'}; + if ((status = switch_ivr_dmachine_feed(args->dmachine, ds, NULL)) != SWITCH_STATUS_SUCCESS) { + break; + } + } else if (args->input_callback) { + if ((status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen)) != SWITCH_STATUS_SUCCESS) { + break; + } } } } From 0a11b9b4333eb960038feca7972470f3770a5cce Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 18 Nov 2010 16:23:01 -0600 Subject: [PATCH 032/237] FS-2859 --- src/include/switch_types.h | 4 +++- src/switch_rtp.c | 49 +++++++++++++++++++++++++++++++++++++- 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/include/switch_types.h b/src/include/switch_types.h index c01638089f..12fac04a8b 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -471,7 +471,9 @@ typedef enum { SWITCH_VAD_FLAG_TALKING = (1 << 0), SWITCH_VAD_FLAG_EVENTS_TALK = (1 << 1), SWITCH_VAD_FLAG_EVENTS_NOTALK = (1 << 2), - SWITCH_VAD_FLAG_CNG = (1 << 3) + SWITCH_VAD_FLAG_CNG = (1 << 3), +/* added to keep track when last normal packet sent */ + SWITCH_VAD_NPACKET_SENT = (1 << 4) } switch_vad_flag_enum_t; typedef uint32_t switch_vad_flag_t; diff --git a/src/switch_rtp.c b/src/switch_rtp.c index ee1c4acf5e..e347212ad5 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -240,6 +240,7 @@ struct switch_rtp { switch_time_t send_time; switch_byte_t auto_adj_used; + int last_voicepkt; }; struct switch_rtcp_senderinfo { @@ -1356,6 +1357,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_create(switch_rtp_t **new_rtp_session rtp_session->pool = pool; rtp_session->te = 101; rtp_session->recv_te = 101; + rtp_session->last_voicepkt=0; switch_mutex_init(&rtp_session->flag_mutex, SWITCH_MUTEX_NESTED, pool); switch_mutex_init(&rtp_session->read_mutex, SWITCH_MUTEX_NESTED, pool); @@ -3155,9 +3157,12 @@ static int rtp_common_write(switch_rtp_t *rtp_session, { switch_size_t bytes, rtcp_bytes; uint8_t send = 1; + uint8_t CNdata[10] = { 0 }; + uint8_t sendCN = 0; uint32_t this_ts = 0; int ret; switch_time_t now; + CNdata[0] = 65; if (!switch_rtp_ready(rtp_session)) { return SWITCH_STATUS_FALSE; @@ -3239,9 +3244,15 @@ static int rtp_common_write(switch_rtp_t *rtp_session, rtp_session->recv_msg.header.pt = 102; } + if ( !switch_test_flag(rtp_session,SWITCH_RTP_FLAG_VAD ) ) + switch_set_flag( rtp_session,SWITCH_RTP_FLAG_VAD); + + +/* if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_VAD) && rtp_session->recv_msg.header.pt == rtp_session->vad_data.read_codec->implementation->ianacode) { - +*/ + if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_VAD)) { int16_t decoded[SWITCH_RECOMMENDED_BUFFER_SIZE / sizeof(int16_t)] = { 0 }; uint32_t rate = 0; uint32_t codec_flags = 0; @@ -3290,6 +3301,7 @@ static int rtp_common_write(switch_rtp_t *rtp_session, if (score > rtp_session->vad_data.bg_level && !switch_test_flag(&rtp_session->vad_data, SWITCH_VAD_FLAG_TALKING)) { uint32_t diff = score - rtp_session->vad_data.bg_level; + if (rtp_session->vad_data.hangover_hits) { rtp_session->vad_data.hangover_hits--; } @@ -3342,11 +3354,31 @@ static int rtp_common_write(switch_rtp_t *rtp_session, this_ts = ntohl(send_msg->header.ts); + + /* if previous normal packet is sent but this one is not scheduled to be sent, send a CN packet */ + if ( !rtp_session->last_voicepkt && send==0 ) { + send=1; + sendCN=1; + //switch_set_flag(&rtp_session->vad_data,SWITCH_VAD_NPACKET_SENT ); + rtp_session->last_voicepkt=1; + } + if (!switch_rtp_ready(rtp_session) || rtp_session->sending_dtmf || !this_ts) { send = 0; } + /* we send CN automatically. ignore other attempts */ + if ( send_msg->header.pt == rtp_session->cng_pt ){ + send = 0; + } + + + if (send) { + if ( !sendCN) + rtp_session->last_voicepkt=0; + + send_msg->header.seq = htons(++rtp_session->seq); if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_SECURE_SEND)) { @@ -3441,6 +3473,18 @@ static int rtp_common_write(switch_rtp_t *rtp_session, } } + if ( sendCN ) { + int CNdatalen = 2; + rtp_session->cn++; + memcpy(send_msg->body, CNdata, CNdatalen); + bytes = CNdatalen + rtp_header_len; + payload = rtp_session->cng_pt; + send_msg->header.pt = rtp_session->cng_pt; + send_msg->header.m = 0; + rtp_session->last_voicepkt=1; + } + + if (switch_socket_sendto(rtp_session->sock_output, rtp_session->remote_addr, 0, (void *) send_msg, &bytes) != SWITCH_STATUS_SUCCESS) { rtp_session->seq--; @@ -3523,6 +3567,9 @@ static int rtp_common_write(switch_rtp_t *rtp_session, } } + + + if (rtp_session->remote_stun_addr) { do_stun_ping(rtp_session); } From 42a4a3dedfe762268d935e5fd5e5de6e0f1d024a Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 18 Nov 2010 18:24:32 -0600 Subject: [PATCH 033/237] revert FS-2859 --- src/include/switch_types.h | 4 +--- src/switch_rtp.c | 49 +------------------------------------- 2 files changed, 2 insertions(+), 51 deletions(-) diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 12fac04a8b..c01638089f 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -471,9 +471,7 @@ typedef enum { SWITCH_VAD_FLAG_TALKING = (1 << 0), SWITCH_VAD_FLAG_EVENTS_TALK = (1 << 1), SWITCH_VAD_FLAG_EVENTS_NOTALK = (1 << 2), - SWITCH_VAD_FLAG_CNG = (1 << 3), -/* added to keep track when last normal packet sent */ - SWITCH_VAD_NPACKET_SENT = (1 << 4) + SWITCH_VAD_FLAG_CNG = (1 << 3) } switch_vad_flag_enum_t; typedef uint32_t switch_vad_flag_t; diff --git a/src/switch_rtp.c b/src/switch_rtp.c index e347212ad5..ee1c4acf5e 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -240,7 +240,6 @@ struct switch_rtp { switch_time_t send_time; switch_byte_t auto_adj_used; - int last_voicepkt; }; struct switch_rtcp_senderinfo { @@ -1357,7 +1356,6 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_create(switch_rtp_t **new_rtp_session rtp_session->pool = pool; rtp_session->te = 101; rtp_session->recv_te = 101; - rtp_session->last_voicepkt=0; switch_mutex_init(&rtp_session->flag_mutex, SWITCH_MUTEX_NESTED, pool); switch_mutex_init(&rtp_session->read_mutex, SWITCH_MUTEX_NESTED, pool); @@ -3157,12 +3155,9 @@ static int rtp_common_write(switch_rtp_t *rtp_session, { switch_size_t bytes, rtcp_bytes; uint8_t send = 1; - uint8_t CNdata[10] = { 0 }; - uint8_t sendCN = 0; uint32_t this_ts = 0; int ret; switch_time_t now; - CNdata[0] = 65; if (!switch_rtp_ready(rtp_session)) { return SWITCH_STATUS_FALSE; @@ -3244,15 +3239,9 @@ static int rtp_common_write(switch_rtp_t *rtp_session, rtp_session->recv_msg.header.pt = 102; } - if ( !switch_test_flag(rtp_session,SWITCH_RTP_FLAG_VAD ) ) - switch_set_flag( rtp_session,SWITCH_RTP_FLAG_VAD); - - -/* if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_VAD) && rtp_session->recv_msg.header.pt == rtp_session->vad_data.read_codec->implementation->ianacode) { -*/ - if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_VAD)) { + int16_t decoded[SWITCH_RECOMMENDED_BUFFER_SIZE / sizeof(int16_t)] = { 0 }; uint32_t rate = 0; uint32_t codec_flags = 0; @@ -3301,7 +3290,6 @@ static int rtp_common_write(switch_rtp_t *rtp_session, if (score > rtp_session->vad_data.bg_level && !switch_test_flag(&rtp_session->vad_data, SWITCH_VAD_FLAG_TALKING)) { uint32_t diff = score - rtp_session->vad_data.bg_level; - if (rtp_session->vad_data.hangover_hits) { rtp_session->vad_data.hangover_hits--; } @@ -3354,31 +3342,11 @@ static int rtp_common_write(switch_rtp_t *rtp_session, this_ts = ntohl(send_msg->header.ts); - - /* if previous normal packet is sent but this one is not scheduled to be sent, send a CN packet */ - if ( !rtp_session->last_voicepkt && send==0 ) { - send=1; - sendCN=1; - //switch_set_flag(&rtp_session->vad_data,SWITCH_VAD_NPACKET_SENT ); - rtp_session->last_voicepkt=1; - } - if (!switch_rtp_ready(rtp_session) || rtp_session->sending_dtmf || !this_ts) { send = 0; } - /* we send CN automatically. ignore other attempts */ - if ( send_msg->header.pt == rtp_session->cng_pt ){ - send = 0; - } - - - if (send) { - if ( !sendCN) - rtp_session->last_voicepkt=0; - - send_msg->header.seq = htons(++rtp_session->seq); if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_SECURE_SEND)) { @@ -3473,18 +3441,6 @@ static int rtp_common_write(switch_rtp_t *rtp_session, } } - if ( sendCN ) { - int CNdatalen = 2; - rtp_session->cn++; - memcpy(send_msg->body, CNdata, CNdatalen); - bytes = CNdatalen + rtp_header_len; - payload = rtp_session->cng_pt; - send_msg->header.pt = rtp_session->cng_pt; - send_msg->header.m = 0; - rtp_session->last_voicepkt=1; - } - - if (switch_socket_sendto(rtp_session->sock_output, rtp_session->remote_addr, 0, (void *) send_msg, &bytes) != SWITCH_STATUS_SUCCESS) { rtp_session->seq--; @@ -3567,9 +3523,6 @@ static int rtp_common_write(switch_rtp_t *rtp_session, } } - - - if (rtp_session->remote_stun_addr) { do_stun_ping(rtp_session); } From de417e99f0c41421f701f86ee5e4e507868be81f Mon Sep 17 00:00:00 2001 From: Mathieu Rene Date: Thu, 18 Nov 2010 21:00:21 -0500 Subject: [PATCH 034/237] Implement switch_queue_pop_timeout() and refactor sofia_profile_worker_thread_run() to use it so it doesn't wake up too often --- libs/apr-util/.update | 2 +- libs/apr-util/include/apr_queue.h | 16 ++++++ libs/apr-util/misc/apr_queue.c | 65 +++++++++++++++++++++ src/include/switch_apr.h | 16 ++++++ src/mod/endpoints/mod_sofia/sofia.c | 89 ++++++++++++++--------------- src/switch_apr.c | 6 ++ 6 files changed, 148 insertions(+), 46 deletions(-) diff --git a/libs/apr-util/.update b/libs/apr-util/.update index f430e64b3b..a573c80504 100644 --- a/libs/apr-util/.update +++ b/libs/apr-util/.update @@ -1 +1 @@ -Mon Dec 28 14:55:57 EST 2009 +Thu 18 Nov 2010 20:56:38 EST diff --git a/libs/apr-util/include/apr_queue.h b/libs/apr-util/include/apr_queue.h index 5a0181b29e..dcf0c137ed 100644 --- a/libs/apr-util/include/apr_queue.h +++ b/libs/apr-util/include/apr_queue.h @@ -78,6 +78,22 @@ APU_DECLARE(apr_status_t) apr_queue_push(apr_queue_t *queue, void *data); */ APU_DECLARE(apr_status_t) apr_queue_pop(apr_queue_t *queue, void **data); +/** + * pop/get an object from the queue, blocking if the queue is already empty + * + * @param queue the queue + * @param data the data + * @param timeout The amount of time in microseconds to wait. This is + * a maximum, not a minimum. If the condition is signaled, we + * will wake up before this time, otherwise the error APR_TIMEUP + * is returned. + * @returns APR_TIMEUP the request timed out + * @returns APR_EINTR the blocking was interrupted (try again) + * @returns APR_EOF if the queue has been terminated + * @returns APR_SUCCESS on a successfull pop + */ +APU_DECLARE(apr_status_t) apr_queue_pop_timeout(apr_queue_t *queue, void **data, apr_interval_time_t timeout); + /** * push/add a object to the queue, returning immediatly if the queue is full * diff --git a/libs/apr-util/misc/apr_queue.c b/libs/apr-util/misc/apr_queue.c index 28d79afcb5..e905a53ebb 100644 --- a/libs/apr-util/misc/apr_queue.c +++ b/libs/apr-util/misc/apr_queue.c @@ -313,6 +313,71 @@ APU_DECLARE(apr_status_t) apr_queue_pop(apr_queue_t *queue, void **data) return rv; } +/** + * Retrieves the next item from the queue. If there are no + * items available, it will block until one becomes available, or + * until timeout is elapsed. Once retrieved, the item is placed into + * the address specified by'data'. + */ +APU_DECLARE(apr_status_t) apr_queue_pop_timeout(apr_queue_t *queue, void **data, apr_interval_time_t timeout) +{ + apr_status_t rv; + + if (queue->terminated) { + return APR_EOF; /* no more elements ever again */ + } + + rv = apr_thread_mutex_lock(queue->one_big_mutex); + if (rv != APR_SUCCESS) { + return rv; + } + + /* Keep waiting until we wake up and find that the queue is not empty. */ + if (apr_queue_empty(queue)) { + if (!queue->terminated) { + queue->empty_waiters++; + rv = apr_thread_cond_timedwait(queue->not_empty, queue->one_big_mutex, timeout); + queue->empty_waiters--; + /* In the event of a timemout, APR_TIMEUP will be returned */ + if (rv != APR_SUCCESS) { + apr_thread_mutex_unlock(queue->one_big_mutex); + return rv; + } + } + /* If we wake up and it's still empty, then we were interrupted */ + if (apr_queue_empty(queue)) { + Q_DBG("queue empty (intr)", queue); + rv = apr_thread_mutex_unlock(queue->one_big_mutex); + if (rv != APR_SUCCESS) { + return rv; + } + if (queue->terminated) { + return APR_EOF; /* no more elements ever again */ + } + else { + return APR_EINTR; + } + } + } + + *data = queue->data[queue->out]; + queue->nelts--; + + queue->out = (queue->out + 1) % queue->bounds; + if (queue->full_waiters) { + Q_DBG("signal !full", queue); + rv = apr_thread_cond_signal(queue->not_full); + if (rv != APR_SUCCESS) { + apr_thread_mutex_unlock(queue->one_big_mutex); + return rv; + } + } + + rv = apr_thread_mutex_unlock(queue->one_big_mutex); + return rv; +} + + /** * Retrieves the next item from the queue. If there are no * items available, return APR_EAGAIN. Once retrieved, diff --git a/src/include/switch_apr.h b/src/include/switch_apr.h index f82b81a7f8..dc81d1a522 100644 --- a/src/include/switch_apr.h +++ b/src/include/switch_apr.h @@ -592,6 +592,22 @@ SWITCH_DECLARE(switch_status_t) switch_queue_create(switch_queue_t ** queue, uns */ SWITCH_DECLARE(switch_status_t) switch_queue_pop(switch_queue_t *queue, void **data); +/** + * pop/get an object from the queue, blocking if the queue is already empty + * + * @param queue the queue + * @param data the data + * @param timeout The amount of time in microseconds to wait. This is + * a maximum, not a minimum. If the condition is signaled, we + * will wake up before this time, otherwise the error APR_TIMEUP + * is returned. + * @returns APR_TIMEUP the request timed out + * @returns APR_EINTR the blocking was interrupted (try again) + * @returns APR_EOF if the queue has been terminated + * @returns APR_SUCCESS on a successfull pop + */ +SWITCH_DECLARE(switch_status_t) switch_queue_pop_timeout(switch_queue_t *queue, void **data, switch_interval_time_t timeout); + /** * push/add a object to the queue, blocking if the queue is already full * diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 5bb2ff0d66..9fadced17f 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -1230,43 +1230,42 @@ static void sofia_perform_profile_start_failure(sofia_profile_t *profile, char * void *SWITCH_THREAD_FUNC sofia_profile_worker_thread_run(switch_thread_t *thread, void *obj) { sofia_profile_t *profile = (sofia_profile_t *) obj; - uint32_t ireg_loops = 0; - uint32_t gateway_loops = 0; - int loops = 0; - uint32_t qsize; - void *pop = NULL; - int loop_count = 0; - switch_size_t sql_len = 1024 * 32; - char *tmp, *sqlbuf = NULL; - char *sql = NULL; + uint32_t ireg_loops = IREG_SECONDS; /* Number of loop iterations done when we haven't checked for registrations */ + uint32_t gateway_loops = GATEWAY_SECONDS; /* Number of loop iterations done when we haven't checked for gateways */ + void *pop = NULL; /* queue_pop placeholder */ + switch_size_t sql_len = 1024 * 32; /* length of sqlbuf */ + char *tmp, *sqlbuf = NULL; /* Buffer for SQL statements */ + char *sql = NULL; /* Current SQL statement */ + switch_time_t last_commit; /* Last time we committed stuff to the DB */ + switch_time_t last_check; /* Last time we did the second-resolution loop that checks various stuff */ + switch_size_t len = 0; /* Current length of sqlbuf */ + uint32_t statements = 0; /* Number of statements in the current sql buffer */ + + last_commit = last_check = switch_micro_time_now(); if (sofia_test_pflag(profile, PFLAG_SQL_IN_TRANS)) { sqlbuf = (char *) malloc(sql_len); } - ireg_loops = IREG_SECONDS; - gateway_loops = GATEWAY_SECONDS; - sofia_set_pflag_locked(profile, PFLAG_WORKER_RUNNING); switch_queue_create(&profile->sql_queue, SOFIA_QUEUE_SIZE, profile->pool); - qsize = switch_queue_size(profile->sql_queue); - - while ((mod_sofia_globals.running == 1 && sofia_test_pflag(profile, PFLAG_RUNNING)) || qsize) { + /* While we're running, or there is a pending sql statment that we haven't appended to sqlbuf yet, because of a lack of buffer space */ + while ((mod_sofia_globals.running == 1 && sofia_test_pflag(profile, PFLAG_RUNNING)) || sql) { if (sofia_test_pflag(profile, PFLAG_SQL_IN_TRANS)) { - if (qsize > 0 && (qsize >= 1024 || ++loop_count >= (int)profile->trans_timeout)) { - switch_size_t newlen; - uint32_t iterations = 0; - switch_size_t len = 0; - - switch_mutex_lock(profile->ireg_mutex); + /* Do we have enough statements or is the timeout expired */ + while (sql || (sofia_test_pflag(profile, PFLAG_RUNNING) && mod_sofia_globals.running == 1 && + (statements == 0 || (statements <= 1024 && (switch_micro_time_now() - last_commit)/1000 < profile->trans_timeout)))) { - while (sql || (switch_queue_trypop(profile->sql_queue, &pop) == SWITCH_STATUS_SUCCESS && pop)) { + switch_interval_time_t sleepy_time = !statements ? 1000000 : switch_micro_time_now() - last_commit - profile->trans_timeout*1000; + + if (sql || (switch_queue_pop_timeout(profile->sql_queue, &pop, sleepy_time) == SWITCH_STATUS_SUCCESS && pop)) { + switch_size_t newlen; + if (!sql) sql = (char *) pop; - newlen = strlen(sql) + 2; - iterations++; + newlen = strlen(sql) + 2 /* strlen(";\n") */ ; if (len + newlen + 10 > sql_len) { switch_size_t new_mlen = len + newlen + 10 + 10240; @@ -1280,7 +1279,7 @@ void *SWITCH_THREAD_FUNC sofia_profile_worker_thread_run(switch_thread_t *thread } sqlbuf = tmp; } else { - goto skip; + break; } } @@ -1288,31 +1287,32 @@ void *SWITCH_THREAD_FUNC sofia_profile_worker_thread_run(switch_thread_t *thread len += newlen; free(sql); sql = NULL; + + statements++; } - - skip: - + } + + /* Execute here */ + last_commit = switch_micro_time_now(); + + if (len) { //printf("TRANS:\n%s\n", sqlbuf); + switch_mutex_lock(profile->ireg_mutex); sofia_glue_actually_execute_sql_trans(profile, sqlbuf, NULL); //sofia_glue_actually_execute_sql(profile, "commit;\n", NULL); switch_mutex_unlock(profile->ireg_mutex); - loop_count = 0; + statements = 0; + len = 0; } + } else { - if (qsize) { - //switch_mutex_lock(profile->ireg_mutex); - while (switch_queue_trypop(profile->sql_queue, &pop) == SWITCH_STATUS_SUCCESS && pop) { - sofia_glue_actually_execute_sql(profile, (char *) pop, profile->ireg_mutex); - free(pop); - } - //switch_mutex_unlock(profile->ireg_mutex); + if (switch_queue_pop_timeout(profile->sql_queue, &pop, 1000000) == SWITCH_STATUS_SUCCESS && pop) { + sofia_glue_actually_execute_sql(profile, (char *) pop, profile->ireg_mutex); + free(pop); } } - if (++loops >= 1000) { - - - + if (switch_micro_time_now() - last_check >= 1000000) { if (profile->watchdog_enabled) { uint32_t event_diff = 0, step_diff = 0, event_fail = 0, step_fail = 0; @@ -1339,7 +1339,7 @@ void *SWITCH_THREAD_FUNC sofia_profile_worker_thread_run(switch_thread_t *thread if (event_fail || step_fail) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Profile %s: SIP STACK FAILURE DETECTED!\n" "GOODBYE CRUEL WORLD, I'M LEAVING YOU TODAY....GOODBYE, GOODBYE, GOOD BYE\n", profile->name); - switch_yield(2000); + switch_yield(2000000); abort(); } } @@ -1354,12 +1354,11 @@ void *SWITCH_THREAD_FUNC sofia_profile_worker_thread_run(switch_thread_t *thread sofia_reg_check_gateway(profile, switch_epoch_time_now(NULL)); gateway_loops = 0; } + sofia_sub_check_gateway(profile, time(NULL)); - loops = 0; + + last_check = switch_micro_time_now(); } - - switch_cond_next(); - qsize = switch_queue_size(profile->sql_queue); } switch_mutex_lock(profile->ireg_mutex); diff --git a/src/switch_apr.c b/src/switch_apr.c index bdff179b4a..dccc37be96 100644 --- a/src/switch_apr.c +++ b/src/switch_apr.c @@ -986,6 +986,12 @@ SWITCH_DECLARE(switch_status_t) switch_queue_pop(switch_queue_t *queue, void **d return apr_queue_pop(queue, data); } +SWITCH_DECLARE(switch_status_t) switch_queue_pop_timeout(switch_queue_t *queue, void **data, switch_interval_time_t timeout) +{ + return apr_queue_pop_timeout(queue, data, timeout); +} + + SWITCH_DECLARE(switch_status_t) switch_queue_push(switch_queue_t *queue, void *data) { apr_status_t s; From 3c76811f0c41998069d21955a306baf3944c8ed0 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Thu, 18 Nov 2010 21:19:57 -0600 Subject: [PATCH 035/237] fix unimrcp build after last commit --- libs/unimrcp/libs/apr-toolkit/src/apt_consumer_task.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/unimrcp/libs/apr-toolkit/src/apt_consumer_task.c b/libs/unimrcp/libs/apr-toolkit/src/apt_consumer_task.c index 3b96373a74..ceb9320d98 100644 --- a/libs/unimrcp/libs/apr-toolkit/src/apt_consumer_task.c +++ b/libs/unimrcp/libs/apr-toolkit/src/apt_consumer_task.c @@ -14,6 +14,7 @@ * limitations under the License. */ +#include #include #include "apt_consumer_task.h" #include "apt_log.h" From d2fd5ba0aa2a968031dc0719576da3f9d63bcf31 Mon Sep 17 00:00:00 2001 From: Mathieu Rene Date: Fri, 19 Nov 2010 12:07:07 -0500 Subject: [PATCH 036/237] fix regression --- src/mod/endpoints/mod_sofia/sofia.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 9fadced17f..9cc515ed9c 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -1256,6 +1256,7 @@ void *SWITCH_THREAD_FUNC sofia_profile_worker_thread_run(switch_thread_t *thread if (sofia_test_pflag(profile, PFLAG_SQL_IN_TRANS)) { /* Do we have enough statements or is the timeout expired */ while (sql || (sofia_test_pflag(profile, PFLAG_RUNNING) && mod_sofia_globals.running == 1 && + switch_micro_time_now() - last_check < 1000000 && (statements == 0 || (statements <= 1024 && (switch_micro_time_now() - last_commit)/1000 < profile->trans_timeout)))) { switch_interval_time_t sleepy_time = !statements ? 1000000 : switch_micro_time_now() - last_commit - profile->trans_timeout*1000; From 8c9f23ea566ac746eb4ed40cdd7816309dffaa45 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 19 Nov 2010 11:16:18 -0600 Subject: [PATCH 037/237] refactor codec_destroy to prevent race --- src/switch_core_codec.c | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/src/switch_core_codec.c b/src/switch_core_codec.c index 9b607ea873..d6b627093e 100644 --- a/src/switch_core_codec.c +++ b/src/switch_core_codec.c @@ -672,14 +672,19 @@ SWITCH_DECLARE(switch_status_t) switch_core_codec_decode(switch_codec_t *codec, SWITCH_DECLARE(switch_status_t) switch_core_codec_destroy(switch_codec_t *codec) { - switch_mutex_t *mutex; - switch_memory_pool_t *pool; + switch_mutex_t *mutex = codec->mutex; + switch_memory_pool_t *pool = codec->memory_pool; int free_pool = 0; switch_assert(codec != NULL); - if (!switch_core_codec_ready(codec)) { + if (mutex) switch_mutex_lock(mutex); + + if (switch_core_codec_ready(codec)) { + switch_clear_flag(codec, SWITCH_CODEC_FLAG_READY); + } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Codec is not initialized!\n"); + if (mutex) switch_mutex_unlock(mutex); return SWITCH_STATUS_NOT_INITALIZED; } @@ -687,23 +692,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_codec_destroy(switch_codec_t *codec) free_pool = 1; } - pool = codec->memory_pool; - mutex = codec->mutex; - - if (mutex) { - switch_mutex_lock(mutex); - switch_clear_flag(codec, SWITCH_CODEC_FLAG_READY); - switch_mutex_unlock(mutex); - switch_mutex_lock(mutex); - } - codec->implementation->destroy(codec); UNPROTECT_INTERFACE(codec->codec_interface); - if (mutex) { - switch_mutex_unlock(mutex); - } + if (mutex) switch_mutex_unlock(mutex); if (free_pool) { switch_core_destroy_memory_pool(&pool); From b004916036465d145d0388a1afb24d5471b48f64 Mon Sep 17 00:00:00 2001 From: Michael S Collins Date: Fri, 19 Nov 2010 10:54:39 -0800 Subject: [PATCH 038/237] Do at least *SOME* verification to make sure that we are getting an IP address in the blacklist list --- scripts/perl/blacklist.pl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/perl/blacklist.pl b/scripts/perl/blacklist.pl index f434669f36..92fa55efe2 100755 --- a/scripts/perl/blacklist.pl +++ b/scripts/perl/blacklist.pl @@ -17,13 +17,15 @@ my @netblocks = split(/\n/, get("http://www.infiltrated.net/voipabuse/netblocks. print "\n"; foreach $addr (@addresses) { - print " \n"; + next unless $addr =~ m/\d+\.\d+\.\d+\.\d+/; + print " \n"; } print "\n"; print "\n"; foreach $netb (@netblocks) { - print " \n"; + next unless $netb =~ m/\d+\.\d+\.\d+\.\d+/; + print " \n"; } print "\n"; From 67fa716bfd78e7a0c78dbe817c8c33ebae4ebd1b Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Fri, 19 Nov 2010 13:15:56 -0600 Subject: [PATCH 039/237] fix critical property for module load --- src/switch_loadable_module.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_loadable_module.c b/src/switch_loadable_module.c index 7aee9a769b..c603e27459 100644 --- a/src/switch_loadable_module.c +++ b/src/switch_loadable_module.c @@ -1293,7 +1293,7 @@ SWITCH_DECLARE(switch_status_t) switch_loadable_module_init(switch_bool_t autolo if (path && zstr(path)) { path = SWITCH_GLOBAL_dirs.mod_dir; } - if (switch_loadable_module_load_module_ex((char *) path, (char *) val, SWITCH_FALSE, global, &err) == SWITCH_STATUS_FALSE) { + if (switch_loadable_module_load_module_ex((char *) path, (char *) val, SWITCH_FALSE, global, &err) == SWITCH_STATUS_GENERR) { if (critical && switch_true(critical)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to load critical module '%s', abort()\n", val); abort(); From 553255c63195ecbc87cdaa72394e425bc6a0f52a Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Fri, 19 Nov 2010 14:33:57 -0500 Subject: [PATCH 040/237] Fixed some windows compile warnings from merge --- conf/autoload_configs/callcenter.conf.xml | 1 - conf/autoload_configs/erlang_event.conf.xml | 9 - conf/autoload_configs/modules.conf.xml | 96 -- conf/autoload_configs/switch.conf.xml | 6 - conf/autoload_configs/voicemail.conf.xml | 7 +- conf/dialplan/default.xml | 845 ++---------------- conf/sip_profiles/internal.xml | 20 - conf/skinny_profiles/internal.xml | 2 +- conf/vars.xml | 2 +- .../ftmod_sangoma_isdn/ftmod_sangoma_isdn.h | 8 +- .../ftmod_sangoma_isdn_stack_cntrl.c | 1 - .../ftmod_sangoma_isdn_support.c | 26 +- 12 files changed, 108 insertions(+), 915 deletions(-) diff --git a/conf/autoload_configs/callcenter.conf.xml b/conf/autoload_configs/callcenter.conf.xml index a069413ac6..9140193b22 100644 --- a/conf/autoload_configs/callcenter.conf.xml +++ b/conf/autoload_configs/callcenter.conf.xml @@ -13,7 +13,6 @@ - diff --git a/conf/autoload_configs/erlang_event.conf.xml b/conf/autoload_configs/erlang_event.conf.xml index 62deb84f67..ec14e21a25 100644 --- a/conf/autoload_configs/erlang_event.conf.xml +++ b/conf/autoload_configs/erlang_event.conf.xml @@ -2,16 +2,7 @@ - - - - - diff --git a/conf/autoload_configs/modules.conf.xml b/conf/autoload_configs/modules.conf.xml index f5627fe965..90d66f5798 100644 --- a/conf/autoload_configs/modules.conf.xml +++ b/conf/autoload_configs/modules.conf.xml @@ -1,113 +1,17 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/conf/autoload_configs/switch.conf.xml b/conf/autoload_configs/switch.conf.xml index 896dd0e712..7a68a7f2bd 100644 --- a/conf/autoload_configs/switch.conf.xml +++ b/conf/autoload_configs/switch.conf.xml @@ -15,11 +15,6 @@ - - - - - @@ -86,7 +81,6 @@ - diff --git a/conf/autoload_configs/voicemail.conf.xml b/conf/autoload_configs/voicemail.conf.xml index 06bd6f6dca..14ad98b41c 100644 --- a/conf/autoload_configs/voicemail.conf.xml +++ b/conf/autoload_configs/voicemail.conf.xml @@ -33,10 +33,9 @@ - --> - - - + + + diff --git a/conf/dialplan/default.xml b/conf/dialplan/default.xml index 42a3bcc31f..9e762b97a2 100644 --- a/conf/dialplan/default.xml +++ b/conf/dialplan/default.xml @@ -1,763 +1,88 @@ - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + +service + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/conf/sip_profiles/internal.xml b/conf/sip_profiles/internal.xml index 93558a3584..50833bfbec 100644 --- a/conf/sip_profiles/internal.xml +++ b/conf/sip_profiles/internal.xml @@ -42,26 +42,6 @@ - - - - - - diff --git a/conf/skinny_profiles/internal.xml b/conf/skinny_profiles/internal.xml index 52da89741d..5feac1ffbf 100644 --- a/conf/skinny_profiles/internal.xml +++ b/conf/skinny_profiles/internal.xml @@ -16,7 +16,7 @@ - + diff --git a/conf/vars.xml b/conf/vars.xml index fced2ef139..c638a80582 100644 --- a/conf/vars.xml +++ b/conf/vars.xml @@ -195,7 +195,7 @@ - + diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h index 052fbd4021..d8c0e48d2c 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h @@ -270,9 +270,11 @@ extern ftdm_sngisdn_data_t g_sngisdn_data; ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_span_t *span); /* Support functions */ -FT_DECLARE(uint32_t) get_unique_suInstId(int16_t cc_id); -FT_DECLARE(void) clear_call_data(sngisdn_chan_data_t *sngisdn_info); -FT_DECLARE(void) clear_call_glare_data(sngisdn_chan_data_t *sngisdn_info); +uint32_t get_unique_suInstId(int16_t cc_id); +void clear_call_data(sngisdn_chan_data_t *sngisdn_info); +void clear_call_glare_data(sngisdn_chan_data_t *sngisdn_info); +ftdm_status_t sngisdn_set_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail); +ftdm_status_t sngisdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t trace_opt); void stack_hdr_init(Header *hdr); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c index d8e6c8e00d..225244f57e 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c @@ -41,7 +41,6 @@ ftdm_status_t sngisdn_activate_phy(ftdm_span_t *span); ftdm_status_t sngisdn_deactivate_phy(ftdm_span_t *span); ftdm_status_t sngisdn_activate_cc(ftdm_span_t *span); -ftdm_status_t sngisdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t trace_opt); ftdm_status_t sngisdn_cntrl_q931(ftdm_span_t *span, uint8_t action, uint8_t subaction); ftdm_status_t sngisdn_cntrl_q921(ftdm_span_t *span, uint8_t action, uint8_t subaction); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c index 7e083073fd..7871debba4 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c @@ -39,7 +39,7 @@ ftdm_status_t sngisdn_check_free_ids(void); extern ftdm_sngisdn_data_t g_sngisdn_data; void get_memory_info(void); -FT_DECLARE(void) clear_call_data(sngisdn_chan_data_t *sngisdn_info) +void clear_call_data(sngisdn_chan_data_t *sngisdn_info) { uint32_t cc_id = ((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->cc_id; @@ -56,7 +56,7 @@ FT_DECLARE(void) clear_call_data(sngisdn_chan_data_t *sngisdn_info) return; } -FT_DECLARE(void) clear_call_glare_data(sngisdn_chan_data_t *sngisdn_info) +void clear_call_glare_data(sngisdn_chan_data_t *sngisdn_info) { ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_DEBUG, "Clearing glare data (suId:%d suInstId:%u spInstId:%u actv-suInstId:%u actv-spInstId:%u)\n", sngisdn_info->glare.suId, @@ -81,7 +81,7 @@ FT_DECLARE(void) clear_call_glare_data(sngisdn_chan_data_t *sngisdn_info) } -FT_DECLARE(uint32_t) get_unique_suInstId(int16_t cc_id) +uint32_t get_unique_suInstId(int16_t cc_id) { uint32_t suInstId; ftdm_assert_return((cc_id > 0 && cc_id <=MAX_VARIANTS), FTDM_FAIL, "Invalid cc_id\n"); @@ -103,7 +103,7 @@ FT_DECLARE(uint32_t) get_unique_suInstId(int16_t cc_id) return 0; } -FT_DECLARE(ftdm_status_t) get_ftdmchan_by_suInstId(int16_t cc_id, uint32_t suInstId, sngisdn_chan_data_t **sngisdn_data) +ftdm_status_t get_ftdmchan_by_suInstId(int16_t cc_id, uint32_t suInstId, sngisdn_chan_data_t **sngisdn_data) { ftdm_assert_return((cc_id > 0 && cc_id <=MAX_VARIANTS), FTDM_FAIL, "Invalid cc_id\n"); ftdm_assert_return(g_sngisdn_data.ccs[cc_id].activation_done, FTDM_FAIL, "Trying to find call on unconfigured CC\n"); @@ -115,7 +115,7 @@ FT_DECLARE(ftdm_status_t) get_ftdmchan_by_suInstId(int16_t cc_id, uint32_t suIns return FTDM_SUCCESS; } -FT_DECLARE(ftdm_status_t) get_ftdmchan_by_spInstId(int16_t cc_id, uint32_t spInstId, sngisdn_chan_data_t **sngisdn_data) +ftdm_status_t get_ftdmchan_by_spInstId(int16_t cc_id, uint32_t spInstId, sngisdn_chan_data_t **sngisdn_data) { ftdm_assert_return((cc_id > 0 && cc_id <=MAX_VARIANTS), FTDM_FAIL, "Invalid cc_id\n"); ftdm_assert_return(g_sngisdn_data.ccs[cc_id].activation_done, FTDM_FAIL, "Trying to find call on unconfigured CC\n"); @@ -147,7 +147,7 @@ ftdm_status_t sngisdn_set_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail) return FTDM_SUCCESS; } -FT_DECLARE(ftdm_status_t) cpy_calling_num_from_stack(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb) +ftdm_status_t cpy_calling_num_from_stack(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb) { if (cgPtyNmb->eh.pres != PRSNT_NODEF) { return FTDM_FAIL; @@ -174,7 +174,7 @@ FT_DECLARE(ftdm_status_t) cpy_calling_num_from_stack(ftdm_caller_data_t *ftdm, C return FTDM_SUCCESS; } -FT_DECLARE(ftdm_status_t) cpy_called_num_from_stack(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb) +ftdm_status_t cpy_called_num_from_stack(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb) { if (cdPtyNmb->eh.pres != PRSNT_NODEF) { return FTDM_FAIL; @@ -196,7 +196,7 @@ FT_DECLARE(ftdm_status_t) cpy_called_num_from_stack(ftdm_caller_data_t *ftdm, Cd return FTDM_SUCCESS; } -FT_DECLARE(ftdm_status_t) cpy_redir_num_from_stack(ftdm_caller_data_t *ftdm, RedirNmb *redirNmb) +ftdm_status_t cpy_redir_num_from_stack(ftdm_caller_data_t *ftdm, RedirNmb *redirNmb) { if (redirNmb->eh.pres != PRSNT_NODEF) { return FTDM_FAIL; @@ -216,7 +216,7 @@ FT_DECLARE(ftdm_status_t) cpy_redir_num_from_stack(ftdm_caller_data_t *ftdm, Red return FTDM_SUCCESS; } -FT_DECLARE(ftdm_status_t) cpy_calling_name_from_stack(ftdm_caller_data_t *ftdm, Display *display) +ftdm_status_t cpy_calling_name_from_stack(ftdm_caller_data_t *ftdm, Display *display) { if (display->eh.pres != PRSNT_NODEF) { return FTDM_FAIL; @@ -229,7 +229,7 @@ FT_DECLARE(ftdm_status_t) cpy_calling_name_from_stack(ftdm_caller_data_t *ftdm, return FTDM_SUCCESS; } -FT_DECLARE(ftdm_status_t) cpy_calling_num_from_user(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *ftdm) +ftdm_status_t cpy_calling_num_from_user(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *ftdm) { uint8_t len = strlen(ftdm->cid_num.digits); if (!len) { @@ -257,7 +257,7 @@ FT_DECLARE(ftdm_status_t) cpy_calling_num_from_user(CgPtyNmb *cgPtyNmb, ftdm_cal return FTDM_SUCCESS; } -FT_DECLARE(ftdm_status_t) cpy_called_num_from_user(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *ftdm) +ftdm_status_t cpy_called_num_from_user(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *ftdm) { uint8_t len = strlen(ftdm->dnis.digits); if (!len) { @@ -287,7 +287,7 @@ FT_DECLARE(ftdm_status_t) cpy_called_num_from_user(CdPtyNmb *cdPtyNmb, ftdm_call return FTDM_SUCCESS; } -FT_DECLARE(ftdm_status_t) cpy_redir_num_from_user(RedirNmb *redirNmb, ftdm_caller_data_t *ftdm) +ftdm_status_t cpy_redir_num_from_user(RedirNmb *redirNmb, ftdm_caller_data_t *ftdm) { uint8_t len = strlen(ftdm->rdnis.digits); if (!len) { @@ -319,7 +319,7 @@ FT_DECLARE(ftdm_status_t) cpy_redir_num_from_user(RedirNmb *redirNmb, ftdm_calle } -FT_DECLARE(ftdm_status_t) cpy_calling_name_from_user(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan) +ftm_status_t cpy_calling_name_from_user(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan) { uint8_t len; ftdm_caller_data_t *ftdm = &ftdmchan->caller_data; From 5c128405b836188ba02f989c0c682fb77c6de2f9 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Fri, 19 Nov 2010 14:41:26 -0500 Subject: [PATCH 041/237] Fix for windows compile errors introduced during previous merge --- .../ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h | 13 +++++++++++++ .../ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h index d8c0e48d2c..81a98cf0d3 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h @@ -273,6 +273,10 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_ uint32_t get_unique_suInstId(int16_t cc_id); void clear_call_data(sngisdn_chan_data_t *sngisdn_info); void clear_call_glare_data(sngisdn_chan_data_t *sngisdn_info); +ftdm_status_t get_ftdmchan_by_suInstId(int16_t cc_id, uint32_t suInstId, sngisdn_chan_data_t **sngisdn_data); +ftdm_status_t get_ftdmchan_by_spInstId(int16_t cc_id, uint32_t spInstId, sngisdn_chan_data_t **sngisdn_data); + + ftdm_status_t sngisdn_set_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail); ftdm_status_t sngisdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t trace_opt); @@ -354,6 +358,15 @@ void sngisdn_rcv_cc_ind(CcMngmt *status); void sngisdn_rcv_sng_log(uint8_t level, char *fmt,...); void sngisdn_rcv_sng_assert(char *message); +ftdm_status_t cpy_calling_num_from_stack(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb); +ftdm_status_t cpy_called_num_from_stack(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb); +ftdm_status_t cpy_redir_num_from_stack(ftdm_caller_data_t *ftdm, RedirNmb *redirNmb); +ftdm_status_t cpy_calling_name_from_stack(ftdm_caller_data_t *ftdm, Display *display); +ftdm_status_t cpy_calling_num_from_user(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *ftdm); +ftdm_status_t cpy_called_num_from_user(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *ftdm); +ftdm_status_t cpy_redir_num_from_user(RedirNmb *redirNmb, ftdm_caller_data_t *ftdm); +ftdm_status_t cpy_calling_name_from_user(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan); + uint8_t sngisdn_get_infoTranCap_from_stack(ftdm_bearer_cap_t bearer_capability); uint8_t sngisdn_get_usrInfoLyr1Prot_from_stack(ftdm_user_layer1_prot_t layer1_prot); ftdm_bearer_cap_t sngisdn_get_infoTranCap_from_user(uint8_t bearer_capability); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c index 7871debba4..056bf66ef2 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c @@ -319,7 +319,7 @@ ftdm_status_t cpy_redir_num_from_user(RedirNmb *redirNmb, ftdm_caller_data_t *ft } -ftm_status_t cpy_calling_name_from_user(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan) +ftdm_status_t cpy_calling_name_from_user(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan) { uint8_t len; ftdm_caller_data_t *ftdm = &ftdmchan->caller_data; From c74573cb16f8892666f16d36dbdc1fe1c5ef7c46 Mon Sep 17 00:00:00 2001 From: Michael S Collins Date: Fri, 19 Nov 2010 11:42:15 -0800 Subject: [PATCH 042/237] Strip whitespace from IP addresses in blacklist --- scripts/perl/blacklist.pl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/perl/blacklist.pl b/scripts/perl/blacklist.pl index 92fa55efe2..a2834b62bf 100755 --- a/scripts/perl/blacklist.pl +++ b/scripts/perl/blacklist.pl @@ -17,7 +17,8 @@ my @netblocks = split(/\n/, get("http://www.infiltrated.net/voipabuse/netblocks. print "\n"; foreach $addr (@addresses) { - next unless $addr =~ m/\d+\.\d+\.\d+\.\d+/; + $addr =~ s/\s//g; # strip whitespace + next unless $addr =~ m/\d+\.\d+\.\d+\.\d+/; # imperfect but useful IP addr check print " \n"; } print "\n"; @@ -25,7 +26,8 @@ print "\n"; print "\n"; foreach $netb (@netblocks) { - next unless $netb =~ m/\d+\.\d+\.\d+\.\d+/; + $netb =~ s/\s//g; # strip whitespace + next unless $netb =~ m/\d+\.\d+\.\d+\.\d+/; # imperfect but useful IP addr check print " \n"; } print "\n"; From 6c4f49a888f5953f977816fc9e2a9ce4ec8e1400 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 19 Nov 2010 13:46:01 -0600 Subject: [PATCH 043/237] apparently some sip device vendors did not read the RFC (who knew?) adding verbose_sdp=true var to add needless a= lines for standard iana codecs that explicitly do not require them --- src/mod/endpoints/mod_sofia/sofia_glue.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 6e9aacb126..fa828607bd 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -187,7 +187,7 @@ void sofia_glue_set_image_sdp(private_object_t *tech_pvt, switch_t38_options_t * static void generate_m(private_object_t *tech_pvt, char *buf, size_t buflen, switch_port_t port, - int cur_ptime, const char *append_audio, const char *sr, int use_cng, int cng_type, switch_event_t *map) + int cur_ptime, const char *append_audio, const char *sr, int use_cng, int cng_type, switch_event_t *map, int verbose_sdp) { int i = 0; int rate; @@ -298,7 +298,7 @@ static void generate_m(private_object_t *tech_pvt, char *buf, size_t buflen, } } - if (tech_pvt->ianacodes[i] > 95) { + if (tech_pvt->ianacodes[i] > 95 || verbose_sdp) { switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d %s/%d\n", tech_pvt->ianacodes[i], imp->iananame, rate); } @@ -373,6 +373,7 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, uint32 const char *fmtp_out_var = switch_channel_get_variable(tech_pvt->channel, "sip_force_audio_fmtp"); switch_event_t *map = NULL, *ptmap = NULL; const char *b_sdp = NULL; + int verbose_sdp = 0; sofia_glue_check_dtmf_type(tech_pvt); @@ -396,6 +397,10 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, uint32 fmtp_out = fmtp_out_var; } + if ((val = switch_channel_get_variable(tech_pvt->channel, "verbose_sdp")) && switch_true(val)) { + verbose_sdp = 1; + } + if (sofia_test_pflag(tech_pvt->profile, PFLAG_SUPPRESS_CNG) || ((val = switch_channel_get_variable(tech_pvt->channel, "supress_cng")) && switch_true(val)) || ((val = switch_channel_get_variable(tech_pvt->channel, "suppress_cng")) && switch_true(val))) { @@ -533,7 +538,7 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, uint32 } if (!switch_true(switch_channel_get_variable(tech_pvt->channel, "sdp_m_per_ptime"))) { - generate_m(tech_pvt, buf, sizeof(buf), port, 0, append_audio, sr, use_cng, cng_type, map); + generate_m(tech_pvt, buf, sizeof(buf), port, 0, append_audio, sr, use_cng, cng_type, map, verbose_sdp); } else { for (i = 0; i < tech_pvt->num_codecs; i++) { @@ -547,7 +552,7 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, uint32 if (cur_ptime != this_ptime) { cur_ptime = this_ptime; - generate_m(tech_pvt, buf, sizeof(buf), port, cur_ptime, append_audio, sr, use_cng, cng_type, map); + generate_m(tech_pvt, buf, sizeof(buf), port, cur_ptime, append_audio, sr, use_cng, cng_type, map, verbose_sdp); } } From f61051af9118ffb67679b8f5634b318194cdbd88 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 19 Nov 2010 14:15:55 -0600 Subject: [PATCH 044/237] silly git needs old-school format param to remain back-compat --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 944511dac9..aeb31eca01 100644 --- a/Makefile.am +++ b/Makefile.am @@ -374,7 +374,7 @@ src/include/switch_version.h: src/include/switch_version.h.in .version $(libfree touch .version ; \ else \ if [ -d .git ] ; then \ - version=`git log --format="%h %ci" -1 HEAD | head -1 | sed -e 's|:|-|g' || echo hacked` ; \ + version=`git log --pretty=format:"%h %ci" -1 HEAD | head -1 | sed -e 's|:|-|g' || echo hacked` ; \ if [ "x$$version" = "xhacked" ] ; then \ version="hacked-`date -u +%Y%m%dT%H%M%SZ`" ; \ else \ From 5973679e3536e50175176b26e29177a409580147 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 19 Nov 2010 14:47:45 -0600 Subject: [PATCH 045/237] fix passing of callee-id --- src/mod/endpoints/mod_sofia/sofia.c | 32 +++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 9cc515ed9c..e749abdc01 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -666,21 +666,32 @@ void sofia_update_callee_id(switch_core_session_t *session, sofia_profile_t *pro } } } - + if (((tmp = switch_channel_get_variable(channel, "effective_callee_id_name")) || - (tmp = switch_channel_get_variable(channel, "sip_callee_id_name")) || - (tmp = switch_channel_get_variable(channel, "callee_id_name"))) && !zstr(tmp)) { + (tmp = switch_channel_get_variable(channel, "sip_callee_id_name"))) && !zstr(tmp)) { name = (char *) tmp; } if (((tmp = switch_channel_get_variable(channel, "effective_callee_id_number")) || - (tmp = switch_channel_get_variable(channel, "sip_callee_id_number")) || - (tmp = switch_channel_get_variable(channel, "callee_id_number"))) && !zstr(tmp)) { + (tmp = switch_channel_get_variable(channel, "sip_callee_id_number"))) && !zstr(tmp)) { number = tmp; } - if (zstr(name)) + if (zstr(number)) { + if ((tmp = switch_channel_get_variable(channel, "callee_id_number")) && !zstr(tmp)) { + number = (char *) tmp; + } + } + + if (zstr(name)) { + if ((tmp = switch_channel_get_variable(channel, "callee_id_name")) && !zstr(tmp)) { + name = (char *) tmp; + } + } + + if (zstr(name)) { name = (char *) number; + } if (zstr(name) && zstr(number)) { goto end; @@ -5947,7 +5958,12 @@ void sofia_handle_sip_i_info(nua_t *nua, sofia_profile_t *profile, nua_handle_t /* Barf if we didn't get our private */ assert(switch_core_session_get_private(session)); - + + if (!strncasecmp(sip->sip_content_type->c_type, "message", 7) && !strcasecmp(sip->sip_content_type->c_subtype, "update_display")) { + sofia_update_callee_id(session, profile, sip, SWITCH_TRUE); + goto end; + } + if (sip && sip->sip_content_type && sip->sip_content_type->c_type && sip->sip_content_type->c_subtype && sip->sip_payload && sip->sip_payload->pl_data) { if (!strncasecmp(sip->sip_content_type->c_type, "application", 11) && !strcasecmp(sip->sip_content_type->c_subtype, "media_control+xml")) { @@ -6000,8 +6016,6 @@ void sofia_handle_sip_i_info(nua_t *nua, sofia_profile_t *profile, nua_handle_t } else if (!strncasecmp(sip->sip_content_type->c_type, "application", 11) && !strcasecmp(sip->sip_content_type->c_subtype, "dtmf")) { int tmp = atoi(sip->sip_payload->pl_data); dtmf.digit = switch_rfc2833_to_char(tmp); - } else if (!strncasecmp(sip->sip_content_type->c_type, "message", 11) && !strcasecmp(sip->sip_content_type->c_subtype, "update_display")) { - sofia_update_callee_id(session, profile, sip, SWITCH_TRUE); } else { goto end; } From 53c41c0463a332447fd5cf1007265dc45446beec Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Sat, 20 Nov 2010 10:25:02 -0500 Subject: [PATCH 046/237] freetdm: ISDN - Fix for main loop going to sleep without processing events from IO module --- libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c index 56efcb491c..cb96107ac3 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c @@ -431,6 +431,7 @@ static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj) /* Poll for events, e.g HW DTMF */ ftdm_sangoma_isdn_poll_events(span); + ftdm_span_trigger_signals(span); if (ftdm_sched_get_time_to_next_timer(signal_data->sched, &sleep) == FTDM_SUCCESS) { if (sleep < 0 || sleep > SNGISDN_EVENT_POLL_RATE) { From a9a31041d47b89c7837ea3bca705da91b40f6d48 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Sat, 20 Nov 2010 18:18:37 -0500 Subject: [PATCH 047/237] freetdm: added wait_dialtone_timeout parameter for ftmod_analog if this parameter is set to 0 ftmod_analog will not wait for dial tone before dialing out the requested number. Anything bigger than 0 is the units in milliseconds to wait for dialtone before aborting the call. --- libs/freetdm/src/ftdm_threadmutex.c | 4 +- .../src/ftmod/ftmod_analog/ftdm_analog.h | 1 + .../src/ftmod/ftmod_analog/ftmod_analog.c | 69 +++++++++++++------ 3 files changed, 51 insertions(+), 23 deletions(-) diff --git a/libs/freetdm/src/ftdm_threadmutex.c b/libs/freetdm/src/ftdm_threadmutex.c index 1271d80f4a..b1884ec587 100644 --- a/libs/freetdm/src/ftdm_threadmutex.c +++ b/libs/freetdm/src/ftdm_threadmutex.c @@ -417,7 +417,7 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_destroy(ftdm_interrupt_t **ininterrupt) FT_DECLARE(ftdm_status_t) ftdm_interrupt_multiple_wait(ftdm_interrupt_t *interrupts[], ftdm_size_t size, int ms) { int numdevices = 0; - unsigned i; + unsigned i = 0; #if defined(__WINDOWS__) DWORD res = 0; @@ -496,6 +496,8 @@ pollagain: } } #else + /* for MacOS compilation, unused vars */ + numdevices = i; #endif return FTDM_SUCCESS; } diff --git a/libs/freetdm/src/ftmod/ftmod_analog/ftdm_analog.h b/libs/freetdm/src/ftmod/ftmod_analog/ftdm_analog.h index 487829fd7b..2c79822b29 100644 --- a/libs/freetdm/src/ftmod/ftmod_analog/ftdm_analog.h +++ b/libs/freetdm/src/ftmod/ftmod_analog/ftdm_analog.h @@ -46,6 +46,7 @@ typedef enum { struct ftdm_analog_data { uint32_t flags; uint32_t max_dialstr; + uint32_t wait_dialtone_timeout; uint32_t digit_timeout; char hotline[FTDM_MAX_HOTLINE_STR]; }; diff --git a/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c b/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c index dacda7e448..fc9bea6ef0 100644 --- a/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c +++ b/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c @@ -49,13 +49,16 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj); */ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(analog_fxo_outgoing_call) { + ftdm_analog_data_t *analog_data = ftdmchan->span->signal_data; if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK) && !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INTHREAD)) { ftdm_channel_clear_needed_tones(ftdmchan); ftdm_channel_clear_detected_tones(ftdmchan); ftdm_channel_command(ftdmchan, FTDM_COMMAND_OFFHOOK, NULL); ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_PROGRESS_DETECT, NULL); - ftdmchan->needed_tones[FTDM_TONEMAP_DIAL] = 1; + if (analog_data->wait_dialtone_timeout) { + ftdmchan->needed_tones[FTDM_TONEMAP_DIAL] = 1; + } ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DIALING); ftdm_thread_create_detached(ftdm_analog_channel_run, ftdmchan); return FTDM_SUCCESS; @@ -157,6 +160,7 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_configure_span) const char *tonemap = "us"; const char *hotline = ""; uint32_t digit_timeout = 10; + uint32_t wait_dialtone_timeout = 30000; uint32_t max_dialstr = MAX_DTMF; const char *var, *val; int *intval; @@ -191,6 +195,15 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_configure_span) break; } digit_timeout = *intval; + } else if (!strcasecmp(var, "wait_dialtone_timeout")) { + if (!(intval = va_arg(ap, int *))) { + break; + } + wait_dialtone_timeout = *intval; + if (wait_dialtone_timeout < 0) { + wait_dialtone_timeout = 0; + } + ftdm_log_chan(span->channels[i], FTDM_LOG_DEBUG, "Wait dial tone ms = %d\n", wait_dialtone_timeout); } else if (!strcasecmp(var, "enable_callerid")) { if (!(val = va_arg(ap, char *))) { break; @@ -221,7 +234,6 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_configure_span) } } - if (digit_timeout < 2000 || digit_timeout > 10000) { digit_timeout = 2000; } @@ -241,6 +253,7 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_configure_span) span->stop = ftdm_analog_stop; analog_data->flags = flags; analog_data->digit_timeout = digit_timeout; + analog_data->wait_dialtone_timeout = wait_dialtone_timeout; analog_data->max_dialstr = max_dialstr; span->signal_cb = sig_cb; strncpy(analog_data->hotline, hotline, sizeof(analog_data->hotline)); @@ -325,6 +338,27 @@ static void send_caller_id(ftdm_channel_t *ftdmchan) ftdm_channel_send_fsk_data(ftdmchan, &fsk_data, -14); } +static void analog_dial(ftdm_channel_t *ftdmchan, uint32_t *state_counter, uint32_t *dial_timeout) +{ + if (ftdm_strlen_zero(ftdmchan->caller_data.dnis.digits)) { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "No Digits to send!\n"); + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY); + } else { + if (ftdm_channel_command(ftdmchan, FTDM_COMMAND_SEND_DTMF, ftdmchan->caller_data.dnis.digits) != FTDM_SUCCESS) { + ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Send Digits Failed [%s]\n", ftdmchan->last_error); + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY); + } else { + *state_counter = 0; + ftdmchan->needed_tones[FTDM_TONEMAP_RING] = 1; + ftdmchan->needed_tones[FTDM_TONEMAP_BUSY] = 1; + ftdmchan->needed_tones[FTDM_TONEMAP_FAIL1] = 1; + ftdmchan->needed_tones[FTDM_TONEMAP_FAIL2] = 1; + ftdmchan->needed_tones[FTDM_TONEMAP_FAIL3] = 1; + *dial_timeout = ((ftdmchan->dtmf_on + ftdmchan->dtmf_off) * strlen(ftdmchan->caller_data.dnis.digits)) + 2000; + } + } +} + /** * \brief Main thread function for analog channel (outgoing call) * \param me Current thread @@ -342,7 +376,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj) ftdm_size_t dtmf_offset = 0; ftdm_analog_data_t *analog_data = ftdmchan->span->signal_data; ftdm_channel_t *closed_chan; - uint32_t state_counter = 0, elapsed = 0, collecting = 0, interval = 0, last_digit = 0, indicate = 0, dial_timeout = 30000; + uint32_t state_counter = 0, elapsed = 0, collecting = 0, interval = 0, last_digit = 0, indicate = 0, dial_timeout = analog_data->wait_dialtone_timeout; ftdm_sigmsg_t sig; ftdm_status_t status; @@ -383,7 +417,11 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj) sig.span_id = ftdmchan->span_id; sig.channel = ftdmchan; - assert(interval != 0); + ftdm_assert(interval != 0, NULL); + + if (!dial_timeout) { + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Not waiting for dial tone to dial number %s\n", ftdmchan->caller_data.dnis.digits); + } while (ftdm_running() && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INTHREAD)) { ftdm_wait_flag_t flags = FTDM_READ; @@ -412,7 +450,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj) } else { ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP); } - } + } } break; case FTDM_CHANNEL_STATE_GENRING: @@ -730,28 +768,15 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj) ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Failure indication detected!\n"); ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY); } else if (ftdmchan->detected_tones[FTDM_TONEMAP_DIAL]) { - if (ftdm_strlen_zero(ftdmchan->caller_data.dnis.digits)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "No Digits to send!\n"); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY); - } else { - if (ftdm_channel_command(ftdmchan, FTDM_COMMAND_SEND_DTMF, ftdmchan->caller_data.dnis.digits) != FTDM_SUCCESS) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Send Digits Failed [%s]\n", ftdmchan->last_error); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY); - } else { - state_counter = 0; - ftdmchan->needed_tones[FTDM_TONEMAP_RING] = 1; - ftdmchan->needed_tones[FTDM_TONEMAP_BUSY] = 1; - ftdmchan->needed_tones[FTDM_TONEMAP_FAIL1] = 1; - ftdmchan->needed_tones[FTDM_TONEMAP_FAIL2] = 1; - ftdmchan->needed_tones[FTDM_TONEMAP_FAIL3] = 1; - dial_timeout = ((ftdmchan->dtmf_on + ftdmchan->dtmf_off) * strlen(ftdmchan->caller_data.dnis.digits)) + 2000; - } - } + analog_dial(ftdmchan, &state_counter, &dial_timeout); } else if (ftdmchan->detected_tones[FTDM_TONEMAP_RING]) { ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP); } ftdm_channel_clear_detected_tones(ftdmchan); + } else if (!dial_timeout) { + /* we were requested not to wait for dial tone, we can dial immediately */ + analog_dial(ftdmchan, &state_counter, &dial_timeout); } if ((ftdmchan->dtmf_buffer && ftdm_buffer_inuse(ftdmchan->dtmf_buffer)) || (ftdmchan->fsk_buffer && ftdm_buffer_inuse(ftdmchan->fsk_buffer))) { From 6dfd39c5f3186000b08a1fa500a98a4a04d65724 Mon Sep 17 00:00:00 2001 From: Brian West Date: Sun, 21 Nov 2010 12:01:48 -0600 Subject: [PATCH 048/237] log ip too --- src/mod/endpoints/mod_sofia/sofia_reg.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index 571c1673eb..4bb879659c 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -1115,7 +1115,8 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand if (auth_res != AUTH_OK && !stale) { if (profile->debug) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Send %s for [%s@%s]\n", forbidden ? "forbidden" : "challenge", to_user, to_host); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Send %s for [%s@%s] from ip '%s'\n", + forbidden ? "forbidden" : "challenge", to_user, to_host, network_ip); } if (auth_res == AUTH_FORBIDDEN) { nua_respond(nh, SIP_403_FORBIDDEN, NUTAG_WITH_THIS(nua), TAG_END()); From 90c156243c89f582d242f13f332a6360659812e6 Mon Sep 17 00:00:00 2001 From: Brian West Date: Mon, 22 Nov 2010 10:10:26 -0600 Subject: [PATCH 049/237] FS-2862: fix seg --- src/mod/endpoints/mod_sofia/sofia.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index e749abdc01..580334a46f 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -5959,7 +5959,9 @@ void sofia_handle_sip_i_info(nua_t *nua, sofia_profile_t *profile, nua_handle_t /* Barf if we didn't get our private */ assert(switch_core_session_get_private(session)); - if (!strncasecmp(sip->sip_content_type->c_type, "message", 7) && !strcasecmp(sip->sip_content_type->c_subtype, "update_display")) { + if (sip->sip_content_type && + !strncasecmp(sip->sip_content_type->c_type, "message", 7) && + !strcasecmp(sip->sip_content_type->c_subtype, "update_display")) { sofia_update_callee_id(session, profile, sip, SWITCH_TRUE); goto end; } From cf398e1a442bc54c05d68837fcad6258cecc7dfe Mon Sep 17 00:00:00 2001 From: Brian West Date: Mon, 22 Nov 2010 14:59:25 -0600 Subject: [PATCH 050/237] FS-535: tested but please test MORE. --- src/mod/endpoints/mod_sofia/mod_sofia.h | 1 + src/mod/endpoints/mod_sofia/sofia_glue.c | 36 +++++++++++++++++++++++- src/mod/endpoints/mod_sofia/sofia_reg.c | 33 +++++++++++++++++++--- 3 files changed, 65 insertions(+), 5 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 750fb60c15..c1244c05f1 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -957,6 +957,7 @@ void sofia_presence_event_thread_start(void); void sofia_reg_expire_call_id(sofia_profile_t *profile, const char *call_id, int reboot); switch_status_t sofia_glue_tech_choose_video_port(private_object_t *tech_pvt, int force); switch_status_t sofia_glue_tech_set_video_codec(private_object_t *tech_pvt, int force); +char *sofia_glue_get_register_host(const char *uri); const char *sofia_glue_strip_proto(const char *uri); switch_status_t reconfig_sofia(sofia_profile_t *profile); void sofia_glue_del_gateway(sofia_gateway_t *gp); diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index fa828607bd..23d3f2904e 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -5734,6 +5734,41 @@ char *sofia_glue_execute_sql2str(sofia_profile_t *profile, switch_mutex_t *mutex return ret; } +char *sofia_glue_get_register_host(const char *uri) +{ + char *register_host = NULL; + const char *s; + char *p = NULL; + + if ((s = switch_stristr("sip:", uri))) { + s += 4; + } else if ((s = switch_stristr("sips:", uri))) { + s += 5; + } + + if (!s) { + return NULL; + } + + register_host = strdup(s); + + /* remove port for register_host for testing nat acl take into account + ipv6 addresses which are required to have brackets around the addr + */ + if ((p = strchr(register_host, ']')) && (*(p + 1) == ':')) { + *(p + 1) = '\0'; + } else { + if ((p = strrchr(register_host, ':'))) { + *p = '\0'; + } + } + + /* register_proxy should always start with "sip:" or "sips:" */ + assert(register_host); + + return register_host; +} + const char *sofia_glue_strip_proto(const char *uri) { char *p; @@ -5983,7 +6018,6 @@ void sofia_glue_tech_simplify(private_object_t *tech_pvt) } } - void sofia_glue_build_vid_refresh_message(switch_core_session_t *session, const char *pl) { switch_core_session_message_t *msg; diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index 4bb879659c..14a7bfdd2c 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -142,16 +142,22 @@ void sofia_sub_check_gateway(sofia_profile_t *profile, time_t now) int ss_state = nua_callstate_authenticating; sub_state_t ostate = gw_sub_ptr->state; char *user_via = NULL; + char *register_host = NULL; if (!now) { gw_sub_ptr->state = ostate = SUB_STATE_UNSUBED; gw_sub_ptr->expires_str = "0"; } - if (sofia_glue_check_nat(gateway_ptr->profile, gateway_ptr->register_proxy)) { + register_host = sofia_glue_get_register_host(gateway_ptr->register_proxy); + + /* check for NAT and place a Via header if necessary (hostname or non-local IP) */ + if (sofia_glue_check_nat(gateway_ptr->profile, register_host)) { user_via = sofia_glue_create_external_via(NULL, gateway_ptr->profile, gateway_ptr->register_transport); } + switch_safe_free(register_host); + switch (ostate) { case SUB_STATE_NOSUB: break; @@ -189,7 +195,15 @@ void sofia_sub_check_gateway(sofia_profile_t *profile, time_t now) nua_handle_bind(gateway_ptr->nh, gateway_ptr->sofia_private); if (now) { - nua_subscribe(gateway_ptr->sub_nh, NUTAG_URL(gateway_ptr->register_url), TAG_IF(user_via, SIPTAG_VIA_STR(user_via)), SIPTAG_EVENT_STR(gw_sub_ptr->event), SIPTAG_ACCEPT_STR(gw_sub_ptr->content_type), SIPTAG_TO_STR(gateway_ptr->register_from), SIPTAG_FROM_STR(gateway_ptr->register_from), SIPTAG_CONTACT_STR(gateway_ptr->register_contact), SIPTAG_EXPIRES_STR(gw_sub_ptr->expires_str), // sofia stack bases its auto-refresh stuff on this + nua_subscribe(gateway_ptr->sub_nh, + NUTAG_URL(gateway_ptr->register_url), + TAG_IF(user_via, SIPTAG_VIA_STR(user_via)), + SIPTAG_EVENT_STR(gw_sub_ptr->event), + SIPTAG_ACCEPT_STR(gw_sub_ptr->content_type), + SIPTAG_TO_STR(gateway_ptr->register_from), + SIPTAG_FROM_STR(gateway_ptr->register_from), + SIPTAG_CONTACT_STR(gateway_ptr->register_contact), + SIPTAG_EXPIRES_STR(gw_sub_ptr->expires_str), /* sofia stack bases its auto-refresh stuff on this */ TAG_NULL()); gw_sub_ptr->retry = now + gw_sub_ptr->retry_seconds; } else { @@ -266,6 +280,7 @@ void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now) for (gateway_ptr = profile->gateways; gateway_ptr; gateway_ptr = gateway_ptr->next) { reg_state_t ostate = gateway_ptr->state; char *user_via = NULL; + char *register_host = NULL; if (!now) { gateway_ptr->state = ostate = REG_STATE_UNREGED; @@ -277,10 +292,15 @@ void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now) nua_handle_t *nh = nua_handle(profile->nua, NULL, NUTAG_URL(gateway_ptr->register_url), TAG_END()); sofia_private_t *pvt; - if (sofia_glue_check_nat(gateway_ptr->profile, gateway_ptr->register_proxy)) { + register_host = sofia_glue_get_register_host(gateway_ptr->register_proxy); + + /* check for NAT and place a Via header if necessary (hostname or non-local IP) */ + if (sofia_glue_check_nat(gateway_ptr->profile, register_host)) { user_via = sofia_glue_create_external_via(NULL, gateway_ptr->profile, gateway_ptr->register_transport); } + switch_safe_free(register_host); + pvt = malloc(sizeof(*pvt)); switch_assert(pvt); memset(pvt, 0, sizeof(*pvt)); @@ -335,10 +355,15 @@ void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now) sofia_reg_new_handle(gateway_ptr, now ? 1 : 0); } - if (sofia_glue_check_nat(gateway_ptr->profile, gateway_ptr->register_proxy)) { + register_host = sofia_glue_get_register_host(gateway_ptr->register_proxy); + + /* check for NAT and place a Via header if necessary (hostname or non-local IP) */ + if (sofia_glue_check_nat(gateway_ptr->profile, register_host)) { user_via = sofia_glue_create_external_via(NULL, gateway_ptr->profile, gateway_ptr->register_transport); } + switch_safe_free(register_host); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Registering %s\n", gateway_ptr->name); if (now) { From 22047f93377fac0c763934603001085428f74d3e Mon Sep 17 00:00:00 2001 From: Brian West Date: Mon, 22 Nov 2010 15:24:22 -0600 Subject: [PATCH 051/237] FS-2862: fix seg more --- src/mod/endpoints/mod_sofia/sofia.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 580334a46f..32d25d0ad6 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -5959,7 +5959,7 @@ void sofia_handle_sip_i_info(nua_t *nua, sofia_profile_t *profile, nua_handle_t /* Barf if we didn't get our private */ assert(switch_core_session_get_private(session)); - if (sip->sip_content_type && + if (sip->sip_content_type && sip->sip_content_type->c_subtype && sip->sip_content_type->c_type && !strncasecmp(sip->sip_content_type->c_type, "message", 7) && !strcasecmp(sip->sip_content_type->c_subtype, "update_display")) { sofia_update_callee_id(session, profile, sip, SWITCH_TRUE); From 87edbed6bbcdb351b9502f66e78b01116ae1ab00 Mon Sep 17 00:00:00 2001 From: Brian West Date: Mon, 22 Nov 2010 15:32:23 -0600 Subject: [PATCH 052/237] FS-535: be more careful and catch ipv6 edge case --- src/mod/endpoints/mod_sofia/sofia_glue.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 23d3f2904e..57a2bfaa6a 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -5740,6 +5740,10 @@ char *sofia_glue_get_register_host(const char *uri) const char *s; char *p = NULL; + if (zstr(uri)) { + return NULL; + } + if ((s = switch_stristr("sip:", uri))) { s += 4; } else if ((s = switch_stristr("sips:", uri))) { @@ -5755,9 +5759,12 @@ char *sofia_glue_get_register_host(const char *uri) /* remove port for register_host for testing nat acl take into account ipv6 addresses which are required to have brackets around the addr */ - if ((p = strchr(register_host, ']')) && (*(p + 1) == ':')) { - *(p + 1) = '\0'; - } else { + + if ((p = strchr(register_host, ']'))) { + if (*(p + 1) == ':') { + *(p + 1) = '\0'; + } + } else { if ((p = strrchr(register_host, ':'))) { *p = '\0'; } From 89dbe0b0a09fa52f47f24884c969d1ed3ef6b6e8 Mon Sep 17 00:00:00 2001 From: Brian West Date: Mon, 22 Nov 2010 17:06:59 -0600 Subject: [PATCH 053/237] ESL-52 --- .../event_handlers/mod_event_socket/mod_event_socket.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mod/event_handlers/mod_event_socket/mod_event_socket.c b/src/mod/event_handlers/mod_event_socket/mod_event_socket.c index 941db22c84..ee7cfc9eaf 100644 --- a/src/mod/event_handlers/mod_event_socket/mod_event_socket.c +++ b/src/mod/event_handlers/mod_event_socket/mod_event_socket.c @@ -691,7 +691,7 @@ SWITCH_STANDARD_API(event_sink_function) switch_mutex_lock(listener->filter_mutex); if (!listener->filters) { - switch_event_create_plain(&listener->filters, SWITCH_EVENT_CHANNEL_DATA); + switch_event_create_plain(&listener->filters, SWITCH_EVENT_CLONE); } if (!strcasecmp(action, "delete")) { @@ -702,7 +702,7 @@ SWITCH_STANDARD_API(event_sink_function) if (!strcasecmp(header_val, "all")) { switch_event_destroy(&listener->filters); - switch_event_create_plain(&listener->filters, SWITCH_EVENT_CHANNEL_DATA); + switch_event_create_plain(&listener->filters, SWITCH_EVENT_CLONE); } else { switch_event_del_header(listener->filters, header_val); } @@ -1744,7 +1744,7 @@ static switch_status_t parse_command(listener_t *listener, switch_event_t **even switch_mutex_lock(listener->filter_mutex); if (!listener->filters) { - switch_event_create_plain(&listener->filters, SWITCH_EVENT_CHANNEL_DATA); + switch_event_create_plain(&listener->filters, SWITCH_EVENT_CLONE); } if (!strcasecmp(header_name, "delete") && header_val) { @@ -1754,7 +1754,7 @@ static switch_status_t parse_command(listener_t *listener, switch_event_t **even } if (!strcasecmp(header_name, "all")) { switch_event_destroy(&listener->filters); - switch_event_create_plain(&listener->filters, SWITCH_EVENT_CHANNEL_DATA); + switch_event_create_plain(&listener->filters, SWITCH_EVENT_CLONE); } else { switch_event_del_header_val(listener->filters, header_name, header_val); } From c109a89e4e81c57963c3cde28774243fce4203ed Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Mon, 22 Nov 2010 21:49:33 -0600 Subject: [PATCH 054/237] VS2010 fix initial build dependency --- libs/unimrcp/modules/mrcp-sofiasip/mrcpsofiasip.2010.vcxproj | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libs/unimrcp/modules/mrcp-sofiasip/mrcpsofiasip.2010.vcxproj b/libs/unimrcp/modules/mrcp-sofiasip/mrcpsofiasip.2010.vcxproj index c6aaba5cd6..b3931497c7 100644 --- a/libs/unimrcp/modules/mrcp-sofiasip/mrcpsofiasip.2010.vcxproj +++ b/libs/unimrcp/modules/mrcp-sofiasip/mrcpsofiasip.2010.vcxproj @@ -127,6 +127,11 @@ + + + {70a49bc2-7500-41d0-b75d-edcc5be987a0} + + From ec8f2c2bc2b65457ab6c6684769463f54125d62e Mon Sep 17 00:00:00 2001 From: Michael S Collins Date: Mon, 22 Nov 2010 22:00:36 -0800 Subject: [PATCH 055/237] scripts: add_user - cmd line utility that lets admin create new users very easily. --- scripts/perl/add_user | 306 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 306 insertions(+) create mode 100755 scripts/perl/add_user diff --git a/scripts/perl/add_user b/scripts/perl/add_user new file mode 100755 index 0000000000..d16ebb5efe --- /dev/null +++ b/scripts/perl/add_user @@ -0,0 +1,306 @@ +#!/usr/bin/perl +# +# add_user +# +# Add one or more users to the XML directory +# +# + +use strict; +use warnings; +use Getopt::Long; +use Data::Dumper; + +## Useful items +my $path_sep; +my $config_path; +my @dir_elem; +my $user_template = &get_user_template; +my $new_user_count = 0; + +## Command line args +my $users; +my $domain; +my $dirpath; +my $help; + +## Misc items somewhat related to cmd line args +my $start; +my $end; +my $user; + +## Check for Windows vs. *nix +if ( $^O =~ m/^win/i ) { + ## Detected Windows (probably) + $path_sep = "\\"; # single backslash (\) + use File::Spec::Win32; +} else { + $path_sep = '/'; # single slash (/) + use File::Spec; +} + +GetOptions( + 'h' => \$help, + 'help' => \$help, + 'domain=s' => \$domain, + 'users=s' => \$users, + 'confpath=s' => \$config_path, +); + +if ( $help ) { + usage(); + exit(0); +} + +if ( ! $domain ) { + $domain='default'; +} + +## Validate users if specified on command line +if ( $users ) { + ($start,$end) = split /-/,$users; + if ( ! $start && ! $end ) { + die "Please specify both a start and end range, separated by a hyphen:\n add_user --users=xxxx-yyyy\n"; + } + + unless ( $start =~ m/[1-9]\d+/ ) { + die "Start of range '$start' is not numeric or is too short\n"; + } + + unless ( $end =~ m/[1-9]\d+/ ) { + die "End of range '$end' is not numberic or is too short\n"; + } + + if ( $end <= $start ) { + die "End of range needs to be greater than start of range\n"; + } +} else { + ## Look for user id in $ARGV[0] + if ( ! $ARGV[0] ) { + die "You must specify user id as a command line argument to add user, or use the --users option.\n"; + } + unless ( $ARGV[0] =~ m/^[1-9]\d+$/ ) { + die "User id must be numeric, be at least 2 digits long, and cannot begin with the digit zero.\n" + } + $user = $ARGV[0]; +} + +if ( ! $config_path ) { + $config_path = '/usr/local/freeswitch/conf'; +} + +## Check to make sure the directories in question exists +unless ( -d $config_path ) { + die "Configuration path '$config_path' does not exist.\n"; +} + +my $directory_path = $config_path . $path_sep . 'directory'; +unless ( -d $directory_path ) { + die "Directory path '$directory_path' does not exist.\n"; +} + +## Now check domain pathname and test existence +if ( ! $domain ) { + $domain = 'default'; +} + +## Full directory path includes the domain name +my $full_dir_path = $directory_path . $path_sep . $domain; +unless ( -d $full_dir_path ) { + die "Full path to directory and domain '$full_dir_path' does not exist. \n"; +} + +unless ( -w $full_dir_path ) { + die "This user does not have write access to '$full_dir_path'.\n"; +} +print "\n"; + +## Regexp assemble items to show user what a PCRE might look like for his new users +my $ra_present; +my $ra_new; +my $ra_all; +eval { require Regexp::Assemble; }; +if ( ! $@ ) { + ## If Regexp::Assemble is available flag it for later building regexes + $ra_present = 'true'; + $ra_new = Regexp::Assemble->new( # new user regex + reduce => 1, + flags => 0, +); + $ra_all = Regexp::Assemble->new( # all users regex w/ new users thrown in + reduce => 1, + flags => 0, +); +} + +## If we're this far then we can read in the existing users and put them in a hash +## Later we can check hash to avoid adding duplicate users +my %current_users; +my @CURRENT_USER_FILES = glob($full_dir_path . $path_sep . '*.xml'); +foreach ( @CURRENT_USER_FILES ) { + #print "User: $_\n"; + open(FILEIN,'<',$_); + while() { + next unless m/user id|number-alias/; + m/user id="(\d+)"/; + my $user_id = $1; + if ( ! $user_id ) { + m/alias="(\d+)"/; + $user_id = $1; + } + + next unless $user_id; + $current_users{$user_id}++; + + if ( $ra_present && $user_id =~ m/^\d+$/ ) { + #print "Adding $user_id to \$re_all...\n"; + $ra_all->add($user_id)->anchor_line_begin->anchor_line_end; + } + last; + } + close(FILEIN); +} + +#print Dumper(%current_users) . "\n"; +if ( $start && $end ) { + ## Add range of users + foreach $user ($start .. $end) { + &add_user($user); + } +} else { + ## Add single user + &add_user($user); +} + +print "\nOperation complete. "; +if ( $new_user_count == 0 ) { + print "No users added.\n"; + exit(0); +} else { + printf "%d user%s added.\n", $new_user_count, $new_user_count==1 ? "" : "s"; + print "Be sure to reloadxml.\n\n"; +} + +if ( $ra_present ) { + print "Regular expression information:\n\n"; + ## Regexp::Assemble adds some stuff we really don't need + ## These lines just make the regexp pattern a bit more readable + my $tmp = $ra_new->as_string; + $tmp =~ s/\?://g; + $tmp =~ s/^\(\?\-xism:\^/^(/; + $tmp =~ s/\$\)$/)\$/; + $tmp =~ s/\\d/[0-9]/g; # [0-9] is sometimes easier to read than \d + print " Sample regex for all new users: " . $tmp . "\n"; + $tmp = $ra_all->as_string; + $tmp =~ s/\?://g; + $tmp =~ s/^\(\?\-xism:\^/^(/; + $tmp =~ s/\$\)$/)\$/; + $tmp =~ s/\\d/[0-9]/g; # [0-9] is sometimes easier to read than \d + print "Sample regex for all new AND current users: " . $tmp . "\n\n"; + print "In the default configuration you can modify the expression in the condition for 'Local_Extension'.\n"; + print "" +} else { + print "If CPAN module Regexp::Assemble were installed this program would be able to suggest a regex for your new users.\n" +} + +exit(0); + +sub add_user { + my $user_id = shift; + if ( exists( $current_users{$user_id} ) ) { + warn "User id $user_id already exists, skipping...\n"; + } else { + my $new_user = $user_template; + $new_user =~ s/__USERID__/$user_id/g; + #print "Adding user id '$user_id' with this XML:\n"; + #print $new_user . "\n"; + + ## Attempt to create the user file + my $user_file_name = $full_dir_path . $path_sep . $user_id . '.xml'; + + ## Does it already exist? + if ( -f $user_file_name ) { + warn "$user_file_name exists, skipping...\n"; + } + my $fh; + open($fh,'>',$user_file_name); + if ( ! $fh ) { + warn "Unable to open '$user_file_name' - $!\n"; + warn "Skipping...\n"; + next; + } + + print $fh $new_user; + close($fh); + print "Added $user_id in file $user_file_name \n"; + $new_user_count++; + if ( $ra_present ) { + $ra_new->add($user_id)->anchor_line_begin->anchor_line_end; + $ra_all->add($user_id)->anchor_line_begin->anchor_line_end; + } + } + +} + +sub get_user_template { + my $templ = < + + + + + + + + + + + + + + + + + + +ENDUSERTEMPLATE + + return $templ; +} + +sub usage { + print < [--domain=] [--confpath=] + add_user --users=- [--domain=] [--confpath=] + +In its simplest form, add_user will simply add the user_id specified at the command line. +By default, users are added to the "default" domain. Use the --domain option to specify +a different domain for the user(s) that are added. + +To specify a range of user IDs use the --users option. Separate the beginning and +end of the range with a hyphen (-) character. + +By default add_user will look for the XML directory in its default location of +/usr/local/freeswitch/conf/directory. Use the --confpath (configuration path) +option to specify an alternate directory location. + + + NOTES: + +add_user assumes +User IDs must be numeric and cannot begin with zero. +User IDs must be at least two digits long and have no specific length limit. +If a user ID exists it will be skipped. +If a domain specified does not exist no users will be created. + +ENDUSAGE + +} From 38f994206f075acf461b399f0e512ec5795b0083 Mon Sep 17 00:00:00 2001 From: Brian West Date: Tue, 23 Nov 2010 09:54:50 -0600 Subject: [PATCH 056/237] FS-535: additional checks and use the right contact for registers inside and outside of nat --- src/mod/endpoints/mod_sofia/sofia.c | 34 +++++++++++++++++-------- src/mod/endpoints/mod_sofia/sofia_reg.c | 6 ++--- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 32d25d0ad6..4d992b0ea1 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -2156,6 +2156,30 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag) sipip = profile->sipip; } + gateway->extension = switch_core_strdup(gateway->pool, extension); + + + if (!strncasecmp(proxy, "sip:", 4)) { + gateway->register_proxy = switch_core_strdup(gateway->pool, proxy); + gateway->register_to = switch_core_sprintf(gateway->pool, "sip:%s@%s", username, proxy + 4); + } else { + gateway->register_proxy = switch_core_sprintf(gateway->pool, "sip:%s", proxy); + gateway->register_to = switch_core_sprintf(gateway->pool, "sip:%s@%s", username, proxy); + } + + /* This checks to make sure we provide the right contact on register for targets behind nat with us. */ + if (sofia_test_pflag(profile, PFLAG_AUTO_NAT)) { + char *register_host = NULL; + + register_host = sofia_glue_get_register_host(gateway->register_proxy); + + if (register_host && !sofia_glue_check_nat(profile, register_host)) { + sipip = profile->sipip; + } + + switch_safe_free(register_host); + } + if (extension_in_contact) { format = strchr(sipip, ':') ? "" : ""; gateway->register_contact = switch_core_sprintf(gateway->pool, format, extension, @@ -2170,16 +2194,6 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag) profile->tls_sip_port : profile->sip_port, params); } - gateway->extension = switch_core_strdup(gateway->pool, extension); - - if (!strncasecmp(proxy, "sip:", 4)) { - gateway->register_proxy = switch_core_strdup(gateway->pool, proxy); - gateway->register_to = switch_core_sprintf(gateway->pool, "sip:%s@%s", username, proxy + 4); - } else { - gateway->register_proxy = switch_core_sprintf(gateway->pool, "sip:%s", proxy); - gateway->register_to = switch_core_sprintf(gateway->pool, "sip:%s@%s", username, proxy); - } - gateway->expires_str = switch_core_strdup(gateway->pool, expire_seconds); if ((gateway->freq = atoi(gateway->expires_str)) < 5) { diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index 14a7bfdd2c..7390378fc8 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -152,7 +152,7 @@ void sofia_sub_check_gateway(sofia_profile_t *profile, time_t now) register_host = sofia_glue_get_register_host(gateway_ptr->register_proxy); /* check for NAT and place a Via header if necessary (hostname or non-local IP) */ - if (sofia_glue_check_nat(gateway_ptr->profile, register_host)) { + if (register_host && sofia_glue_check_nat(gateway_ptr->profile, register_host)) { user_via = sofia_glue_create_external_via(NULL, gateway_ptr->profile, gateway_ptr->register_transport); } @@ -295,7 +295,7 @@ void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now) register_host = sofia_glue_get_register_host(gateway_ptr->register_proxy); /* check for NAT and place a Via header if necessary (hostname or non-local IP) */ - if (sofia_glue_check_nat(gateway_ptr->profile, register_host)) { + if (register_host && sofia_glue_check_nat(gateway_ptr->profile, register_host)) { user_via = sofia_glue_create_external_via(NULL, gateway_ptr->profile, gateway_ptr->register_transport); } @@ -358,7 +358,7 @@ void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now) register_host = sofia_glue_get_register_host(gateway_ptr->register_proxy); /* check for NAT and place a Via header if necessary (hostname or non-local IP) */ - if (sofia_glue_check_nat(gateway_ptr->profile, register_host)) { + if (register_host && sofia_glue_check_nat(gateway_ptr->profile, register_host)) { user_via = sofia_glue_create_external_via(NULL, gateway_ptr->profile, gateway_ptr->register_transport); } From 04e854136675ba1369a73af712b12971d4ee9c69 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Tue, 23 Nov 2010 11:43:52 -0500 Subject: [PATCH 057/237] freetdm: add release event to ftdm core --- libs/freetdm/mod_freetdm/mod_freetdm.c | 7 +++++++ libs/freetdm/src/ftdm_io.c | 9 +++++++++ libs/freetdm/src/include/freetdm.h | 1 + 3 files changed, 17 insertions(+) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index a410e4eac6..165fce0a84 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -1690,6 +1690,7 @@ static FIO_SIGNAL_CB_FUNCTION(on_fxo_signal) } } break; + case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break; default: { @@ -1744,6 +1745,7 @@ static FIO_SIGNAL_CB_FUNCTION(on_fxs_signal) } } break; + case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break; case FTDM_SIGEVENT_STOP: { private_t *tech_pvt = NULL; @@ -1966,6 +1968,8 @@ static FIO_SIGNAL_CB_FUNCTION(on_r2_signal) status = ftdm_channel_from_event(sigmsg, &session); } break; + + case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break; /* on DNIS received from the R2 forward side, return status == FTDM_BREAK to stop requesting DNIS */ case FTDM_SIGEVENT_COLLECTED_DIGIT: @@ -2063,6 +2067,9 @@ static FIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal) return ftdm_channel_from_event(sigmsg, &session); } break; + + case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break; + case FTDM_SIGEVENT_STOP: case FTDM_SIGEVENT_RESTART: { diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 939933af73..24e54574ae 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -2349,6 +2349,8 @@ static void close_dtmf_debug(ftdm_channel_t *ftdmchan) static ftdm_status_t ftdm_channel_clear_vars(ftdm_channel_t *ftdmchan); FT_DECLARE(ftdm_status_t) ftdm_channel_done(ftdm_channel_t *ftdmchan) { + ftdm_sigmsg_t sigmsg; + ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "Null channel can't be done!\n"); ftdm_mutex_lock(ftdmchan->mutex); @@ -2387,6 +2389,13 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_done(ftdm_channel_t *ftdmchan) ftdm_log(FTDM_LOG_DEBUG, "channel done %u:%u\n", ftdmchan->span_id, ftdmchan->chan_id); + memset(&sigmsg, 0, sizeof(sigmsg)); + sigmsg.span_id = ftdmchan->span_id; + sigmsg.chan_id = ftdmchan->chan_id; + sigmsg.channel = ftdmchan; + sigmsg.event_id = FTDM_SIGEVENT_RELEASED; + ftdm_span_send_signal(ftdmchan->span, &sigmsg); + ftdm_mutex_unlock(ftdmchan->mutex); return FTDM_SUCCESS; diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index 55e433d9c7..dc181e15c7 100644 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -287,6 +287,7 @@ typedef enum { typedef enum { FTDM_SIGEVENT_START, /*!< Incoming call (ie: incoming SETUP msg or Ring) */ FTDM_SIGEVENT_STOP, /*!< Hangup */ + FTDM_SIGEVENT_RELEASED, /*!< Channel is completely released and available */ FTDM_SIGEVENT_UP, /*!< Outgoing call has been answered */ FTDM_SIGEVENT_FLASH, /*< Flash event (typically on-hook/off-hook for analog devices) */ FTDM_SIGEVENT_PROGRESS, /*!< Outgoing call is making progress */ From af5f0a4acd0426d63791d8f1c7a18608de3955ff Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Tue, 23 Nov 2010 14:55:59 -0200 Subject: [PATCH 058/237] freetdm: made ftmod_r2 use FTDM_SPAN_USE_SIGNALS_QUEUE and properly send FTDM_SIGEVENT_SIGSTATUS_CHANGED --- libs/freetdm/mod_freetdm/mod_freetdm.c | 8 +++++++ libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 28 ++++++++++++++++++---- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index a410e4eac6..73f5660a7a 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -2028,6 +2028,14 @@ static FIO_SIGNAL_CB_FUNCTION(on_r2_signal) } break; + case FTDM_SIGEVENT_SIGSTATUS_CHANGED: + { + ftdm_signaling_status_t sigstatus = sigmsg->raw_data ? *((ftdm_signaling_status_t*)(sigmsg->raw_data)) : sigmsg->sigstatus; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%d:%d signalling changed to: %s\n", + spanid, chanid, ftdm_signaling_status2str(sigstatus)); + } + break; + default: { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unhandled event %d from R2 for channel %d:%d\n", diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index d5344814f0..30de78857a 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -220,6 +220,23 @@ static char *strsep(char **stringp, const char *delim) } #endif /* WIN32 */ +static void ftdm_r2_set_chan_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status_t status) +{ + ftdm_sigmsg_t sig; + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Signalling link status changed to %s\n", ftdm_signaling_status2str(status)); + + memset(&sig, 0, sizeof(sig)); + sig.chan_id = ftdmchan->chan_id; + sig.span_id = ftdmchan->span_id; + sig.channel = ftdmchan; + sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; + sig.sigstatus = status; + if (ftdm_span_send_signal(ftdmchan->span, &sig) != FTDM_SUCCESS) { + ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to change channel status to %s\n", ftdm_signaling_status2str(status)); + } + return; +} + static ftdm_call_cause_t ftdm_r2_cause_to_ftdm_cause(ftdm_channel_t *fchan, openr2_call_disconnect_cause_t cause) { switch (cause) { @@ -593,17 +610,14 @@ static void ftdm_r2_on_line_blocked(openr2_chan_t *r2chan) { ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan); ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Far end blocked in state %s\n", ftdm_channel_state2str(ftdmchan->state)); - ftdm_set_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED); + ftdm_r2_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_SUSPENDED); } static void ftdm_r2_on_line_idle(openr2_chan_t *r2chan) { ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan); ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Far end unblocked in state %s\n", ftdm_channel_state2str(ftdmchan->state)); - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED); - - /* XXX when should we set/unset this flag? XXX */ - ftdm_set_flag(ftdmchan, FTDM_CHANNEL_SIG_UP); + ftdm_r2_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_UP); } static void ftdm_r2_write_log(openr2_log_level_t level, const char *file, const char *function, int line, const char *message) @@ -1130,6 +1144,9 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_r2_configure_span) span->signal_data = r2data; span->outgoing_call = r2_outgoing_call; + /* use signals queue */ + ftdm_set_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE); + return FTDM_SUCCESS; fail: @@ -1439,6 +1456,7 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) } else if (status != FTDM_TIMEOUT) { ftdm_log(FTDM_LOG_ERROR, "ftdm_span_poll_event returned %d.\n", status); } + ftdm_span_trigger_signals(span); ftdm_sleep(20); } From 8966b4ba6e84f54b8b8262d5cf30a65b686c136e Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 23 Nov 2010 10:07:07 -0600 Subject: [PATCH 059/237] FS-2867 --- src/mod/endpoints/mod_dingaling/mod_dingaling.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_dingaling/mod_dingaling.c b/src/mod/endpoints/mod_dingaling/mod_dingaling.c index 7558e1b1b8..f5d515c8d4 100644 --- a/src/mod/endpoints/mod_dingaling/mod_dingaling.c +++ b/src/mod/endpoints/mod_dingaling/mod_dingaling.c @@ -602,7 +602,7 @@ static void ipchanged_event_handler(switch_event_t *event) for (hi = switch_hash_first(NULL, globals.profile_hash); hi; hi = switch_hash_next(hi)) { switch_hash_this(hi, NULL, NULL, &val); profile = (mdl_profile_t *) val; - if (old_ip4 && !strcmp(profile->extip, old_ip4)) { + if (old_ip4 && profile->extip && !strcmp(profile->extip, old_ip4)) { tmp = profile->extip; profile->extip = strdup(new_ip4); switch_safe_free(tmp); From 21c2a74840ee5413b822b254786310a14f2100f2 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 23 Nov 2010 13:18:50 -0600 Subject: [PATCH 060/237] uncomment --- src/mod/endpoints/mod_sofia/sofia_presence.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index dc02ca47ae..4b853de6b1 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -1616,7 +1616,7 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char * } - /* commenting to test + if (helper->event){ const char *uuid = switch_event_get_header_nil(helper->event, "unique-id"); @@ -1625,7 +1625,7 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char * sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE); } } - */ + nua_handle_bind(nh, &mod_sofia_globals.keep_private); From 4a6be5477aaf72d732292b50674ce2d83947e8fd Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Tue, 23 Nov 2010 17:29:58 -0200 Subject: [PATCH 061/237] freetdm: updated libopenr2 dll name on ftmod_r2 msvc dependency --- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2008.vcproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2008.vcproj b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2008.vcproj index 9ea351ba6a..8942a8f5b6 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2008.vcproj +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2008.vcproj @@ -60,9 +60,9 @@ /> Date: Tue, 23 Nov 2010 15:49:50 -0500 Subject: [PATCH 062/237] freetdm: do not flush events queue on channel start --- libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c index eb42207138..c13455dd21 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c @@ -333,8 +333,8 @@ static unsigned wp_open_range(ftdm_span_t *span, unsigned spanno, unsigned start ftdm_log(FTDM_LOG_ERROR, "Failed to enable RBS/CAS events in device %d:%d fd:%d\n", chan->span_id, chan->chan_id, sockfd); continue; } - /* probably done by the driver but lets write defensive code this time */ sangoma_flush_bufs(chan->sockfd, &tdm_api); + sangoma_flush_event_bufs(chan->sockfd, &tdm_api); #else /* * With wanpipe 3.4.4.2 I get failure even though the events are enabled, /var/log/messages said: @@ -514,9 +514,6 @@ static FIO_OPEN_FUNCTION(wanpipe_open) memset(&tdm_api,0,sizeof(tdm_api)); sangoma_tdm_flush_bufs(ftdmchan->sockfd, &tdm_api); -#ifdef LIBSANGOMA_VERSION - sangoma_flush_event_bufs(ftdmchan->sockfd, &tdm_api); -#endif if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921 || ftdmchan->type == FTDM_CHAN_TYPE_DQ931) { ftdmchan->native_codec = ftdmchan->effective_codec = FTDM_CODEC_NONE; From c059649f8f9d812ec284150f410c0a6d0c77b2d7 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Tue, 23 Nov 2010 16:27:40 -0500 Subject: [PATCH 063/237] freetdm: only notify of released channels when is a voice channel --- libs/freetdm/src/ftdm_io.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 24e54574ae..64233a97ac 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -2349,8 +2349,6 @@ static void close_dtmf_debug(ftdm_channel_t *ftdmchan) static ftdm_status_t ftdm_channel_clear_vars(ftdm_channel_t *ftdmchan); FT_DECLARE(ftdm_status_t) ftdm_channel_done(ftdm_channel_t *ftdmchan) { - ftdm_sigmsg_t sigmsg; - ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "Null channel can't be done!\n"); ftdm_mutex_lock(ftdmchan->mutex); @@ -2389,12 +2387,15 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_done(ftdm_channel_t *ftdmchan) ftdm_log(FTDM_LOG_DEBUG, "channel done %u:%u\n", ftdmchan->span_id, ftdmchan->chan_id); - memset(&sigmsg, 0, sizeof(sigmsg)); - sigmsg.span_id = ftdmchan->span_id; - sigmsg.chan_id = ftdmchan->chan_id; - sigmsg.channel = ftdmchan; - sigmsg.event_id = FTDM_SIGEVENT_RELEASED; - ftdm_span_send_signal(ftdmchan->span, &sigmsg); + if (FTDM_IS_VOICE_CHANNEL(ftdmchan)) { + ftdm_sigmsg_t sigmsg; + memset(&sigmsg, 0, sizeof(sigmsg)); + sigmsg.span_id = ftdmchan->span_id; + sigmsg.chan_id = ftdmchan->chan_id; + sigmsg.channel = ftdmchan; + sigmsg.event_id = FTDM_SIGEVENT_RELEASED; + ftdm_span_send_signal(ftdmchan->span, &sigmsg); + } ftdm_mutex_unlock(ftdmchan->mutex); From 10cb487cb02917dfb563872a8146a67af88b20d9 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 23 Nov 2010 15:50:17 -0600 Subject: [PATCH 064/237] FS-2868 --- src/mod/applications/mod_hash/mod_hash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/applications/mod_hash/mod_hash.c b/src/mod/applications/mod_hash/mod_hash.c index 29a056104f..2609b6cb87 100644 --- a/src/mod/applications/mod_hash/mod_hash.c +++ b/src/mod/applications/mod_hash/mod_hash.c @@ -130,7 +130,7 @@ SWITCH_LIMIT_INCR(limit_incr_hash) { switch_channel_t *channel = switch_core_session_get_channel(session); char *hashkey = NULL; - switch_bool_t status = SWITCH_STATUS_SUCCESS; + switch_status_t status = SWITCH_STATUS_SUCCESS; limit_hash_item_t *item = NULL; time_t now = switch_epoch_time_now(NULL); limit_hash_private_t *pvt = NULL; From eb109a85d5b54b47e54567893cd714b857865984 Mon Sep 17 00:00:00 2001 From: Mathieu Rene Date: Tue, 23 Nov 2010 17:00:08 -0500 Subject: [PATCH 065/237] mod_dingaling: fix leak in chat_send --- src/mod/endpoints/mod_dingaling/mod_dingaling.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mod/endpoints/mod_dingaling/mod_dingaling.c b/src/mod/endpoints/mod_dingaling/mod_dingaling.c index f5d515c8d4..480f2bdf52 100644 --- a/src/mod/endpoints/mod_dingaling/mod_dingaling.c +++ b/src/mod/endpoints/mod_dingaling/mod_dingaling.c @@ -521,6 +521,7 @@ static switch_status_t chat_send(const char *proto, const char *from, const char } } ldl_handle_send_msg(profile->handle, (char *) from, (char *) to, NULL, switch_str_nil(body)); + switch_safe_free(ffrom); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Profile %s\n", f_host ? f_host : "NULL"); return SWITCH_STATUS_FALSE; From 58c28aabc8c0ef3cd00087dbd67640cc85d34a71 Mon Sep 17 00:00:00 2001 From: Mathieu Rene Date: Tue, 23 Nov 2010 17:26:32 -0500 Subject: [PATCH 066/237] mod_dingaling: use the login as message source when not in component mode. (chat_send) --- src/mod/endpoints/mod_dingaling/mod_dingaling.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/mod/endpoints/mod_dingaling/mod_dingaling.c b/src/mod/endpoints/mod_dingaling/mod_dingaling.c index 480f2bdf52..75329a0848 100644 --- a/src/mod/endpoints/mod_dingaling/mod_dingaling.c +++ b/src/mod/endpoints/mod_dingaling/mod_dingaling.c @@ -514,8 +514,13 @@ static switch_status_t chat_send(const char *proto, const char *from, const char from = hint; } else { char *p; - ffrom = switch_mprintf("%s+%s", proto, from); - from = ffrom; + + if (!(profile->user_flags & LDL_FLAG_COMPONENT)) { + from = ffrom = strdup(profile->login); + } else { + from = ffrom = switch_mprintf("%s+%s", proto, from); + } + if ((p = strchr(from, '/'))) { *p = '\0'; } From 9f183fa4b15ec9e5d2249f5da63dc2af3a25d9d2 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Tue, 23 Nov 2010 17:41:40 -0500 Subject: [PATCH 067/237] freetdm: ISDN - Added pendingsignals to list of interrupts in span poll thread --- .../ftmod_sangoma_isdn/ftmod_sangoma_isdn.c | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c index cb96107ac3..77ad917bf1 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c @@ -370,7 +370,7 @@ static void *ftdm_sangoma_isdn_dchan_run(ftdm_thread_t *me, void *obj) static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj) { - ftdm_interrupt_t *ftdm_sangoma_isdn_int[2]; + ftdm_interrupt_t *ftdm_sangoma_isdn_int[3]; ftdm_status_t ret_status; ftdm_span_t *span = (ftdm_span_t *) obj; ftdm_channel_t *ftdmchan = NULL; @@ -388,8 +388,13 @@ static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj) ftdm_log(FTDM_LOG_CRIT, "%s:Failed to get a ftdm_interrupt for span = %s!\n", span->name); goto ftdm_sangoma_isdn_run_exit; } + + if (ftdm_queue_get_interrupt(span->pendingsignals, &ftdm_sangoma_isdn_int[1]) != FTDM_SUCCESS) { + ftdm_log(FTDM_LOG_CRIT, "%s:Failed to get a signal interrupt for span = %s!\n", span->name); + goto ftdm_sangoma_isdn_run_exit; + } - if (ftdm_queue_get_interrupt(signal_data->event_queue, &ftdm_sangoma_isdn_int[1]) != FTDM_SUCCESS) { + if (ftdm_queue_get_interrupt(signal_data->event_queue, &ftdm_sangoma_isdn_int[2]) != FTDM_SUCCESS) { ftdm_log(FTDM_LOG_CRIT, "%s:Failed to get a event interrupt for span = %s!\n", span->name); goto ftdm_sangoma_isdn_run_exit; } @@ -398,8 +403,14 @@ static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj) /* Check if there are any timers to process */ ftdm_sched_run(signal_data->sched); + ftdm_span_trigger_signals(span); - ret_status = ftdm_interrupt_multiple_wait(ftdm_sangoma_isdn_int, 2, sleep); + if (ftdm_sched_get_time_to_next_timer(signal_data->sched, &sleep) == FTDM_SUCCESS) { + if (sleep < 0 || sleep > SNGISDN_EVENT_POLL_RATE) { + sleep = SNGISDN_EVENT_POLL_RATE; + } + } + ret_status = ftdm_interrupt_multiple_wait(ftdm_sangoma_isdn_int, 3, sleep); /* find out why we returned from the interrupt queue */ switch (ret_status) { case FTDM_SUCCESS: /* there was a state change on the span */ @@ -415,7 +426,6 @@ static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj) ftdm_sangoma_isdn_process_stack_event(span, sngisdn_event); ftdm_safe_free(sngisdn_event); } - ftdm_span_trigger_signals(span); break; case FTDM_TIMEOUT: /* twiddle */ @@ -431,13 +441,6 @@ static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj) /* Poll for events, e.g HW DTMF */ ftdm_sangoma_isdn_poll_events(span); - ftdm_span_trigger_signals(span); - - if (ftdm_sched_get_time_to_next_timer(signal_data->sched, &sleep) == FTDM_SUCCESS) { - if (sleep < 0 || sleep > SNGISDN_EVENT_POLL_RATE) { - sleep = SNGISDN_EVENT_POLL_RATE; - } - } } /* clear the IN_THREAD flag so that we know the thread is done */ From 0bd8d187e0a58c708667416f63f30e30c344c295 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 23 Nov 2010 18:03:56 -0600 Subject: [PATCH 068/237] clear controlled flag on recovered calls --- src/switch_ivr.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/switch_ivr.c b/src/switch_ivr.c index f076f6cb9f..df88451a3d 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -763,6 +763,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_park(switch_core_session_t *session, write_frame.samples = write_frame.datalen / sizeof(int16_t); } + if (switch_channel_test_flag(channel, CF_RECOVERED) && switch_channel_test_flag(channel, CF_CONTROLLED)) { + switch_channel_clear_flag(channel, CF_CONTROLLED); + } + if (switch_channel_test_flag(channel, CF_CONTROLLED)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot park channels that are under control already.\n"); return SWITCH_STATUS_FALSE; From dad92067daa6d882a640cccfbf503ec2f800085d Mon Sep 17 00:00:00 2001 From: Brian West Date: Tue, 23 Nov 2010 18:35:45 -0600 Subject: [PATCH 069/237] FS-535: fix issue in is_lan_addr where 172.2 would match 172.250.x.x which is not RFC1918 this also fixes an chicken egg issue --- src/mod/endpoints/mod_sofia/sofia.c | 2 +- src/switch_utils.c | 25 +++++++++++++++++++------ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 4d992b0ea1..4d9bd7fd7b 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -2173,7 +2173,7 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag) register_host = sofia_glue_get_register_host(gateway->register_proxy); - if (register_host && !sofia_glue_check_nat(profile, register_host)) { + if (register_host && switch_is_lan_addr(register_host)) { sipip = profile->sipip; } diff --git a/src/switch_utils.c b/src/switch_utils.c index 75be02a31f..1a29e2b715 100644 --- a/src/switch_utils.c +++ b/src/switch_utils.c @@ -726,18 +726,31 @@ SWITCH_DECLARE(switch_bool_t) switch_is_lan_addr(const char *ip) if (zstr(ip)) return SWITCH_FALSE; - return (strncmp(ip, "10.", 3) && - strncmp(ip, "192.168.", 8) && - strncmp(ip, "127.", 4) && + return (strncmp(ip, "10.", 3) && /* 10.0.0.0 - 10.255.255.255 (10/8 prefix) */ + strncmp(ip, "192.168.", 8) && /* 192.168.0.0 - 192.168.255.255 (192.168/16 prefix) */ + strncmp(ip, "127.", 4) && /* 127.0.0.0 - 127.255.255.255 (127/8 prefix) */ strncmp(ip, "255.", 4) && - strncmp(ip, "0.", 2) && + strncmp(ip, "0.", 2) && strncmp(ip, "1.", 2) && strncmp(ip, "2.", 2) && - strncmp(ip, "172.16.", 7) && + strncmp(ip, "172.16.", 7) && /* 172.16.0.0 - 172.31.255.255 (172.16/12 prefix) */ strncmp(ip, "172.17.", 7) && strncmp(ip, "172.18.", 7) && strncmp(ip, "172.19.", 7) && - strncmp(ip, "172.2", 5) && strncmp(ip, "172.30.", 7) && strncmp(ip, "172.31.", 7) && strncmp(ip, "192.0.2.", 8) && strncmp(ip, "169.254.", 8) + strncmp(ip, "172.20.", 7) && + strncmp(ip, "172.21.", 7) && + strncmp(ip, "172.22.", 7) && + strncmp(ip, "172.23.", 7) && + strncmp(ip, "172.24.", 7) && + strncmp(ip, "172.25.", 7) && + strncmp(ip, "172.26.", 7) && + strncmp(ip, "172.27.", 7) && + strncmp(ip, "172.28.", 7) && + strncmp(ip, "172.29.", 7) && + strncmp(ip, "172.30.", 7) && + strncmp(ip, "172.31.", 7) && + strncmp(ip, "192.0.2.", 8) && /* 192.0.2.0 - 192.0.2.255 (192.0.2/24 prefix) */ + strncmp(ip, "169.254.", 8) /* 169.254.0.0 - 169.254.255.255 (169.254/16 prefix) */ )? SWITCH_FALSE : SWITCH_TRUE; } From 61bc810bf8f252bb33946cb23a8d66a78036569b Mon Sep 17 00:00:00 2001 From: Michael S Collins Date: Tue, 23 Nov 2010 17:17:46 -0800 Subject: [PATCH 070/237] Fix usage formatting in logger.pl --- libs/esl/perl/logger.pl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/esl/perl/logger.pl b/libs/esl/perl/logger.pl index d0dbb1750e..08213c033f 100644 --- a/libs/esl/perl/logger.pl +++ b/libs/esl/perl/logger.pl @@ -17,13 +17,13 @@ my $USAGE = " FreeSWITCH Logger Utility USAGE: --h --helpThis help +-h --help This help -p --port Choose port -P -pass Choose password -f --file Output file -pb --paste-bin Post to FreeSWITCH Paste Bin -sp --sip-profiles List of SIP profiles to trace --sd --sip-debug Set SIP debug level +-sd --sip-debug Set SIP debug level No arguments given will trace profile 'internal' to STDOUT "; From 364c156cdc3f078ba423208bc5c6bf0af85a471c Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Wed, 24 Nov 2010 03:46:06 +0000 Subject: [PATCH 071/237] update .gitignore --- .gitignore | 2 ++ src/mod/.gitignore | 1 + 2 files changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index adcfda37f4..304b42c1f9 100644 --- a/.gitignore +++ b/.gitignore @@ -70,10 +70,12 @@ config.status configure.lineno /freeswitch /fs_cli +/fs_encode /fs_ivrd /libtool /modules.conf /quiet_libtool +/tone2wav /scripts/fsxs /scripts/gentls_cert /a.out.dSYM diff --git a/src/mod/.gitignore b/src/mod/.gitignore index 47cdbafa70..b6e7842a50 100644 --- a/src/mod/.gitignore +++ b/src/mod/.gitignore @@ -7,6 +7,7 @@ /applications/mod_spandsp/mod_spandsp.log /applications/mod_commands/Makefile /applications/mod_conference/Makefile +/applications/mod_db/Makefile /applications/mod_dptools/Makefile /applications/mod_enum/Makefile /applications/mod_enum/Makefile.in From 89245dc5a1f6c4938fff0d760c4660e0bf7974c5 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Wed, 24 Nov 2010 03:58:22 +0000 Subject: [PATCH 072/237] remove ignored file from tree --- libs/libsndfile/M4/lt~obsolete.m4 | 98 ------------------------------- 1 file changed, 98 deletions(-) delete mode 100644 libs/libsndfile/M4/lt~obsolete.m4 diff --git a/libs/libsndfile/M4/lt~obsolete.m4 b/libs/libsndfile/M4/lt~obsolete.m4 deleted file mode 100644 index c573da90c5..0000000000 --- a/libs/libsndfile/M4/lt~obsolete.m4 +++ /dev/null @@ -1,98 +0,0 @@ -# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- -# -# Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc. -# Written by Scott James Remnant, 2004. -# -# This file is free software; the Free Software Foundation gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. - -# serial 5 lt~obsolete.m4 - -# These exist entirely to fool aclocal when bootstrapping libtool. -# -# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) -# which have later been changed to m4_define as they aren't part of the -# exported API, or moved to Autoconf or Automake where they belong. -# -# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN -# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us -# using a macro with the same name in our local m4/libtool.m4 it'll -# pull the old libtool.m4 in (it doesn't see our shiny new m4_define -# and doesn't know about Autoconf macros at all.) -# -# So we provide this file, which has a silly filename so it's always -# included after everything else. This provides aclocal with the -# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything -# because those macros already exist, or will be overwritten later. -# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. -# -# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. -# Yes, that means every name once taken will need to remain here until -# we give up compatibility with versions before 1.7, at which point -# we need to keep only those names which we still refer to. - -# This is to help aclocal find these macros, as it can't see m4_define. -AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) - -m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) -m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) -m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) -m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) -m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) -m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) -m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) -m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) -m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) -m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) -m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) -m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) -m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) -m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) -m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) -m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) -m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) -m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) -m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) -m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) -m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) -m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) -m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) -m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) -m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) -m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) -m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) -m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) -m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) -m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) -m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) -m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) -m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) -m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) -m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) -m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) -m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) -m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) -m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) -m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) -m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) -m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) -m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) -m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) -m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) -m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) -m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) -m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) -m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) -m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) -m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) -m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) -m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) -m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) -m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) -m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) -m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) -m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) -m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) -m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) -m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) From e82828231e7634a06d0230df865bbcf5496f57b7 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Wed, 24 Nov 2010 06:07:21 +0000 Subject: [PATCH 073/237] spelling corrections --- src/include/switch_channel.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/include/switch_channel.h b/src/include/switch_channel.h index a1f13edd85..d6bce5e8bf 100644 --- a/src/include/switch_channel.h +++ b/src/include/switch_channel.h @@ -179,8 +179,8 @@ SWITCH_DECLARE(void) switch_channel_uninit(switch_channel_t *channel); SWITCH_DECLARE(void) switch_channel_set_caller_profile(switch_channel_t *channel, switch_caller_profile_t *caller_profile); /*! - \brief Retrive the given channel's caller profile - \param channel channel to retrive the profile from + \brief Retrieve the given channel's caller profile + \param channel channel to retrieve the profile from \return the requested profile */ SWITCH_DECLARE(switch_caller_profile_t *) switch_channel_get_caller_profile(switch_channel_t *channel); @@ -195,8 +195,8 @@ SWITCH_DECLARE(void) switch_channel_set_originator_caller_profile(switch_channel SWITCH_DECLARE(void) switch_channel_set_hunt_caller_profile(switch_channel_t *channel, switch_caller_profile_t *caller_profile); /*! - \brief Retrive the given channel's originator caller profile - \param channel channel to retrive the profile from + \brief Retrieve the given channel's originator caller profile + \param channel channel to retrieve the profile from \return the requested profile */ SWITCH_DECLARE(switch_caller_profile_t *) switch_channel_get_originator_caller_profile(switch_channel_t *channel); @@ -209,8 +209,8 @@ SWITCH_DECLARE(switch_caller_profile_t *) switch_channel_get_originator_caller_p SWITCH_DECLARE(void) switch_channel_set_originatee_caller_profile(switch_channel_t *channel, switch_caller_profile_t *caller_profile); /*! - \brief Retrive the given channel's originatee caller profile - \param channel channel to retrive the profile from + \brief Retrieve the given channel's originatee caller profile + \param channel channel to retrieve the profile from \return the requested profile */ SWITCH_DECLARE(switch_caller_profile_t *) switch_channel_get_originatee_caller_profile(switch_channel_t *channel); @@ -223,16 +223,16 @@ SWITCH_DECLARE(switch_caller_profile_t *) switch_channel_get_originatee_caller_p SWITCH_DECLARE(void) switch_channel_set_origination_caller_profile(switch_channel_t *channel, switch_caller_profile_t *caller_profile); /*! - \brief Retrive the given channel's origination caller profile - \param channel channel to retrive the profile from + \brief Retrieve the given channel's origination caller profile + \param channel channel to retrieve the profile from \return the requested profile */ SWITCH_DECLARE(switch_caller_profile_t *) switch_channel_get_origination_caller_profile(switch_channel_t *channel); /*! - \brief Retrive the given channel's unique id - \param channel channel to retrive the unique id from + \brief Retrieve the given channel's unique id + \param channel channel to retrieve the unique id from \return the unique id */ SWITCH_DECLARE(char *) switch_channel_get_uuid(switch_channel_t *channel); @@ -241,7 +241,7 @@ SWITCH_DECLARE(char *) switch_channel_get_uuid(switch_channel_t *channel); \brief Set a variable on a given channel \param channel channel to set variable on \param varname the name of the variable - \param value the vaule of the variable + \param value the value of the variable \returns SWITCH_STATUS_SUCCESS if successful */ From 473a04651c3971883cc413b1ee53f4c1ee3135ce Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Wed, 24 Nov 2010 09:28:34 -0500 Subject: [PATCH 074/237] freetdm: add missing string for SIGEVENT_RELEASED --- libs/freetdm/src/include/freetdm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index dc181e15c7..508c6996d5 100644 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -301,7 +301,7 @@ typedef enum { FTDM_SIGEVENT_COLLISION, /*!< Outgoing call was dropped because an incoming call arrived at the same time */ FTDM_SIGEVENT_INVALID } ftdm_signal_event_t; -#define SIGNAL_STRINGS "START", "STOP", "UP", "FLASH", "PROGRESS", \ +#define SIGNAL_STRINGS "START", "STOP", "RELEASED", "UP", "FLASH", "PROGRESS", \ "PROGRESS_MEDIA", "ALARM_TRAP", "ALARM_CLEAR", \ "COLLECTED_DIGIT", "ADD_CALL", "RESTART", "SIGSTATUS_CHANGED", "COLLISION", "INVALID" From 6a948bd98bc29156774d09210fe07548fed3388b Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Wed, 24 Nov 2010 09:50:50 -0600 Subject: [PATCH 075/237] add mono 2.8 patch file see FS-2774 --- src/mod/languages/mod_managed/mono28.patch | 75 ++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 src/mod/languages/mod_managed/mono28.patch diff --git a/src/mod/languages/mod_managed/mono28.patch b/src/mod/languages/mod_managed/mono28.patch new file mode 100644 index 0000000000..7ec60f596c --- /dev/null +++ b/src/mod/languages/mod_managed/mono28.patch @@ -0,0 +1,75 @@ +diff --git a/src/mod/languages/mod_managed/Makefile b/src/mod/languages/mod_managed/Makefile +index 0ac49b4..ec44ff5 100644 +--- a/src/mod/languages/mod_managed/Makefile ++++ b/src/mod/languages/mod_managed/Makefile +@@ -1,6 +1,6 @@ +-LOCAL_INSERT_CFLAGS= /usr/bin/pkg-config mono --cflags +-LOCAL_INSERT_LDFLAGS= /usr/bin/pkg-config mono --libs +-#MOD_CFLAGS=-D_REENTRANT -pthread -I/opt/mono-1.9/lib/pkgconfig/../../include/mono-1.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -lmono ++LOCAL_INSERT_CFLAGS= /usr/bin/pkg-config mono-2 --cflags ++LOCAL_INSERT_LDFLAGS= /usr/bin/pkg-config mono-2 --libs ++#MOD_CFLAGS=-D_REENTRANT -pthread -I/usr/lib/mono -lmono + BASE=../../../.. + VERBOSE=1 + include $(BASE)/build/modmake.rules +diff --git a/src/mod/languages/mod_managed/freeswitch.i b/src/mod/languages/mod_managed/freeswitch.i +index ffbdf9b..117d58c 100644 +--- a/src/mod/languages/mod_managed/freeswitch.i ++++ b/src/mod/languages/mod_managed/freeswitch.i +@@ -8,7 +8,6 @@ + + /* Callback for returning strings to C# without leaking memory */ + #ifndef _MANAGED +-#include + #include + #include + #include +diff --git a/src/mod/languages/mod_managed/freeswitch_managed.h b/src/mod/languages/mod_managed/freeswitch_managed.h +index 1d0b6a7..13ffe5d 100644 +--- a/src/mod/languages/mod_managed/freeswitch_managed.h ++++ b/src/mod/languages/mod_managed/freeswitch_managed.h +@@ -40,7 +40,6 @@ typedef void (*hangupFunction) (void); + typedef char *(*inputFunction) (void *, switch_input_type_t); + + #ifndef _MANAGED +-#include + #include + #include + #include +@@ -73,7 +72,7 @@ extern mod_managed_globals globals; + #ifdef WIN32 + #define RESULT_FREE(x) CoTaskMemFree(x) + #else +-#define RESULT_FREE(x) g_free(x) ++#define RESULT_FREE(x) mono_free(x) + #endif + + SWITCH_END_EXTERN_C +diff --git a/src/mod/languages/mod_managed/mod_managed.cpp b/src/mod/languages/mod_managed/mod_managed.cpp +index ec2d866..87e831f 100644 +--- a/src/mod/languages/mod_managed/mod_managed.cpp ++++ b/src/mod/languages/mod_managed/mod_managed.cpp +@@ -208,18 +208,13 @@ switch_status_t loadRuntime() + } + + /* Already loaded? */ +- MonoAssemblyName name; +- name.name = MOD_MANAGED_ASM_NAME; +- name.major = MOD_MANAGED_ASM_V1; +- name.minor = MOD_MANAGED_ASM_V2; +- name.revision = MOD_MANAGED_ASM_V3; +- name.build = MOD_MANAGED_ASM_V4; +- name.culture = ""; +- name.hash_value = ""; +- ++ MonoAssemblyName *name = mono_assembly_name_new (MOD_MANAGED_ASM_NAME); ++ //Note also that it can't be allocated on the stack anymore and you'll need to create and destroy it with the following API: ++ //mono_assembly_name_free (name); ++ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Calling mono_assembly_loaded.\n"); + +- if (!(globals.mod_mono_asm = mono_assembly_loaded(&name))) { ++ if (!(globals.mod_mono_asm = mono_assembly_loaded(name))) { + /* Open the assembly */ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Calling mono_domain_assembly_open.\n"); + globals.mod_mono_asm = mono_domain_assembly_open(globals.domain, filename); From d73cd50e99529ad9572b5d2892736db292d8367f Mon Sep 17 00:00:00 2001 From: Brian West Date: Wed, 24 Nov 2010 10:34:02 -0600 Subject: [PATCH 076/237] sofia_reg.c lets make this fail2ban stuff better --- src/mod/endpoints/mod_sofia/sofia_reg.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index 7390378fc8..262aff1dda 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -1139,9 +1139,14 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand } if (auth_res != AUTH_OK && !stale) { + if (sofia_test_pflag(profile, PFLAG_LOG_AUTH_FAIL)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SIP auth %s (REGISTER) on sofia profile '%s' " + "for [%s@%s] from ip %s\n", forbidden ? "failure" : "challenge", profile->name, to_user, to_host, network_ip); + } + if (profile->debug) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Send %s for [%s@%s] from ip '%s'\n", - forbidden ? "forbidden" : "challenge", to_user, to_host, network_ip); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Send %s for [%s@%s]\n", + forbidden ? "forbidden" : "challenge", to_user, to_host); } if (auth_res == AUTH_FORBIDDEN) { nua_respond(nh, SIP_403_FORBIDDEN, NUTAG_WITH_THIS(nua), TAG_END()); From 17efb68d1d31deb7cc8d6fcabfc145e4d65da3f1 Mon Sep 17 00:00:00 2001 From: Brian West Date: Wed, 24 Nov 2010 10:53:01 -0600 Subject: [PATCH 077/237] woops don't log reg twice --- src/mod/endpoints/mod_sofia/sofia_reg.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index 262aff1dda..216f808e4f 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -1140,8 +1140,10 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand if (auth_res != AUTH_OK && !stale) { if (sofia_test_pflag(profile, PFLAG_LOG_AUTH_FAIL)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SIP auth %s (REGISTER) on sofia profile '%s' " - "for [%s@%s] from ip %s\n", forbidden ? "failure" : "challenge", profile->name, to_user, to_host, network_ip); + if (regtype == REG_REGISTER) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SIP auth %s (REGISTER) on sofia profile '%s' " + "for [%s@%s] from ip %s\n", forbidden ? "failure" : "challenge", profile->name, to_user, to_host, network_ip); + } } if (profile->debug) { @@ -1150,13 +1152,10 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand } if (auth_res == AUTH_FORBIDDEN) { nua_respond(nh, SIP_403_FORBIDDEN, NUTAG_WITH_THIS(nua), TAG_END()); - + /* Log line added to support Fail2Ban */ if (sofia_test_pflag(profile, PFLAG_LOG_AUTH_FAIL)) { - if (regtype == REG_REGISTER) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "SIP auth failure (REGISTER) on sofia profile '%s' " - "for [%s@%s] from ip %s\n", profile->name, to_user, to_host, network_ip); - } else if (regtype == REG_INVITE) { + if (regtype == REG_INVITE) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "SIP auth failure (INVITE) on sofia profile '%s' " "for [%s@%s] from ip %s\n", profile->name, to_user, to_host, network_ip); } From a697462a589cab5f70e5608e33837bd6e4ada14c Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Wed, 24 Nov 2010 12:30:58 -0500 Subject: [PATCH 078/237] freetdm: ftmod_libpri - Do not unlock the channel until all states pending have been cleared. This should fix issues with state transitions being ignored. --- libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c index 669e85218a..cf84dbeebd 100644 --- a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c +++ b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c @@ -727,15 +727,13 @@ static __inline__ void check_state(ftdm_span_t *span) for (j = 1; j <= ftdm_span_get_chan_count(span); j++) { ftdm_channel_t *chan = ftdm_span_get_channel(span, j); - if (ftdm_test_flag(chan, FTDM_CHANNEL_STATE_CHANGE)) { - ftdm_channel_lock(chan); - + ftdm_channel_lock(chan); + while (ftdm_test_flag(chan, FTDM_CHANNEL_STATE_CHANGE)) { ftdm_clear_flag(chan, FTDM_CHANNEL_STATE_CHANGE); state_advance(chan); ftdm_channel_complete_state(chan); - - ftdm_channel_unlock(chan); } + ftdm_channel_unlock(chan); } } } From 8b61fe440031ae1c66729c3d9f611a91511c8c8e Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Wed, 24 Nov 2010 16:13:52 -0500 Subject: [PATCH 079/237] mod_sangoma_codec: update sample config --- conf/autoload_configs/sangoma_codec.conf.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/conf/autoload_configs/sangoma_codec.conf.xml b/conf/autoload_configs/sangoma_codec.conf.xml index 05d70de0a7..eed9d673e1 100644 --- a/conf/autoload_configs/sangoma_codec.conf.xml +++ b/conf/autoload_configs/sangoma_codec.conf.xml @@ -4,14 +4,15 @@ From b017931c5eb6ea4065060e9b7f22e28274c87c15 Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Wed, 24 Nov 2010 17:22:16 -0500 Subject: [PATCH 080/237] add -lresolv when its present so modules don't have to link to it --- configure.in | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/configure.in b/configure.in index de7261266e..77df2a614c 100644 --- a/configure.in +++ b/configure.in @@ -373,6 +373,11 @@ if test "x$have_libz" = "xyes" ; then APR_ADDTO(SWITCH_AM_LDFLAGS, -lz) fi +AC_CHECK_LIB(resolv, res_init, have_libresolv=yes, have_libresolv=no) +if test "x$have_libresolv" = "xyes" ; then +APR_ADDTO(SWITCH_AM_LDFLAGS, -lresolv) +fi + ESL_LDFLAGS= PLATFORM_CORE_DEPLIBS= # tweak platform specific flags From 03dc3b7b8d734e5a916c0dd48c408e78e6f66f55 Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Wed, 24 Nov 2010 21:25:24 -0200 Subject: [PATCH 081/237] freetdm: ftdm_channel_read_event() to retrieve events from a channel, removed from ftmod_r2: ftdm_r2_sig_read(), FTDM_R2_PROCESSING flag and locks for ftdmchan --- libs/freetdm/src/ftdm_io.c | 45 +++++ libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 145 ++++++-------- .../src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c | 184 +++++++++++++++++- libs/freetdm/src/include/freetdm.h | 4 + libs/freetdm/src/include/private/ftdm_core.h | 17 ++ 5 files changed, 311 insertions(+), 84 deletions(-) diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 64233a97ac..0065d779f6 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -988,6 +988,51 @@ FT_DECLARE(ftdm_status_t) ftdm_span_next_event(ftdm_span_t *span, ftdm_event_t * return status; } +FT_DECLARE(ftdm_status_t) ftdm_channel_read_event(ftdm_channel_t *ftdmchan, ftdm_event_t **event) +{ + ftdm_status_t status = FTDM_FAIL; + ftdm_sigmsg_t sigmsg; + ftdm_span_t *span = ftdmchan->span; + ftdm_assert_return(span->fio != NULL, FTDM_FAIL, "No I/O module attached to this span!\n"); + + if (!span->fio->channel_next_event) { + ftdm_log(FTDM_LOG_ERROR, "channel_next_event method not implemented in module %s!", span->fio->name); + return FTDM_NOTIMPL; + } + + status = span->fio->channel_next_event(ftdmchan, event); + if (status != FTDM_SUCCESS) { + return status; + } + + /* before returning the event to the user we do some core operations with certain OOB events */ + memset(&sigmsg, 0, sizeof(sigmsg)); + sigmsg.span_id = span->span_id; + sigmsg.chan_id = (*event)->channel->chan_id; + sigmsg.channel = (*event)->channel; + switch ((*event)->enum_id) { + case FTDM_OOB_ALARM_CLEAR: + { + sigmsg.event_id = FTDM_SIGEVENT_ALARM_CLEAR; + ftdm_clear_flag_locked((*event)->channel, FTDM_CHANNEL_IN_ALARM); + ftdm_span_send_signal(span, &sigmsg); + } + break; + case FTDM_OOB_ALARM_TRAP: + { + sigmsg.event_id = FTDM_SIGEVENT_ALARM_TRAP; + ftdm_set_flag_locked((*event)->channel, FTDM_CHANNEL_IN_ALARM); + ftdm_span_send_signal(span, &sigmsg); + } + break; + default: + /* NOOP */ + break; + } + + return status; +} + static ftdm_status_t ftdmchan_fsk_write_sample(int16_t *buf, ftdm_size_t buflen, void *user_data) { ftdm_channel_t *ftdmchan = (ftdm_channel_t *) user_data; diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index 30de78857a..7c5f4a46af 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -57,8 +57,7 @@ typedef enum { } ftdm_r2_flag_t; typedef enum { - FTDM_R2_PROCESSING = (1 << 0), - FTDM_R2_WAITING_ACK = (1 << 1), + FTDM_R2_WAITING_ACK = (1 << 0), } ftdm_r2_call_flag_t; /* private call information stored in ftdmchan->call_data void* ptr */ @@ -398,44 +397,26 @@ static ftdm_status_t ftdm_r2_stop(ftdm_span_t *span) return FTDM_SUCCESS; } -static ftdm_status_t ftdm_r2_sig_read(ftdm_channel_t *ftdmchan, void *data, ftdm_size_t size) -{ - openr2_chan_t *r2chan = R2CALL(ftdmchan)->r2chan; - if (!openr2_chan_get_read_enabled(r2chan)) { - ftdm_mutex_lock(ftdmchan->mutex); - //openr2_chan_process_input(r2chan, data, size); - ftdm_mutex_unlock(ftdmchan->mutex); - } - return FTDM_SUCCESS; -} - /* always called from the monitor thread */ static void ftdm_r2_on_call_init(openr2_chan_t *r2chan) { - //ftdm_status_t status; ftdm_r2_call_t *r2call; ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan); - //ftdm_r2_data_t *r2data = ftdmchan->span->signal_data; ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Received request to start call\n"); - ftdm_mutex_lock(ftdmchan->mutex); - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE)) { ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Cannot start call when channel is in use (state = %s)\n", ftdm_channel_state2str(ftdmchan->state)); - ftdm_mutex_unlock(ftdmchan->mutex); return; } if (ftdmchan->state != FTDM_CHANNEL_STATE_DOWN) { ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Cannot handle request to start call in state %s\n", ftdm_channel_state2str(ftdmchan->state)); - ftdm_mutex_unlock(ftdmchan->mutex); return; } if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) { ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to open channel during incoming call! [%s]\n", ftdmchan->last_error); - ftdm_mutex_unlock(ftdmchan->mutex); return; } @@ -448,7 +429,6 @@ static void ftdm_r2_on_call_init(openr2_chan_t *r2chan) /* clean the call data structure but keep the R2 processing flag on! */ ft_r2_clean_call(ftdmchan->call_data); r2call = R2CALL(ftdmchan); - ftdm_set_flag(r2call, FTDM_R2_PROCESSING); if (ftdmchan->state == FTDM_CHANNEL_STATE_DOWN) { R2CALL(ftdmchan)->chanstate = FTDM_CHANNEL_STATE_DOWN; @@ -457,7 +437,6 @@ static void ftdm_r2_on_call_init(openr2_chan_t *r2chan) } ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_COLLECT); - ftdm_mutex_unlock(ftdmchan->mutex); } /* only called for incoming calls when the ANI, DNIS etc is complete and the user has to decide either to accept or reject the call */ @@ -574,11 +553,8 @@ static void ftdm_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_err ftdm_r2_data_t *r2data; ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan); - ftdm_mutex_lock(ftdmchan->mutex); - if (ftdmchan->state == FTDM_CHANNEL_STATE_DOWN) { ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Got protocol error when we're already down!\n"); - ftdm_mutex_unlock(ftdmchan->mutex); } ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Protocol error\n"); @@ -587,7 +563,6 @@ static void ftdm_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_err if (!R2CALL(ftdmchan)->ftdm_started) { ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); - ftdm_mutex_unlock(ftdmchan->mutex); return; } @@ -602,8 +577,6 @@ static void ftdm_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_err r2data = ftdmchan->span->signal_data; ftdm_span_send_signal(ftdmchan->span, &sigev); - - ftdm_mutex_unlock(ftdmchan->mutex); } static void ftdm_r2_on_line_blocked(openr2_chan_t *r2chan) @@ -867,9 +840,37 @@ static int ftdm_r2_io_setup(openr2_chan_t *r2chan) static int ftdm_r2_io_get_oob_event(openr2_chan_t *r2chan, openr2_oob_event_t *event) { - *event = 0; - ftdm_log(FTDM_LOG_ERROR, "I should not be called (I/O get oob event)!!\n"); - return 0; + ftdm_status_t status; + ftdm_event_t *fevent = NULL; + ftdm_channel_t *ftdmchan = openr2_chan_get_fd(r2chan); + + *event = OR2_OOB_EVENT_NONE; + status = ftdm_channel_read_event(ftdmchan, &fevent); + if (status != FTDM_SUCCESS) { + //ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "failed to retrieve freetdm event!\n"); + return -1; + } + if (fevent->e_type != FTDM_EVENT_OOB) + return 0; + switch (fevent->enum_id) { + case FTDM_OOB_CAS_BITS_CHANGE: + { + *event = OR2_OOB_EVENT_CAS_CHANGE; + } + break; + case FTDM_OOB_ALARM_TRAP: + { + *event = OR2_OOB_EVENT_ALARM_ON; + } + break; + case FTDM_OOB_ALARM_CLEAR: + { + *event = OR2_OOB_EVENT_ALARM_OFF; + } + break; + } + ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "returning event: %s\n", ftdm_signal_event2str(*event)); + return 0; } static openr2_io_interface_t ftdm_r2_io_iface = { @@ -1137,7 +1138,7 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_r2_configure_span) span->start = ftdm_r2_start; span->stop = ftdm_r2_stop; - span->sig_read = ftdm_r2_sig_read; + span->sig_read = NULL; span->signal_cb = sig_cb; span->signal_type = FTDM_SIGTYPE_R2; @@ -1350,6 +1351,7 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) int ms; struct timeval start, end; short *poll_events = ftdm_malloc(sizeof(short)*span->chan_count); + ftdm_event_t *event = NULL; #ifdef __linux__ r2data->monitor_thread_id = syscall(SYS_gettid); @@ -1401,63 +1403,44 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) continue; } - if (FTDM_SUCCESS == status) { - ftdm_event_t *event; - while (ftdm_span_next_event(span, &event) == FTDM_SUCCESS) { - if (event->enum_id == FTDM_OOB_CAS_BITS_CHANGE) { - r2call = R2CALL(event->channel); - r2chan = r2call->r2chan; + /* XXX + * when ftdm_span_poll_event() returns FTDM_SUCCESS, means there are events pending on the span. + * is it possible to know on which channels those events are pending, without traversing the span? + * XXX */ + for (i = 1; i <= span->chan_count; i++) { + r2chan = R2CALL(span->channels[i])->r2chan; + r2call = R2CALL(ftdmchan); + ftdmchan = openr2_chan_get_client_data(r2chan); - ftdm_log(FTDM_LOG_DEBUG, "Handling CAS on channel %d.\n", openr2_chan_get_number(r2chan)); - // we only expect CAS and other OOB events on this thread/loop, once a call is started - // the MF events (in-band signaling) are handled in the call thread - openr2_chan_process_cas_signaling(r2chan); - } else { - ftdm_log(FTDM_LOG_DEBUG, "Ignoring event %d on channel %d.\n", event->enum_id, openr2_chan_get_number(r2chan)); - // XXX TODO: handle alarms here XXX + status = ftdm_channel_read_event(ftdmchan, &event); + ftdm_mutex_lock(ftdmchan->mutex); + if (status == FTDM_SUCCESS) { + switch (event->enum_id) { + case FTDM_OOB_CAS_BITS_CHANGE: + { + ftdm_log(FTDM_LOG_DEBUG, "Handling CAS on channel %d.\n", i); + openr2_chan_process_cas_signaling(r2chan); + } + break; + case FTDM_OOB_ALARM_TRAP: + case FTDM_OOB_ALARM_CLEAR: + { + ftdm_log(FTDM_LOG_DEBUG, "OOB EVENT: %s\n", ftdm_signal_event2str(event->enum_id)); + openr2_chan_process_oob_events(r2chan); + } + break; } } - /* XXX - * when ftdm_span_poll_event() returns FTDM_SUCCESS, means there are events pending on the span. - * is it possible to know on which channels those events are pending, without traversing the span? - * XXX */ - for (i = 1; i <= span->chan_count; i++) { - r2chan = R2CALL(span->channels[i])->r2chan; - ftdmchan = openr2_chan_get_client_data(r2chan); - r2call = R2CALL(ftdmchan); - - ftdm_mutex_lock(ftdmchan->mutex); - ftdm_set_flag(r2call, FTDM_R2_PROCESSING); - - if (ftdm_r2_state_advance(ftdmchan)) { - ftdm_clear_flag(r2call, FTDM_R2_PROCESSING); - ftdm_mutex_unlock(ftdmchan->mutex); - continue; - } - - /* handle timeout events first if any */ - openr2_chan_run_schedule(r2chan); - - /* process mf tones, if any */ - if (openr2_chan_get_read_enabled(r2chan)) { - openr2_chan_process_mf_signaling(r2chan); - } - - if (ftdm_r2_state_advance(ftdmchan)) { - ftdm_clear_flag(r2call, FTDM_R2_PROCESSING); - ftdm_mutex_unlock(ftdmchan->mutex); - continue; - } - - ftdm_clear_flag(r2call, FTDM_R2_PROCESSING); + if (!ftdm_r2_state_advance(ftdmchan)) { + ftdm_mutex_unlock(ftdmchan->mutex); + } + openr2_chan_process_signaling(r2chan); + if (!ftdm_r2_state_advance(ftdmchan)) { ftdm_mutex_unlock(ftdmchan->mutex); } - } else if (status != FTDM_TIMEOUT) { - ftdm_log(FTDM_LOG_ERROR, "ftdm_span_poll_event returned %d.\n", status); } ftdm_span_trigger_signals(span); - ftdm_sleep(20); } for (i = 1; i <= span->chan_count; i++) { diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c index c13455dd21..ae46852300 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c @@ -35,6 +35,7 @@ * Moises Silva * David Yat Sin * Nenad Corbic + * Arnaldo Pereira * */ @@ -99,7 +100,8 @@ static struct { /* a bunch of this stuff should go into the wanpipe_tdm_api_iface.h */ FIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event); -FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event); +FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_span_next_event); +FIO_CHANNEL_NEXT_EVENT_FUNCTION(wanpipe_channel_next_event); /** * \brief Poll for event on a wanpipe socket @@ -1110,13 +1112,188 @@ static FIO_GET_ALARMS_FUNCTION(wanpipe_get_alarms) return FTDM_SUCCESS; } +/** + * \brief Retrieves an event from a wanpipe channel + * \param channel Channel to retrieve event from + * \param event FreeTDM event to return + * \return Success or failure + */ +FIO_CHANNEL_NEXT_EVENT_FUNCTION(wanpipe_channel_next_event) +{ + ftdm_status_t status; + ftdm_oob_event_t event_id; + wanpipe_tdm_api_t tdm_api; + ftdm_span_t *span = ftdmchan->span; + + if (ftdmchan->last_event_time && !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_EVENT)) { + uint32_t diff = (uint32_t)(ftdm_current_time_in_ms() - ftdmchan->last_event_time); + /* XX printf("%u %u %u\n", diff, (unsigned)ftdm_current_time_in_ms(), (unsigned)ftdmchan->last_event_time); */ + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_WINK)) { + if (diff > wp_globals.wink_ms) { + ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_WINK); + ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_FLASH); + ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_OFFHOOK); + event_id = FTDM_OOB_OFFHOOK; + goto event; + } + } + + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_FLASH)) { + if (diff > wp_globals.flash_ms) { + ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_FLASH); + ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_WINK); + ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_OFFHOOK); + event_id = FTDM_OOB_ONHOOK; + + if (ftdmchan->type == FTDM_CHAN_TYPE_FXO) { + wanpipe_tdm_api_t tdm_api; + memset(&tdm_api, 0, sizeof(tdm_api)); + + sangoma_tdm_txsig_onhook(ftdmchan->sockfd,&tdm_api); + } + goto event; + } + } + } + + if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_EVENT)) + return FTDM_FAIL; + + memset(&tdm_api, 0, sizeof(tdm_api)); + status = sangoma_tdm_read_event(ftdmchan->sockfd, &tdm_api); + if (status != FTDM_SUCCESS) { + snprintf(span->last_error, sizeof(span->last_error), "%s", strerror(errno)); + ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to read event from channel: %s\n", strerror(errno)); + return FTDM_FAIL; + } + + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "read wanpipe event %d\n", tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type); + switch(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type) { + + case WP_TDMAPI_EVENT_LINK_STATUS: + { + switch(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_link_status) { + case WP_TDMAPI_EVENT_LINK_STATUS_CONNECTED: + event_id = FTDM_OOB_ALARM_CLEAR; + break; + default: + event_id = FTDM_OOB_ALARM_TRAP; + break; + }; + } + break; + + case WP_TDMAPI_EVENT_RXHOOK: + { + if (ftdmchan->type == FTDM_CHAN_TYPE_FXS) { + event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_hook_state & WP_TDMAPI_EVENT_RXHOOK_OFF ? FTDM_OOB_OFFHOOK : FTDM_OOB_ONHOOK; + if (event_id == FTDM_OOB_OFFHOOK) { + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_FLASH)) { + ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_FLASH); + ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_WINK); + event_id = FTDM_OOB_FLASH; + goto event; + } else { + ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_WINK); + } + } else { + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_WINK)) { + ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_WINK); + ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_FLASH); + event_id = FTDM_OOB_WINK; + goto event; + } else { + ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_FLASH); + } + } + break; + } else { + wanpipe_tdm_api_t onhook_tdm_api; + memset(&onhook_tdm_api, 0, sizeof(onhook_tdm_api)); + status = sangoma_tdm_txsig_onhook(ftdmchan->sockfd, &onhook_tdm_api); + if (status) { + snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "ONHOOK Failed"); + return FTDM_FAIL; + } + event_id = onhook_tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_hook_state & WP_TDMAPI_EVENT_RXHOOK_OFF ? FTDM_OOB_ONHOOK : FTDM_OOB_NOOP; + } + } + break; + case WP_TDMAPI_EVENT_RING_DETECT: + { + event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_ring_state == WP_TDMAPI_EVENT_RING_PRESENT ? FTDM_OOB_RING_START : FTDM_OOB_RING_STOP; + } + break; + /* + disabled this ones when configuring, we don't need them, do we? + case WP_TDMAPI_EVENT_RING_TRIP_DETECT: + { + event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_ring_state == WP_TDMAPI_EVENT_RING_PRESENT ? FTDM_OOB_ONHOOK : FTDM_OOB_OFFHOOK; + } + break; + */ + case WP_TDMAPI_EVENT_RBS: + { + event_id = FTDM_OOB_CAS_BITS_CHANGE; + ftdmchan->rx_cas_bits = wanpipe_swap_bits(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_rbs_bits); + } + break; + case WP_TDMAPI_EVENT_DTMF: + { + char tmp_dtmf[2] = { tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_digit, 0 }; + event_id = FTDM_OOB_NOOP; + + if (tmp_dtmf[0] == 'f') { + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Ignoring wanpipe DTMF: %c, fax tones will be passed through!\n", tmp_dtmf[0]); + break; + } + + if (tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_type == WAN_EC_TONE_PRESENT) { + ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_MUTE); + } + + if (tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_type == WAN_EC_TONE_STOP) { + ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_MUTE); + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE)) { + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Queuing wanpipe DTMF: %c\n", tmp_dtmf[0]); + ftdm_channel_queue_dtmf(ftdmchan, tmp_dtmf); + } + } + } + break; + case WP_TDMAPI_EVENT_ALARM: + { + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Got wanpipe alarms %d\n", tdm_api.wp_tdm_cmd.event.wp_api_event_alarm); + event_id = FTDM_OOB_ALARM_TRAP; + } + break; + default: + { + ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Unhandled wanpipe event %d\n", tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type); + event_id = FTDM_OOB_INVALID; + } + break; + } + +event: + + ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_EVENT); + + ftdmchan->last_event_time = 0; + span->event_header.e_type = FTDM_EVENT_OOB; + span->event_header.enum_id = event_id; + span->event_header.channel = ftdmchan; + *event = &span->event_header; + return FTDM_SUCCESS; +} + /** * \brief Retrieves an event from a wanpipe span * \param span Span to retrieve event from * \param event FreeTDM event to return * \return Success or failure */ -FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event) +FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_span_next_event) { uint32_t i,err; ftdm_oob_event_t event_id; @@ -1348,7 +1525,8 @@ static FIO_IO_LOAD_FUNCTION(wanpipe_init) wanpipe_interface.read = wanpipe_read; wanpipe_interface.write = wanpipe_write; wanpipe_interface.poll_event = wanpipe_poll_event; - wanpipe_interface.next_event = wanpipe_next_event; + wanpipe_interface.next_event = wanpipe_span_next_event; + wanpipe_interface.channel_next_event = wanpipe_channel_next_event; wanpipe_interface.channel_destroy = wanpipe_channel_destroy; wanpipe_interface.get_alarms = wanpipe_get_alarms; *fio = &wanpipe_interface; diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index 508c6996d5..9ce213c962 100644 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -465,6 +465,7 @@ struct ftdm_memory_handler { #define FIO_SPAN_GET_SIG_STATUS_ARGS (ftdm_span_t *span, ftdm_signaling_status_t *status) #define FIO_SPAN_POLL_EVENT_ARGS (ftdm_span_t *span, uint32_t ms, short *poll_events) #define FIO_SPAN_NEXT_EVENT_ARGS (ftdm_span_t *span, ftdm_event_t **event) +#define FIO_CHANNEL_NEXT_EVENT_ARGS (ftdm_channel_t *ftdmchan, ftdm_event_t **event) #define FIO_SIGNAL_CB_ARGS (ftdm_sigmsg_t *sigmsg) #define FIO_EVENT_CB_ARGS (ftdm_channel_t *ftdmchan, ftdm_event_t *event) #define FIO_CONFIGURE_SPAN_ARGS (ftdm_span_t *span, const char *str, ftdm_chan_type_t type, char *name, char *number) @@ -496,6 +497,7 @@ typedef ftdm_status_t (*fio_span_set_sig_status_t) FIO_SPAN_SET_SIG_STATUS_ARGS; typedef ftdm_status_t (*fio_span_get_sig_status_t) FIO_SPAN_GET_SIG_STATUS_ARGS; typedef ftdm_status_t (*fio_span_poll_event_t) FIO_SPAN_POLL_EVENT_ARGS ; typedef ftdm_status_t (*fio_span_next_event_t) FIO_SPAN_NEXT_EVENT_ARGS ; +typedef ftdm_status_t (*fio_channel_next_event_t) FIO_CHANNEL_NEXT_EVENT_ARGS ; typedef ftdm_status_t (*fio_signal_cb_t) FIO_SIGNAL_CB_ARGS ; typedef ftdm_status_t (*fio_event_cb_t) FIO_EVENT_CB_ARGS ; typedef ftdm_status_t (*fio_configure_span_t) FIO_CONFIGURE_SPAN_ARGS ; @@ -528,6 +530,7 @@ typedef ftdm_status_t (*fio_api_t) FIO_API_ARGS ; #define FIO_SPAN_GET_SIG_STATUS_FUNCTION(name) ftdm_status_t name FIO_SPAN_GET_SIG_STATUS_ARGS #define FIO_SPAN_POLL_EVENT_FUNCTION(name) ftdm_status_t name FIO_SPAN_POLL_EVENT_ARGS #define FIO_SPAN_NEXT_EVENT_FUNCTION(name) ftdm_status_t name FIO_SPAN_NEXT_EVENT_ARGS +#define FIO_CHANNEL_NEXT_EVENT_FUNCTION(name) ftdm_status_t name FIO_CHANNEL_NEXT_EVENT_ARGS #define FIO_SIGNAL_CB_FUNCTION(name) ftdm_status_t name FIO_SIGNAL_CB_ARGS #define FIO_EVENT_CB_FUNCTION(name) ftdm_status_t name FIO_EVENT_CB_ARGS #define FIO_CONFIGURE_SPAN_FUNCTION(name) ftdm_status_t name FIO_CONFIGURE_SPAN_ARGS @@ -566,6 +569,7 @@ struct ftdm_io_interface { fio_write_t write; /*!< Write data to the channel */ fio_span_poll_event_t poll_event; /*!< Poll for events on the whole span */ fio_span_next_event_t next_event; /*!< Retrieve an event from the span */ + fio_channel_next_event_t channel_next_event; /*!< Retrieve an event from channel */ fio_api_t api; /*!< Execute a text command */ }; diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h index 06f899c8c9..7d3ee68176 100644 --- a/libs/freetdm/src/include/private/ftdm_core.h +++ b/libs/freetdm/src/include/private/ftdm_core.h @@ -615,6 +615,23 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_chan(ftdm_channel_t *ftdmchan); */ FT_DECLARE(ftdm_status_t) ftdm_span_next_event(ftdm_span_t *span, ftdm_event_t **event); +/*! + * \brief Retrieves an event from the span + * + * \note + * This function is non-reentrant and not thread-safe. + * The event returned may be modified if the function is called again + * from a different thread or even the same. It is recommended to + * handle events from the same span in a single thread. + * + * \param span The channel to retrieve the event from + * \param event Pointer to store the pointer to the event + * + * \retval FTDM_SUCCESS success (at least one event available) + * \retval FTDM_FAIL failure + */ +FT_DECLARE(ftdm_status_t) ftdm_channel_read_event(ftdm_channel_t *ftdmchan, ftdm_event_t **event); + /*! * \brief Enqueue a DTMF string into the channel * From a5d53b8a38b770f702fa55d72e996ed54a32f181 Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Wed, 24 Nov 2010 22:14:06 -0200 Subject: [PATCH 082/237] freetdm: removed wrong main loop code --- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 30 +++------------------- 1 file changed, 4 insertions(+), 26 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index 7c5f4a46af..8a4a826906 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -847,7 +847,7 @@ static int ftdm_r2_io_get_oob_event(openr2_chan_t *r2chan, openr2_oob_event_t *e *event = OR2_OOB_EVENT_NONE; status = ftdm_channel_read_event(ftdmchan, &fevent); if (status != FTDM_SUCCESS) { - //ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "failed to retrieve freetdm event!\n"); + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "failed to retrieve freetdm event!\n"); return -1; } if (fevent->e_type != FTDM_EVENT_OOB) @@ -1412,33 +1412,11 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) r2call = R2CALL(ftdmchan); ftdmchan = openr2_chan_get_client_data(r2chan); - status = ftdm_channel_read_event(ftdmchan, &event); ftdm_mutex_lock(ftdmchan->mutex); - if (status == FTDM_SUCCESS) { - switch (event->enum_id) { - case FTDM_OOB_CAS_BITS_CHANGE: - { - ftdm_log(FTDM_LOG_DEBUG, "Handling CAS on channel %d.\n", i); - openr2_chan_process_cas_signaling(r2chan); - } - break; - case FTDM_OOB_ALARM_TRAP: - case FTDM_OOB_ALARM_CLEAR: - { - ftdm_log(FTDM_LOG_DEBUG, "OOB EVENT: %s\n", ftdm_signal_event2str(event->enum_id)); - openr2_chan_process_oob_events(r2chan); - } - break; - } - } - - if (!ftdm_r2_state_advance(ftdmchan)) { - ftdm_mutex_unlock(ftdmchan->mutex); - } + ftdm_r2_state_advance(ftdmchan); openr2_chan_process_signaling(r2chan); - if (!ftdm_r2_state_advance(ftdmchan)) { - ftdm_mutex_unlock(ftdmchan->mutex); - } + ftdm_r2_state_advance(ftdmchan); + ftdm_mutex_unlock(ftdmchan->mutex); } ftdm_span_trigger_signals(span); } From 2b0189becad007b0683272a0a3d46a952cc520ed Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Wed, 24 Nov 2010 22:58:05 -0200 Subject: [PATCH 083/237] freetdm: now wanpipe_channel_next_event() doesn't expect the flag FTDM_CHANNEL_EVENT to be set. If it is, it just clears it. Also removed unused code from wanpipe_channel_next_event() --- .../src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c | 39 ++----------------- 1 file changed, 4 insertions(+), 35 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c index ae46852300..1a43c4db50 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c @@ -1125,45 +1125,16 @@ FIO_CHANNEL_NEXT_EVENT_FUNCTION(wanpipe_channel_next_event) wanpipe_tdm_api_t tdm_api; ftdm_span_t *span = ftdmchan->span; - if (ftdmchan->last_event_time && !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_EVENT)) { - uint32_t diff = (uint32_t)(ftdm_current_time_in_ms() - ftdmchan->last_event_time); - /* XX printf("%u %u %u\n", diff, (unsigned)ftdm_current_time_in_ms(), (unsigned)ftdmchan->last_event_time); */ - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_WINK)) { - if (diff > wp_globals.wink_ms) { - ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_WINK); - ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_FLASH); - ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_OFFHOOK); - event_id = FTDM_OOB_OFFHOOK; - goto event; - } - } - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_FLASH)) { - if (diff > wp_globals.flash_ms) { - ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_FLASH); - ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_WINK); - ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_OFFHOOK); - event_id = FTDM_OOB_ONHOOK; - - if (ftdmchan->type == FTDM_CHAN_TYPE_FXO) { - wanpipe_tdm_api_t tdm_api; - memset(&tdm_api, 0, sizeof(tdm_api)); - - sangoma_tdm_txsig_onhook(ftdmchan->sockfd,&tdm_api); - } - goto event; - } - } - } - - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_EVENT)) - return FTDM_FAIL; + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_EVENT)) + ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_EVENT); memset(&tdm_api, 0, sizeof(tdm_api)); status = sangoma_tdm_read_event(ftdmchan->sockfd, &tdm_api); if (status != FTDM_SUCCESS) { +#if 0 snprintf(span->last_error, sizeof(span->last_error), "%s", strerror(errno)); ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to read event from channel: %s\n", strerror(errno)); +#endif return FTDM_FAIL; } @@ -1277,8 +1248,6 @@ FIO_CHANNEL_NEXT_EVENT_FUNCTION(wanpipe_channel_next_event) event: - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_EVENT); - ftdmchan->last_event_time = 0; span->event_header.e_type = FTDM_EVENT_OOB; span->event_header.enum_id = event_id; From b814dc17ce5aefded953fc7e30db257088f70475 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Wed, 24 Nov 2010 20:04:43 -0500 Subject: [PATCH 084/237] freetdm: ISDN Changes to better match SIP-to-TDM states --- libs/freetdm/mod_freetdm/mod_freetdm.c | 15 ++- libs/freetdm/src/ftdm_io.c | 16 +-- .../src/ftmod/ftmod_analog/ftmod_analog.c | 16 +-- .../ftmod_sangoma_isdn/ftmod_sangoma_isdn.c | 66 +++++++++-- .../ftmod_sangoma_isdn/ftmod_sangoma_isdn.h | 26 ++++- .../ftmod_sangoma_isdn_cfg.c | 9 ++ .../ftmod_sangoma_isdn_stack_hndl.c | 108 +++++++++++++----- .../ftmod_sangoma_isdn_stack_out.c | 85 ++++++++++++-- .../ftmod_sangoma_isdn_support.c | 18 +++ libs/freetdm/src/include/freetdm.h | 8 +- libs/freetdm/src/include/private/ftdm_types.h | 8 +- libs/freetdm/src/testanalog.c | 2 +- 12 files changed, 303 insertions(+), 74 deletions(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 8d961123cb..27dc8d8c92 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -425,8 +425,11 @@ static switch_status_t channel_on_routing(switch_core_session_t *session) tech_pvt = switch_core_session_get_private(session); assert(tech_pvt != NULL); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL ROUTING\n", switch_channel_get_name(channel)); + assert(tech_pvt->ftdmchan != NULL); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL ROUTING\n", switch_channel_get_name(channel)); + + ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_PROCEED); return SWITCH_STATUS_SUCCESS; } @@ -852,7 +855,7 @@ static switch_status_t channel_receive_message_b(switch_core_session_t *session, switch (msg->message_id) { case SWITCH_MESSAGE_INDICATE_RINGING: { - ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_PROGRESS); + ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_RINGING); } break; case SWITCH_MESSAGE_INDICATE_PROGRESS: @@ -935,7 +938,7 @@ static switch_status_t channel_receive_message_fxs(switch_core_session_t *sessio !switch_channel_test_flag(channel, CF_EARLY_MEDIA) && !switch_channel_test_flag(channel, CF_RING_READY) ) { - ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_RING); + ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_RINGING); switch_channel_mark_ring_ready(channel); } break; @@ -2133,7 +2136,7 @@ static FIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal) spanid, chanid, (uuid) ? uuid : "N/A"); } } - break; + break; case FTDM_SIGEVENT_SIGSTATUS_CHANGED: { ftdm_signaling_status_t sigstatus = sigmsg->raw_data ? *((ftdm_signaling_status_t*)(sigmsg->raw_data)) : sigmsg->sigstatus; @@ -2141,6 +2144,10 @@ static FIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal) spanid, chanid, ftdm_signaling_status2str(sigstatus)); } break; + case FTDM_SIGEVENT_PROCEED: + case FTDM_SIGEVENT_MSG: + /* FS does not have handlers for these messages, so ignore them for now */ + break; default: { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unhandled msg type %d for channel %d:%d\n", diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 64233a97ac..ede3ff8fc8 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -2033,7 +2033,6 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_answer(const char *file, const char goto done; } - if (ftdmchan->state < FTDM_CHANNEL_STATE_PROGRESS) { ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS, 1); } @@ -2202,14 +2201,19 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const ch switch (indication) { /* FIXME: ring and busy cannot be used with all signaling stacks * (particularly isdn stacks I think, we should emulate or just move to hangup with busy cause) */ - case FTDM_CHANNEL_INDICATE_RING: - ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_RING, 1); + case FTDM_CHANNEL_INDICATE_RINGING: + ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_RINGING, 1); break; - case FTDM_CHANNEL_INDICATE_BUSY: ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_BUSY, 1); break; - + case FTDM_CHANNEL_INDICATE_PROCEED: + if (ftdm_test_flag(ftdmchan->span, FTDM_SPAN_USE_PROCEED_STATE)) { + if (ftdmchan->state == FTDM_CHANNEL_STATE_RING) { + ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROCEED, 1); + } + } + break; case FTDM_CHANNEL_INDICATE_PROGRESS: if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { ftdm_set_flag(ftdmchan, FTDM_CHANNEL_PROGRESS); @@ -2217,7 +2221,6 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const ch ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS, 1); } break; - case FTDM_CHANNEL_INDICATE_PROGRESS_MEDIA: if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { ftdm_set_flag(ftdmchan, FTDM_CHANNEL_PROGRESS); @@ -2236,7 +2239,6 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const ch ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, 1); } break; - default: ftdm_log(file, func, line, FTDM_LOG_LEVEL_WARNING, "Do not know how to indicate %d\n", indication); status = FTDM_FAIL; diff --git a/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c b/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c index fc9bea6ef0..99d256655a 100644 --- a/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c +++ b/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c @@ -438,7 +438,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj) { if (state_counter > 5000 || !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_CALLERID_DETECT)) { ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_CALLERID_DETECT, NULL); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE); + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING); } } break; @@ -492,8 +492,8 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj) } if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK) && - (ftdmchan->last_state == FTDM_CHANNEL_STATE_RING || ftdmchan->last_state == FTDM_CHANNEL_STATE_DIALTONE - || ftdmchan->last_state >= FTDM_CHANNEL_STATE_IDLE)) { + (ftdmchan->last_state == FTDM_CHANNEL_STATE_RINGING || ftdmchan->last_state == FTDM_CHANNEL_STATE_DIALTONE + || ftdmchan->last_state >= FTDM_CHANNEL_STATE_RING)) { ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY); } else { ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_CLEARING; @@ -535,7 +535,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj) } } case FTDM_CHANNEL_STATE_UP: - case FTDM_CHANNEL_STATE_IDLE: + case FTDM_CHANNEL_STATE_RING: { ftdm_sleep(interval); continue; @@ -599,7 +599,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj) ftdm_channel_use(ftdmchan); } break; - case FTDM_CHANNEL_STATE_IDLE: + case FTDM_CHANNEL_STATE_RING: { ftdm_channel_use(ftdmchan); sig.event_id = FTDM_SIGEVENT_START; @@ -669,7 +669,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj) continue; } break; - case FTDM_CHANNEL_STATE_RING: + case FTDM_CHANNEL_STATE_RINGING: { ftdm_buffer_zero(dt_buffer); teletone_run(&ts, ftdmchan->span->tone_map[FTDM_TONEMAP_RING]); @@ -732,7 +732,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj) if (last_digit && (!collecting || ((elapsed - last_digit > analog_data->digit_timeout) || strlen(dtmf) >= analog_data->max_dialstr))) { ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Number obtained [%s]\n", dtmf); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE); + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING); last_digit = 0; collecting = 0; } @@ -890,7 +890,7 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e if (ftdm_test_flag(analog_data, FTDM_ANALOG_CALLERID)) { ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_GET_CALLERID); } else { - ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_IDLE); + ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_RING); } event->channel->ring_count = 1; ftdm_mutex_unlock(event->channel->mutex); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c index 77ad917bf1..6f5f838590 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c @@ -115,7 +115,19 @@ ftdm_state_map_t sangoma_isdn_state_map = { ZSD_INBOUND, ZSM_UNACCEPTABLE, {FTDM_CHANNEL_STATE_RING, FTDM_END}, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS, FTDM_END} + {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROCEED, FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_END} + }, + { + ZSD_INBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_PROCEED, FTDM_END}, + {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA,FTDM_END} + }, + { + ZSD_INBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_RINGING, FTDM_END}, + {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END}, }, { ZSD_INBOUND, @@ -189,9 +201,17 @@ ftdm_state_map_t sangoma_isdn_state_map = { ZSD_OUTBOUND, ZSM_UNACCEPTABLE, {FTDM_CHANNEL_STATE_DIALING, FTDM_END}, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS, - FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_DOWN, FTDM_END} + {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, + FTDM_CHANNEL_STATE_PROCEED, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, + FTDM_CHANNEL_STATE_DOWN, FTDM_END} }, + { + ZSD_OUTBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_PROCEED, FTDM_END}, + {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, + FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END}, + }, { ZSD_OUTBOUND, ZSM_UNACCEPTABLE, @@ -604,13 +624,15 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan) break; case FTDM_CHANNEL_STATE_GET_CALLERID: { - sngisdn_set_flag(sngisdn_info, FLAG_SENT_PROCEED); - sngisdn_snd_proceed(ftdmchan); + if (!sngisdn_test_flag(sngisdn_info, FLAG_SENT_PROCEED)) { + sngisdn_set_flag(sngisdn_info, FLAG_SENT_PROCEED); + sngisdn_snd_proceed(ftdmchan); + } /* Wait in this state until we get FACILITY msg */ } break; case FTDM_CHANNEL_STATE_RING: /* incoming call request */ - { + { 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); /* we have enough information to inform FTDM of the call*/ @@ -635,6 +657,25 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan) } } break; + case FTDM_CHANNEL_STATE_PROCEED: + { + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { + /*OUTBOUND...so we were told by the line of this so noifiy the user*/ + sigev.event_id = FTDM_SIGEVENT_PROCEED; + ftdm_span_send_signal(ftdmchan->span, &sigev); + } else { + if (!sngisdn_test_flag(sngisdn_info, FLAG_SENT_PROCEED)) { + sngisdn_set_flag(sngisdn_info, FLAG_SENT_PROCEED); + sngisdn_snd_proceed(ftdmchan); + } + } + } + break; + case FTDM_CHANNEL_STATE_RINGING: + { + sngisdn_snd_alert(ftdmchan, SNGISDN_PROGIND_NETE_ISDN); + } + break; case FTDM_CHANNEL_STATE_PROGRESS: { /*check if the channel is inbound or outbound*/ @@ -642,9 +683,12 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan) /*OUTBOUND...so we were told by the line of this so noifiy the user*/ sigev.event_id = FTDM_SIGEVENT_PROGRESS; ftdm_span_send_signal(ftdmchan->span, &sigev); - } else if (!sngisdn_test_flag(sngisdn_info, FLAG_SENT_PROCEED)) { - sngisdn_set_flag(sngisdn_info, FLAG_SENT_PROCEED); - sngisdn_snd_proceed(ftdmchan); + } else { + /* If we already sent a PROCEED before, do not send a PROGRESS as there is nothing to indicate to the remote switch */ + if (ftdmchan->last_state != FTDM_CHANNEL_STATE_PROCEED) { + /* Send a progress message, indicating: Call is not end-to-end ISDN, further call progress may be available */ + sngisdn_snd_progress(ftdmchan, SNGISDN_PROGIND_NETE_ISDN); + } } } break; @@ -654,7 +698,8 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan) sigev.event_id = FTDM_SIGEVENT_PROGRESS_MEDIA; ftdm_span_send_signal(ftdmchan->span, &sigev); } else { - sngisdn_snd_progress(ftdmchan); + /* Send a progress message, indicating: In-band information/pattern available */ + sngisdn_snd_progress(ftdmchan, SNGISDN_PROGIND_IB_AVAIL); } } break; @@ -992,6 +1037,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config) span->state_map = &sangoma_isdn_state_map; ftdm_set_flag(span, FTDM_SPAN_USE_CHAN_QUEUE); ftdm_set_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE); + ftdm_set_flag(span, FTDM_SPAN_USE_PROCEED_STATE); if (span->trunk_type == FTDM_TRUNK_BRI_PTMP || span->trunk_type == FTDM_TRUNK_BRI) { diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h index 81a98cf0d3..25ffef85e5 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h @@ -75,7 +75,8 @@ typedef enum { FLAG_DELAYED_REL = (1 << 7), FLAG_SENT_PROCEED = (1 << 8), FLAG_SEND_DISC = (1 << 9), - FLAG_ACTIVATING = (1 << 10), /* Used for BRI only, flag is set after we request line CONNECTED */ + /* Used for BRI only, flag is set after we request line CONNECTED */ + FLAG_ACTIVATING = (1 << 10), } sngisdn_flag_t; @@ -135,6 +136,21 @@ typedef enum { SNGISDN_EVENT_RST_IND, } ftdm_sngisdn_event_id_t; +typedef enum { + /* Call is not end-to-end ISDN */ + SNGISDN_PROGIND_NETE_ISDN = 1, + /* Destination address is non-ISDN */ + SNGISDN_PROGIND_DEST_NISDN, + /* Origination address is non-ISDN */ + SNGISDN_PROGIND_ORIG_NISDN, + /* Call has returned to the ISDN */ + SNGISDN_PROGIND_RET_ISDN, + /* Interworking as occured and has resulted in a telecommunication service change */ + SNGISDN_PROGIND_SERV_CHANGE, + /* In-band information or an appropriate pattern is now available */ + SNGISDN_PROGIND_IB_AVAIL, +} ftdm_sngisdn_progind_t; + /* Only timers that can be cancelled are listed here */ #define SNGISDN_NUM_TIMERS 1 /* Increase NUM_TIMERS as number of ftdm_sngisdn_timer_t increases */ @@ -181,6 +197,7 @@ typedef struct sngisdn_span_data { uint8_t trace_flags; /* TODO: change to flags, so we can use ftdm_test_flag etc.. */ uint8_t overlap_dial; uint8_t setup_arb; + uint8_t facility_ie_decode; uint8_t facility; int8_t facility_timeout; uint8_t num_local_numbers; @@ -288,13 +305,14 @@ void stack_pst_init(Pst *pst); void sngisdn_snd_setup(ftdm_channel_t *ftdmchan); void sngisdn_snd_setup_ack(ftdm_channel_t *ftdmchan); void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan); -void sngisdn_snd_progress(ftdm_channel_t *ftdmchan); -void sngisdn_snd_alert(ftdm_channel_t *ftdmchan); +void sngisdn_snd_progress(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind); +void sngisdn_snd_alert(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind); void sngisdn_snd_connect(ftdm_channel_t *ftdmchan); void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan); void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare); void sngisdn_snd_reset(ftdm_channel_t *ftdmchan); void sngisdn_snd_con_complete(ftdm_channel_t *ftdmchan); +void sngisdn_snd_fac_req(ftdm_channel_t *ftdmchan); void sngisdn_snd_info_req(ftdm_channel_t *ftdmchan); void sngisdn_snd_status_enq(ftdm_channel_t *ftdmchan); void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len); @@ -362,6 +380,8 @@ ftdm_status_t cpy_calling_num_from_stack(ftdm_caller_data_t *ftdm, CgPtyNmb *cgP ftdm_status_t cpy_called_num_from_stack(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb); ftdm_status_t cpy_redir_num_from_stack(ftdm_caller_data_t *ftdm, RedirNmb *redirNmb); ftdm_status_t cpy_calling_name_from_stack(ftdm_caller_data_t *ftdm, Display *display); +ftdm_status_t cpy_facility_ie_from_stack(ftdm_caller_data_t *ftdm, uint8_t *data, uint32_t data_len); + ftdm_status_t cpy_calling_num_from_user(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *ftdm); ftdm_status_t cpy_called_num_from_user(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *ftdm); ftdm_status_t cpy_redir_num_from_user(RedirNmb *redirNmb, ftdm_caller_data_t *ftdm); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c index 3b264ae02f..657aa5e206 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c @@ -190,6 +190,7 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_ signal_data->min_digits = 8; signal_data->overlap_dial = SNGISDN_OPT_DEFAULT; signal_data->setup_arb = SNGISDN_OPT_DEFAULT; + signal_data->facility_ie_decode = SNGISDN_OPT_TRUE; signal_data->timer_t3 = 8; signal_data->link_id = span->span_id; @@ -289,6 +290,14 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_ if (signal_data->facility_timeout < 0) { signal_data->facility_timeout = 0; } + } else if (!strcasecmp(var, "facility-ie-decode")) { + if (!strcasecmp(val, "yes")) { + signal_data->facility_ie_decode = SNGISDN_OPT_TRUE; + } else if (!strcasecmp(val, "no")) { + signal_data->facility_ie_decode = SNGISDN_OPT_FALSE; + } else { + ftdm_log(FTDM_LOG_ERROR, "Invalid value for parameter:%s:%s\n", var, val); + } } else { ftdm_log(FTDM_LOG_WARNING, "Ignoring unknown parameter %s\n", ftdm_parameters[paramindex].var); } diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c index 3fe0422a4e..209284a8b6 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c @@ -144,31 +144,35 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event) snprintf(ftdmchan->caller_data.aniII, 5, "%.2d", conEvnt->ni2OctStr.str.val[3]); } } - - if (signal_data->facility == SNGISDN_OPT_TRUE && conEvnt->facilityStr.eh.pres) { - /* Verify whether the Caller Name will come in a subsequent FACILITY message */ - uint16_t ret_val; - char retrieved_str[255]; - - ret_val = sng_isdn_retrieve_facility_caller_name(conEvnt->facilityStr.facilityStr.val, conEvnt->facilityStr.facilityStr.len, retrieved_str); - /* - return values for "sng_isdn_retrieve_facility_information_following": - If there will be no information following, or fails to decode IE, returns -1 - If there will be no information following, but current FACILITY IE contains a caller name, returns 0 - If there will be information following, returns 1 - */ - if (ret_val == 1) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Expecting Caller name in FACILITY\n"); - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_GET_CALLERID); - /* Launch timer in case we never get a FACILITY msg */ - if (signal_data->facility_timeout) { - ftdm_sched_timer(signal_data->sched, "facility_timeout", signal_data->facility_timeout, - sngisdn_facility_timeout, (void*) sngisdn_info, &sngisdn_info->timers[SNGISDN_TIMER_FACILITY]); + if (conEvnt->facilityStr.eh.pres) { + if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) { + cpy_facility_ie_from_stack(&ftdmchan->caller_data, conEvnt->facilityStr.facilityStr.val, conEvnt->facilityStr.facilityStr.len); + } else if (signal_data->facility == SNGISDN_OPT_TRUE) { + /* Verify whether the Caller Name will come in a subsequent FACILITY message */ + uint16_t ret_val; + char retrieved_str[255]; + + ret_val = sng_isdn_retrieve_facility_caller_name(conEvnt->facilityStr.facilityStr.val, conEvnt->facilityStr.facilityStr.len, retrieved_str); + /* + return values for "sng_isdn_retrieve_facility_information_following": + If there will be no information following, or fails to decode IE, returns -1 + If there will be no information following, but current FACILITY IE contains a caller name, returns 0 + If there will be information following, returns 1 + */ + + if (ret_val == 1) { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Expecting Caller name in FACILITY\n"); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_GET_CALLERID); + /* Launch timer in case we never get a FACILITY msg */ + if (signal_data->facility_timeout) { + ftdm_sched_timer(signal_data->sched, "facility_timeout", signal_data->facility_timeout, + sngisdn_facility_timeout, (void*) sngisdn_info, &sngisdn_info->timers[SNGISDN_TIMER_FACILITY]); + } + break; + } else if (ret_val == 0) { + strcpy(ftdmchan->caller_data.cid_name, retrieved_str); } - break; - } else if (ret_val == 0) { - strcpy(ftdmchan->caller_data.cid_name, retrieved_str); } } } @@ -269,6 +273,7 @@ void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event) if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { switch(ftdmchan->state) { + case FTDM_CHANNEL_STATE_PROCEED: case FTDM_CHANNEL_STATE_PROGRESS: case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: case FTDM_CHANNEL_STATE_DIALING: @@ -367,8 +372,10 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event) case MI_CALLPROC: switch(ftdmchan->state) { - case FTDM_CHANNEL_STATE_DIALING: - if (evntType == MI_PROGRESS || + case FTDM_CHANNEL_STATE_DIALING: + if (evntType == MI_CALLPROC) { + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROCEED); + } else if (evntType == MI_PROGRESS || (cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL)) { ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); } else { @@ -417,6 +424,7 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event) } break; case FTDM_CHANNEL_STATE_RING: + case FTDM_CHANNEL_STATE_PROCEED: case FTDM_CHANNEL_STATE_PROGRESS: case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: case FTDM_CHANNEL_STATE_UP: @@ -446,6 +454,7 @@ void sngisdn_process_disc_ind (sngisdn_event_data_t *sngisdn_event) uint32_t spInstId = sngisdn_event->spInstId; sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info; ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; + sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; DiscEvnt *discEvnt = &sngisdn_event->event.discEvnt; @@ -454,12 +463,20 @@ void sngisdn_process_disc_ind (sngisdn_event_data_t *sngisdn_event) ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing DISCONNECT (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n"); - switch (ftdmchan->state) { + switch (ftdmchan->state) { case FTDM_CHANNEL_STATE_RING: case FTDM_CHANNEL_STATE_DIALING: + case FTDM_CHANNEL_STATE_PROCEED: case FTDM_CHANNEL_STATE_PROGRESS: case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: - case FTDM_CHANNEL_STATE_UP: + case FTDM_CHANNEL_STATE_UP: + if (discEvnt->facilityStr.eh.pres) { + if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) { + cpy_facility_ie_from_stack(&ftdmchan->caller_data, discEvnt->facilityStr.facilityStr.val, discEvnt->facilityStr.facilityStr.len); + } else { + /* Call libsng_isdn facility decode function and copy variables here */ + } + } if (discEvnt->causeDgn[0].eh.pres && discEvnt->causeDgn[0].causeVal.pres) { ftdmchan->caller_data.hangup_cause = discEvnt->causeDgn[0].causeVal.val; } else { @@ -503,6 +520,7 @@ void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event) uint32_t spInstId = sngisdn_event->spInstId; sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info; ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; + sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; RelEvnt *relEvnt = &sngisdn_event->event.relEvnt; @@ -538,6 +556,7 @@ void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event) sngisdn_set_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN); } /* fall-through */ + case FTDM_CHANNEL_STATE_PROCEED: case FTDM_CHANNEL_STATE_PROGRESS: case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: case FTDM_CHANNEL_STATE_UP: @@ -547,6 +566,15 @@ void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event) not changed while we were waiting for ftdmchan->mutex by comparing suInstId's */ if (((sngisdn_chan_data_t*)ftdmchan->call_data)->suInstId == suInstId || ((sngisdn_chan_data_t*)ftdmchan->call_data)->spInstId == spInstId) { + + if (relEvnt->facilityStr.eh.pres) { + if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) { + cpy_facility_ie_from_stack(&ftdmchan->caller_data, relEvnt->facilityStr.facilityStr.val, relEvnt->facilityStr.facilityStr.len); + } else { + /* Call libsng_isdn facility decode function and copy variables here */ + } + } + if (relEvnt->causeDgn[0].eh.pres && relEvnt->causeDgn[0].causeVal.pres) { ftdmchan->caller_data.hangup_cause = relEvnt->causeDgn[0].causeVal.val; ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "cause:%d\n", ftdmchan->caller_data.hangup_cause); @@ -725,15 +753,16 @@ void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event) switch (ftdmchan->state) { case FTDM_CHANNEL_STATE_GET_CALLERID: /* Update the caller ID Name */ + if (facEvnt->facElmt.facStr.pres) { char retrieved_str[255]; - + /* return values for "sng_isdn_retrieve_facility_information_following": If there will be no information following, or fails to decode IE, returns -1 If there will be no information following, but current FACILITY IE contains a caller name, returns 0 If there will be information following, returns 1 */ - + if (sng_isdn_retrieve_facility_caller_name(&facEvnt->facElmt.facStr.val[2], facEvnt->facElmt.facStr.len, retrieved_str) == 0) { strcpy(ftdmchan->caller_data.cid_name, retrieved_str); } else { @@ -751,6 +780,25 @@ void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event) /* We received the caller ID Name in FACILITY, but its too late, facility-timeout already occurred */ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "FACILITY received, but we already proceeded with call\n"); break; + case FTDM_CHANNEL_STATE_UP: + { + ftdm_sigmsg_t sigev; + if (facEvnt->facElmt.facStr.pres) { + if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) { + cpy_facility_ie_from_stack(&ftdmchan->caller_data, &facEvnt->facElmt.facStr.val[2], facEvnt->facElmt.facStr.len); + } else { + /* Call libsng_isdn facility decode function and copy variables here */ + } + } + memset(&sigev, 0, sizeof(sigev)); + sigev.chan_id = ftdmchan->chan_id; + sigev.span_id = ftdmchan->span_id; + sigev.channel = ftdmchan; + + sigev.event_id = FTDM_SIGEVENT_MSG; + ftdm_span_send_signal(ftdmchan->span, &sigev); + } + break; default: /* We do not support other FACILITY types for now, so do nothing */ break; @@ -865,6 +913,7 @@ void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event) ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "T302 Timer expired, proceeding with call\n"); ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING); break; + case FTDM_CHANNEL_STATE_PROCEED: case FTDM_CHANNEL_STATE_PROGRESS: case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Remote switch expecting OVERLAP receive, but we are already PROCEEDING\n"); @@ -882,6 +931,7 @@ void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event) break; case 3: switch (ftdmchan->state) { + case FTDM_CHANNEL_STATE_PROCEED: case FTDM_CHANNEL_STATE_PROGRESS: /* T310 timer has expired */ ftdmchan->caller_data.hangup_cause = staEvnt->causeDgn[0].causeVal.val; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c index 2853335efc..385d1eba9d 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c @@ -34,6 +34,9 @@ #include "ftmod_sangoma_isdn.h" +static void sngisdn_set_prog_desc(ProgInd *progInd, ftdm_sngisdn_progind_t prod_ind); +static void sngisdn_set_facilityStr(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr); + void sngisdn_snd_setup(ftdm_channel_t *ftdmchan) { ConEvnt conEvnt; @@ -138,6 +141,8 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan) cpy_redir_num_from_user(&conEvnt.redirNmb, &ftdmchan->caller_data); cpy_calling_name_from_user(&conEvnt, ftdmchan); + sngisdn_set_facilityStr(ftdmchan, &conEvnt.facilityStr); + ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending SETUP (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces); if (sng_isdn_con_request(signal_data->cc_id, sngisdn_info->suInstId, &conEvnt, signal_data->dchan_id, sngisdn_info->ces)) { @@ -323,14 +328,14 @@ void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan) return; } -void sngisdn_snd_progress(ftdm_channel_t *ftdmchan) +void sngisdn_snd_progress(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind) { CnStEvnt cnStEvnt; sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data; sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) { + if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) { ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending PROGRESS, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId); sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT); ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); @@ -351,7 +356,8 @@ void sngisdn_snd_progress(ftdm_channel_t *ftdmchan) cnStEvnt.progInd.codeStand0.pres = PRSNT_NODEF; cnStEvnt.progInd.codeStand0.val = IN_CSTD_CCITT; cnStEvnt.progInd.progDesc.pres = PRSNT_NODEF; - cnStEvnt.progInd.progDesc.val = IN_PD_IBAVAIL; + + sngisdn_set_prog_desc(&cnStEvnt.progInd, prog_ind); ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending PROGRESS (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces); if(sng_isdn_con_status(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId,&cnStEvnt, MI_PROGRESS, signal_data->dchan_id, sngisdn_info->ces)) { @@ -360,14 +366,14 @@ void sngisdn_snd_progress(ftdm_channel_t *ftdmchan) return; } -void sngisdn_snd_alert(ftdm_channel_t *ftdmchan) +void sngisdn_snd_alert(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind) { CnStEvnt cnStEvnt; sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data; sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) { + if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) { ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending ALERT, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId); sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT); ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); @@ -382,7 +388,7 @@ void sngisdn_snd_alert(ftdm_channel_t *ftdmchan) cnStEvnt.progInd.codeStand0.pres = PRSNT_NODEF; cnStEvnt.progInd.codeStand0.val = IN_CSTD_CCITT; cnStEvnt.progInd.progDesc.pres = PRSNT_NODEF; - cnStEvnt.progInd.progDesc.val = IN_PD_NOTETEISDN; + sngisdn_set_prog_desc(&cnStEvnt.progInd, prog_ind); ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending ALERT (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces); @@ -456,6 +462,27 @@ void sngisdn_snd_connect(ftdm_channel_t *ftdmchan) return; } +void sngisdn_snd_fac_req(ftdm_channel_t *ftdmchan) +{ + FacEvnt facEvnt; + + sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data; + sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; + + if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) { + ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending FACILITY, but no call data, ignoring (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId); + return; + } + + memset(&facEvnt, 0, sizeof(facEvnt)); + + ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending FACILITY (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces); + + if (sng_isdn_facility_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &facEvnt, MI_FACIL, signal_data->dchan_id, sngisdn_info->ces)) { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused FACILITY request\n"); + } + return; +} void sngisdn_snd_info_req(ftdm_channel_t *ftdmchan) { @@ -510,7 +537,7 @@ void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan) sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data; sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) { + if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) { ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending DISCONNECT, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId); sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT); @@ -531,6 +558,8 @@ void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan) discEvnt.causeDgn[0].recommend.pres = NOTPRSNT; discEvnt.causeDgn[0].dgnVal.pres = NOTPRSNT; + sngisdn_set_facilityStr(ftdmchan, &discEvnt.facilityStr); + ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending DISCONNECT (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId); if (sng_isdn_disc_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &discEvnt)) { ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused DISCONNECT request\n"); @@ -575,6 +604,8 @@ void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare) spInstId = sngisdn_info->spInstId; } + sngisdn_set_facilityStr(ftdmchan, &relEvnt.facilityStr); + ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending RELEASE/RELEASE COMPLETE (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, suInstId, spInstId); if (glare) { @@ -589,6 +620,46 @@ void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare) return; } +static void sngisdn_set_prog_desc(ProgInd *progInd, ftdm_sngisdn_progind_t prog_ind) +{ + switch(prog_ind) { + case SNGISDN_PROGIND_NETE_ISDN: + progInd->progDesc.val = IN_PD_NOTETEISDN; + break; + case SNGISDN_PROGIND_DEST_NISDN: + progInd->progDesc.val = IN_PD_DSTNOTISDN; + break; + case SNGISDN_PROGIND_ORIG_NISDN: + progInd->progDesc.val = IN_PD_ORGNOTISDN; + break; + case SNGISDN_PROGIND_RET_ISDN: + progInd->progDesc.val = IN_PD_CALLRET; + break; + case SNGISDN_PROGIND_SERV_CHANGE: + /* Trillium defines do not match ITU-T Q931 Progress descriptions, + indicate a delayed response for now */ + progInd->progDesc.val = IN_PD_DELRESP; + break; + case SNGISDN_PROGIND_IB_AVAIL: + progInd->progDesc.val = IN_PD_IBAVAIL; + break; + } + return; +} + +static void sngisdn_set_facilityStr(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr) +{ + const char *facility_str = NULL; + + facility_str = ftdm_channel_get_var(ftdmchan, "isdn.facility.val"); + if (facility_str) { + facilityStr->eh.pres = PRSNT_NODEF; + facilityStr->facilityStr.len = strlen(facility_str); + memcpy(facilityStr->facilityStr.val, facility_str, facilityStr->facilityStr.len); + } + return; +} + /* We received an incoming frame on the d-channel, send data to the stack */ void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len) { diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c index 056bf66ef2..379c481c0e 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c @@ -229,6 +229,24 @@ ftdm_status_t cpy_calling_name_from_stack(ftdm_caller_data_t *ftdm, Display *dis return FTDM_SUCCESS; } +ftdm_status_t cpy_facility_ie_from_stack(ftdm_caller_data_t *caller_data, uint8_t *data, uint32_t data_len) +{ + if (data_len > sizeof(caller_data->raw_data)-2) { + ftdm_log(FTDM_LOG_CRIT, "Length of Facility IE exceeds maximum length\n"); + return FTDM_FAIL; + } + + memset(caller_data->raw_data, 0, sizeof(caller_data->raw_data)); + /* Always include Facility IE identifier + len so this can be used as a sanity check by the user */ + caller_data->raw_data[0] = 0x1C; + caller_data->raw_data[1] = data_len; + + memcpy(&caller_data->raw_data[2], data, data_len); + caller_data->raw_data_len = data_len+2; + + return FTDM_SUCCESS; +} + ftdm_status_t cpy_calling_num_from_user(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *ftdm) { uint8_t len = strlen(ftdm->cid_num.digits); diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index 508c6996d5..87da5d1dd0 100644 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -289,7 +289,8 @@ typedef enum { FTDM_SIGEVENT_STOP, /*!< Hangup */ FTDM_SIGEVENT_RELEASED, /*!< Channel is completely released and available */ FTDM_SIGEVENT_UP, /*!< Outgoing call has been answered */ - FTDM_SIGEVENT_FLASH, /*< Flash event (typically on-hook/off-hook for analog devices) */ + FTDM_SIGEVENT_FLASH, /*!< Flash event (typically on-hook/off-hook for analog devices) */ + FTDM_SIGEVENT_PROCEED, /*!< Outgoing call got a response */ FTDM_SIGEVENT_PROGRESS, /*!< Outgoing call is making progress */ FTDM_SIGEVENT_PROGRESS_MEDIA, /*!< Outgoing call is making progress and there is media available */ FTDM_SIGEVENT_ALARM_TRAP, /*!< Hardware alarm ON */ @@ -299,9 +300,10 @@ typedef enum { FTDM_SIGEVENT_RESTART, /*!< Restart has been requested. Typically you hangup your call resources here */ FTDM_SIGEVENT_SIGSTATUS_CHANGED, /*!< Signaling protocol status changed (ie: D-chan up), see new status in raw_data ftdm_sigmsg_t member */ FTDM_SIGEVENT_COLLISION, /*!< Outgoing call was dropped because an incoming call arrived at the same time */ + FTDM_SIGEVENT_MSG, /* !< We received an in-call msg */ FTDM_SIGEVENT_INVALID } ftdm_signal_event_t; -#define SIGNAL_STRINGS "START", "STOP", "RELEASED", "UP", "FLASH", "PROGRESS", \ +#define SIGNAL_STRINGS "START", "STOP", "RELEASED", "UP", "FLASH", "PROCEED", "PROGRESS", \ "PROGRESS_MEDIA", "ALARM_TRAP", "ALARM_CLEAR", \ "COLLECTED_DIGIT", "ADD_CALL", "RESTART", "SIGSTATUS_CHANGED", "COLLISION", "INVALID" @@ -581,7 +583,7 @@ typedef enum { * This is used during incoming calls when you want to request the signaling stack * to notify about indications occurring locally */ typedef enum { - FTDM_CHANNEL_INDICATE_RING, + FTDM_CHANNEL_INDICATE_RINGING, FTDM_CHANNEL_INDICATE_PROCEED, FTDM_CHANNEL_INDICATE_PROGRESS, FTDM_CHANNEL_INDICATE_PROGRESS_MEDIA, diff --git a/libs/freetdm/src/include/private/ftdm_types.h b/libs/freetdm/src/include/private/ftdm_types.h index d9cefc3c6f..f265cb1a3d 100644 --- a/libs/freetdm/src/include/private/ftdm_types.h +++ b/libs/freetdm/src/include/private/ftdm_types.h @@ -181,6 +181,8 @@ typedef enum { * after having called ftdm_send_span_signal(), which with this flag it will just enqueue the signal * for later delivery */ FTDM_SPAN_USE_SIGNALS_QUEUE = (1 << 10), + /* If this flag is set, channel will be moved to proceed state when calls goes to routing */ + FTDM_SPAN_USE_PROCEED_STATE = (1 << 11), } ftdm_span_flag_t; /*! \brief Channel supported features */ @@ -204,6 +206,7 @@ typedef enum { FTDM_CHANNEL_STATE_DIALTONE, FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_RING, + FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_BUSY, FTDM_CHANNEL_STATE_ATTN, FTDM_CHANNEL_STATE_GENRING, @@ -211,6 +214,7 @@ typedef enum { FTDM_CHANNEL_STATE_GET_CALLERID, FTDM_CHANNEL_STATE_CALLWAITING, FTDM_CHANNEL_STATE_RESTART, + FTDM_CHANNEL_STATE_PROCEED, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, @@ -223,8 +227,8 @@ typedef enum { FTDM_CHANNEL_STATE_INVALID } ftdm_channel_state_t; #define CHANNEL_STATE_STRINGS "DOWN", "HOLD", "SUSPENDED", "DIALTONE", "COLLECT", \ - "RING", "BUSY", "ATTN", "GENRING", "DIALING", "GET_CALLERID", "CALLWAITING", \ - "RESTART", "PROGRESS", "PROGRESS_MEDIA", "UP", "IDLE", "TERMINATING", "CANCEL", \ + "RING", "RINGING", "BUSY", "ATTN", "GENRING", "DIALING", "GET_CALLERID", "CALLWAITING", \ + "RESTART", "PROCEED", "PROGRESS", "PROGRESS_MEDIA", "UP", "IDLE", "TERMINATING", "CANCEL", \ "HANGUP", "HANGUP_COMPLETE", "IN_LOOP", "INVALID" FTDM_STR2ENUM_P(ftdm_str2ftdm_channel_state, ftdm_channel_state2str, ftdm_channel_state_t) diff --git a/libs/freetdm/src/testanalog.c b/libs/freetdm/src/testanalog.c index 84d09f73c9..326bb5aec5 100644 --- a/libs/freetdm/src/testanalog.c +++ b/libs/freetdm/src/testanalog.c @@ -50,7 +50,7 @@ static FIO_SIGNAL_CB_FUNCTION(on_signal) switch(sigmsg->event_id) { case FTDM_SIGEVENT_START: - ftdm_channel_call_indicate(sigmsg->channel, FTDM_CHANNEL_INDICATE_RING); + ftdm_channel_call_indicate(sigmsg->channel, FTDM_CHANNEL_INDICATE_RINGING); ftdm_log(FTDM_LOG_DEBUG, "launching thread and indicating ring\n"); ftdm_thread_create_detached(test_call, sigmsg->channel); break; From 9fbecc60bee1601cf7a53775ecaa7e97229cca43 Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Thu, 25 Nov 2010 00:36:01 -0200 Subject: [PATCH 085/237] freetdm: on ftmod_r2, fixed flags for correctly polling the span, now freeing poll_events pointer, enabling/disabling channel reading flag when needed. also removed the test for FTDM_CHANNEL_OPEN flag on ftdm_channel_wait(). --- libs/freetdm/src/ftdm_io.c | 5 ----- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 18 ++++++++++++------ .../src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c | 2 -- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 0065d779f6..23ed68c45a 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -2869,11 +2869,6 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_wait(ftdm_channel_t *ftdmchan, ftdm_wait_ assert(ftdmchan != NULL); assert(ftdmchan->fio != NULL); - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "channel not open"); - return FTDM_FAIL; - } - if (!ftdmchan->fio->wait) { snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "method not implemented"); return FTDM_FAIL; diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index 8a4a826906..52c0f86e6c 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -781,7 +781,7 @@ static int ftdm_r2_io_wait(openr2_chan_t *r2chan, int *flags, int block) int32_t timeout; ftdm_wait_flag_t ftdmflags = 0; - ftdm_channel_t *ftdm_chan = openr2_chan_get_fd(r2chan); + ftdm_channel_t *fchan = openr2_chan_get_fd(r2chan); timeout = block ? -1 : 0; if (*flags & OR2_IO_READ) { @@ -794,9 +794,10 @@ static int ftdm_r2_io_wait(openr2_chan_t *r2chan, int *flags, int block) ftdmflags |= FTDM_EVENTS; } - status = ftdm_channel_wait(ftdm_chan, &ftdmflags, timeout); + status = ftdm_channel_wait(fchan, &ftdmflags, timeout); if (FTDM_SUCCESS != status && FTDM_TIMEOUT != status) { + ftdm_log_chan_msg(fchan, FTDM_LOG_ERROR, "Failed to wait for events on channel\n"); return -1; } @@ -869,7 +870,6 @@ static int ftdm_r2_io_get_oob_event(openr2_chan_t *r2chan, openr2_oob_event_t *e } break; } - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "returning event: %s\n", ftdm_signal_event2str(*event)); return 0; } @@ -1212,6 +1212,7 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan) ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_INTERVAL, &interval); ftdm_assert(interval != 0, "Invalid interval!"); ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Starting processing of incoming call with interval %d\n", interval); + openr2_chan_enable_read(r2chan); } break; @@ -1223,6 +1224,7 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan) ftdm_assert(interval != 0, "Invalid interval!"); ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Starting processing of outgoing call in channel with interval %d\n", interval); + openr2_chan_enable_read(r2chan); } break; @@ -1289,7 +1291,6 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan) { openr2_call_disconnect_cause_t disconnect_cause = ftdm_r2_ftdm_cause_to_openr2_cause(ftdmchan); ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Clearing call, cause = %s\n", openr2_proto_get_disconnect_string(disconnect_cause)); - openr2_chan_enable_read(r2chan); if (!R2CALL(ftdmchan)->disconnect_rcvd) { /* this will disconnect the call, but need to wait for the call end before moving to DOWN */ openr2_chan_disconnect_call(r2chan, disconnect_cause); @@ -1304,7 +1305,6 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan) case FTDM_CHANNEL_STATE_CANCEL: { ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Unable to receive call\n"); - openr2_chan_enable_read(r2chan); openr2_chan_disconnect_call(r2chan, OR2_CAUSE_OUT_OF_ORDER); } break; @@ -1316,6 +1316,7 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan) if (R2CALL(ftdmchan)->txdrops) { ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "dropped %d tx packets\n", R2CALL(ftdmchan)->txdrops); } + openr2_chan_disable_read(r2chan); ret = 1; } break; @@ -1385,7 +1386,10 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) for (i = 0; i < span->chan_count; i++) { r2chan = R2CALL(span->channels[(i+1)])->r2chan; ftdmchan = openr2_chan_get_client_data(r2chan); - poll_events[i] = ftdmchan->state == FTDM_CHANNEL_STATE_DOWN ? POLLPRI : (POLLPRI | POLLIN | POLLOUT); + poll_events[i] = POLLPRI; + if (openr2_chan_get_read_enabled(r2chan)) { + poll_events[i] |= POLLIN; + } } status = ftdm_span_poll_event(span, waitms, poll_events); @@ -1426,6 +1430,8 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) openr2_chan_set_blocked(r2chan); } + ftdm_safe_free(poll_events); + ftdm_clear_flag(r2data, FTDM_R2_RUNNING); ftdm_log(FTDM_LOG_DEBUG, "R2 thread ending.\n"); diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c index 1a43c4db50..c55d42e8b0 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c @@ -1131,10 +1131,8 @@ FIO_CHANNEL_NEXT_EVENT_FUNCTION(wanpipe_channel_next_event) memset(&tdm_api, 0, sizeof(tdm_api)); status = sangoma_tdm_read_event(ftdmchan->sockfd, &tdm_api); if (status != FTDM_SUCCESS) { -#if 0 snprintf(span->last_error, sizeof(span->last_error), "%s", strerror(errno)); ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to read event from channel: %s\n", strerror(errno)); -#endif return FTDM_FAIL; } From 8b0e7d2496e53fd78aae4764c222e2dddfc4bc2a Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 24 Nov 2010 21:25:58 -0600 Subject: [PATCH 086/237] FS-2880 --- src/switch_odbc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/switch_odbc.c b/src/switch_odbc.c index 36c3c996e8..a1c476e4a1 100644 --- a/src/switch_odbc.c +++ b/src/switch_odbc.c @@ -364,7 +364,6 @@ SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_exec_string(switch_odbc_ goto done; } - result = SQLExecute(stmt); result = SQLFetch(stmt); if (result != SQL_SUCCESS && result != SQL_SUCCESS_WITH_INFO && result != SQL_NO_DATA) { From f987903e5ee275ff4afd27245f322e4b8d9eb8f3 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 24 Nov 2010 21:36:21 -0600 Subject: [PATCH 087/237] fix single domain assumption in default config to be more portable *cough* bkw *cough* --- conf/dialplan/default.xml | 2 +- conf/directory/default.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/conf/dialplan/default.xml b/conf/dialplan/default.xml index 42a3bcc31f..a19f68399e 100644 --- a/conf/dialplan/default.xml +++ b/conf/dialplan/default.xml @@ -265,7 +265,7 @@ - + diff --git a/conf/directory/default.xml b/conf/directory/default.xml index 1e583033a9..8af7aea135 100644 --- a/conf/directory/default.xml +++ b/conf/directory/default.xml @@ -21,7 +21,7 @@ - + From 143949941c6a1e4ae68c7ebd86957525caf2242a Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 24 Nov 2010 21:39:08 -0600 Subject: [PATCH 088/237] add presence-probe-on-register sofia param to send a probe on register instead of presence to deal with some broken phones and add some general improvements to allow multi homed presence --- conf/sip_profiles/internal.xml | 2 + src/mod/endpoints/mod_sofia/mod_sofia.c | 3 +- src/mod/endpoints/mod_sofia/mod_sofia.h | 1 + src/mod/endpoints/mod_sofia/sofia.c | 18 ++++++-- src/mod/endpoints/mod_sofia/sofia_presence.c | 47 +++++++++++++------- src/mod/endpoints/mod_sofia/sofia_reg.c | 40 ++++++++--------- 6 files changed, 70 insertions(+), 41 deletions(-) diff --git a/conf/sip_profiles/internal.xml b/conf/sip_profiles/internal.xml index 93558a3584..3e756a85c0 100644 --- a/conf/sip_profiles/internal.xml +++ b/conf/sip_profiles/internal.xml @@ -132,6 +132,8 @@ + + diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 3c8404dd6b..3bb926adf3 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -3936,7 +3936,7 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session dest_num = p + 5; } } -#endif + if (profile->pres_type) { char *sql; @@ -3957,6 +3957,7 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session sofia_glue_actually_execute_sql(profile, sql, profile->ireg_mutex); switch_safe_free(sql); } +#endif caller_profile = switch_caller_profile_clone(nsession, outbound_profile); diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index c1244c05f1..6970a7ab05 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -224,6 +224,7 @@ typedef enum { PFLAG_IN_DIALOG_CHAT, PFLAG_DEL_SUBS_ON_REG, PFLAG_IGNORE_183NOSDP, + PFLAG_PRESENCE_PROBE_ON_REGISTER, /* No new flags below this line */ PFLAG_MAX } PFLAGS; diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 4d9bd7fd7b..e20d868548 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -2405,6 +2405,12 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile) } else { sofia_clear_pflag(profile, PFLAG_IGNORE_183NOSDP); } + } else if (!strcasecmp(var, "presence-probe-on-register")) { + if (switch_true(val)) { + sofia_set_pflag(profile, PFLAG_PRESENCE_PROBE_ON_REGISTER); + } else { + sofia_clear_pflag(profile, PFLAG_PRESENCE_PROBE_ON_REGISTER); + } } else if (!strcasecmp(var, "cid-in-1xx")) { if (switch_true(val)) { sofia_set_pflag(profile, PFLAG_CID_IN_1XX); @@ -3070,6 +3076,12 @@ switch_status_t config_sofia(int reload, char *profile_name) } else { sofia_clear_pflag(profile, PFLAG_IGNORE_183NOSDP); } + } else if (!strcasecmp(var, "presence-probe-on-register")) { + if (switch_true(val)) { + sofia_set_pflag(profile, PFLAG_PRESENCE_PROBE_ON_REGISTER); + } else { + sofia_clear_pflag(profile, PFLAG_PRESENCE_PROBE_ON_REGISTER); + } } else if (!strcasecmp(var, "cid-in-1xx")) { if (switch_true(val)) { sofia_set_pflag(profile, PFLAG_CID_IN_1XX); @@ -4420,7 +4432,6 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status contact_host, astate, "outbound", user_agent, profile->name, mod_sofia_globals.hostname, switch_str_nil(full_contact), switch_str_nil(presence_id), switch_str_nil(presence_data), switch_str_nil(p)); - switch_assert(sql); sofia_glue_actually_execute_sql(profile, sql, profile->ireg_mutex); @@ -6872,8 +6883,9 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ sql = switch_mprintf - ("select call_id from sip_dialogs where call_info='%q' and sip_from_user='%q' and sip_from_host='%q' and call_id is not null", - switch_str_nil(p), user, host); + ("select call_id from sip_dialogs where call_info='%q' and ((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q') " + "and call_id is not null", + switch_str_nil(p), user, host, user, host); if ((str = sofia_glue_execute_sql2str(profile, profile->ireg_mutex, sql, cid, sizeof(cid)))) { bnh = nua_handle_by_call_id(nua, str); diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index 4b853de6b1..95ea913a61 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -567,7 +567,8 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) } if (probe_euser && probe_host && (profile = sofia_glue_find_profile(probe_host))) { - sql = switch_mprintf("select status,rpid from sip_dialogs where sip_from_user='%q' and sip_from_host='%q'", probe_euser, probe_host); + sql = switch_mprintf("select status,rpid from sip_dialogs where ((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q')", + probe_euser, probe_host, probe_euser, probe_host); sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_dialog_callback, &dh); h.profile = profile; @@ -591,9 +592,11 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) "'%q','%q' " "from sip_registrations left join sip_dialogs on " - "(sip_dialogs.sip_from_user = sip_registrations.sip_user " - "and (sip_dialogs.sip_from_host = sip_registrations.orig_server_host or " - "sip_dialogs.sip_from_host = sip_registrations.sip_host) ) " + "sip_dialogs.presence_id = sip_registrations.sip_user || '@' || sip_registrations.sip_host " + + + "or (sip_dialogs.sip_from_user = sip_registrations.sip_user " + "and sip_dialogs.sip_from_host = sip_registrations.sip_host) " "left join sip_presence on " "(sip_registrations.sip_user=sip_presence.sip_user and sip_registrations.orig_server_host=sip_presence.sip_host and " @@ -601,7 +604,8 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) "where sip_dialogs.presence_id='%q@%q' or (sip_registrations.sip_user='%q' and " "(sip_registrations.orig_server_host='%q' or sip_registrations.sip_host='%q' " "or sip_registrations.presence_hosts like '%%%q%%'))", - dh.status, dh.rpid, probe_euser, probe_host, probe_euser, probe_host, probe_host, probe_host); + dh.status, dh.rpid, + probe_euser, probe_host, probe_euser, probe_host, probe_host, probe_host); switch_assert(sql); if (mod_sofia_globals.debug_presence > 0) { @@ -711,9 +715,10 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) sql = switch_mprintf("update sip_dialogs set call_info='%q',call_info_state='%q' where hostname='%q' and uuid='%q'", call_info, call_info_state, mod_sofia_globals.hostname, uuid); } else { - sql = switch_mprintf("update sip_dialogs set call_info='%q', call_info_state='%q' where hostname='%q' and sip_dialogs.sip_from_user='%q' " - "and sip_dialogs.sip_from_host='%q' and call_info='%q'", - call_info, call_info_state, mod_sofia_globals.hostname, euser, host, call_info); + sql = switch_mprintf("update sip_dialogs set call_info='%q', call_info_state='%q' where hostname='%q' and " + "((sip_dialogs.sip_from_user='%q' and sip_dialogs.sip_from_host='%q') or presence_id='%q@%q') and call_info='%q'", + + call_info, call_info_state, mod_sofia_globals.hostname, euser, host, euser, host, call_info); } @@ -737,7 +742,8 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); } - sql = switch_mprintf("select status,rpid from sip_dialogs where sip_from_user='%q' and sip_from_host='%q'", euser, host); + sql = switch_mprintf("select status,rpid from sip_dialogs where ((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q')", + euser, host, euser, host); sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_dialog_callback, &dh); switch_safe_free(sql); @@ -753,17 +759,20 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) "(sip_subscriptions.sub_to_user=sip_presence.sip_user and sip_subscriptions.sub_to_host=sip_presence.sip_host and " "sip_subscriptions.profile_name=sip_presence.profile_name) " "left join sip_dialogs on " + + "sip_dialogs.presence_id = sip_subscriptions.sub_to_user || '@' || sip_subscriptions.sub_to_host or " + "(sip_dialogs.sip_from_user = sip_subscriptions.sub_to_user " "and sip_dialogs.sip_from_host = sip_subscriptions.sub_to_host) " "where sip_subscriptions.expires > -1 and " - "(event='%q' or event='%q') and (sub_to_user='%q' or sip_dialogs.presence_id like '%q@%%') " + "(event='%q' or event='%q') and sub_to_user='%q' " "and (sub_to_host='%q' or presence_hosts like '%%%q%%') " "and (sip_subscriptions.profile_name = '%q' or sip_subscriptions.presence_hosts != sip_subscriptions.sub_to_host)", switch_str_nil(status), switch_str_nil(rpid), host, dh.status,dh.rpid, - event_type, alt_event_type, euser, euser, host, host, profile->name))) { + event_type, alt_event_type, euser, host, host, profile->name))) { struct presence_helper helper = { 0 }; @@ -1918,7 +1927,8 @@ static void sync_sla(sofia_profile_t *profile, const char *to_user, const char * switch_core_hash_init(&sh->hash, sh->pool); sql = switch_mprintf("select sip_from_user,sip_from_host,call_info,call_info_state,uuid from sip_dialogs " - "where hostname='%q' " "and sip_from_user='%q' and sip_from_host='%q' ", mod_sofia_globals.hostname, to_user, to_host); + "where hostname='%q' " "and ((sip_from_user='%q' and sip_from_host='%q) or presence_id='%q@%q')' ", + mod_sofia_globals.hostname, to_user, to_host, to_user, to_host); if (mod_sofia_globals.debug_sla > 1) { @@ -1954,7 +1964,8 @@ static void sync_sla(sofia_profile_t *profile, const char *to_user, const char * if (clear) { - sql = switch_mprintf("delete from sip_dialogs where sip_from_user='%q' and sip_from_host='%q' and call_info_state='seized'", to_user, to_host); + sql = switch_mprintf("delete from sip_dialogs where ((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q') " + "and call_info_state='seized'", to_user, to_host, to_user, to_host); if (mod_sofia_globals.debug_sla > 1) { @@ -2326,8 +2337,9 @@ void sofia_presence_handle_sip_i_subscribe(int status, switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "CANCEL LINE SEIZE\n"); } - sql = switch_mprintf("delete from sip_dialogs where sip_from_user='%q' and sip_from_host='%q' and call_info_state='seized'", - to_user, to_host); + sql = switch_mprintf("delete from sip_dialogs where ((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q') " + "and call_info_state='seized'", + to_user, to_host, to_user, to_host); if (mod_sofia_globals.debug_sla > 1) { @@ -2360,8 +2372,9 @@ void sofia_presence_handle_sip_i_subscribe(int status, - sql = switch_mprintf("delete from sip_dialogs where sip_from_user='%q' and sip_from_host='%q' and call_info_state='seized'", - to_user, to_host); + sql = switch_mprintf("delete from sip_dialogs where ((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q') " + "and call_info_state='seized'", + to_user, to_host, to_user, to_host); if (mod_sofia_globals.debug_sla > 1) { diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index 216f808e4f..e93bdaac08 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -1445,27 +1445,27 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand } } - -#if 0 - if (switch_event_create(&s_event, SWITCH_EVENT_PRESENCE_PROBE) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO); - switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "login", profile->name); - switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, sub_host); - switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "to", "%s@%s", to_user, sub_host); - switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "event_type", "presence"); - switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog"); - switch_event_fire(&s_event); + if (sofia_test_pflag(profile, PFLAG_PRESENCE_PROBE_ON_REGISTER)) { + if (switch_event_create(&s_event, SWITCH_EVENT_PRESENCE_PROBE) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO); + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "login", profile->name); + switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, sub_host); + switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "to", "%s@%s", to_user, sub_host); + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "event_type", "presence"); + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog"); + switch_event_fire(&s_event); + } + } else { + if (switch_event_create(&s_event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO); + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "login", profile->name); + switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, sub_host); + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "rpid", "unknown"); + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "status", "Registered"); + switch_event_fire(&s_event); + } } -#else - if (switch_event_create(&s_event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO); - switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "login", profile->name); - switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, sub_host); - switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "rpid", "unknown"); - switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "status", "Registered"); - switch_event_fire(&s_event); - } -#endif + } else { if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_UNREGISTER) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile-name", profile->name); From 6a9a27b791a231b970b37eadb1ebf927b0c30bea Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Wed, 24 Nov 2010 22:13:12 -0600 Subject: [PATCH 089/237] VS2010 fix output paths --- src/mod/codecs/mod_celt/mod_celt.vcxproj | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/mod/codecs/mod_celt/mod_celt.vcxproj b/src/mod/codecs/mod_celt/mod_celt.vcxproj index 01c55d4217..ee8a70ca3f 100644 --- a/src/mod/codecs/mod_celt/mod_celt.vcxproj +++ b/src/mod/codecs/mod_celt/mod_celt.vcxproj @@ -62,10 +62,6 @@ <_ProjectFileVersion>10.0.30319.1 - $(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ From 75bd5642105532f80101fc84849b96996d710a04 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Thu, 25 Nov 2010 09:35:14 -0500 Subject: [PATCH 090/237] freetdm: wait for state change to be cleared when placing outgoing calls this fixes a race where the call is hangup even before the state DIALING is processed and therefore the HANGUP state change is ignored. --- libs/freetdm/src/ftdm_io.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 0aeaeedce4..bcceba58ca 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -2270,6 +2270,8 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_place(const char *file, const char UNREFERENCED_PARAMETER(line); #endif + ftdm_wait_for_flag_cleared(ftdmchan, FTDM_CHANNEL_STATE_CHANGE, 100); + ftdm_channel_unlock(ftdmchan); return status; From 37ce4003e129097e179f213c86e00b3307cc1738 Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Thu, 25 Nov 2010 14:31:30 -0200 Subject: [PATCH 091/237] freetdm: eliminated some warnings from ftmod_r2 windows build --- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index 52c0f86e6c..bfe49fd8ca 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -889,7 +889,7 @@ static openr2_io_interface_t ftdm_r2_io_iface = { static FIO_SIG_CONFIGURE_FUNCTION(ftdm_r2_configure_span) //ftdm_status_t (ftdm_span_t *span, fio_signal_cb_t sig_cb, va_list ap) { - int i = 0; + unsigned int i = 0; int conf_failure = 0; char *var = NULL; char *val = NULL; @@ -1107,11 +1107,6 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_r2_configure_span) openr2_chan_set_log_level(r2chan, r2conf.loglevel); if (r2conf.call_files) { openr2_chan_enable_call_files(r2chan); -#if 0 - if (r2conf.mf_files) { - openr2_chan_enable_mf_files(r2chan); - } -#endif } r2call = ftdm_malloc(sizeof(*r2call)); @@ -1348,8 +1343,8 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) ftdm_span_t *span = (ftdm_span_t *) obj; ftdm_r2_data_t *r2data = span->signal_data; int waitms = 20; - int i, res; - int ms; + unsigned int i; + int res, ms; struct timeval start, end; short *poll_events = ftdm_malloc(sizeof(short)*span->chan_count); ftdm_event_t *event = NULL; @@ -1413,8 +1408,8 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) * XXX */ for (i = 1; i <= span->chan_count; i++) { r2chan = R2CALL(span->channels[i])->r2chan; - r2call = R2CALL(ftdmchan); ftdmchan = openr2_chan_get_client_data(r2chan); + r2call = R2CALL(ftdmchan); ftdm_mutex_lock(ftdmchan->mutex); ftdm_r2_state_advance(ftdmchan); @@ -1487,8 +1482,8 @@ static FIO_API_FUNCTION(ftdm_r2_api) char *mycmd = NULL, *argv[10] = { 0 }; int argc = 0; int span_id = 0; - int chan_id = 0; - int i = 0; + unsigned int chan_id = 0; + unsigned int i = 0; ftdm_r2_data_t *r2data = NULL; openr2_chan_t *r2chan = NULL; openr2_context_t *r2context = NULL; From c57c17604c175e9c154d2552c608087a4e98807d Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Thu, 25 Nov 2010 10:40:20 -0600 Subject: [PATCH 092/237] Update mod_cepstral for windows vs2010 --- src/mod/asr_tts/mod_cepstral/WinReadme.txt | 4 ++++ .../mod_cepstral/mod_cepstral.2010.vcxproj | 19 +++++++++---------- 2 files changed, 13 insertions(+), 10 deletions(-) create mode 100644 src/mod/asr_tts/mod_cepstral/WinReadme.txt diff --git a/src/mod/asr_tts/mod_cepstral/WinReadme.txt b/src/mod/asr_tts/mod_cepstral/WinReadme.txt new file mode 100644 index 0000000000..56b4e79a39 --- /dev/null +++ b/src/mod/asr_tts/mod_cepstral/WinReadme.txt @@ -0,0 +1,4 @@ +The Cepstral SDK for Windows should be placed in c:\dev\cepstral +ex. C:\dev\cepstral\sdk\include +This SDK can be obtained from http://cepstral.com/ +If you want a prebuilt version you may download one from http://files.freeswitch.org/windows/installer/ \ No newline at end of file diff --git a/src/mod/asr_tts/mod_cepstral/mod_cepstral.2010.vcxproj b/src/mod/asr_tts/mod_cepstral/mod_cepstral.2010.vcxproj index 2bc46efdca..b7e42eb850 100644 --- a/src/mod/asr_tts/mod_cepstral/mod_cepstral.2010.vcxproj +++ b/src/mod/asr_tts/mod_cepstral/mod_cepstral.2010.vcxproj @@ -66,13 +66,13 @@ - C:\Program Files\Cepstral\sdk\include;%(AdditionalIncludeDirectories) + C:\dev\cepstral\sdk\include;%(AdditionalIncludeDirectories) swift.lib;%(AdditionalDependencies) - C:\Program Files\Cepstral\sdk\lib\winnt;C:\Program Files\Cepstral\sdk\lib\windows;%(AdditionalLibraryDirectories) + C:\dev\cepstral\sdk\lib\lib-windows;%(AdditionalLibraryDirectories) false @@ -83,13 +83,13 @@ X64 - C:\Program Files\Cepstral\sdk\include;%(AdditionalIncludeDirectories) + C:\dev\cepstral\sdk\include;%(AdditionalIncludeDirectories) swift.lib;%(AdditionalDependencies) - C:\Program Files\Cepstral\sdk\lib\winnt;C:\Program Files\Cepstral\sdk\lib\windows;%(AdditionalLibraryDirectories) + C:\dev\cepstral\sdk\lib\lib-windows_x64;%(AdditionalLibraryDirectories) false @@ -98,13 +98,13 @@ - C:\Program Files\Cepstral\sdk\include;%(AdditionalIncludeDirectories) + C:\dev\cepstral\sdk\include;%(AdditionalIncludeDirectories) swift.lib;%(AdditionalDependencies) - C:\Program Files\Cepstral\sdk\lib\winnt;C:\Program Files\Cepstral\sdk\lib\windows;%(AdditionalLibraryDirectories) + C:\dev\cepstral\sdk\lib\lib-windows;%(AdditionalLibraryDirectories) false @@ -115,13 +115,13 @@ X64 - C:\Program Files\Cepstral\sdk\include;%(AdditionalIncludeDirectories) + C:\dev\cepstral\sdk\include;%(AdditionalIncludeDirectories) swift.lib;%(AdditionalDependencies) - C:\Program Files\Cepstral\sdk\lib\winnt;C:\Program Files\Cepstral\sdk\lib\windows;%(AdditionalLibraryDirectories) + C:\dev\cepstral\sdk\lib\lib-windows_x64;%(AdditionalLibraryDirectories) false @@ -132,9 +132,8 @@ - + {202d7a4e-760d-4d0e-afa1-d7459ced30ff} - false From b7c82d4c2efa974e8c867826253732139f9fb385 Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Thu, 25 Nov 2010 15:40:44 -0200 Subject: [PATCH 093/237] freetdm: moved ftdm_channel_read_event() to freetdm.h --- libs/freetdm/src/include/freetdm.h | 17 +++++++++++++++++ libs/freetdm/src/include/private/ftdm_core.h | 17 ----------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index 9ce213c962..eff6305913 100644 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -888,6 +888,23 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_add_to_group(const char* name, ftdm_chann /*! \brief Remove the channel from a hunt group */ FT_DECLARE(ftdm_status_t) ftdm_channel_remove_from_group(ftdm_group_t* group, ftdm_channel_t* ftdmchan); +/*! + * \brief Retrieves an event from the span + * + * \note + * This function is non-reentrant and not thread-safe. + * The event returned may be modified if the function is called again + * from a different thread or even the same. It is recommended to + * handle events from the same span in a single thread. + * + * \param span The channel to retrieve the event from + * \param event Pointer to store the pointer to the event + * + * \retval FTDM_SUCCESS success (at least one event available) + * \retval FTDM_FAIL failure + */ +FT_DECLARE(ftdm_status_t) ftdm_channel_read_event(ftdm_channel_t *ftdmchan, ftdm_event_t **event); + /*! \brief Find a hunt group by id */ FT_DECLARE(ftdm_status_t) ftdm_group_find(uint32_t id, ftdm_group_t **group); diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h index 7d3ee68176..06f899c8c9 100644 --- a/libs/freetdm/src/include/private/ftdm_core.h +++ b/libs/freetdm/src/include/private/ftdm_core.h @@ -615,23 +615,6 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_chan(ftdm_channel_t *ftdmchan); */ FT_DECLARE(ftdm_status_t) ftdm_span_next_event(ftdm_span_t *span, ftdm_event_t **event); -/*! - * \brief Retrieves an event from the span - * - * \note - * This function is non-reentrant and not thread-safe. - * The event returned may be modified if the function is called again - * from a different thread or even the same. It is recommended to - * handle events from the same span in a single thread. - * - * \param span The channel to retrieve the event from - * \param event Pointer to store the pointer to the event - * - * \retval FTDM_SUCCESS success (at least one event available) - * \retval FTDM_FAIL failure - */ -FT_DECLARE(ftdm_status_t) ftdm_channel_read_event(ftdm_channel_t *ftdmchan, ftdm_event_t **event); - /*! * \brief Enqueue a DTMF string into the channel * From ffbded67fdd5dc177d950be82951d3fa6208cf24 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Thu, 25 Nov 2010 12:33:36 -0500 Subject: [PATCH 094/237] freetdm: ftmod_libpri - lock the channel in libpri on_ring callback this should fix potential call_data pointer corruption --- .../freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c index cf84dbeebd..c8e865214c 100644 --- a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c +++ b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c @@ -495,6 +495,7 @@ static ftdm_state_map_t isdn_state_map = { /** * \brief Handler for channel state change * \param ftdmchan Channel to handle + * \note This function MUST be called with the channel locked */ static __inline__ void state_advance(ftdm_channel_t *chan) { @@ -989,7 +990,16 @@ static int on_ring(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event if (!chan) { ftdm_log(FTDM_LOG_ERROR, "-- Unable to get channel %d:%d\n", ftdm_span_get_id(span), pevent->ring.channel); - goto done; + return ret; + } + + ftdm_channel_lock(chan); + + if (chan->call_data) { + /* we could drop the incoming call, but most likely the pointer is just a ghost of the past, + * this check is just to detect potentially unreleased pointers */ + ftdm_log_chan(chan, FTDM_LOG_ERROR, "channel already has call %p!\n", chan->call_data); + chan->call_data = NULL; } if (ftdm_channel_get_state(chan) != FTDM_CHANNEL_STATE_DOWN || ftdm_test_flag(chan, FTDM_CHANNEL_INUSE)) { @@ -1049,9 +1059,10 @@ static int on_ring(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event /* hurr, this is valid as along as nobody releases the call */ chan->call_data = pevent->ring.call; - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RING); + ftdm_set_state(chan, FTDM_CHANNEL_STATE_RING); done: + ftdm_channel_unlock(chan); return ret; } From 7433a1e5786f91f07f3b13f392596943062b4a13 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Thu, 25 Nov 2010 13:16:44 -0500 Subject: [PATCH 095/237] Fix for caller ID not received properly on BRI --- .../ftmod_sangoma_isdn/ftmod_sangoma_isdn.h | 20 +-- .../ftmod_sangoma_isdn_stack_hndl.c | 22 +-- .../ftmod_sangoma_isdn_stack_out.c | 30 ++--- .../ftmod_sangoma_isdn_support.c | 125 +++++++++++------- libs/freetdm/src/include/freetdm.h | 6 +- 5 files changed, 115 insertions(+), 88 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h index 25ffef85e5..a82ed283e1 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h @@ -376,16 +376,18 @@ void sngisdn_rcv_cc_ind(CcMngmt *status); void sngisdn_rcv_sng_log(uint8_t level, char *fmt,...); void sngisdn_rcv_sng_assert(char *message); -ftdm_status_t cpy_calling_num_from_stack(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb); -ftdm_status_t cpy_called_num_from_stack(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb); -ftdm_status_t cpy_redir_num_from_stack(ftdm_caller_data_t *ftdm, RedirNmb *redirNmb); -ftdm_status_t cpy_calling_name_from_stack(ftdm_caller_data_t *ftdm, Display *display); -ftdm_status_t cpy_facility_ie_from_stack(ftdm_caller_data_t *ftdm, uint8_t *data, uint32_t data_len); +ftdm_status_t get_calling_num(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb); +ftdm_status_t get_called_num(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb); +ftdm_status_t get_redir_num(ftdm_caller_data_t *ftdm, RedirNmb *redirNmb); +ftdm_status_t get_calling_name_from_display(ftdm_caller_data_t *ftdm, Display *display); +ftdm_status_t get_calling_name_from_usr_usr(ftdm_caller_data_t *ftdm, UsrUsr *usrUsr); +ftdm_status_t get_facility_ie(ftdm_caller_data_t *ftdm, uint8_t *data, uint32_t data_len); -ftdm_status_t cpy_calling_num_from_user(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *ftdm); -ftdm_status_t cpy_called_num_from_user(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *ftdm); -ftdm_status_t cpy_redir_num_from_user(RedirNmb *redirNmb, ftdm_caller_data_t *ftdm); -ftdm_status_t cpy_calling_name_from_user(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan); +ftdm_status_t set_calling_num(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *ftdm); +ftdm_status_t set_called_num(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *ftdm); +ftdm_status_t set_redir_num(RedirNmb *redirNmb, ftdm_caller_data_t *ftdm); +ftdm_status_t set_calling_name(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan); +ftdm_status_t set_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr); uint8_t sngisdn_get_infoTranCap_from_stack(ftdm_bearer_cap_t bearer_capability); uint8_t sngisdn_get_usrInfoLyr1Prot_from_stack(ftdm_user_layer1_prot_t layer1_prot); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c index 209284a8b6..a541a655d8 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c @@ -127,10 +127,14 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event) ftdm_channel_add_var(ftdmchan, "isdn_specific_var", "1"); #endif /* Fill in call information */ - cpy_calling_num_from_stack(&ftdmchan->caller_data, &conEvnt->cgPtyNmb); - cpy_called_num_from_stack(&ftdmchan->caller_data, &conEvnt->cdPtyNmb); - cpy_calling_name_from_stack(&ftdmchan->caller_data, &conEvnt->display); - cpy_redir_num_from_stack(&ftdmchan->caller_data, &conEvnt->redirNmb); + get_calling_num(&ftdmchan->caller_data, &conEvnt->cgPtyNmb); + get_called_num(&ftdmchan->caller_data, &conEvnt->cdPtyNmb); + get_redir_num(&ftdmchan->caller_data, &conEvnt->redirNmb); + + if (get_calling_name_from_display(&ftdmchan->caller_data, &conEvnt->display) != FTDM_SUCCESS) { + get_calling_name_from_usr_usr(&ftdmchan->caller_data, &conEvnt->usrUsr); + } + ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Incoming call: Called No:[%s] Calling No:[%s]\n", ftdmchan->caller_data.dnis.digits, ftdmchan->caller_data.cid_num.digits); if (conEvnt->bearCap[0].eh.pres) { @@ -147,7 +151,7 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event) if (conEvnt->facilityStr.eh.pres) { if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) { - cpy_facility_ie_from_stack(&ftdmchan->caller_data, conEvnt->facilityStr.facilityStr.val, conEvnt->facilityStr.facilityStr.len); + get_facility_ie(&ftdmchan->caller_data, conEvnt->facilityStr.facilityStr.val, conEvnt->facilityStr.facilityStr.len); } else if (signal_data->facility == SNGISDN_OPT_TRUE) { /* Verify whether the Caller Name will come in a subsequent FACILITY message */ uint16_t ret_val; @@ -413,7 +417,7 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event) ftdm_size_t min_digits = ((sngisdn_span_data_t*)ftdmchan->span->signal_data)->min_digits; ftdm_size_t num_digits; - cpy_called_num_from_stack(&ftdmchan->caller_data, &cnStEvnt->cdPtyNmb); + get_called_num(&ftdmchan->caller_data, &cnStEvnt->cdPtyNmb); num_digits = strlen(ftdmchan->caller_data.dnis.digits); if (cnStEvnt->sndCmplt.eh.pres || num_digits >= min_digits) { @@ -472,7 +476,7 @@ void sngisdn_process_disc_ind (sngisdn_event_data_t *sngisdn_event) case FTDM_CHANNEL_STATE_UP: if (discEvnt->facilityStr.eh.pres) { if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) { - cpy_facility_ie_from_stack(&ftdmchan->caller_data, discEvnt->facilityStr.facilityStr.val, discEvnt->facilityStr.facilityStr.len); + get_facility_ie(&ftdmchan->caller_data, discEvnt->facilityStr.facilityStr.val, discEvnt->facilityStr.facilityStr.len); } else { /* Call libsng_isdn facility decode function and copy variables here */ } @@ -569,7 +573,7 @@ void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event) if (relEvnt->facilityStr.eh.pres) { if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) { - cpy_facility_ie_from_stack(&ftdmchan->caller_data, relEvnt->facilityStr.facilityStr.val, relEvnt->facilityStr.facilityStr.len); + get_facility_ie(&ftdmchan->caller_data, relEvnt->facilityStr.facilityStr.val, relEvnt->facilityStr.facilityStr.len); } else { /* Call libsng_isdn facility decode function and copy variables here */ } @@ -785,7 +789,7 @@ void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event) ftdm_sigmsg_t sigev; if (facEvnt->facElmt.facStr.pres) { if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) { - cpy_facility_ie_from_stack(&ftdmchan->caller_data, &facEvnt->facElmt.facStr.val[2], facEvnt->facElmt.facStr.len); + get_facility_ie(&ftdmchan->caller_data, &facEvnt->facElmt.facStr.val[2], facEvnt->facElmt.facStr.len); } else { /* Call libsng_isdn facility decode function and copy variables here */ } diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c index 385d1eba9d..36c6782a97 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c @@ -35,7 +35,6 @@ #include "ftmod_sangoma_isdn.h" static void sngisdn_set_prog_desc(ProgInd *progInd, ftdm_sngisdn_progind_t prod_ind); -static void sngisdn_set_facilityStr(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr); void sngisdn_snd_setup(ftdm_channel_t *ftdmchan) { @@ -136,12 +135,11 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan) } ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Outgoing call: Called No:[%s] Calling No:[%s]\n", ftdmchan->caller_data.dnis.digits, ftdmchan->caller_data.cid_num.digits); - cpy_called_num_from_user(&conEvnt.cdPtyNmb, &ftdmchan->caller_data); - cpy_calling_num_from_user(&conEvnt.cgPtyNmb, &ftdmchan->caller_data); - cpy_redir_num_from_user(&conEvnt.redirNmb, &ftdmchan->caller_data); - cpy_calling_name_from_user(&conEvnt, ftdmchan); - - sngisdn_set_facilityStr(ftdmchan, &conEvnt.facilityStr); + set_called_num(&conEvnt.cdPtyNmb, &ftdmchan->caller_data); + set_calling_num(&conEvnt.cgPtyNmb, &ftdmchan->caller_data); + set_redir_num(&conEvnt.redirNmb, &ftdmchan->caller_data); + set_calling_name(&conEvnt, ftdmchan); + set_facility_ie(ftdmchan, &conEvnt.facilityStr); ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending SETUP (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces); @@ -558,7 +556,8 @@ void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan) discEvnt.causeDgn[0].recommend.pres = NOTPRSNT; discEvnt.causeDgn[0].dgnVal.pres = NOTPRSNT; - sngisdn_set_facilityStr(ftdmchan, &discEvnt.facilityStr); + set_facility_ie(ftdmchan, &discEvnt.facilityStr); + ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending DISCONNECT (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId); if (sng_isdn_disc_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &discEvnt)) { @@ -604,7 +603,7 @@ void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare) spInstId = sngisdn_info->spInstId; } - sngisdn_set_facilityStr(ftdmchan, &relEvnt.facilityStr); + set_facility_ie(ftdmchan, &relEvnt.facilityStr); ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending RELEASE/RELEASE COMPLETE (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, suInstId, spInstId); @@ -647,19 +646,6 @@ static void sngisdn_set_prog_desc(ProgInd *progInd, ftdm_sngisdn_progind_t prog_ return; } -static void sngisdn_set_facilityStr(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr) -{ - const char *facility_str = NULL; - - facility_str = ftdm_channel_get_var(ftdmchan, "isdn.facility.val"); - if (facility_str) { - facilityStr->eh.pres = PRSNT_NODEF; - facilityStr->facilityStr.len = strlen(facility_str); - memcpy(facilityStr->facilityStr.val, facility_str, facilityStr->facilityStr.len); - } - return; -} - /* We received an incoming frame on the d-channel, send data to the stack */ void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len) { diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c index 379c481c0e..4ddb90bbd3 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c @@ -147,76 +147,79 @@ ftdm_status_t sngisdn_set_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail) return FTDM_SUCCESS; } -ftdm_status_t cpy_calling_num_from_stack(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb) +ftdm_status_t get_calling_num(ftdm_caller_data_t *caller_data, CgPtyNmb *cgPtyNmb) { if (cgPtyNmb->eh.pres != PRSNT_NODEF) { return FTDM_FAIL; } if (cgPtyNmb->screenInd.pres == PRSNT_NODEF) { - ftdm->screen = cgPtyNmb->screenInd.val; + caller_data->screen = cgPtyNmb->screenInd.val; } if (cgPtyNmb->presInd0.pres == PRSNT_NODEF) { - ftdm->pres = cgPtyNmb->presInd0.val; + caller_data->pres = cgPtyNmb->presInd0.val; } if (cgPtyNmb->nmbPlanId.pres == PRSNT_NODEF) { - ftdm->cid_num.plan = cgPtyNmb->nmbPlanId.val; + caller_data->cid_num.plan = cgPtyNmb->nmbPlanId.val; } + if (cgPtyNmb->typeNmb1.pres == PRSNT_NODEF) { - ftdm->cid_num.type = cgPtyNmb->typeNmb1.val; + caller_data->cid_num.type = cgPtyNmb->typeNmb1.val; } if (cgPtyNmb->nmbDigits.pres == PRSNT_NODEF) { - ftdm_copy_string(ftdm->cid_num.digits, (const char*)cgPtyNmb->nmbDigits.val, cgPtyNmb->nmbDigits.len+1); + ftdm_copy_string(caller_data->cid_num.digits, (const char*)cgPtyNmb->nmbDigits.val, cgPtyNmb->nmbDigits.len+1); } + memcpy(&caller_data->ani, &caller_data->cid_num, sizeof(caller_data->ani)); return FTDM_SUCCESS; } -ftdm_status_t cpy_called_num_from_stack(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb) +ftdm_status_t get_called_num(ftdm_caller_data_t *caller_data, CdPtyNmb *cdPtyNmb) { if (cdPtyNmb->eh.pres != PRSNT_NODEF) { return FTDM_FAIL; } if (cdPtyNmb->nmbPlanId.pres == PRSNT_NODEF) { - ftdm->dnis.plan = cdPtyNmb->nmbPlanId.val; + caller_data->dnis.plan = cdPtyNmb->nmbPlanId.val; } if (cdPtyNmb->typeNmb0.pres == PRSNT_NODEF) { - ftdm->dnis.type = cdPtyNmb->typeNmb0.val; + caller_data->dnis.type = cdPtyNmb->typeNmb0.val; } if (cdPtyNmb->nmbDigits.pres == PRSNT_NODEF) { - unsigned i = strlen(ftdm->dnis.digits); + /* In overlap receive mode, append the new digits to the existing dnis */ + unsigned i = strlen(caller_data->dnis.digits); - ftdm_copy_string(&ftdm->dnis.digits[i], (const char*)cdPtyNmb->nmbDigits.val, cdPtyNmb->nmbDigits.len+1); + ftdm_copy_string(&caller_data->dnis.digits[i], (const char*)cdPtyNmb->nmbDigits.val, cdPtyNmb->nmbDigits.len+1); } return FTDM_SUCCESS; } -ftdm_status_t cpy_redir_num_from_stack(ftdm_caller_data_t *ftdm, RedirNmb *redirNmb) +ftdm_status_t get_redir_num(ftdm_caller_data_t *caller_data, RedirNmb *redirNmb) { if (redirNmb->eh.pres != PRSNT_NODEF) { return FTDM_FAIL; } if (redirNmb->nmbPlanId.pres == PRSNT_NODEF) { - ftdm->rdnis.plan = redirNmb->nmbPlanId.val; + caller_data->rdnis.plan = redirNmb->nmbPlanId.val; } if (redirNmb->typeNmb.pres == PRSNT_NODEF) { - ftdm->rdnis.type = redirNmb->typeNmb.val; + caller_data->rdnis.type = redirNmb->typeNmb.val; } if (redirNmb->nmbDigits.pres == PRSNT_NODEF) { - ftdm_copy_string(ftdm->rdnis.digits, (const char*)redirNmb->nmbDigits.val, redirNmb->nmbDigits.len+1); + ftdm_copy_string(caller_data->rdnis.digits, (const char*)redirNmb->nmbDigits.val, redirNmb->nmbDigits.len+1); } return FTDM_SUCCESS; } -ftdm_status_t cpy_calling_name_from_stack(ftdm_caller_data_t *ftdm, Display *display) +ftdm_status_t get_calling_name_from_display(ftdm_caller_data_t *caller_data, Display *display) { if (display->eh.pres != PRSNT_NODEF) { return FTDM_FAIL; @@ -225,11 +228,29 @@ ftdm_status_t cpy_calling_name_from_stack(ftdm_caller_data_t *ftdm, Display *dis return FTDM_FAIL; } - ftdm_copy_string(ftdm->cid_name, (const char*)display->dispInfo.val, display->dispInfo.len+1); + ftdm_copy_string(caller_data->cid_name, (const char*)display->dispInfo.val, display->dispInfo.len+1); return FTDM_SUCCESS; } -ftdm_status_t cpy_facility_ie_from_stack(ftdm_caller_data_t *caller_data, uint8_t *data, uint32_t data_len) +ftdm_status_t get_calling_name_from_usr_usr(ftdm_caller_data_t *caller_data, UsrUsr *usrUsr) +{ + if (usrUsr->eh.pres != PRSNT_NODEF) { + return FTDM_FAIL; + } + + if (usrUsr->protocolDisc.val != PD_IA5) { + return FTDM_FAIL; + } + + if (usrUsr->usrInfo.pres != PRSNT_NODEF) { + return FTDM_FAIL; + } + + ftdm_copy_string(caller_data->cid_name, (const char*)usrUsr->usrInfo.val, usrUsr->usrInfo.len+1); + return FTDM_SUCCESS; +} + +ftdm_status_t get_facility_ie(ftdm_caller_data_t *caller_data, uint8_t *data, uint32_t data_len) { if (data_len > sizeof(caller_data->raw_data)-2) { ftdm_log(FTDM_LOG_CRIT, "Length of Facility IE exceeds maximum length\n"); @@ -247,67 +268,67 @@ ftdm_status_t cpy_facility_ie_from_stack(ftdm_caller_data_t *caller_data, uint8_ return FTDM_SUCCESS; } -ftdm_status_t cpy_calling_num_from_user(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *ftdm) +ftdm_status_t set_calling_num(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *caller_data) { - uint8_t len = strlen(ftdm->cid_num.digits); + uint8_t len = strlen(caller_data->cid_num.digits); if (!len) { return FTDM_SUCCESS; } cgPtyNmb->eh.pres = PRSNT_NODEF; cgPtyNmb->screenInd.pres = PRSNT_NODEF; - cgPtyNmb->screenInd.val = ftdm->screen; + cgPtyNmb->screenInd.val = caller_data->screen; cgPtyNmb->presInd0.pres = PRSNT_NODEF; - cgPtyNmb->presInd0.val = ftdm->pres; - + cgPtyNmb->presInd0.val = caller_data->pres; + cgPtyNmb->nmbPlanId.pres = PRSNT_NODEF; - cgPtyNmb->nmbPlanId.val = ftdm->cid_num.plan; + cgPtyNmb->nmbPlanId.val = caller_data->cid_num.plan; cgPtyNmb->typeNmb1.pres = PRSNT_NODEF; - cgPtyNmb->typeNmb1.val = ftdm->cid_num.type; + cgPtyNmb->typeNmb1.val = caller_data->cid_num.type; cgPtyNmb->nmbDigits.pres = PRSNT_NODEF; cgPtyNmb->nmbDigits.len = len; - memcpy(cgPtyNmb->nmbDigits.val, ftdm->cid_num.digits, len); + memcpy(cgPtyNmb->nmbDigits.val, caller_data->cid_num.digits, len); return FTDM_SUCCESS; } -ftdm_status_t cpy_called_num_from_user(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *ftdm) +ftdm_status_t set_called_num(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *caller_data) { - uint8_t len = strlen(ftdm->dnis.digits); + uint8_t len = strlen(caller_data->dnis.digits); if (!len) { return FTDM_SUCCESS; } cdPtyNmb->eh.pres = PRSNT_NODEF; cdPtyNmb->nmbPlanId.pres = PRSNT_NODEF; - if (ftdm->dnis.plan == FTDM_NPI_INVALID) { + if (caller_data->dnis.plan == FTDM_NPI_INVALID) { cdPtyNmb->nmbPlanId.val = FTDM_NPI_UNKNOWN; } else { - cdPtyNmb->nmbPlanId.val = ftdm->dnis.plan; + cdPtyNmb->nmbPlanId.val = caller_data->dnis.plan; } cdPtyNmb->typeNmb0.pres = PRSNT_NODEF; - if (ftdm->dnis.type == FTDM_TON_INVALID) { + if (caller_data->dnis.type == FTDM_TON_INVALID) { cdPtyNmb->typeNmb0.val = FTDM_TON_UNKNOWN; } else { - cdPtyNmb->typeNmb0.val = ftdm->dnis.type; + cdPtyNmb->typeNmb0.val = caller_data->dnis.type; } cdPtyNmb->nmbDigits.pres = PRSNT_NODEF; cdPtyNmb->nmbDigits.len = len; - memcpy(cdPtyNmb->nmbDigits.val, ftdm->dnis.digits, len); + memcpy(cdPtyNmb->nmbDigits.val, caller_data->dnis.digits, len); return FTDM_SUCCESS; } -ftdm_status_t cpy_redir_num_from_user(RedirNmb *redirNmb, ftdm_caller_data_t *ftdm) +ftdm_status_t set_redir_num(RedirNmb *redirNmb, ftdm_caller_data_t *caller_data) { - uint8_t len = strlen(ftdm->rdnis.digits); + uint8_t len = strlen(caller_data->rdnis.digits); if (!len) { return FTDM_SUCCESS; } @@ -315,36 +336,36 @@ ftdm_status_t cpy_redir_num_from_user(RedirNmb *redirNmb, ftdm_caller_data_t *ft redirNmb->eh.pres = PRSNT_NODEF; redirNmb->nmbPlanId.pres = PRSNT_NODEF; - if (ftdm->rdnis.plan == FTDM_NPI_INVALID) { + if (caller_data->rdnis.plan == FTDM_NPI_INVALID) { redirNmb->nmbPlanId.val = FTDM_NPI_UNKNOWN; } else { - redirNmb->nmbPlanId.val = ftdm->rdnis.plan; + redirNmb->nmbPlanId.val = caller_data->rdnis.plan; } redirNmb->typeNmb.pres = PRSNT_NODEF; - if (ftdm->rdnis.type == FTDM_TON_INVALID) { + if (caller_data->rdnis.type == FTDM_TON_INVALID) { redirNmb->typeNmb.val = FTDM_TON_UNKNOWN; } else { - redirNmb->typeNmb.val = ftdm->rdnis.type; + redirNmb->typeNmb.val = caller_data->rdnis.type; } redirNmb->nmbDigits.pres = PRSNT_NODEF; redirNmb->nmbDigits.len = len; - memcpy(redirNmb->nmbDigits.val, ftdm->rdnis.digits, len); + memcpy(redirNmb->nmbDigits.val, caller_data->rdnis.digits, len); return FTDM_SUCCESS; } -ftdm_status_t cpy_calling_name_from_user(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan) +ftdm_status_t set_calling_name(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan) { uint8_t len; - ftdm_caller_data_t *ftdm = &ftdmchan->caller_data; + ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; /* sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data; */ sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - len = strlen(ftdm->cid_name); + len = strlen(caller_data->cid_name); if (!len) { return FTDM_SUCCESS; } @@ -359,7 +380,7 @@ ftdm_status_t cpy_calling_name_from_user(ConEvnt *conEvnt, ftdm_channel_t *ftdmc conEvnt->usrUsr.usrInfo.len = len; /* in sangoma_brid we used to send usr-usr info as !, change to previous style if current one does not work */ - memcpy(conEvnt->usrUsr.usrInfo.val, ftdm->cid_name, len); + memcpy(conEvnt->usrUsr.usrInfo.val, caller_data->cid_name, len); } else { switch (signal_data->switchtype) { case SNGISDN_SWITCH_NI2: @@ -377,7 +398,7 @@ ftdm_status_t cpy_calling_name_from_user(ConEvnt *conEvnt, ftdm_channel_t *ftdmc conEvnt->display.eh.pres = PRSNT_NODEF; conEvnt->display.dispInfo.pres = PRSNT_NODEF; conEvnt->display.dispInfo.len = len; - memcpy(conEvnt->display.dispInfo.val, ftdm->cid_name, len); + memcpy(conEvnt->display.dispInfo.val, caller_data->cid_name, len); break; case SNGISDN_SWITCH_QSIG: /* It seems like QSIG does not support Caller ID Name */ @@ -390,6 +411,20 @@ ftdm_status_t cpy_calling_name_from_user(ConEvnt *conEvnt, ftdm_channel_t *ftdmc return FTDM_SUCCESS; } +ftdm_status_t set_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr) +{ + const char *facility_str = NULL; + + facility_str = ftdm_channel_get_var(ftdmchan, "isdn.facility.val"); + if (facility_str) { + facilityStr->eh.pres = PRSNT_NODEF; + facilityStr->facilityStr.len = strlen(facility_str); + memcpy(facilityStr->facilityStr.val, facility_str, facilityStr->facilityStr.len); + return FTDM_SUCCESS; + } + return FTDM_FAIL; +} + void sngisdn_t3_timeout(void* p_sngisdn_info) { sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info; diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index 87da5d1dd0..014eeef852 100644 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -285,7 +285,7 @@ typedef enum { /*! \brief Signaling messages sent by the stacks */ typedef enum { - FTDM_SIGEVENT_START, /*!< Incoming call (ie: incoming SETUP msg or Ring) */ + FTDM_SIGEVENT_START,/*!< Incoming call (ie: incoming SETUP msg or Ring) */ FTDM_SIGEVENT_STOP, /*!< Hangup */ FTDM_SIGEVENT_RELEASED, /*!< Channel is completely released and available */ FTDM_SIGEVENT_UP, /*!< Outgoing call has been answered */ @@ -300,12 +300,12 @@ typedef enum { FTDM_SIGEVENT_RESTART, /*!< Restart has been requested. Typically you hangup your call resources here */ FTDM_SIGEVENT_SIGSTATUS_CHANGED, /*!< Signaling protocol status changed (ie: D-chan up), see new status in raw_data ftdm_sigmsg_t member */ FTDM_SIGEVENT_COLLISION, /*!< Outgoing call was dropped because an incoming call arrived at the same time */ - FTDM_SIGEVENT_MSG, /* !< We received an in-call msg */ + FTDM_SIGEVENT_MSG, /*!< We received an in-call msg */ FTDM_SIGEVENT_INVALID } ftdm_signal_event_t; #define SIGNAL_STRINGS "START", "STOP", "RELEASED", "UP", "FLASH", "PROCEED", "PROGRESS", \ "PROGRESS_MEDIA", "ALARM_TRAP", "ALARM_CLEAR", \ - "COLLECTED_DIGIT", "ADD_CALL", "RESTART", "SIGSTATUS_CHANGED", "COLLISION", "INVALID" + "COLLECTED_DIGIT", "ADD_CALL", "RESTART", "SIGSTATUS_CHANGED", "COLLISION", "MSG", "INVALID" /*! \brief Move from string to ftdm_signal_event_t and viceversa */ FTDM_STR2ENUM_P(ftdm_str2ftdm_signal_event, ftdm_signal_event2str, ftdm_signal_event_t) From c9fa092a9ef7a48ee702a729da2d8c30f62e7d65 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Thu, 25 Nov 2010 13:22:41 -0600 Subject: [PATCH 096/237] VS2010 add mod_cepstral to Setup --- w32/Setup/Setup.wixproj | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/w32/Setup/Setup.wixproj b/w32/Setup/Setup.wixproj index 7d11c90a4b..fa6c832777 100644 --- a/w32/Setup/Setup.wixproj +++ b/w32/Setup/Setup.wixproj @@ -336,6 +336,15 @@ Binaries;Content;Satellites MODLOCATION + + mod_cepstral + {692f6330-4d87-4c82-81df-40db5892636e} + True + + + Binaries;Content;Satellites + MODLOCATION + mod_pocketsphinx {2286da73-9fc5-45bc-a508-85994c3317ab} From b8fb8acca152a5850b4a0fa4c0625f0094909059 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Thu, 25 Nov 2010 16:16:36 -0500 Subject: [PATCH 097/237] freetdm: ISDN allow change state from PROCEED to UP --- libs/freetdm/src/ftdm_io.c | 7 ++++++- .../src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c | 3 ++- .../ftmod_sangoma_isdn_stack_hndl.c | 11 +++++------ 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index ede3ff8fc8..6f543304a2 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -2033,6 +2033,11 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_answer(const char *file, const char goto done; } +#if 0 + /* DAVIDY - We will fail RFC's if we do that, but some modules apart from ftmod_sangoma_isdn + * expect the call to always to go PROGRESS and PROGRESS MEDIA state before going to UP, so + * remove this only in netborder branch for now */ + if (ftdmchan->state < FTDM_CHANNEL_STATE_PROGRESS) { ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS, 1); } @@ -2052,7 +2057,7 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_answer(const char *file, const char ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Ignoring answer because the call has moved to TERMINATING while we're moving to UP\n"); goto done; } - +#endif ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_UP, 1); done: diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c index 6f5f838590..9aa52f816c 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c @@ -121,7 +121,8 @@ ftdm_state_map_t sangoma_isdn_state_map = { ZSD_INBOUND, ZSM_UNACCEPTABLE, {FTDM_CHANNEL_STATE_PROCEED, FTDM_END}, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA,FTDM_END} + {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, + FTDM_CHANNEL_STATE_UP, FTDM_END} }, { ZSD_INBOUND, diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c index a541a655d8..f10fa766e3 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c @@ -377,18 +377,17 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event) switch(ftdmchan->state) { case FTDM_CHANNEL_STATE_DIALING: - if (evntType == MI_CALLPROC) { - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROCEED); - } else if (evntType == MI_PROGRESS || - (cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL)) { + if (cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL) { ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); + } else if (evntType == MI_CALLPROC) { + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROCEED); } else { ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS); } break; + case FTDM_CHANNEL_STATE_PROCEED: case FTDM_CHANNEL_STATE_PROGRESS: - if (evntType == MI_PROGRESS || - (cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL)) { + if (cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL) { ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); } break; From 2973776b6480309a5fe95aa8b2a3ba5151288c6b Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Thu, 25 Nov 2010 16:36:49 -0500 Subject: [PATCH 098/237] changed set_facility_ie --- Freeswitch.2008.sln | 20 +++++-------------- .../ftmod_sangoma_isdn_support.c | 12 +++++------ 2 files changed, 10 insertions(+), 22 deletions(-) diff --git a/Freeswitch.2008.sln b/Freeswitch.2008.sln index 01a4cf43c1..4ffd66abac 100644 --- a/Freeswitch.2008.sln +++ b/Freeswitch.2008.sln @@ -36,7 +36,6 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Default", "Default", "{3B08FEFD-4D3D-4C16-BA94-EE83509E32A0}" ProjectSection(SolutionItems) = preProject conf\freeswitch.xml = conf\freeswitch.xml - conf\vars.xml = conf\vars.xml EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Release", "Release", "{7BFD517E-7F8F-4A40-A78E-8D3632738227}" @@ -57,7 +56,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_Build System", "_Build Sys bootstrap.sh = bootstrap.sh build\buildlib.sh = build\buildlib.sh configure.in = configure.in - Makefile.am = Makefile.am build\modmake.rules.in = build\modmake.rules.in build\modules.conf.in = build\modules.conf.in libs\win32\util.vbs = libs\win32\util.vbs @@ -92,15 +90,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "autoload_configs", "autoloa conf\autoload_configs\limit.conf.xml = conf\autoload_configs\limit.conf.xml conf\autoload_configs\local_stream.conf.xml = conf\autoload_configs\local_stream.conf.xml conf\autoload_configs\logfile.conf.xml = conf\autoload_configs\logfile.conf.xml - conf\autoload_configs\modules.conf.xml = conf\autoload_configs\modules.conf.xml conf\autoload_configs\openmrcp.conf.xml = conf\autoload_configs\openmrcp.conf.xml conf\autoload_configs\portaudio.conf.xml = conf\autoload_configs\portaudio.conf.xml conf\autoload_configs\rss.conf.xml = conf\autoload_configs\rss.conf.xml conf\autoload_configs\sofia.conf.xml = conf\autoload_configs\sofia.conf.xml conf\autoload_configs\spidermonkey.conf.xml = conf\autoload_configs\spidermonkey.conf.xml - conf\autoload_configs\switch.conf.xml = conf\autoload_configs\switch.conf.xml conf\autoload_configs\syslog.conf.xml = conf\autoload_configs\syslog.conf.xml - conf\autoload_configs\voicemail.conf.xml = conf\autoload_configs\voicemail.conf.xml conf\autoload_configs\wanpipe.conf.xml = conf\autoload_configs\wanpipe.conf.xml conf\autoload_configs\woomera.conf.xml = conf\autoload_configs\woomera.conf.xml conf\autoload_configs\xml_cdr.conf.xml = conf\autoload_configs\xml_cdr.conf.xml @@ -111,7 +106,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "autoload_configs", "autoloa EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dialplan", "dialplan", "{C7E2382E-2C22-4D18-BF93-80C6A1FFA7AC}" ProjectSection(SolutionItems) = preProject - conf\dialplan\default.xml = conf\dialplan\default.xml conf\dialplan\public.xml = conf\dialplan\public.xml EndProjectSection EndProject @@ -123,7 +117,6 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sip_profiles", "sip_profiles", "{8E2E8798-8B6F-4A55-8E4F-4E6FDE40ED26}" ProjectSection(SolutionItems) = preProject conf\sip_profiles\external.xml = conf\sip_profiles\external.xml - conf\sip_profiles\internal.xml = conf\sip_profiles\internal.xml conf\sip_profiles\nat.xml = conf\sip_profiles\nat.xml EndProjectSection EndProject @@ -308,9 +301,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "autoload_configs", "autoloa EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dialplan", "dialplan", "{23874F4B-C0AF-4587-9F7E-DB0F06DE8CB4}" - ProjectSection(SolutionItems) = preProject - conf\dialplan\default.xml = conf\dialplan\default.xml - EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "directory", "directory", "{19ED97F6-30D8-4FCE-AE1D-8B7FCB170D40}" ProjectSection(SolutionItems) = preProject @@ -1271,15 +1261,15 @@ Global {89385C74-5860-4174-9CAF-A39E7C48909C}.Release|Win32.Build.0 = Release|Win32 {89385C74-5860-4174-9CAF-A39E7C48909C}.Release|x64.ActiveCfg = Release|x64 {89385C74-5860-4174-9CAF-A39E7C48909C}.Release|x64.Build.0 = Release|x64 - {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.All|Win32.ActiveCfg = Release|x64 - {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.All|x64.ActiveCfg = Release|x64 - {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.All|x64.Build.0 = Release|x64 + {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.All|Win32.ActiveCfg = Release|Win32 + {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.All|Win32.Build.0 = Release|Win32 + {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.All|x64.ActiveCfg = Release|Win32 {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Debug|Win32.ActiveCfg = Debug|Win32 {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Debug|Win32.Build.0 = Debug|Win32 - {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Debug|x64.ActiveCfg = Debug|x64 + {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Debug|x64.ActiveCfg = Debug|Win32 {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Release|Win32.ActiveCfg = Release|Win32 {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Release|Win32.Build.0 = Release|Win32 - {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Release|x64.ActiveCfg = Release|x64 + {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Release|x64.ActiveCfg = Release|Win32 {692F6330-4D87-4C82-81DF-40DB5892636E}.All|Win32.ActiveCfg = Release|x64 {692F6330-4D87-4C82-81DF-40DB5892636E}.All|x64.ActiveCfg = Release|x64 {692F6330-4D87-4C82-81DF-40DB5892636E}.All|x64.Build.0 = Release|x64 diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c index 4ddb90bbd3..c9aa3f035c 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c @@ -412,14 +412,12 @@ ftdm_status_t set_calling_name(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan) } ftdm_status_t set_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr) -{ - const char *facility_str = NULL; - - facility_str = ftdm_channel_get_var(ftdmchan, "isdn.facility.val"); - if (facility_str) { +{ + if (ftdmchan->caller_data.raw_data_len && + ftdmchan->caller_data.raw_data[0] == 0x1C) { facilityStr->eh.pres = PRSNT_NODEF; - facilityStr->facilityStr.len = strlen(facility_str); - memcpy(facilityStr->facilityStr.val, facility_str, facilityStr->facilityStr.len); + facilityStr->facilityStr.len = ftdmchan->caller_data.raw_data_len-2; + memcpy(facilityStr->facilityStr.val, &ftdmchan->caller_data.raw_data[2], facilityStr->facilityStr.len); return FTDM_SUCCESS; } return FTDM_FAIL; From 5c747b699cfe3b2e19a3dc66a815cf7bfc9574a0 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Thu, 25 Nov 2010 18:54:15 -0500 Subject: [PATCH 099/237] Fix for receiving/transmitting facility IE --- .../ftmod_sangoma_isdn_stack_hndl.c | 23 ++++++++++--------- .../ftmod_sangoma_isdn_stack_out.c | 2 -- .../ftmod_sangoma_isdn_support.c | 4 +++- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c index f10fa766e3..f3fc23e317 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c @@ -142,21 +142,22 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event) ftdmchan->caller_data.bearer_capability = sngisdn_get_infoTranCap_from_stack(conEvnt->bearCap[0].infoTranCap.val); } - if (signal_data->switchtype == SNGISDN_SWITCH_NI2) { - if (conEvnt->shift11.eh.pres && conEvnt->ni2OctStr.eh.pres) { - if (conEvnt->ni2OctStr.str.len == 4 && conEvnt->ni2OctStr.str.val[0] == 0x37) { - snprintf(ftdmchan->caller_data.aniII, 5, "%.2d", conEvnt->ni2OctStr.str.val[3]); - } + + if (conEvnt->shift11.eh.pres && conEvnt->ni2OctStr.eh.pres) { + if (conEvnt->ni2OctStr.str.len == 4 && conEvnt->ni2OctStr.str.val[0] == 0x37) { + snprintf(ftdmchan->caller_data.aniII, 5, "%.2d", conEvnt->ni2OctStr.str.val[3]); } + } - if (conEvnt->facilityStr.eh.pres) { - if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) { - get_facility_ie(&ftdmchan->caller_data, conEvnt->facilityStr.facilityStr.val, conEvnt->facilityStr.facilityStr.len); - } else if (signal_data->facility == SNGISDN_OPT_TRUE) { + if (conEvnt->facilityStr.eh.pres) { + if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) { + get_facility_ie(&ftdmchan->caller_data, conEvnt->facilityStr.facilityStr.val, conEvnt->facilityStr.facilityStr.len); + } else if (signal_data->facility == SNGISDN_OPT_TRUE) { + if (signal_data->switchtype == SNGISDN_SWITCH_NI2) { /* Verify whether the Caller Name will come in a subsequent FACILITY message */ uint16_t ret_val; char retrieved_str[255]; - + ret_val = sng_isdn_retrieve_facility_caller_name(conEvnt->facilityStr.facilityStr.val, conEvnt->facilityStr.facilityStr.len, retrieved_str); /* return values for "sng_isdn_retrieve_facility_information_following": @@ -170,7 +171,7 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event) ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_GET_CALLERID); /* Launch timer in case we never get a FACILITY msg */ if (signal_data->facility_timeout) { - ftdm_sched_timer(signal_data->sched, "facility_timeout", signal_data->facility_timeout, + ftdm_sched_timer(signal_data->sched, "facility_timeout", signal_data->facility_timeout, sngisdn_facility_timeout, (void*) sngisdn_info, &sngisdn_info->timers[SNGISDN_TIMER_FACILITY]); } break; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c index 36c6782a97..1b906a2004 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c @@ -412,7 +412,6 @@ void sngisdn_snd_connect(ftdm_channel_t *ftdmchan) memset(&cnStEvnt, 0, sizeof(cnStEvnt)); - cnStEvnt.chanId.eh.pres = PRSNT_NODEF; cnStEvnt.chanId.prefExc.pres = PRSNT_NODEF; cnStEvnt.chanId.prefExc.val = IN_PE_EXCLSVE; @@ -557,7 +556,6 @@ void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan) discEvnt.causeDgn[0].dgnVal.pres = NOTPRSNT; set_facility_ie(ftdmchan, &discEvnt.facilityStr); - ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending DISCONNECT (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId); if (sng_isdn_disc_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &discEvnt)) { diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c index c9aa3f035c..241bb43a90 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c @@ -412,14 +412,16 @@ ftdm_status_t set_calling_name(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan) } ftdm_status_t set_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr) -{ +{ if (ftdmchan->caller_data.raw_data_len && ftdmchan->caller_data.raw_data[0] == 0x1C) { facilityStr->eh.pres = PRSNT_NODEF; + facilityStr->facilityStr.pres = PRSNT_NODEF; facilityStr->facilityStr.len = ftdmchan->caller_data.raw_data_len-2; memcpy(facilityStr->facilityStr.val, &ftdmchan->caller_data.raw_data[2], facilityStr->facilityStr.len); return FTDM_SUCCESS; } + return FTDM_FAIL; } From 1bd4de4fd95c4dc33a379f537f93ab36f4134d5f Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Thu, 25 Nov 2010 22:11:20 -0200 Subject: [PATCH 100/237] freetdm: when protocol errors occurs on ftmod_r2, the channel state is properly set as down now --- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 42 +++++++++++++--------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index bfe49fd8ca..f089846fae 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -67,9 +67,9 @@ typedef struct ftdm_r2_call_t { ftdm_r2_call_flag_t flags; int accepted:1; int answer_pending:1; - int state_ack_pending:1; int disconnect_rcvd:1; int ftdm_started:1; + int protocol_error:1; ftdm_channel_state_t chanstate; ftdm_size_t dnis_index; ftdm_size_t ani_index; @@ -456,10 +456,12 @@ static void ftdm_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t m openr2_chan_disable_read(r2chan); R2CALL(ftdmchan)->accepted = 1; if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) { - R2CALL(ftdmchan)->state_ack_pending = 1; + ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE); + ftdm_channel_complete_state(ftdmchan); if (R2CALL(ftdmchan)->answer_pending) { ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Answer was pending, answering now.\n"); ft_r2_answer_call(ftdmchan); + R2CALL(ftdmchan)->answer_pending = 0; return; } } else { @@ -522,7 +524,7 @@ static void ftdm_r2_on_call_end(openr2_chan_t *r2chan) ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Call finished\n"); /* the call is done as far as the stack is concerned, lets move to down here */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); /* in some circumstances openr2 can call on_call_init right after this, so let's advance the state right here */ ftdm_r2_state_advance(ftdmchan); @@ -560,6 +562,7 @@ static void ftdm_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_err ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Protocol error\n"); R2CALL(ftdmchan)->disconnect_rcvd = 1; + R2CALL(ftdmchan)->protocol_error = 1; if (!R2CALL(ftdmchan)->ftdm_started) { ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); @@ -1173,13 +1176,13 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan) ret = 0; - if (R2CALL(ftdmchan)->state_ack_pending) { - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE); - ftdm_channel_complete_state(ftdmchan); - R2CALL(ftdmchan)->state_ack_pending = 0; - } - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE) && (R2CALL(ftdmchan)->chanstate != ftdmchan->state)) { + /* because we do not always acknowledge the state change (clearing the FTDM_CHANNEL_STATE_CHANGE flag) due to the accept + * procedure described below, we need the chanstate member to NOT process some states twice, so is valid entering this + * function with the FTDM_CHANNEL_STATE_CHANGE flag set but with a state that was already processed and is just waiting + * to complete (the processing is media-bound) + * */ + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE) + && (R2CALL(ftdmchan)->chanstate != ftdmchan->state)) { ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Executing state handler for %s\n", ftdm_channel_state2str(ftdmchan->state)); R2CALL(ftdmchan)->chanstate = ftdmchan->state; @@ -1188,10 +1191,15 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan) (ftdmchan->state == FTDM_CHANNEL_STATE_PROGRESS || ftdmchan->state == FTDM_CHANNEL_STATE_PROGRESS_MEDIA || ftdmchan->state == FTDM_CHANNEL_STATE_UP) ) { - /* if an accept ack will be required we should not acknowledge the state change just yet, - it will be done below after processing the MF signals, otherwise we have a race condition between freetdm calling - openr2_chan_answer_call and openr2 accepting the call first, if freetdm calls openr2_chan_answer_call before the accept cycle - completes, openr2 will fail to answer the call */ + /* + Moving to PROGRESS, PROGRESS_MEDIA or UP means that we must accept the call, and accepting + the call in R2 means sending a tone, then waiting for the acknowledge from the other end, + since all of that requires sending and detecting tones, it takes a few milliseconds (I'd say around 100) + which means during that time the user should not try to perform any operations like answer, hangup or anything + else, therefore we DO NOT clear the FTDM_CHANNEL_STATE_CHANGE flag here, we rely on ftdm_io.c to block + the user thread until we're done with the accept (see on_call_accepted callback) and then we clear the state change flag, + otherwise we have a race condition between freetdm calling openr2_chan_answer_call and openr2 accepting the call first, + if freetdm calls openr2_chan_answer_call before the accept cycle completes, openr2 will fail to answer the call */ ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "State ack for state %s will have to wait a bit\n", ftdm_channel_state2str(ftdmchan->state)); } else if (ftdmchan->state != FTDM_CHANNEL_STATE_DOWN){ ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE); @@ -1289,9 +1297,12 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan) if (!R2CALL(ftdmchan)->disconnect_rcvd) { /* this will disconnect the call, but need to wait for the call end before moving to DOWN */ openr2_chan_disconnect_call(r2chan, disconnect_cause); - } else { + } else if (!R2CALL(ftdmchan)->protocol_error) { /* just ack the hangup, on_call_end will be called by openr2 right after */ openr2_chan_disconnect_call(r2chan, disconnect_cause); + } else { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Clearing call due to protocol error\n"); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); } } break; @@ -1347,7 +1358,6 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) int res, ms; struct timeval start, end; short *poll_events = ftdm_malloc(sizeof(short)*span->chan_count); - ftdm_event_t *event = NULL; #ifdef __linux__ r2data->monitor_thread_id = syscall(SYS_gettid); From 54a3c95cb0aeb52ca1b8f6cbb80ca0e5d0afdf39 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Thu, 25 Nov 2010 23:42:36 -0500 Subject: [PATCH 101/237] freetdm: add r2 loop timing statistics --- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 64 +++++++++++++++++----- 1 file changed, 51 insertions(+), 13 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index f089846fae..06d1abdc04 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -123,11 +123,13 @@ typedef struct ftdm_r2_data_s { /* whether accept the call when offered, or wait until the user decides to accept */ int accept_on_offer:1; /* max time spent in ms doing real work in a single loop */ - int jobmax; - /* total working loops */ - unsigned long loops; + int32_t jobmax; + /* Total number of loops performed so far */ + uint64_t total_loops; + /* number of loops per 10ms increment from 0-9ms, 10-19ms .. 100ms and above */ + uint64_t loops[11]; /* LWP */ - unsigned long monitor_thread_id; + uint32_t monitor_thread_id; } ftdm_r2_data_t; /* one element per span will be stored in g_mod_data_hash global var to keep track of them @@ -1356,8 +1358,9 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) int waitms = 20; unsigned int i; int res, ms; + int index = 0; struct timeval start, end; - short *poll_events = ftdm_malloc(sizeof(short)*span->chan_count); + short *poll_events = ftdm_malloc(sizeof(short) * span->chan_count); #ifdef __linux__ r2data->monitor_thread_id = syscall(SYS_gettid); @@ -1374,14 +1377,20 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) memset(&start, 0, sizeof(start)); memset(&end, 0, sizeof(end)); while (ftdm_running() && ftdm_test_flag(r2data, FTDM_R2_RUNNING)) { - r2data->loops++; res = gettimeofday(&end, NULL); if (start.tv_sec) { ms = ((end.tv_sec - start.tv_sec) * 1000) + ((( 1000000 + end.tv_usec - start.tv_usec) / 1000) - 1000); + if (ms < 0) { + ms = 0; + } if (ms > r2data->jobmax) { r2data->jobmax = ms; } + index = (ms / 10); + index = (index > 10) ? 10 : index; + r2data->loops[index]++; + r2data->total_loops++; } #ifndef WIN32 @@ -1576,7 +1585,7 @@ static FIO_API_FUNCTION(ftdm_r2_api) goto done; } if (!(r2data = span->signal_data)) { - stream->write_function(stream, "-ERR invalid span. No R2 singal data in span.\n"); + stream->write_function(stream, "-ERR invalid span. No R2 signal data in span.\n"); goto done; } r2context = r2data->r2context; @@ -1587,19 +1596,17 @@ static FIO_API_FUNCTION(ftdm_r2_api) "Max DNIS: %d\n" "ANI First: %s\n" "Immediate Accept: %s\n" - "Side: %s\n" + "Job Thread: %lu\n" "Job Max ms: %d\n" - "Job Loops: %lu\n" - "Monitor Thread: %lu\n", + "Job Loops: %lu\n", openr2_proto_get_variant_string(r2variant), openr2_context_get_max_ani(r2context), openr2_context_get_max_dnis(r2context), openr2_context_get_ani_first(r2context) ? "Yes" : "No", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No", - "no side", + r2data->monitor_thread_id, r2data->jobmax, - r2data->loops, - r2data->monitor_thread_id); + r2data->total_loops); stream->write_function(stream, "\n"); stream->write_function(stream, "%4s %-12.12s %-12.12s\n", "Channel", "Tx CAS", "Rx CAS"); for (i = 1; i <= span->chan_count; i++) { @@ -1618,6 +1625,37 @@ static FIO_API_FUNCTION(ftdm_r2_api) } } + if (!strcasecmp(argv[0], "loopstats")) { + int range; + span_id = atoi(argv[1]); + + if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS || ftdm_span_find(span_id, &span) == FTDM_SUCCESS) { + if (span->start != ftdm_r2_start) { + stream->write_function(stream, "-ERR not an R2 span.\n"); + goto done; + } + if (!(r2data = span->signal_data)) { + stream->write_function(stream, "-ERR invalid span. No R2 signal data in span.\n"); + goto done; + } + range = 0; + for (i = 0; i < ftdm_array_len(r2data->loops); i++) { + if ((i + 1) == ftdm_array_len(r2data->loops)) { + stream->write_function(stream, ">= %dms: %llu\n", range, r2data->loops[i]); + } else { + stream->write_function(stream, "%d-%dms: %llu\n", range, range + 9, r2data->loops[i]); + } + range += 10; + } + stream->write_function(stream, "\n"); + stream->write_function(stream, "+OK.\n"); + goto done; + } else { + stream->write_function(stream, "-ERR invalid span.\n"); + goto done; + } + } + } if (argc == 1) { From c7aefe934fc6d603b7756406528f6881af198b0b Mon Sep 17 00:00:00 2001 From: Giovanni Maruzzelli Date: Fri, 26 Nov 2010 06:44:57 -0600 Subject: [PATCH 102/237] gsmopen: retry serial initialization if failed, zeroing audio buffers, slower retry on soundcard busy (EAGAIN) --- src/mod/endpoints/mod_gsmopen/gsmopen.h | 2 +- .../mod_gsmopen/gsmopen_protocol.cpp | 20 +++++++++++--- src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp | 27 +++++++++++++------ 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/src/mod/endpoints/mod_gsmopen/gsmopen.h b/src/mod/endpoints/mod_gsmopen/gsmopen.h index fd94bccc2a..05ef1641bf 100644 --- a/src/mod/endpoints/mod_gsmopen/gsmopen.h +++ b/src/mod/endpoints/mod_gsmopen/gsmopen.h @@ -158,7 +158,7 @@ typedef enum { #define WARNINGA(...) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "rev "GSMOPEN_SVN_VERSION "[%p|%-7lx][WARNINGA %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ ); #define NOTICA(...) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "rev "GSMOPEN_SVN_VERSION "[%p|%-7lx][NOTICA %-5d][%-10s][%2d,%2d,%2d] " __VA_ARGS__ ); -#define GSMOPEN_P_LOG NULL, (unsigned long)55, __LINE__, tech_pvt ? tech_pvt->name ? tech_pvt->name : "none" : "none", -1, tech_pvt ? tech_pvt->interface_state : -1, tech_pvt ? tech_pvt->phone_callflow : -1 +#define GSMOPEN_P_LOG (void *)NULL, (unsigned long)55, __LINE__, tech_pvt ? tech_pvt->name ? tech_pvt->name : "none" : "none", -1, tech_pvt ? tech_pvt->interface_state : -1, tech_pvt ? tech_pvt->phone_callflow : -1 /*********************************/ #define GSMOPEN_CAUSE_NORMAL 1 diff --git a/src/mod/endpoints/mod_gsmopen/gsmopen_protocol.cpp b/src/mod/endpoints/mod_gsmopen/gsmopen_protocol.cpp index e4bb6b9200..76d32ac3f0 100644 --- a/src/mod/endpoints/mod_gsmopen/gsmopen_protocol.cpp +++ b/src/mod/endpoints/mod_gsmopen/gsmopen_protocol.cpp @@ -3294,12 +3294,18 @@ int alsa_write(private_t * tech_pvt, short *data, int datalen) time_t now_timestamp; /* size_t frames = 0; */ snd_pcm_state_t state; - snd_pcm_sframes_t delayp1; - snd_pcm_sframes_t delayp2; + snd_pcm_sframes_t delayp1=0; + snd_pcm_sframes_t delayp2=0; if(tech_pvt->no_sound==1){ return res; } + + + memset(sizbuf, 255, sizeof(sizbuf)); + memset(sizbuf2, 255, sizeof(sizbuf)); + memset(silencebuf, 255, sizeof(sizbuf)); + //ERRORA("data=%p, datalen=%d\n", GSMOPEN_P_LOG, (void *)data, datalen); /* We have to digest the frame in 160-byte portions */ if (datalen > sizeof(sizbuf) - sizpos) { @@ -3307,8 +3313,11 @@ int alsa_write(private_t * tech_pvt, short *data, int datalen) res = -1; } else { memcpy(sizbuf + sizpos, data, datalen); + memset(data, 255, datalen); len += datalen; pos = 0; + + #ifdef ALSA_MONITOR alsa_monitor_write(sizbuf, len); #endif @@ -3456,6 +3465,7 @@ int alsa_write(private_t * tech_pvt, short *data, int datalen) if (res == -ESTRPIPE) { ERRORA("You've got some big problems\n", GSMOPEN_P_LOG); } else if (res == -EAGAIN) { + DEBUGA_GSMOPEN("Momentarily busy\n", GSMOPEN_P_LOG); res = 0; } else if (res < 0) { ERRORA("Error %d on audio write: \"%s\"\n", GSMOPEN_P_LOG, res, snd_strerror(res)); @@ -3572,9 +3582,11 @@ int alsa_read(private_t * tech_pvt, short *data, int datalen) return r; } else if (r == -EAGAIN) { - DEBUGA_GSMOPEN("ALSA read -EAGAIN, the soundcard is not ready to be read by gsmopen\n", GSMOPEN_P_LOG); + int count=0; while (r == -EAGAIN) { - gsmopen_sleep(1000); + gsmopen_sleep(10000); + DEBUGA_GSMOPEN("%d ALSA read -EAGAIN, the soundcard is not ready to be read by gsmopen\n", GSMOPEN_P_LOG, count); + count++; if (tech_pvt->alsa_capture_is_mono) { r = snd_pcm_readi(tech_pvt->alsac, buf + readpos, left); diff --git a/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp b/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp index cb440d3bcb..7e20b7c25e 100644 --- a/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp +++ b/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp @@ -1904,14 +1904,25 @@ static switch_status_t load_config(int reload_type) if (globals.GSMOPEN_INTERFACES[interface_id].controldevprotocol != PROTOCOL_NO_SERIAL) { res = gsmopen_serial_config(&globals.GSMOPEN_INTERFACES[interface_id]); if (res) { - ERRORA("gsmopen_serial_config failed\n", GSMOPEN_P_LOG); - ERRORA("STARTING interface_id=%d FAILED\n", GSMOPEN_P_LOG, interface_id); - //return SWITCH_STATUS_FALSE; - globals.GSMOPEN_INTERFACES[interface_id].running=0; - alarm_event(&globals.GSMOPEN_INTERFACES[interface_id], ALARM_FAILED_INTERFACE, "gsmopen_serial_config failed"); - globals.GSMOPEN_INTERFACES[interface_id].active=0; - globals.GSMOPEN_INTERFACES[interface_id].name[0]='\0'; - continue; + int count = 0; + ERRORA("gsmopen_serial_config failed, let's try again\n", GSMOPEN_P_LOG); + while(res && count < 5){ + switch_sleep(100000); //0.1 seconds + res = gsmopen_serial_config(&globals.GSMOPEN_INTERFACES[interface_id]); + count++; + if (res) { + ERRORA("%d: gsmopen_serial_config failed, let's try again\n", GSMOPEN_P_LOG, count); + } + } + if (res) { + ERRORA("STARTING interface_id=%d FAILED\n", GSMOPEN_P_LOG, interface_id); + //return SWITCH_STATUS_FALSE; + globals.GSMOPEN_INTERFACES[interface_id].running=0; + alarm_event(&globals.GSMOPEN_INTERFACES[interface_id], ALARM_FAILED_INTERFACE, "gsmopen_serial_config failed"); + globals.GSMOPEN_INTERFACES[interface_id].active=0; + globals.GSMOPEN_INTERFACES[interface_id].name[0]='\0'; + continue; + } } } From 599a200509e4f164aa494e1798f61e8138d5d20a Mon Sep 17 00:00:00 2001 From: Giovanni Maruzzelli Date: Fri, 26 Nov 2010 07:05:16 -0600 Subject: [PATCH 103/237] skypopen: adding osscuse directory, lot of news to come in some days ;) --- .../mod_skypopen/osscuse/98-osscuse.rules | 7 + .../endpoints/mod_skypopen/osscuse/LICENSE | 339 +++ .../endpoints/mod_skypopen/osscuse/Makefile | 69 + src/mod/endpoints/mod_skypopen/osscuse/README | 119 + .../mod_skypopen/osscuse/ossp-alsap.c | 613 +++++ .../mod_skypopen/osscuse/ossp-slave.c | 250 ++ .../mod_skypopen/osscuse/ossp-slave.h | 28 + .../mod_skypopen/osscuse/ossp-util.c | 369 +++ .../mod_skypopen/osscuse/ossp-util.h | 609 +++++ src/mod/endpoints/mod_skypopen/osscuse/ossp.c | 83 + src/mod/endpoints/mod_skypopen/osscuse/ossp.h | 117 + .../endpoints/mod_skypopen/osscuse/osspd.c | 2374 +++++++++++++++++ 12 files changed, 4977 insertions(+) create mode 100644 src/mod/endpoints/mod_skypopen/osscuse/98-osscuse.rules create mode 100644 src/mod/endpoints/mod_skypopen/osscuse/LICENSE create mode 100644 src/mod/endpoints/mod_skypopen/osscuse/Makefile create mode 100644 src/mod/endpoints/mod_skypopen/osscuse/README create mode 100644 src/mod/endpoints/mod_skypopen/osscuse/ossp-alsap.c create mode 100644 src/mod/endpoints/mod_skypopen/osscuse/ossp-slave.c create mode 100644 src/mod/endpoints/mod_skypopen/osscuse/ossp-slave.h create mode 100644 src/mod/endpoints/mod_skypopen/osscuse/ossp-util.c create mode 100644 src/mod/endpoints/mod_skypopen/osscuse/ossp-util.h create mode 100644 src/mod/endpoints/mod_skypopen/osscuse/ossp.c create mode 100644 src/mod/endpoints/mod_skypopen/osscuse/ossp.h create mode 100644 src/mod/endpoints/mod_skypopen/osscuse/osspd.c diff --git a/src/mod/endpoints/mod_skypopen/osscuse/98-osscuse.rules b/src/mod/endpoints/mod_skypopen/osscuse/98-osscuse.rules new file mode 100644 index 0000000000..c1430fd5c0 --- /dev/null +++ b/src/mod/endpoints/mod_skypopen/osscuse/98-osscuse.rules @@ -0,0 +1,7 @@ +# Since these devices are not part of 'sound' subsystem the group is forced +# to audio by name +# /dev/cuse can stay mode 0660 root:root since osspd is run as root +# and drops privileges to user level when opened by user +KERNEL=="dsp", GROUP="audio" +KERNEL=="mixer", GROUP="audio" +KERNEL=="adsp", GROUP="audio" diff --git a/src/mod/endpoints/mod_skypopen/osscuse/LICENSE b/src/mod/endpoints/mod_skypopen/osscuse/LICENSE new file mode 100644 index 0000000000..d511905c16 --- /dev/null +++ b/src/mod/endpoints/mod_skypopen/osscuse/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/src/mod/endpoints/mod_skypopen/osscuse/Makefile b/src/mod/endpoints/mod_skypopen/osscuse/Makefile new file mode 100644 index 0000000000..a42d37a8a3 --- /dev/null +++ b/src/mod/endpoints/mod_skypopen/osscuse/Makefile @@ -0,0 +1,69 @@ +# These can be overridden if needed +# DESTDIR is completely respected +CC := gcc +AR := ar +CFLAGS := -Wall $(CFLAGS) +XLDFLAGS := $(LDFLAGS) +LDFLAGS := -L. -lossp $(LDFLAGS) +prefix := /usr/local +DESTDIR := +UDEVDIR := /etc/udev/rules.d + +ifeq "$(origin OSSPD_CFLAGS)" "undefined" +OSSPD_CFLAGS := $(shell pkg-config --cflags fuse) +endif + +ifeq "$(origin OSSPD_LDFLAGS)" "undefined" +OSSPD_LDFLAGS := $(shell pkg-config --libs fuse) +endif + +ifeq "$(origin OSSP_PADSP_CFLAGS)" "undefined" +OSSP_PADSP_CFLAGS := $(shell pkg-config --cflags libpulse) +endif + +ifeq "$(origin OSSP_PADSP_LDFLAGS)" "undefined" +OSSP_PADSP_LDFLAGS := $(shell pkg-config --libs libpulse) +endif + +ifeq "$(origin OSSP_ALSAP_CFLAGS)" "undefined" +OSSP_ALSAP_CFLAGS := $(shell pkg-config --libs alsa) +endif + +ifeq "$(origin OSSP_ALSAP_LDFLAGS)" "undefined" +OSSP_ALSAP_LDFLAGS := $(shell pkg-config --libs alsa) +endif + +headers := ossp.h ossp-util.h ossp-slave.h + +#all: osspd ossp-padsp ossp-alsap +all: osspd ossp-alsap + +install: + mkdir -p $(DESTDIR)$(prefix)/sbin + install -m755 osspd ossp-padsp ossp-alsap $(DESTDIR)$(prefix)/sbin + mkdir -p $(DESTDIR)$(UDEVDIR) + install -m644 98-osscuse.rules $(DESTDIR)$(UDEVDIR) + +libossp.a: ossp.c ossp.h ossp-util.c ossp-util.h ossp-slave.c ossp-slave.h + $(CC) $(CFLAGS) -c -o ossp.o ossp.c + $(CC) $(CFLAGS) -c -o ossp-util.o ossp-util.c + $(CC) $(CFLAGS) -c -o ossp-slave.o ossp-slave.c + $(AR) rc $@ ossp.o ossp-util.o ossp-slave.o + +osspd: osspd.c libossp.a $(headers) + $(CC) $(CFLAGS) $(OSSPD_CFLAGS) -o $@ $< $(OSSPD_LDFLAGS) $(LDFLAGS) + +ossp-padsp: ossp-padsp.c libossp.a $(headers) + $(CC) $(CFLAGS) $(OSSP_PADSP_CFLAGS) -o $@ $< $(OSSP_PADSP_LDFLAGS) $(LDFLAGS) + +ossp-alsap: ossp-alsap.c libossp.a $(headers) + $(CC) $(CFLAGS) $(OSSP_ALSAP_CFLAGS) -o $@ $< $(OSSP_ALSAP_LDFLAGS) $(LDFLAGS) + +osstest: osstest.c + $(CC) $(CFLAGS) -o $@ $< $(XLDFLAGS) + +test: osstest + @./osstest + +clean: + rm -f *.o *.a osspd ossp-padsp ossp-alsap osstest diff --git a/src/mod/endpoints/mod_skypopen/osscuse/README b/src/mod/endpoints/mod_skypopen/osscuse/README new file mode 100644 index 0000000000..6b716c76e4 --- /dev/null +++ b/src/mod/endpoints/mod_skypopen/osscuse/README @@ -0,0 +1,119 @@ + + OSS Proxy - emulate OSS device using CUSE + + Copyright (C) 2008-2009 SUSE Linux Products GmbH + Copyright (C) 2008-2009 Tejun Heo + +1. What is it? +-------------- + +Well, first, OSS refers to Open Sound System. If it still doesn't +ring a bell, think /dev/dsp, /dev/adsp and /dev/mixer. + +Currently, Linux supports two audio programming interface - ALSA and +OSS. The latter one is deprecated and has been that way for a long +time but there still are applications which still use them including +UML (usermode Linux) host sound support. + +ALSA contains OSS emulation but sadly the emulation is behind +multiplexing layer (which is in userland) which means that if your +sound card doesn't support multiple audio streams, only either one of +ALSA or OSS interface would be usable at any given moment. + +There have been also attempts to emulate OSS in userland using dynamic +library preloading - aoss and more recently padsp. This works for +many applications but it's just not easy to emulate everything using +the technique. Things like polling, signals, forking, privilege +changes make it very difficult to emulate things reliably. + +OSS Proxy uses CUSE (extension of FUSE allowing character devices to +be implemented in userspace) to implement OSS interface - /dev/dsp, +/dev/adsp and /dev/mixer. From the POV of the applications, these +devices are proper character devices and behave exactly the same way +so it can be made quite versatile. + + +2. Hmmm... So, how does the whole thing work? +--------------------------------------------- + +The OSS Proxy daemon - osspd - should be started first. Note that +osspd will fail to start if sound device number regions are already +occupied. You'll need to turn off OSS or its emulation[1]. + +On startup, osspd creates /dev/dsp, /dev/adsp and /dev/mixer using +CUSE. When an application access one of the devices, all IOs are +redirected to osspd via CUSE. Upon receiving a new DSP open request, +osspd creates a slave process which drops the root privilege and +assumes the opening process's credentials. After handshaking, osspd +forwards all relevant IOs to the slave which is responsible for +actually playing the sound. + +Currently there's only one slave implemented - ossp-padsp, which as +the name suggests forwards (again) the sound to pulseaudio. To sum +up, the whole pipe looks like the following. + + App <-> /dev/dsp <-> CUSE <-> osspd <-> ossp-padsp <-> pulseaudio + +Which is a lot of forwarding, but on modern machines, it won't be too +noticeable. + + +3. What works? +-------------- + +Well, MIDI part isn't implemented and I doubt it will be in any near +future but except that everything should work. Playing, recording, +5.1ch, A-V syncing, all should work. If not, it's a bug, so please +report. + +The mixer behaves a bit differently tho. In the original OSS, +/dev/mixer is the hardware mixer, so adjusting volumes there affects +all audio streams. When using ossp, each process group gets its own +mixer and the mixer always contains only two knobs - PCM and IGAIN. +Combined with per-stream volume control of pulseaudio, this scheme +works quite well for applications with embedded volume control +although it makes standalone OSS mixer programs virtually useless[2]. + + +4. How do I use it? +------------------- + +First you need CUSE support in kernel which might land on 2.6.28 with +sufficient luck[3] and then you also need libfuse which supports +CUSE[4]. Once you have both, it should be easy. First build it by +running `make'. You can set OSSPD_CFLAGS, OSSPD_LDFLAGS, +OSSP_PADSP_CFLAGS and OSSP_PADSP_LDFLAGS if you have stuff at +non-default locations. + +After build completes, there will be two executables - `osspd' and +`ossp-padsp'. Just copy them to where other system executables live. +Specific location doesn't matter as long as both files end up in the +same directory. + +Execute `osspd'. It will create the device files and you're all set. +`osspd' uses syslog with LOG_DAEMON facility, so if something doesn't +work take a look at what osspd complains about. + + +[1] As of this writing, turning on any sound support makes the + soundcore module claim OSS device regions. Patch to make it claim + OSS device regions only when OSS support or emulation is enabled + is scheduled for 2.6.28. Even with the patch, soundcore will + claim OSS device regions if OSS support or ALSA OSS emulation is + enabled. Make sure they're turned off. + +[2] If you have a strong reason to use standalone OSS mixer program, + you can play some shell tricks to put it into the same process + group as the target audio application. e.g. To use aumix with + mpg123 - `(mpg123 asdf.mp3 > /dev/null 2>&1 & aumix)', but + seriously, just use PA or ALSA one. + +[3] For the time being, here's the git tree with all the necessary + changes. This tree is base on top of 2.6.27-rc3. + + http://git.kernel.org/?p=linux/kernel/git/tj/misc.git;a=shortlog;h=cuse + git://git.kernel.org/pub/scm/linux/kernel/git/tj/misc.git cuse + +[4] And libfuse with the modifications can be found at... + + http://userweb.kernel.org/~tj/ossp/fuse-cuse.tar.gz diff --git a/src/mod/endpoints/mod_skypopen/osscuse/ossp-alsap.c b/src/mod/endpoints/mod_skypopen/osscuse/ossp-alsap.c new file mode 100644 index 0000000000..607e05ca84 --- /dev/null +++ b/src/mod/endpoints/mod_skypopen/osscuse/ossp-alsap.c @@ -0,0 +1,613 @@ +/* + * ossp-alsap - ossp DSP slave which forwards to alsa + * + * Copyright (C) 2009 Maarten Lankhorst + * + * This file is released under the GPLv2. + * + * Why an alsa plugin as well? Just to show how much + * the alsa userspace api sucks ;-) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ossp-slave.h" + +enum { + AFMT_FLOAT = 0x00004000, + AFMT_S32_LE = 0x00001000, + AFMT_S32_BE = 0x00002000, +}; + +static size_t page_size; + +/* alsa structures */ +static snd_pcm_t *pcm[2]; +static snd_pcm_hw_params_t *hw_params; +static snd_pcm_sw_params_t *sw_params; +static int block; + +static unsigned int byte_counter[2]; +static snd_pcm_uframes_t mmap_pos[2]; +static int stream_corked[2]; +static int stream_notify; + +static struct format { + snd_pcm_format_t format; + snd_pcm_sframes_t rate; + int channels; +} hw_format = { SND_PCM_FORMAT_U8, 8000, 1 }; + +#if 0 +/* future mmap stuff */ +static size_t mmap_raw_size, mmap_size; +static int mmap_fd[2] = { -1, -1 }; +static void *mmap_map[2]; +static uint64_t mmap_idx[2]; /* mmap pointer */ +static uint64_t mmap_last_idx[2]; /* last idx for get_ptr */ +static struct ring_buf mmap_stg[2]; /* staging ring buffer */ +static size_t mmap_lead[2]; /* lead bytes */ +static int mmap_sync[2]; /* sync with backend stream */ +#endif + +static snd_pcm_format_t fmt_oss_to_alsa(int fmt) +{ + switch (fmt) { + case AFMT_U8: return SND_PCM_FORMAT_U8; + case AFMT_A_LAW: return SND_PCM_FORMAT_A_LAW; + case AFMT_MU_LAW: return SND_PCM_FORMAT_MU_LAW; + case AFMT_S16_LE: return SND_PCM_FORMAT_S16_LE; + case AFMT_S16_BE: return SND_PCM_FORMAT_S16_BE; + case AFMT_FLOAT: return SND_PCM_FORMAT_FLOAT; + case AFMT_S32_LE: return SND_PCM_FORMAT_S32_LE; + case AFMT_S32_BE: return SND_PCM_FORMAT_S32_BE; + default: return SND_PCM_FORMAT_U8; + } +} + +static int fmt_alsa_to_oss(snd_pcm_format_t fmt) +{ + switch (fmt) { + case SND_PCM_FORMAT_U8: return AFMT_U8; + case SND_PCM_FORMAT_A_LAW: return AFMT_A_LAW; + case SND_PCM_FORMAT_MU_LAW: return AFMT_MU_LAW; + case SND_PCM_FORMAT_S16_LE: return AFMT_S16_LE; + case SND_PCM_FORMAT_S16_BE: return AFMT_S16_BE; + case SND_PCM_FORMAT_FLOAT: return AFMT_FLOAT; + case SND_PCM_FORMAT_S32_LE: return AFMT_S32_LE; + case SND_PCM_FORMAT_S32_BE: return AFMT_S32_BE; + default: return AFMT_U8; + } +} + +static void flush_streams(int drain) +{ + /* FIXME: snd_pcm_drain appears to be able to deadlock, + * always drop or check state? */ + if (drain) { + if (pcm[PLAY]) + snd_pcm_drain(pcm[PLAY]); + if (pcm[REC]) + snd_pcm_drain(pcm[REC]); + } else { + if (pcm[PLAY]) + snd_pcm_drop(pcm[PLAY]); + if (pcm[REC]) + snd_pcm_drop(pcm[REC]); + } + + /* XXX: Really needed? */ +#if 0 + if (pcm[PLAY]) { + snd_pcm_close(pcm[PLAY]); + snd_pcm_open(&pcm[PLAY], "default", + SND_PCM_STREAM_PLAYBACK, block); + } + if (pcm[REC]) { + snd_pcm_close(pcm[REC]); + snd_pcm_open(&pcm[REC], "default", + SND_PCM_STREAM_CAPTURE, block); + } +#endif +} + +static void kill_streams(void) +{ + flush_streams(0); +} + +static int trigger_streams(int play, int rec) +{ + int ret = 0; + + if (pcm[PLAY] && play >= 0) { + ret = snd_pcm_sw_params_set_start_threshold(pcm[PLAY], sw_params, + play ? 1 : -1); + if (ret >= 0) + snd_pcm_sw_params(pcm[PLAY], sw_params); + } + if (ret >= 0 && pcm[REC] && rec >= 0) { + ret = snd_pcm_sw_params_set_start_threshold(pcm[REC], sw_params, + rec ? 1 : -1); + if (ret >= 0) + snd_pcm_sw_params(pcm[REC], sw_params); + } + + return ret; +} + +static ssize_t alsap_mixer(enum ossp_opcode opcode, + void *carg, void *din, size_t din_sz, + void *rarg, void *dout, size_t *dout_szp, int tfd) +{ +return -EBUSY; +} + +static int set_hw_params(snd_pcm_t *pcm) +{ + int ret; + unsigned rate; + + ret = snd_pcm_hw_params_any(pcm, hw_params); + if (ret >= 0) + ret = snd_pcm_hw_params_set_access(pcm, hw_params, + SND_PCM_ACCESS_RW_INTERLEAVED); + rate = hw_format.rate; + if (ret >= 0) + ret = snd_pcm_hw_params_set_rate_minmax(pcm, hw_params, + &rate, NULL, + &rate, NULL); + if (ret >= 0) + ret = snd_pcm_hw_params_set_format(pcm, hw_params, hw_format.format); + if (ret >= 0) + ret = snd_pcm_hw_params_set_channels(pcm, hw_params, + hw_format.channels); + if (ret >= 0) + ret = snd_pcm_hw_params(pcm, hw_params); + if (ret >= 0) + ret = snd_pcm_sw_params_current(pcm, sw_params); + if (ret >= 0) + ret = snd_pcm_sw_params(pcm, sw_params); + return ret; +} + +static ssize_t alsap_open(enum ossp_opcode opcode, + void *carg, void *din, size_t din_sz, + void *rarg, void *dout, size_t *dout_szp, int tfd) +{ + struct ossp_dsp_open_arg *arg = carg; + int ret; + block = arg->flags & O_NONBLOCK ? SND_PCM_NONBLOCK : 0; + int access; +// block |= SND_PCM_ASYNC; + /* Woop dee dooo.. I love handling things in SIGIO (PAIN!!) + * Probably needed for MMAP + */ + + if (!hw_params) + ret = snd_pcm_hw_params_malloc(&hw_params); + if (ret < 0) + return ret; + + if (!sw_params) + ret = snd_pcm_sw_params_malloc(&sw_params); + if (ret < 0) + return ret; + + if (pcm[PLAY]) + snd_pcm_close(pcm[PLAY]); + if (pcm[REC]) + snd_pcm_close(pcm[REC]); + pcm[REC] = pcm[PLAY] = NULL; + + access = arg->flags & O_ACCMODE; + if (access == O_WRONLY || access == O_RDWR) { + ret = snd_pcm_open(&pcm[PLAY], "default", + SND_PCM_STREAM_PLAYBACK, block); + if (ret >= 0) + ret = set_hw_params(pcm[PLAY]); + } + + if (ret >= 0 && (access == O_RDONLY || access == O_RDWR)) { + ret = snd_pcm_open(&pcm[REC], "default", + SND_PCM_STREAM_CAPTURE, block); + if (ret >= 0) + ret = set_hw_params(pcm[REC]); + } + + if (ret < 0) { + if (pcm[PLAY]) + snd_pcm_close(pcm[PLAY]); + if (pcm[REC]) + snd_pcm_close(pcm[REC]); + pcm[REC] = pcm[PLAY] = NULL; + return ret; + } + return 0; +} + +#define GIOVANNI +#ifdef GIOVANNI + +#define GIOVA_SLEEP 40000 +#define GIOVA_BLK 3840 +static ssize_t alsap_write(enum ossp_opcode opcode, + void *carg, void *din, size_t din_sz, + void *rarg, void *dout, size_t *dout_szp, int tfd) +{ + usleep((GIOVA_SLEEP/GIOVA_BLK)* din_sz); + return din_sz; +} +static ssize_t alsap_read(enum ossp_opcode opcode, + void *carg, void *din, size_t din_sz, + void *rarg, void *dout, size_t *dout_szp, int tfd) +{ + usleep((GIOVA_SLEEP/GIOVA_BLK)* *dout_szp); + return *dout_szp; +} +#else// GIOVANNI +static ssize_t alsap_write(enum ossp_opcode opcode, + void *carg, void *din, size_t din_sz, + void *rarg, void *dout, size_t *dout_szp, int tfd) +{ +// struct ossp_dsp_rw_arg *arg = carg; + int ret, insize; + + insize = snd_pcm_bytes_to_frames(pcm[PLAY], din_sz); + + if (snd_pcm_state(pcm[PLAY]) == SND_PCM_STATE_SETUP) + snd_pcm_prepare(pcm[PLAY]); + +// snd_pcm_start(pcm[PLAY]); + ret = snd_pcm_writei(pcm[PLAY], din, insize); + if (ret < 0) + ret = snd_pcm_recover(pcm[PLAY], ret, 1); + + if (ret >= 0) + return snd_pcm_frames_to_bytes(pcm[PLAY], ret); + else + return ret; +} + +static ssize_t alsap_read(enum ossp_opcode opcode, + void *carg, void *din, size_t din_sz, + void *rarg, void *dout, size_t *dout_szp, int tfd) +{ +// struct ossp_dsp_rw_arg *arg = carg; + int ret, outsize; + + outsize = snd_pcm_bytes_to_frames(pcm[REC], *dout_szp); + + if (snd_pcm_state(pcm[REC]) == SND_PCM_STATE_SETUP) + snd_pcm_prepare(pcm[REC]); + + ret = snd_pcm_readi(pcm[REC], dout, outsize); + if (ret < 0) + ret = snd_pcm_recover(pcm[REC], ret, 1); + if (ret >= 0) + *dout_szp = ret = snd_pcm_frames_to_bytes(pcm[REC], ret); + else + *dout_szp = 0; + + return ret; +} +#endif// GIOVANNI + +static ssize_t alsap_poll(enum ossp_opcode opcode, + void *carg, void *din, size_t din_sz, + void *rarg, void *dout, size_t *dout_szp, int tfd) +{ + unsigned revents = 0; + + stream_notify |= *(int *)carg; + + if (pcm[PLAY]) + revents |= POLLOUT; + if (pcm[REC]) + revents |= POLLIN; + + *(unsigned *)rarg = revents; + return 0; +} + + +static ssize_t alsap_flush(enum ossp_opcode opcode, + void *carg, void *din, size_t din_sz, + void *rarg, void *dout, size_t *dout_szp, int tfd) +{ + flush_streams(opcode == OSSP_DSP_SYNC); + return 0; +} + +static ssize_t alsap_post(enum ossp_opcode opcode, + void *carg, void *din, size_t din_sz, + void *rarg, void *dout, size_t *dout_szp, int tfd) +{ + int ret; + + ret = trigger_streams(1, 1); + if (ret >= 0 && pcm[PLAY]) + ret = snd_pcm_start(pcm[PLAY]); + if (pcm[REC]) + ret = snd_pcm_start(pcm[REC]); + return ret; +} + +static ssize_t alsap_get_param(enum ossp_opcode opcode, + void *carg, void *din, size_t din_sz, + void *rarg, void *dout, size_t *dout_szp, + int tfd) +{ + int v = 0; + + switch (opcode) { + case OSSP_DSP_GET_RATE: + return hw_format.rate; + + case OSSP_DSP_GET_CHANNELS: + return hw_format.channels; + + case OSSP_DSP_GET_FORMAT: { + v = fmt_alsa_to_oss(hw_format.format); + break; + } + + case OSSP_DSP_GET_BLKSIZE: { + snd_pcm_uframes_t psize; + snd_pcm_hw_params_get_period_size(hw_params, &psize, NULL); + v = psize; + break; + } + + case OSSP_DSP_GET_FORMATS: + v = AFMT_U8 | AFMT_A_LAW | AFMT_MU_LAW | AFMT_S16_LE | + AFMT_S16_BE | AFMT_FLOAT | AFMT_S32_LE | AFMT_S32_BE; + break; + + case OSSP_DSP_GET_TRIGGER: + if (!stream_corked[PLAY]) + v |= PCM_ENABLE_OUTPUT; + if (!stream_corked[REC]) + v |= PCM_ENABLE_INPUT; + break; + + default: + assert(0); + } + + *(int *)rarg = v; + + return 0; +} + +static ssize_t alsap_set_param(enum ossp_opcode opcode, + void *carg, void *din, size_t din_sz, + void *rarg, void *dout, size_t *dout_szp, + int tfd) +{ + int v = *(int *)carg; + int ret = 0; + + /* kill the streams before changing parameters */ + kill_streams(); + + switch (opcode) { + case OSSP_DSP_SET_RATE: { + hw_format.rate = v; + break; + } + + case OSSP_DSP_SET_CHANNELS: { + hw_format.channels = v; + break; + } + + case OSSP_DSP_SET_FORMAT: { + snd_pcm_format_t format = fmt_oss_to_alsa(v); + hw_format.format = format; + break; + } + + case OSSP_DSP_SET_SUBDIVISION: + if (!v) + v = 1; +#if 0 + if (!v) { + v = user_subdivision ?: 1; + break; + } + user_frag_size = 0; + user_subdivision = v; + break; + + case OSSP_DSP_SET_FRAGMENT: + user_subdivision = 0; + user_frag_size = 1 << (v & 0xffff); + user_max_frags = (v >> 16) & 0xffff; + if (user_frag_size < 4) + user_frag_size = 4; + if (user_max_frags < 2) + user_max_frags = 2; +#else + case OSSP_DSP_SET_FRAGMENT: +#endif + break; + default: + assert(0); + } + + if (pcm[PLAY]) + ret = set_hw_params(pcm[PLAY]); + if (ret >= 0 && pcm[REC]) + ret = set_hw_params(pcm[REC]); + + if (rarg) + *(int *)rarg = v; + return 0; +} + +static ssize_t alsap_set_trigger(enum ossp_opcode opcode, + void *carg, void *din, size_t din_sz, + void *rarg, void *dout, size_t *dout_szp, + int fd) +{ + int enable = *(int *)carg; + + stream_corked[PLAY] = !!(enable & PCM_ENABLE_OUTPUT); + stream_corked[REC] = !!(enable & PCM_ENABLE_INPUT); + + return trigger_streams(enable & PCM_ENABLE_OUTPUT, + enable & PCM_ENABLE_INPUT); +} + +static ssize_t alsap_get_space(enum ossp_opcode opcode, + void *carg, void *din, size_t din_sz, + void *rarg, void *dout, size_t *dout_szp, int tfd) +{ + int dir = (opcode == OSSP_DSP_GET_OSPACE) ? PLAY : REC; + int underrun = 0; + struct audio_buf_info info = { }; + unsigned long bufsize; + snd_pcm_uframes_t avail, fragsize; + snd_pcm_state_t state; + + if (!pcm[dir]) + return -EINVAL; + + state = snd_pcm_state(pcm[dir]); + if (state == SND_PCM_STATE_XRUN) { + snd_pcm_recover(pcm[dir], -EPIPE, 0); + underrun = 1; + } else if (state == SND_PCM_STATE_SUSPENDED) { + snd_pcm_recover(pcm[dir], -ESTRPIPE, 0); + underrun = 1; + } + + snd_pcm_hw_params_current(pcm[dir], hw_params); + snd_pcm_hw_params_get_period_size(hw_params, &fragsize, NULL); + snd_pcm_hw_params_get_buffer_size(hw_params, &bufsize); + info.fragsize = snd_pcm_frames_to_bytes(pcm[dir], fragsize); + info.fragstotal = bufsize / fragsize; + if (!underrun) { + avail = snd_pcm_avail_update(pcm[dir]); + info.fragments = avail / fragsize; + } else + info.fragments = info.fragstotal; + + info.bytes = info.fragsize * info.fragments; + + *(struct audio_buf_info *)rarg = info; + return 0; +} + +static ssize_t alsap_get_ptr(enum ossp_opcode opcode, + void *carg, void *din, size_t din_sz, + void *rarg, void *dout, size_t *dout_szp, int tfd) +{ + int dir = (opcode == OSSP_DSP_GET_OPTR) ? PLAY : REC; + struct count_info info = { }; + + if (!pcm[dir]) + return -EIO; + + snd_pcm_hw_params_current(pcm[dir], hw_params); + info.bytes = byte_counter[dir]; + snd_pcm_hw_params_get_periods(hw_params, (unsigned int *)&info.blocks, NULL); + info.ptr = mmap_pos[dir]; + + *(struct count_info *)rarg = info; + return 0; +} + +static ssize_t alsap_get_odelay(enum ossp_opcode opcode, + void *carg, void *din, size_t din_sz, + void *rarg, void *dout, size_t *dout_szp, + int fd) +{ + snd_pcm_sframes_t delay; + + if (!pcm[PLAY]) + return -EIO; + + if (snd_pcm_delay(pcm[PLAY], &delay) < 0) + return -EIO; + + *(int *)rarg = snd_pcm_frames_to_bytes(pcm[PLAY], delay); + return 0; +} + +static ossp_action_fn_t action_fn_tbl[OSSP_NR_OPCODES] = { + [OSSP_MIXER] = alsap_mixer, + [OSSP_DSP_OPEN] = alsap_open, + [OSSP_DSP_READ] = alsap_read, + [OSSP_DSP_WRITE] = alsap_write, + [OSSP_DSP_POLL] = alsap_poll, +#if 0 + [OSSP_DSP_MMAP] = alsap_mmap, + [OSSP_DSP_MUNMAP] = alsap_munmap, +#endif + [OSSP_DSP_RESET] = alsap_flush, + [OSSP_DSP_SYNC] = alsap_flush, + [OSSP_DSP_POST] = alsap_post, + [OSSP_DSP_GET_RATE] = alsap_get_param, + [OSSP_DSP_GET_CHANNELS] = alsap_get_param, + [OSSP_DSP_GET_FORMAT] = alsap_get_param, + [OSSP_DSP_GET_BLKSIZE] = alsap_get_param, + [OSSP_DSP_GET_FORMATS] = alsap_get_param, + [OSSP_DSP_SET_RATE] = alsap_set_param, + [OSSP_DSP_SET_CHANNELS] = alsap_set_param, + [OSSP_DSP_SET_FORMAT] = alsap_set_param, + [OSSP_DSP_SET_SUBDIVISION] = alsap_set_param, + [OSSP_DSP_SET_FRAGMENT] = alsap_set_param, + [OSSP_DSP_GET_TRIGGER] = alsap_get_param, + [OSSP_DSP_SET_TRIGGER] = alsap_set_trigger, + [OSSP_DSP_GET_OSPACE] = alsap_get_space, + [OSSP_DSP_GET_ISPACE] = alsap_get_space, + [OSSP_DSP_GET_OPTR] = alsap_get_ptr, + [OSSP_DSP_GET_IPTR] = alsap_get_ptr, + [OSSP_DSP_GET_ODELAY] = alsap_get_odelay, +}; + +static int action_pre(void) +{ + return 0; +} + +static void action_post(void) +{ +} + +int main(int argc, char **argv) +{ + int rc; + + ossp_slave_init(argc, argv); + + page_size = sysconf(_SC_PAGE_SIZE); + + /* Okay, now we're open for business */ + rc = 0; + do { + rc = ossp_slave_process_command(ossp_cmd_fd, action_fn_tbl, + action_pre, action_post); + } while (rc > 0); + + return rc ? 1 : 0; +} diff --git a/src/mod/endpoints/mod_skypopen/osscuse/ossp-slave.c b/src/mod/endpoints/mod_skypopen/osscuse/ossp-slave.c new file mode 100644 index 0000000000..4c5cb2d129 --- /dev/null +++ b/src/mod/endpoints/mod_skypopen/osscuse/ossp-slave.c @@ -0,0 +1,250 @@ +/* + * ossp-slave - OSS Proxy: Common codes for slaves + * + * Copyright (C) 2008-2010 SUSE Linux Products GmbH + * Copyright (C) 2008-2010 Tejun Heo + * + * This file is released under the GPLv2. + */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ossp-slave.h" + +static const char *usage = +"usage: ossp-SLAVE [options]\n" +"\n" +"proxies commands from osspd to pulseaudio\n" +"\n" +"options:\n" +" -u UID uid to use\n" +" -g GID gid to use\n" +" -c CMD_FD fd to receive commands from osspd\n" +" -n NOTIFY_FD fd to send async notifications to osspd\n" +" -m MMAP_FD fd to use for mmap\n" +" -o MMAP_OFFSET mmap offset\n" +" -s MMAP_SIZE mmap size\n" +" -l LOG_LEVEL set log level\n" +" -t enable log timestamps\n"; + +char ossp_user_name[OSSP_USER_NAME_LEN]; +int ossp_cmd_fd = -1, ossp_notify_fd = -1; +void *ossp_mmap_addr[2]; + +void ossp_slave_init(int argc, char **argv) +{ + int have_uid = 0, have_gid = 0; + uid_t uid; + gid_t gid; + int mmap_fd = -1; + off_t mmap_off = 0; + size_t mmap_size = 0; + int opt; + struct passwd *pw, pw_buf; + struct sigaction sa; + char pw_sbuf[sysconf(_SC_GETPW_R_SIZE_MAX)]; + + while ((opt = getopt(argc, argv, "u:g:c:n:m:o:s:l:t")) != -1) { + switch (opt) { + case 'u': + have_uid = 1; + uid = strtol(optarg, NULL, 0); + break; + case 'g': + have_gid = 1; + gid = strtol(optarg, NULL, 0); + break; + case 'c': + ossp_cmd_fd = strtol(optarg, NULL, 0); + break; + case 'n': + ossp_notify_fd = strtol(optarg, NULL, 0); + break; + case 'm': + mmap_fd = strtol(optarg, NULL, 0); + break; + case 'o': + mmap_off = strtoull(optarg, NULL, 0); + break; + case 's': + mmap_size = strtoul(optarg, NULL, 0); + break; + case 'l': + ossp_log_level = strtol(optarg, NULL, 0); + break; + case 't': + ossp_log_timestamp = 1; + break; + } + } + + if (!have_uid || !have_gid || ossp_cmd_fd < 0 || ossp_notify_fd < 0) { + fprintf(stderr, usage); + _exit(1); + } + + snprintf(ossp_user_name, sizeof(ossp_user_name), "uid%d", uid); + if (getpwuid_r(uid, &pw_buf, pw_sbuf, sizeof(pw_sbuf), &pw) == 0) + snprintf(ossp_user_name, sizeof(ossp_user_name), "%s", + pw->pw_name); + + snprintf(ossp_log_name, sizeof(ossp_log_name), "ossp-padsp[%s:%d]", + ossp_user_name, getpid()); + + if (mmap_fd >= 0) { + void *p; + + if (!mmap_off || !mmap_size) { + fprintf(stderr, usage); + _exit(1); + } + + p = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, + mmap_fd, mmap_off); + if (p == MAP_FAILED) + fatal_e(-errno, "mmap failed"); + + ossp_mmap_addr[PLAY] = p; + ossp_mmap_addr[REC] = p + mmap_size / 2; + close(mmap_fd); + } + + /* mmap done, drop privileges */ + if (setresgid(gid, gid, gid) || setresuid(uid, uid, uid)) + fatal_e(-errno, "failed to drop privileges"); + + /* block SIGPIPE */ + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = SIG_IGN; + if (sigaction(SIGPIPE, &sa, NULL)) + fatal_e(-errno, "failed to ignore SIGPIPE"); +} + +int ossp_slave_process_command(int cmd_fd, + ossp_action_fn_t const *action_fn_tbl, + int (*action_pre_fn)(void), + void (*action_post_fn)(void)) +{ + static struct sized_buf carg_sbuf = { }, rarg_sbuf = { }; + static struct sized_buf din_sbuf = { }, dout_sbuf = { }; + struct ossp_cmd cmd; + int fd = -1; + char cmsg_buf[CMSG_SPACE(sizeof(fd))]; + struct iovec iov = { &cmd, sizeof(cmd) }; + struct msghdr msg = { .msg_iov = &iov, .msg_iovlen = 1, + .msg_control = cmsg_buf, + .msg_controllen = sizeof(cmsg_buf) }; + struct cmsghdr *cmsg; + size_t carg_size, din_size, rarg_size, dout_size; + char *carg = NULL, *din = NULL, *rarg = NULL, *dout = NULL; + struct ossp_reply reply = { .magic = OSSP_REPLY_MAGIC }; + ssize_t ret; + + ret = recvmsg(cmd_fd, &msg, 0); + if (ret == 0) + return 0; + if (ret < 0) { + ret = -errno; + err_e(ret, "failed to read command channel"); + return ret; + } + + if (ret != sizeof(cmd)) { + err("command struct size mismatch (%zu, should be %zu)", + ret, sizeof(cmd)); + return -EINVAL; + } + + if (cmd.magic != OSSP_CMD_MAGIC) { + err("illegal command magic 0x%x", cmd.magic); + return -EINVAL; + } + + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; + cmsg = CMSG_NXTHDR(&msg, cmsg)) { + if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_RIGHTS) + fd = *(int *)CMSG_DATA(cmsg); + else { + err("unknown cmsg %d:%d received (opcode %d)", + cmsg->cmsg_level, cmsg->cmsg_type, cmd.opcode); + return -EINVAL; + } + } + + if (cmd.opcode >= OSSP_NR_OPCODES) { + err("unknown opcode %d", cmd.opcode); + return -EINVAL; + } + + carg_size = ossp_arg_sizes[cmd.opcode].carg_size; + din_size = cmd.din_size; + rarg_size = ossp_arg_sizes[cmd.opcode].rarg_size; + dout_size = cmd.dout_size; + + if ((fd >= 0) != ossp_arg_sizes[cmd.opcode].has_fd) { + err("fd=%d unexpected for opcode %d", fd, cmd.opcode); + return -EINVAL; + } + + if (ensure_sbuf_size(&carg_sbuf, carg_size) || + ensure_sbuf_size(&din_sbuf, din_size) || + ensure_sbuf_size(&rarg_sbuf, rarg_size) || + ensure_sbuf_size(&dout_sbuf, dout_size)) { + err("failed to allocate command buffers"); + return -ENOMEM; + } + + if (carg_size) { + carg = carg_sbuf.buf; + ret = read_fill(cmd_fd, carg, carg_size); + if (ret < 0) + return ret; + } + if (din_size) { + din = din_sbuf.buf; + ret = read_fill(cmd_fd, din, din_size); + if (ret < 0) + return ret; + } + if (rarg_size) + rarg = rarg_sbuf.buf; + if (dout_size) + dout = dout_sbuf.buf; + + ret = -EINVAL; + if (action_fn_tbl[cmd.opcode]) { + ret = action_pre_fn(); + if (ret == 0) { + ret = action_fn_tbl[cmd.opcode](cmd.opcode, carg, + din, din_size, rarg, + dout, &dout_size, fd); + action_post_fn(); + } + } + + reply.result = ret; + if (ret >= 0) + reply.dout_size = dout_size; + else { + rarg_size = 0; + dout_size = 0; + } + + if (write_fill(cmd_fd, &reply, sizeof(reply)) < 0 || + write_fill(cmd_fd, rarg, rarg_size) < 0 || + write_fill(cmd_fd, dout, dout_size) < 0) + return -EIO; + + return 1; +} diff --git a/src/mod/endpoints/mod_skypopen/osscuse/ossp-slave.h b/src/mod/endpoints/mod_skypopen/osscuse/ossp-slave.h new file mode 100644 index 0000000000..10c22cdb02 --- /dev/null +++ b/src/mod/endpoints/mod_skypopen/osscuse/ossp-slave.h @@ -0,0 +1,28 @@ +/* + * ossp-slave - OSS Proxy: Common codes for slaves + * + * Copyright (C) 2008-2010 SUSE Linux Products GmbH + * Copyright (C) 2008-2010 Tejun Heo + * + * This file is released under the GPLv2. + */ + +#ifndef _OSSP_SLAVE_H +#define _OSSP_SLAVE_H + +#include "ossp.h" +#include "ossp-util.h" + +#define OSSP_USER_NAME_LEN 128 + +extern char ossp_user_name[OSSP_USER_NAME_LEN]; +extern int ossp_cmd_fd, ossp_notify_fd; +extern void *ossp_mmap_addr[2]; + +void ossp_slave_init(int argc, char **argv); +int ossp_slave_process_command(int cmd_fd, + ossp_action_fn_t const *action_fn_tbl, + int (*action_pre_fn)(void), + void (*action_post_fn)(void)); + +#endif /* _OSSP_SLAVE_H */ diff --git a/src/mod/endpoints/mod_skypopen/osscuse/ossp-util.c b/src/mod/endpoints/mod_skypopen/osscuse/ossp-util.c new file mode 100644 index 0000000000..325cefd5fd --- /dev/null +++ b/src/mod/endpoints/mod_skypopen/osscuse/ossp-util.c @@ -0,0 +1,369 @@ +/* + * ossp-util - OSS Proxy: Common utilities + * + * Copyright (C) 2008-2010 SUSE Linux Products GmbH + * Copyright (C) 2008-2010 Tejun Heo + * + * This file is released under the GPLv2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ossp-util.h" + +#define BIT(nr) (1UL << (nr)) +#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) +#define BIT_WORD(nr) ((nr) / BITS_PER_LONG) +#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) +#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG) + +char ossp_log_name[OSSP_LOG_NAME_LEN]; +int ossp_log_level = OSSP_LOG_DFL; +int ossp_log_timestamp; + +static const char *severity_strs[] = { + [OSSP_LOG_CRIT] = "CRIT", + [OSSP_LOG_ERR] = " ERR", + [OSSP_LOG_WARN] = "WARN", + [OSSP_LOG_INFO] = NULL, + [OSSP_LOG_DBG0] = "DBG0", + [OSSP_LOG_DBG1] = "DBG1", +}; + +static int severity_map[] = { + [OSSP_LOG_CRIT] = LOG_ERR, + [OSSP_LOG_ERR] = LOG_ERR, + [OSSP_LOG_WARN] = LOG_WARNING, + [OSSP_LOG_INFO] = LOG_INFO, + [OSSP_LOG_DBG0] = LOG_DEBUG, + [OSSP_LOG_DBG1] = LOG_DEBUG, +}; + +void log_msg(int severity, const char *fmt, ...) +{ + static int syslog_opened = 0; + char buf[1024]; + size_t len = sizeof(buf), off = 0; + va_list ap; + + if (severity > abs(ossp_log_level)) + return; + + if (ossp_log_level < 0 && !syslog_opened) + openlog(ossp_log_name, 0, LOG_DAEMON); + + assert(severity >= 0 && severity < ARRAY_SIZE(severity_strs)); + + if (ossp_log_timestamp) { + static uint64_t start; + uint64_t now; + struct timeval tv; + gettimeofday(&tv, NULL); + now = tv.tv_sec * 1000 + tv.tv_usec / 1000; + if (!start) + start = now; + + off += snprintf(buf + off, len - off, "<%08"PRIu64"> ", + now - start); + } + + if (ossp_log_level > 0) { + char sev_buf[16] = ""; + if (severity_strs[severity]) + snprintf(sev_buf, sizeof(sev_buf), " %s", + severity_strs[severity]); + off += snprintf(buf + off, len - off, "%s%s: ", + ossp_log_name, sev_buf); + } else if (severity_strs[severity]) + off += snprintf(buf + off, len - off, "%s ", + severity_strs[severity]); + + va_start(ap, fmt); + off += vsnprintf(buf + off, len - off, fmt, ap); + va_end(ap); + + off += snprintf(buf + off, len - off, "\n"); + + if (ossp_log_level > 0) + fputs(buf, stderr); + else + syslog(severity_map[severity], "%s", buf); +} + +int read_fill(int fd, void *buf, size_t size) +{ + while (size) { + ssize_t ret; + int rc; + + ret = read(fd, buf, size); + if (ret <= 0) { + if (ret == 0) + rc = -EIO; + else + rc = -errno; + err_e(rc, "failed to read_fill %zu bytes from fd %d", + size, fd); + return rc; + } + buf += ret; + size -= ret; + } + return 0; +} + +int write_fill(int fd, const void *buf, size_t size) +{ + while (size) { + ssize_t ret; + int rc; + + ret = write(fd, buf, size); + if (ret <= 0) { + if (ret == 0) + rc = -EIO; + else + rc = -errno; + err_e(rc, "failed to write_fill %zu bytes to fd %d", + size, fd); + return rc; + } + buf += ret; + size -= ret; + } + return 0; +} + +void ring_fill(struct ring_buf *ring, const void *buf, size_t size) +{ + size_t tail; + + assert(ring_space(ring) >= size); + + tail = (ring->head + ring->size - ring->bytes) % ring->size; + + if (ring->head >= tail) { + size_t todo = min(size, ring->size - ring->head); + + memcpy(ring->buf + ring->head, buf, todo); + ring->head = (ring->head + todo) % ring->size; + ring->bytes += todo; + buf += todo; + size -= todo; + } + + assert(ring->size - ring->head >= size); + memcpy(ring->buf + ring->head, buf, size); + ring->head += size; + ring->bytes += size; +} + +void *ring_data(struct ring_buf *ring, size_t *sizep) +{ + size_t tail; + + if (!ring->bytes) + return NULL; + + tail = (ring->head + ring->size - ring->bytes) % ring->size; + + *sizep = min(ring->bytes, ring->size - tail); + return ring->buf + tail; +} + +int ring_resize(struct ring_buf *ring, size_t new_size) +{ + struct ring_buf new_ring = { .size = new_size }; + void *p; + size_t size; + + if (ring_bytes(ring) > new_size) + return -ENOSPC; + + new_ring.buf = calloc(1, new_size); + if (new_size && !new_ring.buf) + return -ENOMEM; + + while ((p = ring_data(ring, &size))) { + ring_fill(&new_ring, p, size); + ring_consume(ring, size); + } + + free(ring->buf); + *ring = new_ring; + return 0; +} + +int ensure_sbuf_size(struct sized_buf *sbuf, size_t size) +{ + char *new_buf; + + if (sbuf->size >= size) + return 0; + + new_buf = realloc(sbuf->buf, size); + if (size && !new_buf) + return -ENOMEM; + + sbuf->buf = new_buf; + sbuf->size = size; + return 0; +} + +static unsigned long __ffs(unsigned long word) +{ + int num = 0; + + if (BITS_PER_LONG == 64) { + if ((word & 0xffffffff) == 0) { + num += 32; + word >>= 32; + } + } + + if ((word & 0xffff) == 0) { + num += 16; + word >>= 16; + } + if ((word & 0xff) == 0) { + num += 8; + word >>= 8; + } + if ((word & 0xf) == 0) { + num += 4; + word >>= 4; + } + if ((word & 0x3) == 0) { + num += 2; + word >>= 2; + } + if ((word & 0x1) == 0) + num += 1; + return num; +} + +#define ffz(x) __ffs(~(x)) + +unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, + unsigned long offset) +{ + const unsigned long *p = addr + BITOP_WORD(offset); + unsigned long result = offset & ~(BITS_PER_LONG-1); + unsigned long tmp; + + if (offset >= size) + return size; + size -= result; + offset %= BITS_PER_LONG; + if (offset) { + tmp = *(p++); + tmp |= ~0UL >> (BITS_PER_LONG - offset); + if (size < BITS_PER_LONG) + goto found_first; + if (~tmp) + goto found_middle; + size -= BITS_PER_LONG; + result += BITS_PER_LONG; + } + while (size & ~(BITS_PER_LONG-1)) { + if (~(tmp = *(p++))) + goto found_middle; + result += BITS_PER_LONG; + size -= BITS_PER_LONG; + } + if (!size) + return result; + tmp = *p; + +found_first: + tmp |= ~0UL << size; + if (tmp == ~0UL) /* Are any bits zero? */ + return result + size; /* Nope. */ +found_middle: + return result + ffz(tmp); +} + +void __set_bit(int nr, volatile unsigned long *addr) +{ + unsigned long mask = BIT_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); + + *p |= mask; +} + +void __clear_bit(int nr, volatile unsigned long *addr) +{ + unsigned long mask = BIT_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); + + *p &= ~mask; +} + +int get_proc_self_info(pid_t pid, pid_t *ppid_r, + char *cmd_buf, size_t cmd_buf_sz) + +{ + char path[64], buf[4096]; + int fd = -1; + char *cmd_start, *cmd_end, *ppid_start, *end; + ssize_t ret; + pid_t ppid; + int i, rc; + + snprintf(path, sizeof(path), "/proc/%ld/stat", (long)pid); + fd = open(path, O_RDONLY); + if (fd < 0) { + rc = -errno; + goto out; + } + + ret = read(fd, buf, sizeof(buf)); + if (ret < 0) + goto out; + if (ret == sizeof(buf)) { + rc = -EOVERFLOW; + goto out; + } + buf[ret] = '\0'; + + rc = -EINVAL; + cmd_start = strchr(buf, '('); + cmd_end = strrchr(buf, ')'); + if (!cmd_start || !cmd_end) + goto out; + cmd_start++; + + ppid_start = cmd_end; + for (i = 0; i < 3; i++) { + ppid_start = strchr(ppid_start, ' '); + if (!ppid_start) + goto out; + ppid_start++; + } + + ppid = strtoul(ppid_start, &end, 10); + if (end == ppid_start || *end != ' ') + goto out; + + if (ppid_r) + *ppid_r = ppid; + if (cmd_buf) { + size_t len = min_t(size_t, cmd_end - cmd_start, cmd_buf_sz - 1); + memcpy(cmd_buf, cmd_start, len); + cmd_buf[len] = '\0'; + } + + rc = 0; + out: + close(fd); + + return rc; +} diff --git a/src/mod/endpoints/mod_skypopen/osscuse/ossp-util.h b/src/mod/endpoints/mod_skypopen/osscuse/ossp-util.h new file mode 100644 index 0000000000..f48d02257a --- /dev/null +++ b/src/mod/endpoints/mod_skypopen/osscuse/ossp-util.h @@ -0,0 +1,609 @@ +/* + * ossp-util - OSS Proxy: Common utilities + * + * Copyright (C) 2008-2010 SUSE Linux Products GmbH + * Copyright (C) 2008-2010 Tejun Heo + * + * This file is released under the GPLv2. + */ + +#ifndef _OSSP_UTIL_H +#define _OSSP_UTIL_H + +#include +#include +#include +#include +#include +#include +#include "ossp.h" + +#define OSSP_LOG_NAME_LEN 128 + +enum { + OSSP_LOG_CRIT = 1, + OSSP_LOG_ERR, + OSSP_LOG_WARN, + OSSP_LOG_INFO, + OSSP_LOG_DFL = OSSP_LOG_INFO, /* default log level */ + OSSP_LOG_DBG0, + OSSP_LOG_DBG1, + OSSP_LOG_MAX = OSSP_LOG_DBG1, +}; + +extern char ossp_log_name[OSSP_LOG_NAME_LEN]; +extern int ossp_log_level; +extern int ossp_log_timestamp; + +#define BITS_PER_BYTE 8 +#define BITS_PER_LONG (BITS_PER_BYTE * sizeof(long)) +#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) +#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) + +/* ARRAY_SIZE and min/max macros stolen from linux/kernel.h */ +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) + +#define min(x, y) ({ \ + typeof(x) _min1 = (x); \ + typeof(y) _min2 = (y); \ + (void) (&_min1 == &_min2); \ + _min1 < _min2 ? _min1 : _min2; }) + +#define max(x, y) ({ \ + typeof(x) _max1 = (x); \ + typeof(y) _max2 = (y); \ + (void) (&_max1 == &_max2); \ + _max1 > _max2 ? _max1 : _max2; }) + +#define min_t(type, x, y) ({ \ + type __min1 = (x); \ + type __min2 = (y); \ + __min1 < __min2 ? __min1: __min2; }) + +#define max_t(type, x, y) ({ \ + type __max1 = (x); \ + type __max2 = (y); \ + __max1 > __max2 ? __max1: __max2; }) + +void log_msg(int severity, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); + +#define fatal(fmt, args...) do { \ + log_msg(OSSP_LOG_CRIT, fmt , ##args); \ + _exit(1); \ +} while (0) +#define err(fmt, args...) log_msg(OSSP_LOG_ERR, fmt , ##args) +#define warn(fmt, args...) log_msg(OSSP_LOG_WARN, fmt , ##args) +#define info(fmt, args...) log_msg(OSSP_LOG_INFO, fmt , ##args) +#define dbg0(fmt, args...) log_msg(OSSP_LOG_DBG0, fmt , ##args) +#define dbg1(fmt, args...) log_msg(OSSP_LOG_DBG1, fmt , ##args) + +#define fatal_e(e, fmt, args...) \ + fatal(fmt" (%s)" , ##args, strerror(-(e))) +#define err_e(e, fmt, args...) \ + err(fmt" (%s)" , ##args, strerror(-(e))) +#define warn_e(e, fmt, args...) \ + warn(fmt" (%s)" , ##args, strerror(-(e))) +#define info_e(e, fmt, args...) \ + info(fmt" (%s)" , ##args, strerror(-(e))) +#define dbg0_e(e, fmt, args...) \ + dbg0(fmt" (%s)" , ##args, strerror(-(e))) +#define dbg1_e(e, fmt, args...) \ + dbg1(fmt" (%s)" , ##args, strerror(-(e))) + +struct ring_buf { + char *buf; + size_t size; + size_t head; + size_t bytes; +}; + +static inline size_t ring_size(struct ring_buf *ring) +{ + return ring->size; +} + +static inline size_t ring_bytes(struct ring_buf *ring) +{ + return ring->bytes; +} + +static inline size_t ring_space(struct ring_buf *ring) +{ + return ring->size - ring->bytes; +} + +static inline void ring_consume(struct ring_buf *ring, size_t size) +{ + assert(ring->bytes >= size); + ring->bytes -= size; +} + +static inline void ring_manual_init(struct ring_buf *ring, void *buf, + size_t size, size_t head, size_t bytes) +{ + ring->buf = buf; + ring->size = size; + ring->head = head; + ring->bytes = bytes; +} + +void ring_fill(struct ring_buf *ring, const void *buf, size_t size); +void *ring_data(struct ring_buf *ring, size_t *sizep); +int ring_resize(struct ring_buf *ring, size_t new_size); + +struct sized_buf { + char *buf; + size_t size; +}; + +int ensure_sbuf_size(struct sized_buf *sbuf, size_t size); + +int read_fill(int fd, void *buf, size_t size); +int write_fill(int fd, const void *buf, size_t size); + +/* + * Bitops lifted from linux asm-generic implementation. + */ +unsigned long find_next_zero_bit(const unsigned long *addr, unsigned + long size, unsigned long offset); +#define find_first_zero_bit(addr, size) find_next_zero_bit((addr), (size), 0) +extern void __set_bit(int nr, volatile unsigned long *addr); +extern void __clear_bit(int nr, volatile unsigned long *addr); + +typedef ssize_t (*ossp_action_fn_t)(enum ossp_opcode opcode, + void *carg, void *din, size_t din_sz, + void *rarg, void *dout, size_t *dout_szp, + int fd); + +int get_proc_self_info(pid_t tid, pid_t *pgrp, + char *cmd_buf, size_t cmd_buf_sz); + +/* + * Doubly linked list handling code shamelessly stolen from the Linux + * kernel 2.6.26 include/linux/list.h. + */ + +/** + * container_of - cast a member of a structure out to the containing structure + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + * + */ +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) + +#define LIST_POISON1 ((void *) 0x00100100) +#define LIST_POISON2 ((void *) 0x00200200) + +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +struct list_head { + struct list_head *next, *prev; +}; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +static inline void INIT_LIST_HEAD(struct list_head *list) +{ + list->next = list; + list->prev = list; +} + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add(struct list_head *new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head * prev, struct list_head * next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty() on entry does not return true after this, the entry is + * in an undefined state. + */ +static inline void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->next = LIST_POISON1; + entry->prev = LIST_POISON2; +} + +/** + * list_replace - replace old entry by new one + * @old : the element to be replaced + * @new : the new element to insert + * + * If @old was empty, it will be overwritten. + */ +static inline void list_replace(struct list_head *old, + struct list_head *new) +{ + new->next = old->next; + new->next->prev = new; + new->prev = old->prev; + new->prev->next = new; +} + +static inline void list_replace_init(struct list_head *old, + struct list_head *new) +{ + list_replace(old, new); + INIT_LIST_HEAD(old); +} + +/** + * list_del_init - deletes entry from list and reinitialize it. + * @entry: the element to delete from the list. + */ +static inline void list_del_init(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + INIT_LIST_HEAD(entry); +} + +/** + * list_move - delete from one list and add as another's head + * @list: the entry to move + * @head: the head that will precede our entry + */ +static inline void list_move(struct list_head *list, struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add(list, head); +} + +/** + * list_move_tail - delete from one list and add as another's tail + * @list: the entry to move + * @head: the head that will follow our entry + */ +static inline void list_move_tail(struct list_head *list, + struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add_tail(list, head); +} + +/** + * list_is_last - tests whether @list is the last entry in list @head + * @list: the entry to test + * @head: the head of the list + */ +static inline int list_is_last(const struct list_head *list, + const struct list_head *head) +{ + return list->next == head; +} + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(const struct list_head *head) +{ + return head->next == head; +} + +/** + * list_empty_careful - tests whether a list is empty and not being modified + * @head: the list to test + * + * Description: + * tests whether a list is empty _and_ checks that no other CPU might be + * in the process of modifying either member (next or prev) + * + * NOTE: using list_empty_careful() without synchronization + * can only be safe if the only activity that can happen + * to the list entry is list_del_init(). Eg. it cannot be used + * if another CPU could re-list_add() it. + */ +static inline int list_empty_careful(const struct list_head *head) +{ + struct list_head *next = head->next; + return (next == head) && (next == head->prev); +} + +/** + * list_is_singular - tests whether a list has just one entry. + * @head: the list to test. + */ +static inline int list_is_singular(const struct list_head *head) +{ + return !list_empty(head) && (head->next == head->prev); +} + +static inline void __list_splice(const struct list_head *list, + struct list_head *head) +{ + struct list_head *first = list->next; + struct list_head *last = list->prev; + struct list_head *at = head->next; + + first->prev = head; + head->next = first; + + last->next = at; + at->prev = last; +} + +/** + * list_splice - join two lists + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static inline void list_splice(const struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) + __list_splice(list, head); +} + +/** + * list_splice_init - join two lists and reinitialise the emptied list. + * @list: the new list to add. + * @head: the place to add it in the first list. + * + * The list at @list is reinitialised + */ +static inline void list_splice_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head); + INIT_LIST_HEAD(list); + } +} + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define list_entry(ptr, type, member) \ + container_of(ptr, type, member) + +/** + * list_first_entry - get the first element from a list + * @ptr: the list head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + * + * Note, that list is expected to be not empty. + */ +#define list_first_entry(ptr, type, member) \ + list_entry((ptr)->next, type, member) + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +/** + * list_for_each_prev - iterate over a list backwards + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + */ +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev; pos != (head); pos = pos->prev) + +/** + * list_for_each_safe - iterate over a list safe against removal of list entry + * @pos: the &struct list_head to use as a loop cursor. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +/** + * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry + * @pos: the &struct list_head to use as a loop cursor. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_prev_safe(pos, n, head) \ + for (pos = (head)->prev, n = pos->prev; \ + pos != (head); pos = n, n = pos->prev) + +/** + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +/** + * list_for_each_entry_reverse - iterate backwards over list of given type. + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_reverse(pos, head, member) \ + for (pos = list_entry((head)->prev, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.prev, typeof(*pos), member)) + +/** + * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue() + * @pos: the type * to use as a start point + * @head: the head of the list + * @member: the name of the list_struct within the struct. + * + * Prepares a pos entry for use as a start point in list_for_each_entry_continue(). + */ +#define list_prepare_entry(pos, head, member) \ + ((pos) ? : list_entry(head, typeof(*pos), member)) + +/** + * list_for_each_entry_continue - continue iteration over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Continue to iterate over list of given type, continuing after + * the current position. + */ +#define list_for_each_entry_continue(pos, head, member) \ + for (pos = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +/** + * list_for_each_entry_continue_reverse - iterate backwards from the given point + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Start to iterate over list of given type backwards, continuing after + * the current position. + */ +#define list_for_each_entry_continue_reverse(pos, head, member) \ + for (pos = list_entry(pos->member.prev, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.prev, typeof(*pos), member)) + +/** + * list_for_each_entry_from - iterate over list of given type from the current point + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Iterate over list of given type, continuing from current position. + */ +#define list_for_each_entry_from(pos, head, member) \ + for (; &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +/** + * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +/** + * list_for_each_entry_safe_continue + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Iterate over list of given type, continuing after current point, + * safe against removal of list entry. + */ +#define list_for_each_entry_safe_continue(pos, n, head, member) \ + for (pos = list_entry(pos->member.next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +/** + * list_for_each_entry_safe_from + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Iterate over list of given type from current point, safe against + * removal of list entry. + */ +#define list_for_each_entry_safe_from(pos, n, head, member) \ + for (n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +/** + * list_for_each_entry_safe_reverse + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Iterate backwards over list of given type, safe against removal + * of list entry. + */ +#define list_for_each_entry_safe_reverse(pos, n, head, member) \ + for (pos = list_entry((head)->prev, typeof(*pos), member), \ + n = list_entry(pos->member.prev, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.prev, typeof(*n), member)) + +#endif /*_OSSP_UTIL_H*/ diff --git a/src/mod/endpoints/mod_skypopen/osscuse/ossp.c b/src/mod/endpoints/mod_skypopen/osscuse/ossp.c new file mode 100644 index 0000000000..96f98fa37a --- /dev/null +++ b/src/mod/endpoints/mod_skypopen/osscuse/ossp.c @@ -0,0 +1,83 @@ +/* + * ossp - OSS Proxy: emulate OSS device using CUSE + * + * Copyright (C) 2008-2010 SUSE Linux Products GmbH + * Copyright (C) 2008-2010 Tejun Heo + * + * This file is released under the GPLv2. + */ + +#include "ossp.h" + +const struct ossp_arg_size ossp_arg_sizes[OSSP_NR_OPCODES] = { + [OSSP_MIXER] = { sizeof(struct ossp_mixer_arg), + sizeof(struct ossp_mixer_arg), 0 }, + + [OSSP_DSP_OPEN] = { sizeof(struct ossp_dsp_open_arg), 0, 0 }, + [OSSP_DSP_READ] = { sizeof(struct ossp_dsp_rw_arg), 0, 0 }, + [OSSP_DSP_WRITE] = { sizeof(struct ossp_dsp_rw_arg), 0, 0 }, + [OSSP_DSP_POLL] = { sizeof(int), sizeof(unsigned), 0 }, + [OSSP_DSP_MMAP] = { sizeof(struct ossp_dsp_mmap_arg), 0, 0 }, + [OSSP_DSP_MUNMAP] = { sizeof(int), 0, 0 }, + + [OSSP_DSP_RESET] = { 0, 0, 0 }, + [OSSP_DSP_SYNC] = { 0, 0, 0 }, + [OSSP_DSP_POST] = { 0, 0, 0 }, + [OSSP_DSP_GET_RATE] = { 0, sizeof(int), 0 }, + [OSSP_DSP_GET_CHANNELS] = { 0, sizeof(int), 0 }, + [OSSP_DSP_GET_FORMAT] = { 0, sizeof(int), 0 }, + [OSSP_DSP_GET_BLKSIZE] = { 0, sizeof(int), 0 }, + [OSSP_DSP_GET_FORMATS] = { 0, sizeof(int), 0 }, + [OSSP_DSP_SET_RATE] = { sizeof(int), sizeof(int), 0 }, + [OSSP_DSP_SET_CHANNELS] = { sizeof(int), sizeof(int), 0 }, + [OSSP_DSP_SET_FORMAT] = { sizeof(int), sizeof(int), 0 }, + [OSSP_DSP_SET_SUBDIVISION] = { sizeof(int), sizeof(int), 0 }, + [OSSP_DSP_SET_FRAGMENT] = { sizeof(int), 0, 0 }, + [OSSP_DSP_GET_TRIGGER] = { 0, sizeof(int), 0 }, + [OSSP_DSP_SET_TRIGGER] = { sizeof(int), 0, 0 }, + [OSSP_DSP_GET_OSPACE] = { 0, sizeof(struct audio_buf_info), 0 }, + [OSSP_DSP_GET_ISPACE] = { 0, sizeof(struct audio_buf_info), 0 }, + [OSSP_DSP_GET_OPTR] = { 0, sizeof(struct count_info), 0 }, + [OSSP_DSP_GET_IPTR] = { 0, sizeof(struct count_info), 0 }, + [OSSP_DSP_GET_ODELAY] = { 0, sizeof(int), 0 }, +}; + +const char *ossp_cmd_str[OSSP_NR_OPCODES] = { + [OSSP_MIXER] = "MIXER", + + [OSSP_DSP_OPEN] = "OPEN", + [OSSP_DSP_READ] = "READ", + [OSSP_DSP_WRITE] = "WRITE", + [OSSP_DSP_POLL] = "POLL", + [OSSP_DSP_MMAP] = "MMAP", + [OSSP_DSP_MUNMAP] = "MUNMAP", + + [OSSP_DSP_RESET] = "RESET", + [OSSP_DSP_SYNC] = "SYNC", + [OSSP_DSP_POST] = "POST", + + [OSSP_DSP_GET_RATE] = "GET_RATE", + [OSSP_DSP_GET_CHANNELS] = "GET_CHANNELS", + [OSSP_DSP_GET_FORMAT] = "GET_FORMAT", + [OSSP_DSP_GET_BLKSIZE] = "GET_BLKSIZE", + [OSSP_DSP_GET_FORMATS] = "GET_FORMATS", + [OSSP_DSP_SET_RATE] = "SET_RATE", + [OSSP_DSP_SET_CHANNELS] = "SET_CHANNELS", + [OSSP_DSP_SET_FORMAT] = "SET_FORMAT", + [OSSP_DSP_SET_SUBDIVISION] = "SET_BUSDIVISION", + + [OSSP_DSP_SET_FRAGMENT] = "SET_FRAGMENT", + [OSSP_DSP_GET_TRIGGER] = "GET_TRIGGER", + [OSSP_DSP_SET_TRIGGER] = "SET_TRIGGER", + [OSSP_DSP_GET_OSPACE] = "GET_OSPACE", + [OSSP_DSP_GET_ISPACE] = "GET_ISPACE", + [OSSP_DSP_GET_OPTR] = "GET_OPTR", + [OSSP_DSP_GET_IPTR] = "GET_IPTR", + [OSSP_DSP_GET_ODELAY] = "GET_ODELAY", +}; + +const char *ossp_notify_str[OSSP_NR_NOTIFY_OPCODES] = { + [OSSP_NOTIFY_POLL] = "POLL", + [OSSP_NOTIFY_OBITUARY] = "OBITUARY", + [OSSP_NOTIFY_VOLCHG] = "VOLCHG", +}; diff --git a/src/mod/endpoints/mod_skypopen/osscuse/ossp.h b/src/mod/endpoints/mod_skypopen/osscuse/ossp.h new file mode 100644 index 0000000000..9d03e63adf --- /dev/null +++ b/src/mod/endpoints/mod_skypopen/osscuse/ossp.h @@ -0,0 +1,117 @@ +/* + * ossp - OSS Proxy: emulate OSS device using CUSE + * + * Copyright (C) 2008-2010 SUSE Linux Products GmbH + * Copyright (C) 2008-2010 Tejun Heo + * + * This file is released under the GPLv2. + */ + +#ifndef _OSSP_H +#define _OSSP_H + +#include +#include +#include + +#define OSSP_VERSION "1.3.2" +#define OSSP_CMD_MAGIC 0xdeadbeef +#define OSSP_REPLY_MAGIC 0xbeefdead +#define OSSP_NOTIFY_MAGIC 0xbebebebe + +#define PLAY 0 +#define REC 1 +#define LEFT 0 +#define RIGHT 1 + +enum ossp_opcode { + OSSP_MIXER, + + OSSP_DSP_OPEN, + OSSP_DSP_READ, + OSSP_DSP_WRITE, + OSSP_DSP_POLL, + OSSP_DSP_MMAP, + OSSP_DSP_MUNMAP, + + OSSP_DSP_RESET, + OSSP_DSP_SYNC, + OSSP_DSP_POST, + + OSSP_DSP_GET_RATE, + OSSP_DSP_GET_CHANNELS, + OSSP_DSP_GET_FORMAT, + OSSP_DSP_GET_BLKSIZE, + OSSP_DSP_GET_FORMATS, + OSSP_DSP_SET_RATE, + OSSP_DSP_SET_CHANNELS, + OSSP_DSP_SET_FORMAT, + OSSP_DSP_SET_SUBDIVISION, + + OSSP_DSP_SET_FRAGMENT, + OSSP_DSP_GET_TRIGGER, + OSSP_DSP_SET_TRIGGER, + OSSP_DSP_GET_OSPACE, + OSSP_DSP_GET_ISPACE, + OSSP_DSP_GET_OPTR, + OSSP_DSP_GET_IPTR, + OSSP_DSP_GET_ODELAY, + + OSSP_NR_OPCODES, +}; + +enum ossp_notify_opcode { + OSSP_NOTIFY_POLL, + OSSP_NOTIFY_OBITUARY, + OSSP_NOTIFY_VOLCHG, + + OSSP_NR_NOTIFY_OPCODES, +}; + +struct ossp_mixer_arg { + int vol[2][2]; +}; + +struct ossp_dsp_open_arg { + int flags; + pid_t opener_pid; +}; + +struct ossp_dsp_rw_arg { + unsigned nonblock:1; +}; + +struct ossp_dsp_mmap_arg { + int dir; + size_t size; +}; + +struct ossp_cmd { + unsigned magic; + enum ossp_opcode opcode; + size_t din_size; + size_t dout_size; +}; + +struct ossp_reply { + unsigned magic; + int result; + size_t dout_size; /* <= cmd.data_in_size */ +}; + +struct ossp_notify { + unsigned magic; + enum ossp_notify_opcode opcode; +}; + +struct ossp_arg_size { + ssize_t carg_size; + ssize_t rarg_size; + unsigned has_fd:1; +}; + +extern const struct ossp_arg_size ossp_arg_sizes[OSSP_NR_OPCODES]; +extern const char *ossp_cmd_str[OSSP_NR_OPCODES]; +extern const char *ossp_notify_str[OSSP_NR_NOTIFY_OPCODES]; + +#endif /* _OSSP_H */ diff --git a/src/mod/endpoints/mod_skypopen/osscuse/osspd.c b/src/mod/endpoints/mod_skypopen/osscuse/osspd.c new file mode 100644 index 0000000000..dc9f36a09b --- /dev/null +++ b/src/mod/endpoints/mod_skypopen/osscuse/osspd.c @@ -0,0 +1,2374 @@ +/* + * osspd - OSS Proxy Daemon: emulate OSS device using CUSE + * + * Copyright (C) 2008-2010 SUSE Linux Products GmbH + * Copyright (C) 2008-2010 Tejun Heo + * + * This file is released under the GPLv2. + */ +#undef GIOVANNI + +#define FUSE_USE_VERSION 28 +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ossp.h" +#include "ossp-util.h" + +/* + * MMAP support needs to be updated to the new fuse MMAP API. Disable + * it for the time being. + */ +#warning mmap support disabled for now +/* #define OSSP_MMAP */ + +#define DFL_MIXER_NAME "mixer" +#define DFL_DSP_NAME "dsp" +#define DFL_ADSP_NAME "adsp" +#define STRFMT "S[%u/%d]" +#define STRID(os) os->id, os->pid + +#define dbg1_os(os, fmt, args...) dbg1(STRFMT" "fmt, STRID(os) , ##args) +#define dbg0_os(os, fmt, args...) dbg0(STRFMT" "fmt, STRID(os) , ##args) +#define warn_os(os, fmt, args...) warn(STRFMT" "fmt, STRID(os) , ##args) +#define err_os(os, fmt, args...) err(STRFMT" "fmt, STRID(os) , ##args) +#define warn_ose(os, err, fmt, args...) \ + warn_e(err, STRFMT" "fmt, STRID(os) , ##args) +#define err_ose(os, err, fmt, args...) \ + err_e(err, STRFMT" "fmt, STRID(os) , ##args) + +enum { + SNDRV_OSS_VERSION = ((3<<16)|(8<<8)|(1<<4)|(0)), /* 3.8.1a */ + DFL_MIXER_MAJOR = 14, + DFL_MIXER_MINOR = 0, + DFL_DSP_MAJOR = 14, + DFL_DSP_MINOR = 3, + DFL_ADSP_MAJOR = 14, + DFL_ADSP_MINOR = 12, + DFL_MAX_STREAMS = 128, + MIXER_PUT_DELAY = 600, /* 10 mins */ + /* DSPS_MMAP_SIZE / 2 must be multiple of SHMLBA */ + DSPS_MMAP_SIZE = 2 * (512 << 10), /* 512k for each dir */ +}; + +struct ossp_uid_cnt { + struct list_head link; + uid_t uid; + unsigned nr_os; +}; + +struct ossp_mixer { + pid_t pgrp; + struct list_head link; + struct list_head delayed_put_link; + unsigned refcnt; + /* the following two fields are protected by mixer_mutex */ + int vol[2][2]; + int modify_counter; + time_t put_expires; +}; + +struct ossp_mixer_cmd { + struct ossp_mixer *mixer; + struct ossp_mixer_arg set; + int out_dir; + int rvol; +}; + +#define for_each_vol(i, j) \ + for (i = 0, j = 0; i < 2; j += i << 1, j++, i = j >> 1, j &= 1) + +struct ossp_stream { + unsigned id; /* stream ID */ + struct list_head link; + struct list_head pgrp_link; + struct list_head notify_link; + unsigned refcnt; + pthread_mutex_t cmd_mutex; + pthread_mutex_t mmap_mutex; + struct fuse_pollhandle *ph; + + /* stream owner info */ + pid_t pid; + pid_t pgrp; + uid_t uid; + gid_t gid; + + /* slave info */ + pid_t slave_pid; + int cmd_fd; + int notify_tx; + int notify_rx; + + /* the following dead flag is set asynchronously, keep it separate. */ + int dead; + + /* stream mixer state, protected by mixer_mutex */ + int mixer_pending; + int vol[2][2]; + int vol_set[2][2]; + + off_t mmap_off; + size_t mmap_size; + + struct ossp_uid_cnt *ucnt; + struct fuse_session *se; /* associated fuse session */ + struct ossp_mixer *mixer; +}; + +struct ossp_dsp_stream { + struct ossp_stream os; + unsigned rw; + unsigned mmapped; + int nonblock; +}; + +#define os_to_dsps(_os) container_of(_os, struct ossp_dsp_stream, os) + +static unsigned max_streams; +static unsigned umax_streams; +static unsigned hashtbl_size; +static char dsp_slave_path[PATH_MAX]; + +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t mixer_mutex = PTHREAD_MUTEX_INITIALIZER; +static unsigned long *os_id_bitmap; +static unsigned nr_mixers; +static struct list_head *mixer_tbl; /* indexed by PGRP */ +static struct list_head *os_tbl; /* indexed by ID */ +static struct list_head *os_pgrp_tbl; /* indexed by PGRP */ +static struct list_head *os_notify_tbl; /* indexed by notify fd */ +static LIST_HEAD(uid_cnt_list); +static int notify_epfd; /* epoll used to monitor notify fds */ +static pthread_t notify_poller_thread; +static pthread_t slave_reaper_thread; +static pthread_t mixer_delayed_put_thread; +static pthread_t cuse_mixer_thread; +static pthread_t cuse_adsp_thread; +static pthread_cond_t notify_poller_kill_wait = PTHREAD_COND_INITIALIZER; +static pthread_cond_t slave_reaper_wait = PTHREAD_COND_INITIALIZER; +static LIST_HEAD(slave_corpse_list); +static LIST_HEAD(mixer_delayed_put_head); /* delayed reference */ +static pthread_cond_t mixer_delayed_put_cond = PTHREAD_COND_INITIALIZER; + +static int init_wait_fd = -1; +static int exit_on_idle; +static struct fuse_session *mixer_se; +static struct fuse_session *dsp_se; +static struct fuse_session *adsp_se; + +static void put_os(struct ossp_stream *os); + + +/*************************************************************************** + * Accessors + */ + +static struct list_head *mixer_tbl_head(pid_t pid) +{ + return &mixer_tbl[pid % hashtbl_size]; +} + +static struct list_head *os_tbl_head(uint64_t id) +{ + return &os_tbl[id % hashtbl_size]; +} + +static struct list_head *os_pgrp_tbl_head(pid_t pgrp) +{ + return &os_pgrp_tbl[pgrp % hashtbl_size]; +} + +static struct list_head *os_notify_tbl_head(int notify_rx) +{ + return &os_notify_tbl[notify_rx % hashtbl_size]; +} + +static struct ossp_mixer *find_mixer_locked(pid_t pgrp) +{ + struct ossp_mixer *mixer; + + list_for_each_entry(mixer, mixer_tbl_head(pgrp), link) + if (mixer->pgrp == pgrp) + return mixer; + return NULL; +} + +static struct ossp_mixer *find_mixer(pid_t pgrp) +{ + struct ossp_mixer *mixer; + + pthread_mutex_lock(&mutex); + mixer = find_mixer_locked(pgrp); + pthread_mutex_unlock(&mutex); + return mixer; +} + +static struct ossp_stream *find_os(unsigned id) +{ + struct ossp_stream *os, *found = NULL; + + pthread_mutex_lock(&mutex); + list_for_each_entry(os, os_tbl_head(id), link) + if (os->id == id) { + found = os; + break; + } + pthread_mutex_unlock(&mutex); + return found; +} + +static struct ossp_stream *find_os_by_notify_rx(int notify_rx) +{ + struct ossp_stream *os, *found = NULL; + + pthread_mutex_lock(&mutex); + list_for_each_entry(os, os_notify_tbl_head(notify_rx), notify_link) + if (os->notify_rx == notify_rx) { + found = os; + break; + } + pthread_mutex_unlock(&mutex); + return found; +} + + +/*************************************************************************** + * Command and ioctl helpers + */ + +static ssize_t exec_cmd_intern(struct ossp_stream *os, enum ossp_opcode opcode, + const void *carg, size_t carg_size, const void *din, size_t din_size, + void *rarg, size_t rarg_size, void *dout, size_t *dout_sizep, int fd) +{ + size_t dout_size = dout_sizep ? *dout_sizep : 0; + struct ossp_cmd cmd = { .magic = OSSP_CMD_MAGIC, .opcode = opcode, + .din_size = din_size, + .dout_size = dout_size }; + struct iovec iov = { &cmd, sizeof(cmd) }; + struct msghdr msg = { .msg_iov = &iov, .msg_iovlen = 1 }; + struct ossp_reply reply = { }; + char cmsg_buf[CMSG_SPACE(sizeof(fd))]; + char reason[512]; + int rc; + + if (os->dead) + return -EIO; + + //dbg1_os(os, "opcode %s=%d carg=%zu din=%zu rarg=%zu dout=%zu", + //ossp_cmd_str[opcode], opcode, carg_size, din_size, rarg_size, + //dout_size); +#ifndef GIOVANNI +memset(dout, 255, dout_size); +memset(din, 255, din_size); + +#define GIOVA_BLK 3840 +#define GIOVA_SLEEP 40000 +switch(opcode){ + + case 1: //OPEN + reply.result = 0; + break; + case 2: //READ + usleep((GIOVA_SLEEP/GIOVA_BLK)* *dout_sizep); + reply.result = *dout_sizep; + break; + case 3: //WRITE + usleep((GIOVA_SLEEP/GIOVA_BLK)* din_size); + reply.result = din_size; + break; + case 9: //POST + reply.result = -32; + break; + case 13: //GET_BLKSIZE + reply.result = 0; + *(int *)rarg = GIOVA_BLK; + break; + case 14: //GET_FORMATS + reply.result = 0; + *(int *)rarg = 28731; + break; + case 15: //SET_RATE + reply.result = 0; + *(int *)rarg = *(int *) carg; + break; + case 16: //SET_CHANNELS + reply.result = 0; + *(int *)rarg = *(int *) carg; + break; + case 17: //SET_FORMAT + reply.result = 0; + *(int *)rarg = *(int *) carg; + break; + case 19: //SET_FRAGMENT + reply.result = 0; + break; + default: + reply.result = 0; + break; +} +#endif // GIOVANNI + +#ifdef GIOVANNI + if (fd >= 0) { + struct cmsghdr *cmsg; + + msg.msg_control = cmsg_buf; + msg.msg_controllen = sizeof(cmsg_buf); + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); + *(int *)CMSG_DATA(cmsg) = fd; + msg.msg_controllen = cmsg->cmsg_len; + } + + if (sendmsg(os->cmd_fd, &msg, 0) <= 0) { + rc = -errno; + snprintf(reason, sizeof(reason), "command sendmsg failed: %s", + strerror(-rc)); + goto fail; + } + + if ((rc = write_fill(os->cmd_fd, carg, carg_size)) < 0 || + (rc = write_fill(os->cmd_fd, din, din_size)) < 0) { + snprintf(reason, sizeof(reason), + "can't tranfer command argument and/or data: %s", + strerror(-rc)); + goto fail; + } + if ((rc = read_fill(os->cmd_fd, &reply, sizeof(reply))) < 0) { + snprintf(reason, sizeof(reason), "can't read reply: %s", + strerror(-rc)); + goto fail; + } + + if (reply.magic != OSSP_REPLY_MAGIC) { + snprintf(reason, sizeof(reason), + "reply magic mismatch %x != %x", + reply.magic, OSSP_REPLY_MAGIC); + rc = -EINVAL; + goto fail; + } + + if (reply.result < 0) + goto out_unlock; + + if (reply.dout_size > dout_size) { + snprintf(reason, sizeof(reason), + "data out size overflow %zu > %zu", + reply.dout_size, dout_size); + rc = -EINVAL; + goto fail; + } + + dout_size = reply.dout_size; + if (dout_sizep) + *dout_sizep = dout_size; + + if ((rc = read_fill(os->cmd_fd, rarg, rarg_size)) < 0 || + (rc = read_fill(os->cmd_fd, dout, dout_size)) < 0) { + snprintf(reason, sizeof(reason), "can't read data out: %s", + strerror(-rc)); + goto fail; + } + +#endif // GIOVANNI + +out_unlock: + //dbg1_os(os, " completed, result=%d dout=%zu", + //reply.result, dout_size); + +//if(rarg) + //dbg1_os(os, " 2 %s=%d completed, result=%d dout=%zu carg=%d rarg=%d", ossp_cmd_str[opcode], opcode, + //reply.result, dout_size, carg ? *(int *) carg : 666, *(int *)rarg); + return reply.result; + +fail: + warn_os(os, "communication with slave failed (%s)", reason); + os->dead = 1; + return rc; +} + +static ssize_t exec_cmd(struct ossp_stream *os, enum ossp_opcode opcode, + const void *carg, size_t carg_size, const void *din, size_t din_size, + void *rarg, size_t rarg_size, void *dout, size_t *dout_sizep, int fd) +{ + int is_mixer; + int i, j; + ssize_t ret, mret; + + /* mixer command is handled exlicitly below */ + is_mixer = opcode == OSSP_MIXER; + if (is_mixer) { + ret = -pthread_mutex_trylock(&os->cmd_mutex); + if (ret) + return ret; + } else { + pthread_mutex_lock(&os->cmd_mutex); + + ret = exec_cmd_intern(os, opcode, carg, carg_size, + din, din_size, rarg, rarg_size, + dout, dout_sizep, fd); + } + + /* lazy mixer handling */ + pthread_mutex_lock(&mixer_mutex); + + if (os->mixer_pending) { + struct ossp_mixer_arg marg; + repeat_mixer: + /* we have mixer command pending */ + memcpy(marg.vol, os->vol_set, sizeof(os->vol_set)); + memset(os->vol_set, -1, sizeof(os->vol_set)); + + pthread_mutex_unlock(&mixer_mutex); + mret = exec_cmd_intern(os, OSSP_MIXER, &marg, sizeof(marg), + NULL, 0, &marg, sizeof(marg), NULL, NULL, + -1); + pthread_mutex_lock(&mixer_mutex); + + /* was there mixer set request while executing mixer command? */ + for_each_vol(i, j) + if (os->vol_set[i][j] >= 0) + goto repeat_mixer; + + /* update internal mixer state */ + if (mret == 0) { + for_each_vol(i, j) { + if (marg.vol[i][j] >= 0) { + if (os->vol[i][j] != marg.vol[i][j]) + os->mixer->modify_counter++; + os->vol[i][j] = marg.vol[i][j]; + } + } + } + os->mixer_pending = 0; + } + + pthread_mutex_unlock(&os->cmd_mutex); + + /* + * mixer mutex must be released after cmd_mutex so that + * exec_mixer_cmd() can guarantee that mixer_pending flags + * will be handled immediately or when the currently + * in-progress command completes. + */ + pthread_mutex_unlock(&mixer_mutex); + + return is_mixer ? mret : ret; +} + +static ssize_t exec_simple_cmd(struct ossp_stream *os, + enum ossp_opcode opcode, void *carg, void *rarg) +{ + return exec_cmd(os, opcode, + carg, ossp_arg_sizes[opcode].carg_size, NULL, 0, + rarg, ossp_arg_sizes[opcode].rarg_size, NULL, NULL, -1); +} + +static int ioctl_prep_uarg(fuse_req_t req, void *in, size_t in_sz, void *out, + size_t out_sz, void *uarg, const void *in_buf, + size_t in_bufsz, size_t out_bufsz) +{ + struct iovec in_iov = { }, out_iov = { }; + int retry = 0; + + if (in) { + if (!in_bufsz) { + in_iov.iov_base = uarg; + in_iov.iov_len = in_sz; + retry = 1; + } else { + assert(in_bufsz == in_sz); + memcpy(in, in_buf, in_sz); + } + } + + if (out) { + if (!out_bufsz) { + out_iov.iov_base = uarg; + out_iov.iov_len = out_sz; + retry = 1; + } else + assert(out_bufsz == out_sz); + } + + if (retry) + fuse_reply_ioctl_retry(req, &in_iov, 1, &out_iov, 1); + + return retry; +} + +#define PREP_UARG(inp, outp) do { \ + if (ioctl_prep_uarg(req, (inp), sizeof(*(inp)), \ + (outp), sizeof(*(outp)), uarg, \ + in_buf, in_bufsz, out_bufsz)) \ + return; \ +} while (0) + +#define IOCTL_RETURN(result, outp) do { \ + if ((outp) != NULL) \ + fuse_reply_ioctl(req, result, (outp), sizeof(*(outp))); \ + else \ + fuse_reply_ioctl(req, result, NULL, 0); \ + return; \ +} while (0) + + +/*************************************************************************** + * Mixer implementation + */ + +static void put_mixer_real(struct ossp_mixer *mixer) +{ + if (!--mixer->refcnt) { + dbg0("DESTROY mixer(%d)", mixer->pgrp); + list_del_init(&mixer->link); + list_del_init(&mixer->delayed_put_link); + free(mixer); + nr_mixers--; + + /* + * If exit_on_idle, mixer for pgrp0 is touched during + * init and each stream has mixer attached. As mixers + * are destroyed after they have been idle for + * MIXER_PUT_DELAY seconds, we can use it for idle + * detection. Note that this might race with + * concurrent open. The race is inherent. + */ + if (exit_on_idle && !nr_mixers) { + info("idle, exiting"); + exit(0); + } + } +} + +static struct ossp_mixer *get_mixer(pid_t pgrp) +{ + struct ossp_mixer *mixer; + + pthread_mutex_lock(&mutex); + + /* is there a matching one? */ + mixer = find_mixer_locked(pgrp); + if (mixer) { + if (list_empty(&mixer->delayed_put_link)) + mixer->refcnt++; + else + list_del_init(&mixer->delayed_put_link); + goto out_unlock; + } + + /* reap delayed put list if there are too many mixers */ + while (nr_mixers > 2 * max_streams && + !list_empty(&mixer_delayed_put_head)) { + struct ossp_mixer *mixer = + list_first_entry(&mixer_delayed_put_head, + struct ossp_mixer, delayed_put_link); + + assert(mixer->refcnt == 1); + put_mixer_real(mixer); + } + + /* create a new one */ + mixer = calloc(1, sizeof(*mixer)); + if (!mixer) { + warn("failed to allocate mixer for %d", pgrp); + mixer = NULL; + goto out_unlock; + } + + mixer->pgrp = pgrp; + INIT_LIST_HEAD(&mixer->link); + INIT_LIST_HEAD(&mixer->delayed_put_link); + mixer->refcnt = 1; + memset(mixer->vol, -1, sizeof(mixer->vol)); + + list_add(&mixer->link, mixer_tbl_head(pgrp)); + nr_mixers++; + dbg0("CREATE mixer(%d)", pgrp); + +out_unlock: + pthread_mutex_unlock(&mutex); + return mixer; +} + +static void put_mixer(struct ossp_mixer *mixer) +{ + pthread_mutex_lock(&mutex); + + if (mixer) { + if (mixer->refcnt == 1) { + struct timespec ts; + + clock_gettime(CLOCK_REALTIME, &ts); + mixer->put_expires = ts.tv_sec + MIXER_PUT_DELAY; + list_add_tail(&mixer->delayed_put_link, + &mixer_delayed_put_head); + pthread_cond_signal(&mixer_delayed_put_cond); + } else + put_mixer_real(mixer); + } + + pthread_mutex_unlock(&mutex); +} + +static void *mixer_delayed_put_worker(void *arg) +{ + struct ossp_mixer *mixer; + struct timespec ts; + time_t now; + + pthread_mutex_lock(&mutex); +again: + clock_gettime(CLOCK_REALTIME, &ts); + now = ts.tv_sec; + + mixer = NULL; + while (!list_empty(&mixer_delayed_put_head)) { + mixer = list_first_entry(&mixer_delayed_put_head, + struct ossp_mixer, delayed_put_link); + + if (now <= mixer->put_expires) + break; + + assert(mixer->refcnt == 1); + put_mixer_real(mixer); + mixer = NULL; + } + + if (mixer) { + ts.tv_sec = mixer->put_expires + 1; + pthread_cond_timedwait(&mixer_delayed_put_cond, &mutex, &ts); + } else + pthread_cond_wait(&mixer_delayed_put_cond, &mutex); + + goto again; +} + +static void init_mixer_cmd(struct ossp_mixer_cmd *mxcmd, + struct ossp_mixer *mixer) +{ + memset(mxcmd, 0, sizeof(*mxcmd)); + memset(&mxcmd->set.vol, -1, sizeof(mxcmd->set.vol)); + mxcmd->mixer = mixer; + mxcmd->out_dir = -1; +} + +static int exec_mixer_cmd(struct ossp_mixer_cmd *mxcmd, struct ossp_stream *os) +{ + int i, j, rc; + + /* + * Set pending flags before trying to execute mixer command. + * Combined with lock release order in exec_cmd(), this + * guarantees that the mixer command will be executed + * immediately or when the current command completes. + */ + pthread_mutex_lock(&mixer_mutex); + os->mixer_pending = 1; + for_each_vol(i, j) + if (mxcmd->set.vol[i][j] >= 0) + os->vol_set[i][j] = mxcmd->set.vol[i][j]; + pthread_mutex_unlock(&mixer_mutex); + + rc = exec_simple_cmd(os, OSSP_MIXER, NULL, NULL); + if (rc >= 0) { + dbg0_os(os, "volume set=%d/%d:%d/%d get=%d/%d:%d/%d", + mxcmd->set.vol[PLAY][LEFT], mxcmd->set.vol[PLAY][RIGHT], + mxcmd->set.vol[REC][LEFT], mxcmd->set.vol[REC][RIGHT], + os->vol[PLAY][LEFT], os->vol[PLAY][RIGHT], + os->vol[REC][LEFT], os->vol[REC][RIGHT]); + } else if (rc != -EBUSY) + warn_ose(os, rc, "mixer command failed"); + + return rc; +} + +static void finish_mixer_cmd(struct ossp_mixer_cmd *mxcmd) +{ + struct ossp_mixer *mixer = mxcmd->mixer; + struct ossp_stream *os; + int dir = mxcmd->out_dir; + int vol[2][2] = { }; + int cnt[2][2] = { }; + int i, j; + + pthread_mutex_lock(&mixer_mutex); + + /* get volume of all streams attached to this mixer */ + pthread_mutex_lock(&mutex); + list_for_each_entry(os, os_pgrp_tbl_head(mixer->pgrp), pgrp_link) { + if (os->pgrp != mixer->pgrp) + continue; + for_each_vol(i, j) { + if (os->vol[i][j] < 0) + continue; + vol[i][j] += os->vol[i][j]; + cnt[i][j]++; + } + } + pthread_mutex_unlock(&mutex); + + /* calculate the summary volume values */ + for_each_vol(i, j) { + if (mxcmd->set.vol[i][j] >= 0) + vol[i][j] = mxcmd->set.vol[i][j]; + else if (cnt[i][j]) + vol[i][j] = vol[i][j] / cnt[i][j]; + else if (mixer->vol[i][j] >= 0) + vol[i][j] = mixer->vol[i][j]; + else + vol[i][j] = 100; + + vol[i][j] = min(max(0, vol[i][j]), 100); + } + + if (dir >= 0) + mxcmd->rvol = vol[dir][LEFT] | (vol[dir][RIGHT] << 8); + + pthread_mutex_unlock(&mixer_mutex); +} + +static void mixer_simple_ioctl(fuse_req_t req, struct ossp_mixer *mixer, + unsigned cmd, void *uarg, const void *in_buf, + size_t in_bufsz, size_t out_bufsz, + int *not_minep) +{ + const char *id = "OSS Proxy", *name = "Mixer"; + int i; + + switch (cmd) { + case SOUND_MIXER_INFO: { + struct mixer_info info = { }; + + PREP_UARG(NULL, &info); + strncpy(info.id, id, sizeof(info.id) - 1); + strncpy(info.name, name, sizeof(info.name) - 1); + info.modify_counter = mixer->modify_counter; + IOCTL_RETURN(0, &info); + } + + case SOUND_OLD_MIXER_INFO: { + struct _old_mixer_info info = { }; + + PREP_UARG(NULL, &info); + strncpy(info.id, id, sizeof(info.id) - 1); + strncpy(info.name, name, sizeof(info.name) - 1); + IOCTL_RETURN(0, &info); + } + + case OSS_GETVERSION: + i = SNDRV_OSS_VERSION; + goto puti; + case SOUND_MIXER_READ_DEVMASK: + case SOUND_MIXER_READ_STEREODEVS: + i = SOUND_MASK_PCM | SOUND_MASK_IGAIN; + goto puti; + case SOUND_MIXER_READ_CAPS: + i = SOUND_CAP_EXCL_INPUT; + goto puti; + case SOUND_MIXER_READ_RECMASK: + case SOUND_MIXER_READ_RECSRC: + i = SOUND_MASK_IGAIN; + goto puti; + puti: + PREP_UARG(NULL, &i); + IOCTL_RETURN(0, &i); + + case SOUND_MIXER_WRITE_RECSRC: + IOCTL_RETURN(0, NULL); + + default: + *not_minep = 1; + return; + } + assert(0); +} + +static void mixer_do_ioctl(fuse_req_t req, struct ossp_mixer *mixer, + unsigned cmd, void *uarg, const void *in_buf, + size_t in_bufsz, size_t out_bufsz) +{ + struct ossp_mixer_cmd mxcmd; + struct ossp_stream *os, **osa; + int not_mine = 0; + int slot = cmd & 0xff, dir; + int nr_os; + int i, rc; + + mixer_simple_ioctl(req, mixer, cmd, uarg, in_buf, in_bufsz, out_bufsz, + ¬_mine); + if (!not_mine) + return; + + rc = -ENXIO; + if (!(cmd & (SIOC_IN | SIOC_OUT))) + goto err; + + /* + * Okay, it's not one of the easy ones. Build mxcmd for + * actual volume control. + */ + if (cmd & SIOC_IN) + PREP_UARG(&i, &i); + else + PREP_UARG(NULL, &i); + + switch (slot) { + case SOUND_MIXER_PCM: + dir = PLAY; + break; + case SOUND_MIXER_IGAIN: + dir = REC; + break; + default: + i = 0; + IOCTL_RETURN(0, &i); + } + + init_mixer_cmd(&mxcmd, mixer); + + if (cmd & SIOC_IN) { + unsigned l, r; + + rc = -EINVAL; + l = i & 0xff; + r = (i >> 8) & 0xff; + if (l > 100 || r > 100) + goto err; + + mixer->vol[dir][LEFT] = mxcmd.set.vol[dir][LEFT] = l; + mixer->vol[dir][RIGHT] = mxcmd.set.vol[dir][RIGHT] = r; + } + mxcmd.out_dir = dir; + + /* + * Apply volume conrol + */ + /* acquire target streams */ + pthread_mutex_lock(&mutex); + osa = calloc(max_streams, sizeof(osa[0])); + if (!osa) { + pthread_mutex_unlock(&mutex); + rc = -ENOMEM; + goto err; + } + + nr_os = 0; + list_for_each_entry(os, os_pgrp_tbl_head(mixer->pgrp), pgrp_link) { + if (os->pgrp == mixer->pgrp) { + osa[nr_os++] = os; + os->refcnt++; + } + } + + pthread_mutex_unlock(&mutex); + + /* execute mxcmd for each stream and put it */ + for (i = 0; i < nr_os; i++) { + exec_mixer_cmd(&mxcmd, osa[i]); + put_os(osa[i]); + } + + finish_mixer_cmd(&mxcmd); + free(osa); + + IOCTL_RETURN(0, out_bufsz ? &mxcmd.rvol : NULL); + +err: + fuse_reply_err(req, -rc); +} + +static void mixer_open(fuse_req_t req, struct fuse_file_info *fi) +{ + pid_t pid = fuse_req_ctx(req)->pid, pgrp; + struct ossp_mixer *mixer; + int rc; + + rc = get_proc_self_info(pid, &pgrp, NULL, 0); + if (rc) { + err_e(rc, "get_proc_self_info(%d) failed", pid); + fuse_reply_err(req, -rc); + return; + } + + mixer = get_mixer(pgrp); + fi->fh = pgrp; + + if (mixer) + fuse_reply_open(req, fi); + else + fuse_reply_err(req, ENOMEM); +} + +static void mixer_ioctl(fuse_req_t req, int signed_cmd, void *uarg, + struct fuse_file_info *fi, unsigned int flags, + const void *in_buf, size_t in_bufsz, size_t out_bufsz) +{ + struct ossp_mixer *mixer; + + mixer = find_mixer(fi->fh); + if (!mixer) { + fuse_reply_err(req, EBADF); + return; + } + + mixer_do_ioctl(req, mixer, signed_cmd, uarg, in_buf, in_bufsz, + out_bufsz); +} + +static void mixer_release(fuse_req_t req, struct fuse_file_info *fi) +{ + struct ossp_mixer *mixer; + + mixer = find_mixer(fi->fh); + if (mixer) { + put_mixer(mixer); + fuse_reply_err(req, 0); + } else + fuse_reply_err(req, EBADF); +} + + +/*************************************************************************** + * Stream implementation + */ + +static int alloc_os(size_t stream_size, size_t mmap_size, pid_t pid, uid_t pgrp, + uid_t uid, gid_t gid, int cmd_sock, + const int *notify, struct fuse_session *se, + struct ossp_stream **osp) +{ + struct ossp_uid_cnt *tmp_ucnt, *ucnt = NULL; + struct ossp_stream *os; + int rc; + + assert(stream_size >= sizeof(struct ossp_stream)); + os = calloc(1, stream_size); + if (!os) + return -ENOMEM; + + INIT_LIST_HEAD(&os->link); + INIT_LIST_HEAD(&os->pgrp_link); + INIT_LIST_HEAD(&os->notify_link); + os->refcnt = 1; + + rc = -pthread_mutex_init(&os->cmd_mutex, NULL); + if (rc) + goto err_free; + + rc = -pthread_mutex_init(&os->mmap_mutex, NULL); + if (rc) + goto err_destroy_cmd_mutex; + + pthread_mutex_lock(&mutex); + + list_for_each_entry(tmp_ucnt, &uid_cnt_list, link) + if (tmp_ucnt->uid == uid) { + ucnt = tmp_ucnt; + break; + } + if (!ucnt) { + rc = -ENOMEM; + ucnt = calloc(1, sizeof(*ucnt)); + if (!ucnt) + goto err_unlock; + ucnt->uid = uid; + list_add(&ucnt->link, &uid_cnt_list); + } + + rc = -EBUSY; + if (ucnt->nr_os + 1 > umax_streams) + goto err_unlock; + + /* everything looks fine, allocate id and init stream */ + rc = -EBUSY; + os->id = find_next_zero_bit(os_id_bitmap, max_streams, 0); + if (os->id >= max_streams) + goto err_unlock; + __set_bit(os->id, os_id_bitmap); + + os->cmd_fd = cmd_sock; + os->notify_tx = notify[1]; + os->notify_rx = notify[0]; + os->pid = pid; + os->pgrp = pgrp; + os->uid = uid; + os->gid = gid; + if (mmap_size) { + os->mmap_off = os->id * mmap_size; + os->mmap_size = mmap_size; + } + os->ucnt = ucnt; + os->se = se; + + memset(os->vol, -1, sizeof(os->vol)); + memset(os->vol_set, -1, sizeof(os->vol)); + + list_add(&os->link, os_tbl_head(os->id)); + list_add(&os->pgrp_link, os_pgrp_tbl_head(os->pgrp)); + + ucnt->nr_os++; + *osp = os; + pthread_mutex_unlock(&mutex); + return 0; + +err_unlock: + pthread_mutex_unlock(&mutex); + pthread_mutex_destroy(&os->mmap_mutex); +err_destroy_cmd_mutex: + pthread_mutex_destroy(&os->cmd_mutex); +err_free: + free(os); + return rc; +} + +static void shutdown_notification(struct ossp_stream *os) +{ + struct ossp_notify obituary = { .magic = OSSP_NOTIFY_MAGIC, + .opcode = OSSP_NOTIFY_OBITUARY }; + ssize_t ret; + + /* + * Shutdown notification for this stream. We politely ask + * notify_poller to shut the receive side down to avoid racing + * with it. + */ + while (os->notify_rx >= 0) { + ret = write(os->notify_tx, &obituary, sizeof(obituary)); + if (ret <= 0) { + if (ret == 0) + warn_os(os, "unexpected EOF on notify_tx"); + else if (errno != EPIPE) + warn_ose(os, -errno, + "unexpected error on notify_tx"); + close(os->notify_rx); + os->notify_rx = -1; + break; + } + + if (ret != sizeof(obituary)) + warn_os(os, "short transfer on notify_tx"); + pthread_cond_wait(¬ify_poller_kill_wait, &mutex); + } +} + +static void put_os(struct ossp_stream *os) +{ + if (!os) + return; + + pthread_mutex_lock(&mutex); + + assert(os->refcnt); + if (--os->refcnt) { + pthread_mutex_unlock(&mutex); + return; + } + + os->dead = 1; + shutdown_notification(os); + + dbg0_os(os, "DESTROY"); + + list_del_init(&os->link); + list_del_init(&os->pgrp_link); + list_del_init(&os->notify_link); + os->ucnt->nr_os--; + + pthread_mutex_unlock(&mutex); + + close(os->cmd_fd); + close(os->notify_tx); + put_mixer(os->mixer); + pthread_mutex_destroy(&os->cmd_mutex); + pthread_mutex_destroy(&os->mmap_mutex); + + pthread_mutex_lock(&mutex); + dbg1_os(os, "stream dead, requesting reaping"); + list_add_tail(&os->link, &slave_corpse_list); + pthread_cond_signal(&slave_reaper_wait); + pthread_mutex_unlock(&mutex); +} + +static void set_extra_env(pid_t pid) +{ + char procenviron[32]; + const int step = 1024; + char *data = malloc(step + 1); + int ofs = 0; + int fd; + int ret; + + if (!data) + return; + + sprintf(procenviron, "/proc/%d/environ", pid); + fd = open(procenviron, O_RDONLY); + if (fd < 0) + return; + + /* + * There should really be a 'read whole file to a newly allocated + * buffer' function. + */ + while ((ret = read(fd, data + ofs, step)) > 0) { + char *newdata; + ofs += ret; + newdata = realloc(data, ofs + step + 1); + if (!newdata) { + ret = -1; + break; + } + data = newdata; + } + if (ret == 0) { + char *ptr = data; + /* Append the extra 0 for end condition */ + data[ofs] = 0; + + while ((ret = strlen(ptr)) > 0) { + /* + * Copy all PULSE variables and DISPLAY so that + * ssh -X remotehost 'mplayer -ao oss' will work + */ + if (!strncmp(ptr, "DISPLAY=", 8) || + !strncmp(ptr, "PULSE_", 6)) + putenv(ptr); + ptr += ret + 1; + } + } + + free(data); + close(fd); +} + +#ifndef GIOVANNI +int contapid = 13000; +#endif// GIOVANNI + +static int create_os(const char *slave_path, + size_t stream_size, size_t mmap_size, + pid_t pid, pid_t pgrp, uid_t uid, gid_t gid, + struct fuse_session *se, struct ossp_stream **osp) +{ + static pthread_mutex_t create_mutex = PTHREAD_MUTEX_INITIALIZER; + int cmd_sock[2] = { -1, -1 }; + int notify_sock[2] = { -1, -1 }; + struct ossp_stream *os = NULL; + struct epoll_event ev = { }; + int i, rc; + + /* + * Only one thread can be creating a stream. This is to avoid + * leaking unwanted fds into slaves. + */ + pthread_mutex_lock(&create_mutex); + + /* prepare communication channels */ + if (socketpair(AF_UNIX, SOCK_STREAM, 0, cmd_sock) || + socketpair(AF_UNIX, SOCK_STREAM, 0, notify_sock)) { + rc = -errno; + warn_e(rc, "failed to create slave command channel"); + goto close_all; + } + + if (fcntl(notify_sock[0], F_SETFL, O_NONBLOCK) < 0) { + rc = -errno; + warn_e(rc, "failed to set NONBLOCK on notify sock"); + goto close_all; + } + + /* + * Alloc stream which will be responsible for all server side + * resources from now on. + */ + rc = alloc_os(stream_size, mmap_size, pid, pgrp, uid, gid, cmd_sock[0], + notify_sock, se, &os); + if (rc) { + warn_e(rc, "failed to allocate stream for %d", pid); + goto close_all; + } + + rc = -ENOMEM; + os->mixer = get_mixer(pgrp); + if (!os->mixer) + goto put_os; + + /* + * Register notification. If successful, notify_poller has + * custody of notify_rx fd. + */ + pthread_mutex_lock(&mutex); + list_add(&os->notify_link, os_notify_tbl_head(os->notify_rx)); + pthread_mutex_unlock(&mutex); + +#ifndef GIOVANNI + os->slave_pid = contapid; + contapid++; + if(contapid > 30000) + contapid=13000; +#endif //GIOVANNI + +//#ifdef GIOVANNI + ev.events = EPOLLIN; + ev.data.fd = notify_sock[0]; + if (epoll_ctl(notify_epfd, EPOLL_CTL_ADD, notify_sock[0], &ev)) { + /* + * Without poller watching this notify sock, poller + * shutdown sequence in shutdown_notification() can't + * be used. Kill notification rx manually. + */ + rc = -errno; + warn_ose(os, rc, "failed to add notify epoll"); + close(os->notify_rx); + os->notify_rx = -1; + goto put_os; + } + + /* start slave */ + os->slave_pid = fork(); + if (os->slave_pid < 0) { + rc = -errno; + warn_ose(os, rc, "failed to fork slave"); + goto put_os; + } + + if (os->slave_pid == 0) { + /* child */ + char id_str[2][16], fd_str[3][16]; + char mmap_off_str[32], mmap_size_str[32]; + char log_str[16], slave_path_copy[PATH_MAX]; + char *argv[] = { slave_path_copy, "-u", id_str[0], + "-g", id_str[1], "-c", fd_str[0], + "-n", fd_str[1], "-m", fd_str[2], + "-o", mmap_off_str, "-s", mmap_size_str, + "-l", log_str, NULL, NULL }; + struct passwd *pwd; + + /* drop stuff we don't need */ + if (close(cmd_sock[0]) || close(notify_sock[0])) + fatal_e(-errno, "failed to close server pipe fds"); + +#ifdef OSSP_MMAP + if (!mmap_size) + close(fuse_mmap_fd(se)); +#endif + + clearenv(); + pwd = getpwuid(os->uid); + if (pwd) { + setenv("LOGNAME", pwd->pw_name, 1); + setenv("USER", pwd->pw_name, 1); + setenv("HOME", pwd->pw_dir, 1); + } + /* Set extra environment variables from the caller */ + set_extra_env(pid); + + /* prep and exec */ + slave_path_copy[sizeof(slave_path_copy) - 1] = '\0'; + strncpy(slave_path_copy, slave_path, sizeof(slave_path_copy) - 1); + if (slave_path_copy[sizeof(slave_path_copy) - 1] != '\0') { + rc = -errno; + err_ose(os, rc, "slave path too long"); + goto child_fail; + } + + snprintf(id_str[0], sizeof(id_str[0]), "%d", os->uid); + snprintf(id_str[1], sizeof(id_str[0]), "%d", os->gid); + snprintf(fd_str[0], sizeof(fd_str[0]), "%d", cmd_sock[1]); + snprintf(fd_str[1], sizeof(fd_str[1]), "%d", notify_sock[1]); + snprintf(fd_str[2], sizeof(fd_str[2]), "%d", +#ifdef OSSP_MMAP + mmap_size ? fuse_mmap_fd(se) : +#endif + -1); + snprintf(mmap_off_str, sizeof(mmap_off_str), "0x%llx", + (unsigned long long)os->mmap_off); + snprintf(mmap_size_str, sizeof(mmap_size_str), "0x%zx", + mmap_size); + snprintf(log_str, sizeof(log_str), "%d", ossp_log_level); + if (ossp_log_timestamp) + argv[ARRAY_SIZE(argv) - 2] = "-t"; + + execv(slave_path, argv); + rc = -errno; + err_ose(os, rc, "execv failed for <%d>", pid); + child_fail: + _exit(1); + } +//#endif //GIOVANNI + + /* turn on CLOEXEC on all server side fds */ + if (fcntl(os->cmd_fd, F_SETFD, FD_CLOEXEC) < 0 || + fcntl(os->notify_tx, F_SETFD, FD_CLOEXEC) < 0 || + fcntl(os->notify_rx, F_SETFD, FD_CLOEXEC) < 0) { + rc = -errno; + err_ose(os, rc, "failed to set CLOEXEC on server side fds"); + goto put_os; + } + + dbg0_os(os, "CREATE slave=%d %s", os->slave_pid, slave_path); + dbg0_os(os, " client=%d cmd=%d:%d notify=%d:%d mmap=%d:0x%llx:%zu", + pid, cmd_sock[0], cmd_sock[1], notify_sock[0], notify_sock[1], +#ifdef OSSP_MMAP + os->mmap_size ? fuse_mmap_fd(se) : +#endif + -1, + (unsigned long long)os->mmap_off, os->mmap_size); + + *osp = os; + rc = 0; + goto close_client_fds; + +put_os: + put_os(os); +close_client_fds: + close(cmd_sock[1]); + pthread_mutex_unlock(&create_mutex); + return rc; + +close_all: + for (i = 0; i < 2; i++) { + close(cmd_sock[i]); + close(notify_sock[i]); + } + pthread_mutex_unlock(&create_mutex); + return rc; +} + +static void dsp_open_common(fuse_req_t req, struct fuse_file_info *fi, + struct fuse_session *se) +{ + const struct fuse_ctx *fuse_ctx = fuse_req_ctx(req); + struct ossp_dsp_open_arg arg = { }; + struct ossp_stream *os = NULL; + struct ossp_mixer *mixer; + struct ossp_dsp_stream *dsps; + struct ossp_mixer_cmd mxcmd; + pid_t pgrp; + ssize_t ret; + + ret = get_proc_self_info(fuse_ctx->pid, &pgrp, NULL, 0); + if (ret) { + err_e(ret, "get_proc_self_info(%d) failed", fuse_ctx->pid); + goto err; + } + + ret = create_os(dsp_slave_path, sizeof(*dsps), DSPS_MMAP_SIZE, + fuse_ctx->pid, pgrp, fuse_ctx->uid, fuse_ctx->gid, + se, &os); + if (ret) + goto err; + dsps = os_to_dsps(os); + mixer = os->mixer; + + switch (fi->flags & O_ACCMODE) { + case O_WRONLY: + dsps->rw |= 1 << PLAY; + break; + case O_RDONLY: + dsps->rw |= 1 << REC; + break; + case O_RDWR: + dsps->rw |= (1 << PLAY) | (1 << REC); + break; + default: + assert(0); + } + + arg.flags = fi->flags; + arg.opener_pid = os->pid; + ret = exec_simple_cmd(&dsps->os, OSSP_DSP_OPEN, &arg, NULL); + if (ret < 0) { + put_os(os); + goto err; + } + + memcpy(os->vol, mixer->vol, sizeof(os->vol)); + if (os->vol[PLAY][0] >= 0 || os->vol[REC][0] >= 0) { + init_mixer_cmd(&mxcmd, mixer); + memcpy(mxcmd.set.vol, os->vol, sizeof(os->vol)); + exec_mixer_cmd(&mxcmd, os); + finish_mixer_cmd(&mxcmd); + } + + fi->direct_io = 1; + fi->nonseekable = 1; + fi->fh = os->id; + + fuse_reply_open(req, fi); + return; + +err: + fuse_reply_err(req, -ret); +} + +static void dsp_open(fuse_req_t req, struct fuse_file_info *fi) +{ + dsp_open_common(req, fi, dsp_se); +} + +static void adsp_open(fuse_req_t req, struct fuse_file_info *fi) +{ + dsp_open_common(req, fi, adsp_se); +} + +static void dsp_release(fuse_req_t req, struct fuse_file_info *fi) +{ + struct ossp_stream *os; + + os = find_os(fi->fh); + if (os) { + put_os(os); + fuse_reply_err(req, 0); + } else + fuse_reply_err(req, EBADF); +} + +static void dsp_read(fuse_req_t req, size_t size, off_t off, + struct fuse_file_info *fi) +{ + struct ossp_dsp_rw_arg arg = { }; + struct ossp_stream *os; + struct ossp_dsp_stream *dsps; + void *buf = NULL; + ssize_t ret; + + ret = -EBADF; + os = find_os(fi->fh); + if (!os) + goto out; + dsps = os_to_dsps(os); + + ret = -EINVAL; + if (!(dsps->rw & (1 << REC))) + goto out; + + ret = -ENXIO; + if (dsps->mmapped) + goto out; + + ret = -ENOMEM; + buf = malloc(size); + if (!buf) + goto out; + + arg.nonblock = (fi->flags & O_NONBLOCK) || dsps->nonblock; + + ret = exec_cmd(os, OSSP_DSP_READ, &arg, sizeof(arg), + NULL, 0, NULL, 0, buf, &size, -1); +out: + if (ret >= 0) + fuse_reply_buf(req, buf, size); + else + fuse_reply_err(req, -ret); + + free(buf); +} + +static void dsp_write(fuse_req_t req, const char *buf, size_t size, off_t off, + struct fuse_file_info *fi) +{ + struct ossp_dsp_rw_arg arg = { }; + struct ossp_stream *os; + struct ossp_dsp_stream *dsps; + ssize_t ret; + + ret = -EBADF; + os = find_os(fi->fh); + if (!os) + goto out; + dsps = os_to_dsps(os); + + ret = -EINVAL; + if (!(dsps->rw & (1 << PLAY))) + goto out; + + ret = -ENXIO; + if (dsps->mmapped) + goto out; + + arg.nonblock = (fi->flags & O_NONBLOCK) || dsps->nonblock; + + ret = exec_cmd(os, OSSP_DSP_WRITE, &arg, sizeof(arg), + buf, size, NULL, 0, NULL, NULL, -1); +out: + if (ret >= 0) + fuse_reply_write(req, ret); + else + fuse_reply_err(req, -ret); +} + +static void dsp_poll(fuse_req_t req, struct fuse_file_info *fi, + struct fuse_pollhandle *ph) +{ + int notify = ph != NULL; + unsigned revents = 0; + struct ossp_stream *os; + ssize_t ret; + + ret = -EBADF; + os = find_os(fi->fh); + if (!os) + goto out; + + if (ph) { + pthread_mutex_lock(&mutex); + if (os->ph) + fuse_pollhandle_destroy(os->ph); + os->ph = ph; + pthread_mutex_unlock(&mutex); + } + + ret = exec_simple_cmd(os, OSSP_DSP_POLL, ¬ify, &revents); +out: + if (ret >= 0) + fuse_reply_poll(req, revents); + else + fuse_reply_err(req, -ret); +} + +static void dsp_ioctl(fuse_req_t req, int signed_cmd, void *uarg, + struct fuse_file_info *fi, unsigned int flags, + const void *in_buf, size_t in_bufsz, size_t out_bufsz) +{ + /* some ioctl constants are long and has the highest bit set */ + unsigned cmd = signed_cmd; + struct ossp_stream *os; + struct ossp_dsp_stream *dsps; + enum ossp_opcode op; + ssize_t ret; + int i; + + ret = -EBADF; + os = find_os(fi->fh); + if (!os) + goto err; + dsps = os_to_dsps(os); + + /* mixer commands are allowed on DSP devices */ + if (((cmd >> 8) & 0xff) == 'M') { + mixer_do_ioctl(req, os->mixer, cmd, uarg, in_buf, in_bufsz, + out_bufsz); + return; + } + + /* and the rest */ + switch (cmd) { + case OSS_GETVERSION: + i = SNDRV_OSS_VERSION; + PREP_UARG(NULL, &i); + IOCTL_RETURN(0, &i); + + case SNDCTL_DSP_GETCAPS: + i = DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER | +#ifdef OSSP_MMAP + DSP_CAP_MMAP | +#endif + DSP_CAP_MULTI; + PREP_UARG(NULL, &i); + IOCTL_RETURN(0, &i); + + case SNDCTL_DSP_NONBLOCK: + dsps->nonblock = 1; + ret = 0; + IOCTL_RETURN(0, NULL); + + case SNDCTL_DSP_RESET: op = OSSP_DSP_RESET; goto nd; + case SNDCTL_DSP_SYNC: op = OSSP_DSP_SYNC; goto nd; + case SNDCTL_DSP_POST: op = OSSP_DSP_POST; goto nd; + nd: + ret = exec_simple_cmd(&dsps->os, op, NULL, NULL); + if (ret) + goto err; + IOCTL_RETURN(0, NULL); + + case SOUND_PCM_READ_RATE: op = OSSP_DSP_GET_RATE; goto ri; + case SOUND_PCM_READ_BITS: op = OSSP_DSP_GET_FORMAT; goto ri; + case SOUND_PCM_READ_CHANNELS: op = OSSP_DSP_GET_CHANNELS; goto ri; + case SNDCTL_DSP_GETBLKSIZE: op = OSSP_DSP_GET_BLKSIZE; goto ri; + case SNDCTL_DSP_GETFMTS: op = OSSP_DSP_GET_FORMATS; goto ri; + case SNDCTL_DSP_GETTRIGGER: op = OSSP_DSP_GET_TRIGGER; goto ri; + ri: + PREP_UARG(NULL, &i); + ret = exec_simple_cmd(&dsps->os, op, NULL, &i); + if (ret) + goto err; + IOCTL_RETURN(0, &i); + + case SNDCTL_DSP_SPEED: op = OSSP_DSP_SET_RATE; goto wi; + case SNDCTL_DSP_SETFMT: op = OSSP_DSP_SET_FORMAT; goto wi; + case SNDCTL_DSP_CHANNELS: op = OSSP_DSP_SET_CHANNELS; goto wi; + case SNDCTL_DSP_SUBDIVIDE: op = OSSP_DSP_SET_SUBDIVISION; goto wi; + wi: + PREP_UARG(&i, &i); + ret = exec_simple_cmd(&dsps->os, op, &i, &i); + if (ret) + goto err; + IOCTL_RETURN(0, &i); + + case SNDCTL_DSP_STEREO: + PREP_UARG(NULL, &i); + i = 2; + ret = exec_simple_cmd(&dsps->os, OSSP_DSP_SET_CHANNELS, &i, &i); + i--; + if (ret) + goto err; + IOCTL_RETURN(0, &i); + + case SNDCTL_DSP_SETFRAGMENT: + PREP_UARG(&i, NULL); + ret = exec_simple_cmd(&dsps->os, + OSSP_DSP_SET_FRAGMENT, &i, NULL); + if (ret) + goto err; + IOCTL_RETURN(0, NULL); + + case SNDCTL_DSP_SETTRIGGER: + PREP_UARG(&i, NULL); + ret = exec_simple_cmd(&dsps->os, + OSSP_DSP_SET_TRIGGER, &i, NULL); + if (ret) + goto err; + IOCTL_RETURN(0, NULL); + + case SNDCTL_DSP_GETOSPACE: + case SNDCTL_DSP_GETISPACE: { + struct audio_buf_info info; + + ret = -EINVAL; + if (cmd == SNDCTL_DSP_GETOSPACE) { + if (!(dsps->rw & (1 << PLAY))) + goto err; + op = OSSP_DSP_GET_OSPACE; + } else { + if (!(dsps->rw & (1 << REC))) + goto err; + op = OSSP_DSP_GET_ISPACE; + } + + PREP_UARG(NULL, &info); + ret = exec_simple_cmd(&dsps->os, op, NULL, &info); + if (ret) + goto err; + IOCTL_RETURN(0, &info); + } + + case SNDCTL_DSP_GETOPTR: + case SNDCTL_DSP_GETIPTR: { + struct count_info info; + + op = cmd == SNDCTL_DSP_GETOPTR ? OSSP_DSP_GET_OPTR + : OSSP_DSP_GET_IPTR; + PREP_UARG(NULL, &info); + ret = exec_simple_cmd(&dsps->os, op, NULL, &info); + if (ret) + goto err; + IOCTL_RETURN(0, &info); + } + + case SNDCTL_DSP_GETODELAY: + PREP_UARG(NULL, &i); + i = 0; + ret = exec_simple_cmd(&dsps->os, OSSP_DSP_GET_ODELAY, NULL, &i); + IOCTL_RETURN(ret, &i); /* always copy out result, 0 on err */ + + case SOUND_PCM_WRITE_FILTER: + case SOUND_PCM_READ_FILTER: + ret = -EIO; + goto err; + + case SNDCTL_DSP_MAPINBUF: + case SNDCTL_DSP_MAPOUTBUF: + ret = -EINVAL; + goto err; + + case SNDCTL_DSP_SETSYNCRO: + case SNDCTL_DSP_SETDUPLEX: + case SNDCTL_DSP_PROFILE: + IOCTL_RETURN(0, NULL); + + default: + warn_os(os, "unknown ioctl 0x%x", cmd); + ret = -EINVAL; + goto err; + } + assert(0); /* control shouldn't reach here */ +err: + fuse_reply_err(req, -ret); +} + +#ifdef OSSP_MMAP +static int dsp_mmap_dir(int prot) +{ + if (!(prot & PROT_WRITE)) + return REC; + return PLAY; +} + +static void dsp_mmap(fuse_req_t req, void *addr, size_t len, int prot, + int flags, off_t offset, struct fuse_file_info *fi, + uint64_t mh) +{ + int dir = dsp_mmap_dir(prot); + struct ossp_dsp_mmap_arg arg = { }; + struct ossp_stream *os; + struct ossp_dsp_stream *dsps; + ssize_t ret; + + os = find_os(fi->fh); + if (!os) { + fuse_reply_err(req, EBADF); + return; + } + dsps = os_to_dsps(os); + + if (!os->mmap_off || len > os->mmap_size / 2) { + fuse_reply_err(req, EINVAL); + return; + } + + pthread_mutex_lock(&os->mmap_mutex); + + ret = -EBUSY; + if (dsps->mmapped & (1 << dir)) + goto out_unlock; + + arg.dir = dir; + arg.size = len; + + ret = exec_simple_cmd(os, OSSP_DSP_MMAP, &arg, NULL); + if (ret == 0) + dsps->mmapped |= 1 << dir; + +out_unlock: + pthread_mutex_unlock(&os->mmap_mutex); + + if (ret == 0) + fuse_reply_mmap(req, os->mmap_off + dir * os->mmap_size / 2, 0); + else + fuse_reply_err(req, -ret); +} + +static void dsp_munmap(fuse_req_t req, size_t len, struct fuse_file_info *fi, + off_t offset, uint64_t mh) +{ + struct ossp_stream *os; + struct ossp_dsp_stream *dsps; + int dir, rc; + + os = find_os(fi->fh); + if (!os) + goto out; + dsps = os_to_dsps(os); + + pthread_mutex_lock(&os->mmap_mutex); + + for (dir = 0; dir < 2; dir++) + if (offset == os->mmap_off + dir * os->mmap_size / 2) + break; + if (dir == 2 || len > os->mmap_size / 2) { + warn_os(os, "invalid munmap request " + "offset=%llu len=%zu mmapped=0x%x", + (unsigned long long)offset, len, dsps->mmapped); + goto out_unlock; + } + + rc = exec_simple_cmd(os, OSSP_DSP_MUNMAP, &dir, NULL); + if (rc) + warn_ose(os, rc, "MUNMAP failed for dir=%d", dir); + + dsps->mmapped &= ~(1 << dir); + +out_unlock: + pthread_mutex_unlock(&os->mmap_mutex); +out: + fuse_reply_none(req); +} +#endif + + +/*************************************************************************** + * Notify poller + */ + +static void *notify_poller(void *arg) +{ + struct epoll_event events[1024]; + int i, nfds; + +repeat: + nfds = epoll_wait(notify_epfd, events, ARRAY_SIZE(events), -1); + for (i = 0; i < nfds; i++) { + int do_notify = 0; + struct ossp_stream *os; + struct ossp_notify notify; + ssize_t ret; + + os = find_os_by_notify_rx(events[i].data.fd); + if (!os) { + err("can't find stream for notify_rx fd %d", + events[i].data.fd); + epoll_ctl(notify_epfd, EPOLL_CTL_DEL, events[i].data.fd, + NULL); + /* we don't know what's going on, don't close the fd */ + continue; + } + + while ((ret = read(os->notify_rx, + ¬ify, sizeof(notify))) > 0) { + if (os->dead) + continue; + if (ret != sizeof(notify)) { + warn_os(os, "short read on notify_rx (%zu, " + "expected %zu), killing the stream", + ret, sizeof(notify)); + os->dead = 1; + break; + } + if (notify.magic != OSSP_NOTIFY_MAGIC) { + warn_os(os, "invalid magic on notification, " + "killing the stream"); + os->dead = 1; + break; + } + + if (notify.opcode >= OSSP_NR_NOTIFY_OPCODES) + goto unknown; + + dbg1_os(os, "NOTIFY %s", ossp_notify_str[notify.opcode]); + + switch (notify.opcode) { + case OSSP_NOTIFY_POLL: + do_notify = 1; + break; + case OSSP_NOTIFY_OBITUARY: + os->dead = 1; + break; + case OSSP_NOTIFY_VOLCHG: + pthread_mutex_lock(&mixer_mutex); + os->mixer->modify_counter++; + pthread_mutex_unlock(&mixer_mutex); + break; + default: + unknown: + warn_os(os, "unknown notification %d", + notify.opcode); + } + } + if (ret == 0) + os->dead = 1; + else if (ret < 0 && errno != EAGAIN) { + warn_ose(os, -errno, "read fail on notify fd"); + os->dead = 1; + } + + if (!do_notify && !os->dead) + continue; + + pthread_mutex_lock(&mutex); + + if (os->ph) { + fuse_lowlevel_notify_poll(os->ph); + fuse_pollhandle_destroy(os->ph); + os->ph = NULL; + } + + if (os->dead) { + dbg0_os(os, "removing %d from notify poll list", + os->notify_rx); + epoll_ctl(notify_epfd, EPOLL_CTL_DEL, os->notify_rx, + NULL); + close(os->notify_rx); + os->notify_rx = -1; + pthread_cond_broadcast(¬ify_poller_kill_wait); + } + + pthread_mutex_unlock(&mutex); + } + goto repeat; +} + + +/*************************************************************************** + * Slave corpse reaper + */ + +static void *slave_reaper(void *arg) +{ + struct ossp_stream *os; + int status; + pid_t pid; + + pthread_mutex_lock(&mutex); +repeat: + while (list_empty(&slave_corpse_list)) + pthread_cond_wait(&slave_reaper_wait, &mutex); + + os = list_first_entry(&slave_corpse_list, struct ossp_stream, link); + list_del_init(&os->link); + + pthread_mutex_unlock(&mutex); + + do { + pid = waitpid(os->slave_pid, &status, 0); + } while (pid < 0 && errno == EINTR); + + if (pid < 0) { + if (errno == ECHILD) + warn_ose(os, -errno, "slave %d already gone?", + os->slave_pid); + else + fatal_e(-errno, "waitpid(%d) failed", os->slave_pid); + } + + pthread_mutex_lock(&mutex); + + dbg1_os(os, "slave %d reaped", os->slave_pid); + __clear_bit(os->id, os_id_bitmap); + free(os); + + goto repeat; +} + + +/*************************************************************************** + * Stuff to bind and start everything + */ + +static void ossp_daemonize(void) +{ + int fd, pfd[2]; + pid_t pid; + ssize_t ret; + int err; + + fd = open("/dev/null", O_RDWR); + if (fd >= 0) { + dup2(fd, 0); + dup2(fd, 1); + dup2(fd, 2); + if (fd > 2) + close(fd); + } + + if (pipe(pfd)) + fatal_e(-errno, "failed to create pipe for init wait"); + + if (fcntl(pfd[0], F_SETFD, FD_CLOEXEC) < 0 || + fcntl(pfd[1], F_SETFD, FD_CLOEXEC) < 0) + fatal_e(-errno, "failed to set CLOEXEC on init wait pipe"); + + pid = fork(); + if (pid < 0) + fatal_e(-errno, "failed to fork for daemon"); + + if (pid == 0) { + close(pfd[0]); + init_wait_fd = pfd[1]; + + /* be evil, my child */ + chdir("/"); + setsid(); + return; + } + + /* wait for init completion and pass over success indication */ + close(pfd[1]); + + do { + ret = read(pfd[0], &err, sizeof(err)); + } while (ret < 0 && errno == EINTR); + + if (ret == sizeof(err) && err == 0) + exit(0); + + fatal("daemon init failed ret=%zd err=%d", ret, err); + exit(1); +} + +static void ossp_init_done(void *userdata) +{ + /* init complete, notify parent if it's waiting */ + if (init_wait_fd >= 0) { + ssize_t ret; + int err = 0; + + ret = write(init_wait_fd, &err, sizeof(err)); + if (ret != sizeof(err)) + fatal_e(-errno, "failed to notify init completion, " + "ret=%zd", ret); + close(init_wait_fd); + init_wait_fd = -1; + } +} + +static const struct cuse_lowlevel_ops mixer_ops = { + .open = mixer_open, + .release = mixer_release, + .ioctl = mixer_ioctl, +}; + +static const struct cuse_lowlevel_ops dsp_ops = { + .init_done = ossp_init_done, + .open = dsp_open, + .release = dsp_release, + .read = dsp_read, + .write = dsp_write, + .poll = dsp_poll, + .ioctl = dsp_ioctl, +#ifdef OSSP_MMAP + .mmap = dsp_mmap, + .munmap = dsp_munmap, +#endif +}; + +static const struct cuse_lowlevel_ops adsp_ops = { + .open = adsp_open, + .release = dsp_release, + .read = dsp_read, + .write = dsp_write, + .poll = dsp_poll, + .ioctl = dsp_ioctl, +#ifdef OSSP_MMAP + .mmap = dsp_mmap, + .munmap = dsp_munmap, +#endif +}; + +static const char *usage = +"usage: osspd [options]\n" +"\n" +"options:\n" +" --help print this help message\n" +" --dsp=NAME DSP device name (default dsp)\n" +" --dsp-maj=MAJ DSP device major number (default 14)\n" +" --dsp-min=MIN DSP device minor number (default 3)\n" +" --adsp=NAME Aux DSP device name (default adsp, blank to disable)\n" +" --adsp-maj=MAJ Aux DSP device major number (default 14)\n" +" --adsp-min=MIN Aux DSP device minor number (default 12)\n" +" --mixer=NAME mixer device name (default mixer, blank to disable)\n" +" --mixer-maj=MAJ mixer device major number (default 14)\n" +" --mixer-min=MIN mixer device minor number (default 0)\n" +" --max=MAX maximum number of open streams (default 256)\n" +" --umax=MAX maximum number of open streams per UID (default --max)\n" +" --exit-on-idle exit if idle\n" +" --dsp-slave=PATH DSP slave (default ossp-padsp in the same dir)\n" +" --log=LEVEL log level (0..6)\n" +" --timestamp timestamp log messages\n" +" -v increase verbosity, can be specified multiple times\n" +" -f Run in foreground (don't daemonize)\n" +"\n"; + +struct ossp_param { + char *dsp_name; + unsigned dsp_major; + unsigned dsp_minor; + char *adsp_name; + unsigned adsp_major; + unsigned adsp_minor; + char *mixer_name; + unsigned mixer_major; + unsigned mixer_minor; + unsigned max_streams; + unsigned umax_streams; + char *dsp_slave_path; + unsigned log_level; + int exit_on_idle; + int timestamp; + int fg; + int help; +}; + +#define OSSP_OPT(t, p) { t, offsetof(struct ossp_param, p), 1 } + +static const struct fuse_opt ossp_opts[] = { + OSSP_OPT("--dsp=%s", dsp_name), + OSSP_OPT("--dsp-maj=%u", dsp_major), + OSSP_OPT("--dsp-min=%u", dsp_minor), + OSSP_OPT("--adsp=%s", adsp_name), + OSSP_OPT("--adsp-maj=%u", adsp_major), + OSSP_OPT("--adsp-min=%u", adsp_minor), + OSSP_OPT("--mixer=%s", mixer_name), + OSSP_OPT("--mixer-maj=%u", mixer_major), + OSSP_OPT("--mixer-min=%u", mixer_minor), + OSSP_OPT("--max=%u", max_streams), + OSSP_OPT("--umax=%u", umax_streams), + OSSP_OPT("--exit-on-idle", exit_on_idle), + OSSP_OPT("--dsp-slave=%s", dsp_slave_path), + OSSP_OPT("--timestamp", timestamp), + OSSP_OPT("--log=%u", log_level), + OSSP_OPT("-f", fg), + FUSE_OPT_KEY("-h", 0), + FUSE_OPT_KEY("--help", 0), + FUSE_OPT_KEY("-v", 1), + FUSE_OPT_END +}; + +static struct fuse_session *setup_ossp_cuse(const struct cuse_lowlevel_ops *ops, + const char *name, int major, + int minor, int argc, char **argv) +{ + char name_buf[128]; + const char *bufp = name_buf; + struct cuse_info ci = { .dev_major = major, .dev_minor = minor, + .dev_info_argc = 1, .dev_info_argv = &bufp, + .flags = CUSE_UNRESTRICTED_IOCTL }; + struct fuse_session *se; + int fd; + + snprintf(name_buf, sizeof(name_buf), "DEVNAME=%s", name); + + se = cuse_lowlevel_setup(argc, argv, &ci, ops, NULL, NULL); + if (!se) { + err("failed to setup %s CUSE", name); + return NULL; + } + + fd = fuse_chan_fd(fuse_session_next_chan(se, NULL)); + if ( +#ifdef OSSP_MMAP + fd != fuse_mmap_fd(se) && +#endif + fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) { + err_e(-errno, "failed to set CLOEXEC on %s CUSE fd", name); + cuse_lowlevel_teardown(se); + return NULL; + } + + return se; +} + +static void *cuse_worker(void *arg) +{ + struct fuse_session *se = arg; + int rc; + + rc = fuse_session_loop_mt(se); + cuse_lowlevel_teardown(se); + + return (void *)(unsigned long)rc; +} + +static int process_arg(void *data, const char *arg, int key, + struct fuse_args *outargs) +{ + struct ossp_param *param = data; + + switch (key) { + case 0: + fprintf(stderr, usage); + param->help = 1; + return 0; + case 1: + param->log_level++; + return 0; + } + return 1; +} + +int main(int argc, char **argv) +{ + static struct ossp_param param = { + .dsp_name = DFL_DSP_NAME, + .dsp_major = DFL_DSP_MAJOR, .dsp_minor = DFL_DSP_MINOR, + .adsp_name = DFL_ADSP_NAME, + .adsp_major = DFL_ADSP_MAJOR, .adsp_minor = DFL_ADSP_MINOR, + .mixer_name = DFL_MIXER_NAME, + .mixer_major = DFL_MIXER_MAJOR, .mixer_minor = DFL_MIXER_MINOR, + .max_streams = DFL_MAX_STREAMS, + }; + struct fuse_args args = FUSE_ARGS_INIT(argc, argv); + char path_buf[PATH_MAX], *dir; + char adsp_buf[64] = "", mixer_buf[64] = ""; + struct sigaction sa; + struct stat stat_buf; + ssize_t ret; + unsigned u; + + snprintf(ossp_log_name, sizeof(ossp_log_name), "osspd"); + param.log_level = ossp_log_level; + + if (fuse_opt_parse(&args, ¶m, ossp_opts, process_arg)) + fatal("failed to parse arguments"); + + if (param.help) + return 0; + + max_streams = param.max_streams; + hashtbl_size = max_streams / 2 + 13; + + umax_streams = max_streams; + if (param.umax_streams) + umax_streams = param.umax_streams; + if (param.log_level > OSSP_LOG_MAX) + param.log_level = OSSP_LOG_MAX; + if (!param.fg) + param.log_level = -param.log_level; + ossp_log_level = param.log_level; + ossp_log_timestamp = param.timestamp; + + if (!param.fg) + ossp_daemonize(); + + /* daemonization already handled, prevent forking inside FUSE */ + fuse_opt_add_arg(&args, "-f"); + + info("OSS Proxy v%s (C) 2008-2010 by Tejun Heo ", + OSSP_VERSION); + + /* ignore stupid SIGPIPEs */ + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = SIG_IGN; + if (sigaction(SIGPIPE, &sa, NULL)) + fatal_e(-errno, "failed to ignore SIGPIPE"); + +//#ifdef GIOVANNI + /* determine slave path and check for availability */ + ret = readlink("/proc/self/exe", path_buf, PATH_MAX - 1); + if (ret < 0) + fatal_e(-errno, "failed to determine executable path"); + path_buf[ret] = '\0'; + dir = dirname(path_buf); + + if (param.dsp_slave_path) { + strncpy(dsp_slave_path, param.dsp_slave_path, PATH_MAX - 1); + dsp_slave_path[PATH_MAX - 1] = '\0'; + } else { + ret = snprintf(dsp_slave_path, PATH_MAX, "%s/%s", + dir, "ossp-padsp"); + if (ret >= PATH_MAX) + fatal("dsp slave pathname too long"); + } + + if (stat(dsp_slave_path, &stat_buf)) + fatal_e(-errno, "failed to stat %s", dsp_slave_path); + if (!S_ISREG(stat_buf.st_mode) || !(stat_buf.st_mode & 0444)) + fatal("%s is not executable", dsp_slave_path); + +//#endif// GIOVANNI + /* allocate tables */ + os_id_bitmap = calloc(BITS_TO_LONGS(max_streams), sizeof(long)); + mixer_tbl = calloc(hashtbl_size, sizeof(mixer_tbl[0])); + os_tbl = calloc(hashtbl_size, sizeof(os_tbl[0])); + os_pgrp_tbl = calloc(hashtbl_size, sizeof(os_pgrp_tbl[0])); + os_notify_tbl = calloc(hashtbl_size, sizeof(os_notify_tbl[0])); + if (!os_id_bitmap || !mixer_tbl || !os_tbl || !os_pgrp_tbl || + !os_notify_tbl) + fatal("failed to allocate stream hash tables"); + for (u = 0; u < hashtbl_size; u++) { + INIT_LIST_HEAD(&mixer_tbl[u]); + INIT_LIST_HEAD(&os_tbl[u]); + INIT_LIST_HEAD(&os_pgrp_tbl[u]); + INIT_LIST_HEAD(&os_notify_tbl[u]); + } + __set_bit(0, os_id_bitmap); /* don't use id 0 */ + + /* create mixer delayed reference worker */ + ret = -pthread_create(&mixer_delayed_put_thread, NULL, + mixer_delayed_put_worker, NULL); + if (ret) + fatal_e(ret, "failed to create mixer delayed put worker"); + + /* if exit_on_idle, touch mixer for pgrp0 */ + exit_on_idle = param.exit_on_idle; + if (exit_on_idle) { + struct ossp_mixer *mixer; + + mixer = get_mixer(0); + if (!mixer) + fatal("failed to touch idle mixer"); + put_mixer(mixer); + } + + /* create notify epoll and kick off watcher thread */ + notify_epfd = epoll_create(max_streams); + if (notify_epfd < 0) + fatal_e(-errno, "failed to create notify epoll"); + if (fcntl(notify_epfd, F_SETFD, FD_CLOEXEC) < 0) + fatal_e(-errno, "failed to set CLOEXEC on notify epfd"); + + ret = -pthread_create(¬ify_poller_thread, NULL, notify_poller, NULL); + if (ret) + fatal_e(ret, "failed to create notify poller thread"); + + /* create reaper for slave corpses */ + ret = -pthread_create(&slave_reaper_thread, NULL, slave_reaper, NULL); + if (ret) + fatal_e(ret, "failed to create slave reaper thread"); + +#ifdef GIOVANNI + /* we're set, let's setup fuse structures */ + if (strlen(param.mixer_name)) + mixer_se = setup_ossp_cuse(&mixer_ops, param.mixer_name, + param.mixer_major, param.mixer_minor, + args.argc, args.argv); + if (strlen(param.adsp_name)) + adsp_se = setup_ossp_cuse(&dsp_ops, param.adsp_name, + param.adsp_major, param.adsp_minor, + args.argc, args.argv); + +#endif// GIOVANNI + dsp_se = setup_ossp_cuse(&dsp_ops, param.dsp_name, + param.dsp_major, param.dsp_minor, + args.argc, args.argv); + if (!dsp_se) + fatal("can't create dsp, giving up"); + +#ifdef GIOVANNI + if (mixer_se) + snprintf(mixer_buf, sizeof(mixer_buf), ", %s (%d:%d)", + param.mixer_name, param.mixer_major, param.mixer_minor); + if (adsp_se) + snprintf(adsp_buf, sizeof(adsp_buf), ", %s (%d:%d)", + param.adsp_name, param.adsp_major, param.adsp_minor); + +#endif// GIOVANNI + info("Creating %s (%d:%d)%s%s", param.dsp_name, param.dsp_major, + param.dsp_minor, adsp_buf, mixer_buf); + +#ifdef GIOVANNI + /* start threads for mixer and adsp */ + if (mixer_se) { + ret = -pthread_create(&cuse_mixer_thread, NULL, + cuse_worker, mixer_se); + if (ret) + err_e(ret, "failed to create mixer worker"); + } + if (adsp_se) { + ret = -pthread_create(&cuse_adsp_thread, NULL, + cuse_worker, adsp_se); + if (ret) + err_e(ret, "failed to create adsp worker"); + } +#endif// GIOVANNI + + /* run CUSE for /dev/dsp in the main thread */ + ret = (ssize_t)cuse_worker(dsp_se); + if (ret < 0) + fatal("dsp worker failed"); + return 0; +} From 86657a6c0aefb1cb52f47c77aae38415bc584dfe Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Fri, 26 Nov 2010 10:42:37 -0500 Subject: [PATCH 104/237] freetdm: ftmod_r2 - process all state changes before moving to openr2 events or going back to sleep --- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index 06d1abdc04..84ddea586c 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -152,6 +152,7 @@ static ftdm_hash_t *g_mod_data_hash; static ftdm_io_interface_t g_ftdm_r2_interface; static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan); +static int ftdm_r2_state_advance_all(ftdm_channel_t *ftdmchan); /* functions not available on windows */ @@ -529,7 +530,7 @@ static void ftdm_r2_on_call_end(openr2_chan_t *r2chan) ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); /* in some circumstances openr2 can call on_call_init right after this, so let's advance the state right here */ - ftdm_r2_state_advance(ftdmchan); + ftdm_r2_state_advance_all(ftdmchan); } static void ftdm_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen) @@ -1347,6 +1348,20 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan) return ret; } +/* the channel must be locked when calling this function */ +static void ftdm_r2_state_advance_all(ftdm_channel_t *ftdmchan) +{ + /* because we do not always acknowledge the state change (clearing the FTDM_CHANNEL_STATE_CHANGE flag) due to the accept + * procedure described below, we need the chanstate member to NOT process some states twice, so is valid entering this + * function with the FTDM_CHANNEL_STATE_CHANGE flag set but with a state that was already processed and is just waiting + * to complete (the processing is media-bound) + * */ + while (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE) + && (R2CALL(ftdmchan)->chanstate != ftdmchan->state)) { + ftdm_r2_state_advance(ftdmchan); + } +} + static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) { openr2_chan_t *r2chan; @@ -1431,9 +1446,9 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) r2call = R2CALL(ftdmchan); ftdm_mutex_lock(ftdmchan->mutex); - ftdm_r2_state_advance(ftdmchan); + ftdm_r2_state_advance_all(ftdmchan); openr2_chan_process_signaling(r2chan); - ftdm_r2_state_advance(ftdmchan); + ftdm_r2_state_advance_all(ftdmchan); ftdm_mutex_unlock(ftdmchan->mutex); } ftdm_span_trigger_signals(span); From ef8682507650792e6a3c38b9a5612526ab0b1ecb Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Fri, 26 Nov 2010 13:49:34 -0200 Subject: [PATCH 105/237] freetdm: ftmod_r2 - fixed ftdm_r2_state_advance_all() definition --- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index 84ddea586c..8514569509 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -152,7 +152,7 @@ static ftdm_hash_t *g_mod_data_hash; static ftdm_io_interface_t g_ftdm_r2_interface; static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan); -static int ftdm_r2_state_advance_all(ftdm_channel_t *ftdmchan); +static void ftdm_r2_state_advance_all(ftdm_channel_t *ftdmchan); /* functions not available on windows */ From 80031c3e17d78c50d533644bd4bbbbbc181d6252 Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Fri, 26 Nov 2010 14:51:09 -0200 Subject: [PATCH 106/237] freetdm: ftmod_r2 - added percentage to loop timing stats --- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index 8514569509..513adfd975 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -1642,6 +1642,7 @@ static FIO_API_FUNCTION(ftdm_r2_api) if (!strcasecmp(argv[0], "loopstats")) { int range; + float pct; span_id = atoi(argv[1]); if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS || ftdm_span_find(span_id, &span) == FTDM_SUCCESS) { @@ -1655,10 +1656,11 @@ static FIO_API_FUNCTION(ftdm_r2_api) } range = 0; for (i = 0; i < ftdm_array_len(r2data->loops); i++) { + pct = 100*r2data->loops[i]/r2data->total_loops; if ((i + 1) == ftdm_array_len(r2data->loops)) { - stream->write_function(stream, ">= %dms: %llu\n", range, r2data->loops[i]); + stream->write_function(stream, ">= %dms: %llu - %.03lf%%\n", range, r2data->loops[i], pct); } else { - stream->write_function(stream, "%d-%dms: %llu\n", range, range + 9, r2data->loops[i]); + stream->write_function(stream, "%d-%dms: %llu - %.03lf%%\n", range, range + 9, r2data->loops[i], pct); } range += 10; } From 2b126a1510abae4364341d29d49cb31711f2119b Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Fri, 26 Nov 2010 15:03:31 -0200 Subject: [PATCH 107/237] freetdm: ftmod_r2 - cast added --- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index 513adfd975..c8d669ca5c 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -1656,7 +1656,7 @@ static FIO_API_FUNCTION(ftdm_r2_api) } range = 0; for (i = 0; i < ftdm_array_len(r2data->loops); i++) { - pct = 100*r2data->loops[i]/r2data->total_loops; + pct = 100*(float)r2data->loops[i]/r2data->total_loops; if ((i + 1) == ftdm_array_len(r2data->loops)) { stream->write_function(stream, ">= %dms: %llu - %.03lf%%\n", range, r2data->loops[i], pct); } else { From 894dea2803a66ad933899b4377a9154ee3f16394 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Fri, 26 Nov 2010 12:39:30 -0500 Subject: [PATCH 108/237] freetdm: ftmod_wanpipe - flush stats when opening a channel --- libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c index c55d42e8b0..98da73ec92 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c @@ -516,6 +516,7 @@ static FIO_OPEN_FUNCTION(wanpipe_open) memset(&tdm_api,0,sizeof(tdm_api)); sangoma_tdm_flush_bufs(ftdmchan->sockfd, &tdm_api); + sangoma_flush_stats(ftdmchan->sockfd, &tdm_api); if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921 || ftdmchan->type == FTDM_CHAN_TYPE_DQ931) { ftdmchan->native_codec = ftdmchan->effective_codec = FTDM_CODEC_NONE; From 546a2961cb5fa1cf056b682c1a4553381d9ec75a Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Fri, 26 Nov 2010 12:59:36 -0500 Subject: [PATCH 109/237] Added channel-restart-on-link-up option --- .../src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h | 1 + .../ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c | 10 ++++++++++ .../ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c | 11 ++++++++++- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h index 2a65a82985..36b5662faf 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h @@ -183,6 +183,7 @@ typedef struct sngisdn_span_data { int8_t facility_timeout; uint8_t num_local_numbers; uint8_t timer_t3; + uint8_t restart_opt; char* local_numbers[SNGISDN_NUM_LOCAL_NUMBERS]; ftdm_sched_t *sched; ftdm_queue_t *event_queue; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c index 18ca9c38dd..a869bda48d 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c @@ -182,6 +182,7 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_ signal_data->overlap_dial = SNGISDN_OPT_DEFAULT; signal_data->setup_arb = SNGISDN_OPT_DEFAULT; signal_data->timer_t3 = 8; + signal_data->restart_opt = SNGISDN_OPT_DEFAULT; signal_data->link_id = span->span_id; span->default_caller_data.bearer_capability = IN_ITC_SPEECH; @@ -271,6 +272,15 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_ ftdm_span_set_bearer_capability(val, &span->default_caller_data.bearer_capability); } else if (!strcasecmp(var, "outbound-bearer_layer1")) { ftdm_span_set_bearer_layer1(val, &span->default_caller_data.bearer_layer1); + } else if (!strcasecmp(var, "channel-restart-on-link-up")) { + if (!strcasecmp(val, "yes")) { + signal_data->restart_opt = SNGISDN_OPT_TRUE; + } else if (!strcasecmp(val, "no")) { + signal_data->restart_opt = SNGISDN_OPT_FALSE; + } else { + ftdm_log(FTDM_LOG_ERROR, "Invalid value for parameter:%s:%s\n", var, val); + } + } else if (!strcasecmp(var, "local-number")) { if (add_local_number(val, span) != FTDM_SUCCESS) { return FTDM_FAIL; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c index bb46fb7fba..94683d8a4b 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c @@ -701,7 +701,16 @@ ftdm_status_t sng_isdn_stack_cfg_q931_dlsap(ftdm_span_t *span) cfg.t.cfg.s.inDLSAP.statEnqOpt = FALSE; cfg.t.cfg.s.inDLSAP.rstOpt = FALSE; } - + + /* Override the restart options if user selected that option */ + if (signal_data->restart_opt != SNGISDN_OPT_DEFAULT) { + if (signal_data->restart_opt == SNGISDN_OPT_TRUE) { + cfg.t.cfg.s.inDLSAP.rstOpt = TRUE; + } else { + cfg.t.cfg.s.inDLSAP.rstOpt = FALSE; + } + } + for (i = 0; i < IN_MAXBCHNL; i++) { cfg.t.cfg.s.inDLSAP.bProf[i].profNmb = 0; From 17fc3bd62b640196825f3002732affaa9b22da85 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Fri, 26 Nov 2010 14:03:16 -0500 Subject: [PATCH 110/237] freetdm: ftmod_wanpipe, ftmod_sangoma_isdn and and core - Updated stats code --- .../ftmod_sangoma_isdn_stack_out.c | 14 +-- .../src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c | 86 ++++++++++++------- libs/freetdm/src/include/private/ftdm_core.h | 38 ++++---- 3 files changed, 81 insertions(+), 57 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c index 2853335efc..b58bef23e5 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c @@ -600,32 +600,32 @@ void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len) memcpy(&l1_frame.data, data, len); - if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_CRC)) { + if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_CRC)) { l1_frame.flags |= SNG_L1FRAME_ERROR_CRC; } - if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_FRAME)) { + if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_FRAME)) { l1_frame.flags |= SNG_L1FRAME_ERROR_FRAME; } - if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_ABORT)) { + if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_ABORT)) { l1_frame.flags |= SNG_L1FRAME_ERROR_ABORT; } - if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_FIFO)) { + if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_FIFO)) { l1_frame.flags |= SNG_L1FRAME_ERROR_FIFO; } - if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_DMA)) { + if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_DMA)) { l1_frame.flags |= SNG_L1FRAME_ERROR_DMA; } - if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES)) { + if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES)) { /* Should we trigger congestion here? */ l1_frame.flags |= SNG_L1FRAME_QUEUE_THRES; } - if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL)) { + if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL)) { /* Should we trigger congestion here? */ l1_frame.flags |= SNG_L1FRAME_QUEUE_FULL; } diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c index 98da73ec92..b97b75cdfc 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c @@ -515,8 +515,10 @@ static FIO_OPEN_FUNCTION(wanpipe_open) wanpipe_tdm_api_t tdm_api; memset(&tdm_api,0,sizeof(tdm_api)); + sangoma_tdm_flush_bufs(ftdmchan->sockfd, &tdm_api); sangoma_flush_stats(ftdmchan->sockfd, &tdm_api); + memset(&ftdmchan->iostats, 0, sizeof(ftdmchan->iostats)); if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921 || ftdmchan->type == FTDM_CHAN_TYPE_DQ931) { ftdmchan->native_codec = ftdmchan->effective_codec = FTDM_CODEC_NONE; @@ -753,6 +755,7 @@ static FIO_COMMAND_FUNCTION(wanpipe_command) case FTDM_COMMAND_FLUSH_IOSTATS: { err = sangoma_flush_stats(ftdmchan->sockfd, &tdm_api); + memset(&ftdmchan->iostats, 0, sizeof(ftdmchan->iostats)); } break; case FTDM_COMMAND_SET_RX_QUEUE_SIZE: @@ -782,42 +785,67 @@ static FIO_COMMAND_FUNCTION(wanpipe_command) static void wanpipe_read_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_rx_hdr_t *rx_stats) { - ftdmchan->iostats.stats.rx.flags = 0; - - ftdmchan->iostats.stats.rx.errors = rx_stats->wp_api_rx_hdr_errors; - ftdmchan->iostats.stats.rx.rx_queue_size = rx_stats->wp_api_rx_hdr_max_queue_length; - ftdmchan->iostats.stats.rx.rx_queue_len = rx_stats->wp_api_rx_hdr_number_of_frames_in_queue; + ftdmchan->iostats.rx.errors = rx_stats->wp_api_rx_hdr_errors; + ftdmchan->iostats.rx.queue_size = rx_stats->wp_api_rx_hdr_max_queue_length; + ftdmchan->iostats.rx.queue_len = rx_stats->wp_api_rx_hdr_number_of_frames_in_queue; - if (rx_stats->wp_api_rx_hdr_error_map & (1<iostats.stats.rx), FTDM_IOSTATS_ERROR_ABORT); - } - if (rx_stats->wp_api_rx_hdr_error_map & (1<iostats.stats.rx), FTDM_IOSTATS_ERROR_DMA); - } - if (rx_stats->wp_api_rx_hdr_error_map & (1<iostats.stats.rx), FTDM_IOSTATS_ERROR_FIFO); - } - if (rx_stats->wp_api_rx_hdr_error_map & (1<iostats.stats.rx), FTDM_IOSTATS_ERROR_CRC); - } - if (rx_stats->wp_api_rx_hdr_error_map & (1<iostats.stats.rx), FTDM_IOSTATS_ERROR_FRAME); + if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_ABORT_ERROR_BIT))) { + ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_ABORT); + } else { + ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_ABORT); } - if (ftdmchan->iostats.stats.rx.rx_queue_len >= (0.8*ftdmchan->iostats.stats.rx.rx_queue_size)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Rx Queue length exceeded threshold (%d/%d)\n", - ftdmchan->iostats.stats.rx.rx_queue_len, ftdmchan->iostats.stats.rx.rx_queue_size); - - ftdm_set_flag(&(ftdmchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES); + if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_DMA_ERROR_BIT))) { + ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_DMA); + } else { + ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_DMA); + } + + if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_FIFO_ERROR_BIT))) { + ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_FIFO); + } else { + ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_FIFO); + } + + if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_CRC_ERROR_BIT))) { + ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_CRC); + } else { + ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_CRC); + } + + if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_FRAME_ERROR_BIT))) { + ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_FRAME); + } else { + ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_FRAME); + } + + if (ftdmchan->iostats.rx.queue_len >= (0.8 * ftdmchan->iostats.rx.queue_size)) { + ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Rx Queue length exceeded 80% threshold (%d/%d)\n", + ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); + ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES); + } else if (ftdm_test_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES)){ + /* any reason we have wanpipe_tdm_api_iface.h in ftmod_wanpipe/ dir? */ + ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Rx Queue length reduced 80% threshold (%d/%d)\n", + ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); + ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES); } - if (ftdmchan->iostats.stats.rx.rx_queue_len >= ftdmchan->iostats.stats.rx.rx_queue_size) { + if (ftdmchan->iostats.rx.queue_len >= ftdmchan->iostats.rx.queue_size) { ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Rx Queue Full (%d/%d)\n", - ftdmchan->iostats.stats.rx.rx_queue_len, ftdmchan->iostats.stats.rx.rx_queue_size); - - ftdm_set_flag(&(ftdmchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL); + ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); + ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL); + } else if (ftdm_test_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL)){ + ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Rx Queue no longer full (%d/%d)\n", + ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); + ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL); } - return; + + if (!ftdmchan->iostats.rx.packets) { + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "First packet read stats: Rx queue len: %d, Rx queue size: %d\n", + ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); + } + + ftdmchan->iostats.rx.packets++; } /** diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h index 06f899c8c9..5c235ad4ea 100644 --- a/libs/freetdm/src/include/private/ftdm_core.h +++ b/libs/freetdm/src/include/private/ftdm_core.h @@ -368,30 +368,26 @@ typedef struct { } ftdm_channel_history_entry_t; typedef enum { - FTDM_IOSTATS_ERROR_CRC = (1<<0), - FTDM_IOSTATS_ERROR_FRAME = (1<<1), - FTDM_IOSTATS_ERROR_ABORT = (1<<2), - FTDM_IOSTATS_ERROR_FIFO = (1<<3), - FTDM_IOSTATS_ERROR_DMA = (1<<4), - FTDM_IOSTATS_ERROR_QUEUE_THRES = (1<<5), /* Queue reached high threshold */ - FTDM_IOSTATS_ERROR_QUEUE_FULL = (1<<6), /* Queue is full */ + FTDM_IOSTATS_ERROR_CRC = (1 << 0), + FTDM_IOSTATS_ERROR_FRAME = (1 << 1), + FTDM_IOSTATS_ERROR_ABORT = (1 << 2), + FTDM_IOSTATS_ERROR_FIFO = (1 << 3), + FTDM_IOSTATS_ERROR_DMA = (1 << 4), + FTDM_IOSTATS_ERROR_QUEUE_THRES = (1 << 5), /* Queue reached high threshold */ + FTDM_IOSTATS_ERROR_QUEUE_FULL = (1 << 6), /* Queue is full */ } ftdm_iostats_error_type_t; +typedef struct iostats_element { + uint32_t errors; + uint16_t flags; + uint8_t queue_size; /* max queue size configured */ + uint8_t queue_len; /* Current number of elements in queue */ + uint64_t packets; +} iostats_element_t; + typedef struct { - union { - struct { - uint32_t errors; - uint16_t flags; - uint8_t rx_queue_size; /* max queue size configured */ - uint8_t rx_queue_len; /* Current number of elements in queue */ - } rx; - struct { - uint32_t errors; - uint16_t flags; - uint8_t tx_queue_size; /* max queue size configured */ - uint8_t tx_queue_len; /* Current number of elements in queue */ - } tx; - } stats; + iostats_element_t rx; + iostats_element_t tx; } ftdm_channel_iostats_t; /* 2^8 table size, one for each byte (sample) value */ From 8fd62850e4ba65a249900c044bdbf057e1117477 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Fri, 26 Nov 2010 13:07:57 -0600 Subject: [PATCH 111/237] vs2010 add mod_cepstral to setup build --- Freeswitch.2010.sln | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Freeswitch.2010.sln b/Freeswitch.2010.sln index 186969891a..4f48314f5b 100644 --- a/Freeswitch.2010.sln +++ b/Freeswitch.2010.sln @@ -964,7 +964,9 @@ Global {692F6330-4D87-4C82-81DF-40DB5892636E}.Release|Win32.ActiveCfg = Release|Win32 {692F6330-4D87-4C82-81DF-40DB5892636E}.Release|x64.ActiveCfg = Release|x64 {692F6330-4D87-4C82-81DF-40DB5892636E}.Release|x64 Setup.ActiveCfg = Release|x64 + {692F6330-4D87-4C82-81DF-40DB5892636E}.Release|x64 Setup.Build.0 = Release|x64 {692F6330-4D87-4C82-81DF-40DB5892636E}.Release|x86 Setup.ActiveCfg = Release|Win32 + {692F6330-4D87-4C82-81DF-40DB5892636E}.Release|x86 Setup.Build.0 = Release|Win32 {D3EC0AFF-76FC-4210-A825-9A17410660A3}.All|Win32.ActiveCfg = Release|x64 {D3EC0AFF-76FC-4210-A825-9A17410660A3}.All|x64.ActiveCfg = Release|x64 {D3EC0AFF-76FC-4210-A825-9A17410660A3}.All|x64.Build.0 = Release|x64 From d53db202435868cfac98ed0ce6fe537d84a4947d Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Fri, 26 Nov 2010 15:06:36 -0500 Subject: [PATCH 112/237] freetdm: ftmod_wanpipe - add tx stats --- .../src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c | 44 +++++++++++++++++++ libs/freetdm/src/include/private/ftdm_core.h | 26 ++++++----- 2 files changed, 60 insertions(+), 10 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c index b97b75cdfc..804c6cfe8f 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c @@ -783,6 +783,47 @@ static FIO_COMMAND_FUNCTION(wanpipe_command) return FTDM_SUCCESS; } +static void wanpipe_write_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_tx_hdr_t *tx_stats) +{ + ftdmchan->iostats.tx.errors = tx_stats->wp_api_tx_hdr_errors; + ftdmchan->iostats.tx.queue_size = tx_stats->wp_api_tx_hdr_max_queue_length; + ftdmchan->iostats.tx.queue_len = tx_stats->wp_api_tx_hdr_number_of_frames_in_queue; + + if (ftdmchan->iostats.tx.queue_len >= (0.8 * ftdmchan->iostats.tx.queue_size)) { + ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Tx Queue length exceeded 80% threshold (%d/%d)\n", + ftdmchan->iostats.tx.queue_len, ftdmchan->iostats.tx.queue_size); + ftdm_set_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_THRES); + } else if (ftdm_test_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_THRES)){ + ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Tx Queue length reduced 80% threshold (%d/%d)\n", + ftdmchan->iostats.tx.queue_len, ftdmchan->iostats.tx.queue_size); + ftdm_clear_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_THRES); + } + + if (ftdmchan->iostats.tx.queue_len >= ftdmchan->iostats.rx.queue_size) { + ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Tx Queue Full (%d/%d)\n", + ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); + ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL); + } else if (ftdm_test_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_FULL)){ + ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Tx Queue no longer full (%d/%d)\n", + ftdmchan->iostats.tx.queue_len, ftdmchan->iostats.tx.queue_size); + ftdm_clear_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_FULL); + } + + if (ftdmchan->iostats.tx.idle_packets < tx_stats->wp_api_tx_hdr_number_of_frames_in_queue) { + ftdmchan->iostats.tx.idle_packets = tx_stats->wp_api_tx_hdr_tx_idle_packets; + ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Tx idle: %d\n", ftdmchan->iostats.tx.idle_packets); + } + + if (!ftdmchan->iostats.tx.packets) { + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "First packet write stats: Tx queue len: %d, Tx queue size: %d, Tx idle: %d\n", + ftdmchan->iostats.tx.queue_len, + ftdmchan->iostats.tx.queue_size, + ftdmchan->iostats.tx.idle_packets); + } + + ftdmchan->iostats.tx.packets++; +} + static void wanpipe_read_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_rx_hdr_t *rx_stats) { ftdmchan->iostats.rx.errors = rx_stats->wp_api_rx_hdr_errors; @@ -906,6 +947,9 @@ static FIO_WRITE_FUNCTION(wanpipe_write) /* should we be checking if bsent == *datalen here? */ if (bsent > 0) { *datalen = bsent; + if (ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS)) { + wanpipe_write_stats(ftdmchan, &hdrframe); + } return FTDM_SUCCESS; } diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h index 5c235ad4ea..7683ec7145 100644 --- a/libs/freetdm/src/include/private/ftdm_core.h +++ b/libs/freetdm/src/include/private/ftdm_core.h @@ -377,17 +377,23 @@ typedef enum { FTDM_IOSTATS_ERROR_QUEUE_FULL = (1 << 6), /* Queue is full */ } ftdm_iostats_error_type_t; -typedef struct iostats_element { - uint32_t errors; - uint16_t flags; - uint8_t queue_size; /* max queue size configured */ - uint8_t queue_len; /* Current number of elements in queue */ - uint64_t packets; -} iostats_element_t; - typedef struct { - iostats_element_t rx; - iostats_element_t tx; + struct { + uint32_t errors; + uint16_t flags; + uint8_t queue_size; /* max queue size configured */ + uint8_t queue_len; /* Current number of elements in queue */ + uint64_t packets; + } rx; + + struct { + uint32_t errors; + uint16_t flags; + uint8_t idle_packets; + uint8_t queue_size; /* max queue size configured */ + uint8_t queue_len; /* Current number of elements in queue */ + uint64_t packets; + } tx; } ftdm_channel_iostats_t; /* 2^8 table size, one for each byte (sample) value */ From 0b7a2d4c92501980983bd71365f339a674a86a3c Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Fri, 26 Nov 2010 15:10:18 -0500 Subject: [PATCH 113/237] freetdm: remove openzap projects --- libs/freetdm/openzap.2005.sln | 82 ---- .../ftmod_analog/ozmod_analog.2005.vcproj | 202 ---------- .../ozmod_analog_em.2005.vcproj | 202 ---------- .../ftmod_wanpipe/ozmod_wanpipe.2005.vcproj | 196 ---------- .../ftmod_wanpipe/wanpipe_tdm_api_iface.h | 351 ------------------ 5 files changed, 1033 deletions(-) delete mode 100644 libs/freetdm/openzap.2005.sln delete mode 100644 libs/freetdm/src/ftmod/ftmod_analog/ozmod_analog.2005.vcproj delete mode 100644 libs/freetdm/src/ftmod/ftmod_analog_em/ozmod_analog_em.2005.vcproj delete mode 100644 libs/freetdm/src/ftmod/ftmod_wanpipe/ozmod_wanpipe.2005.vcproj delete mode 100644 libs/freetdm/src/ftmod/ftmod_wanpipe/wanpipe_tdm_api_iface.h diff --git a/libs/freetdm/openzap.2005.sln b/libs/freetdm/openzap.2005.sln deleted file mode 100644 index c9f666b381..0000000000 --- a/libs/freetdm/openzap.2005.sln +++ /dev/null @@ -1,82 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual Studio 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "openzap", "msvc\openzap.2005.vcproj", "{93B8812C-3EC4-4F78-8970-FFBFC99E167D}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testanalog", "msvc\testanalog\testanalog.2005.vcproj", "{BB833648-BAFF-4BE2-94DB-F8BB043C588C}" - ProjectSection(ProjectDependencies) = postProject - {93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testisdn", "msvc\testisdn\testisdn.2005.vcproj", "{6DA6FD42-641D-4147-92F5-3BC4AAA6589B}" - ProjectSection(ProjectDependencies) = postProject - {93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_openzap", "mod_openzap\mod_openzap.2005.vcproj", "{FE3540C5-3303-46E0-A69E-D92F775687F1}" - ProjectSection(ProjectDependencies) = postProject - {93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ozmod_analog", "src\ozmod\ozmod_analog\ozmod_analog.2005.vcproj", "{37C94798-6E33-4B4F-8EE0-C72A7DC91157}" - ProjectSection(ProjectDependencies) = postProject - {93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ozmod_analog_em", "src\ozmod\ozmod_analog_em\ozmod_analog_em.2005.vcproj", "{C539D7C8-26A8-4A94-B938-77672165C130}" - ProjectSection(ProjectDependencies) = postProject - {93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ozmod_isdn", "src\ozmod\ozmod_isdn\ozmod_isdn.2005.vcproj", "{729344A5-D5E9-434D-8EE8-AF8C6C795D15}" - ProjectSection(ProjectDependencies) = postProject - {93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ozmod_wanpipe", "src\ozmod\ozmod_wanpipe\ozmod_wanpipe.2005.vcproj", "{1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ozmod_pika", "src\ozmod\ozmod_pika\ozmod_pika.2005.vcproj", "{E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Debug|Win32.ActiveCfg = Debug|Win32 - {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Debug|Win32.Build.0 = Debug|Win32 - {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Release|Win32.ActiveCfg = Release|Win32 - {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Release|Win32.Build.0 = Release|Win32 - {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Debug|Win32.ActiveCfg = Debug|Win32 - {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Debug|Win32.Build.0 = Debug|Win32 - {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Release|Win32.ActiveCfg = Release|Win32 - {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Release|Win32.Build.0 = Release|Win32 - {6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Debug|Win32.ActiveCfg = Debug|Win32 - {6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Debug|Win32.Build.0 = Debug|Win32 - {6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Release|Win32.ActiveCfg = Release|Win32 - {6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Release|Win32.Build.0 = Release|Win32 - {FE3540C5-3303-46E0-A69E-D92F775687F1}.Debug|Win32.ActiveCfg = Debug|Win32 - {FE3540C5-3303-46E0-A69E-D92F775687F1}.Debug|Win32.Build.0 = Debug|Win32 - {FE3540C5-3303-46E0-A69E-D92F775687F1}.Release|Win32.ActiveCfg = Release|Win32 - {FE3540C5-3303-46E0-A69E-D92F775687F1}.Release|Win32.Build.0 = Release|Win32 - {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Debug|Win32.ActiveCfg = Debug|Win32 - {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Debug|Win32.Build.0 = Debug|Win32 - {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Release|Win32.ActiveCfg = Release|Win32 - {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Release|Win32.Build.0 = Release|Win32 - {C539D7C8-26A8-4A94-B938-77672165C130}.Debug|Win32.ActiveCfg = Debug|Win32 - {C539D7C8-26A8-4A94-B938-77672165C130}.Debug|Win32.Build.0 = Debug|Win32 - {C539D7C8-26A8-4A94-B938-77672165C130}.Release|Win32.ActiveCfg = Release|Win32 - {C539D7C8-26A8-4A94-B938-77672165C130}.Release|Win32.Build.0 = Release|Win32 - {729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Debug|Win32.ActiveCfg = Debug|Win32 - {729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Debug|Win32.Build.0 = Debug|Win32 - {729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Release|Win32.ActiveCfg = Release|Win32 - {729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Release|Win32.Build.0 = Release|Win32 - {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Debug|Win32.ActiveCfg = Debug|Win32 - {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Release|Win32.ActiveCfg = Release|Win32 - {E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}.Debug|Win32.ActiveCfg = Debug|Win32 - {E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}.Release|Win32.ActiveCfg = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/libs/freetdm/src/ftmod/ftmod_analog/ozmod_analog.2005.vcproj b/libs/freetdm/src/ftmod/ftmod_analog/ozmod_analog.2005.vcproj deleted file mode 100644 index 7a1cf53b20..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_analog/ozmod_analog.2005.vcproj +++ /dev/null @@ -1,202 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs/freetdm/src/ftmod/ftmod_analog_em/ozmod_analog_em.2005.vcproj b/libs/freetdm/src/ftmod/ftmod_analog_em/ozmod_analog_em.2005.vcproj deleted file mode 100644 index 9ecbadc232..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_analog_em/ozmod_analog_em.2005.vcproj +++ /dev/null @@ -1,202 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ozmod_wanpipe.2005.vcproj b/libs/freetdm/src/ftmod/ftmod_wanpipe/ozmod_wanpipe.2005.vcproj deleted file mode 100644 index abebf30427..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ozmod_wanpipe.2005.vcproj +++ /dev/null @@ -1,196 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/wanpipe_tdm_api_iface.h b/libs/freetdm/src/ftmod/ftmod_wanpipe/wanpipe_tdm_api_iface.h deleted file mode 100644 index 3801ff9c8c..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/wanpipe_tdm_api_iface.h +++ /dev/null @@ -1,351 +0,0 @@ -/***************************************************************************** -* wanpipe_tdm_api_iface.h -* -* WANPIPE(tm) AFT TE1 Hardware Support -* -* Authors: Nenad Corbic -* -* Copyright (c) 2007 - 08, Sangoma Technologies -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -* ============================================================================ -* Oct 04, 2005 Nenad Corbic Initial version. -* -* Jul 25, 2006 David Rokhvarg Ported to Windows. -*****************************************************************************/ - -#ifndef __WANPIPE_TDM_API_IFACE_H_ -#define __WANPIPE_TDM_API_IFACE_H_ - - -#if defined(__WINDOWS__) -typedef HANDLE sng_fd_t; -#else -typedef int sng_fd_t; -#endif - -/* Indicate to library that new features exist */ -#define WP_TDM_FEATURE_DTMF_EVENTS 1 -#define WP_TDM_FEATURE_FE_ALARM 1 -#define WP_TDM_FEATURE_EVENTS 1 -#define WP_TDM_FEATURE_LINK_STATUS 1 - -enum wanpipe_tdm_api_cmds { - - SIOC_WP_TDM_GET_USR_MTU_MRU, /* 0x00 */ - - SIOC_WP_TDM_SET_USR_PERIOD, /* 0x01 */ - SIOC_WP_TDM_GET_USR_PERIOD, /* 0x02 */ - - SIOC_WP_TDM_SET_HW_MTU_MRU, /* 0x03 */ - SIOC_WP_TDM_GET_HW_MTU_MRU, /* 0x04 */ - - SIOC_WP_TDM_SET_CODEC, /* 0x05 */ - SIOC_WP_TDM_GET_CODEC, /* 0x06 */ - - SIOC_WP_TDM_SET_POWER_LEVEL, /* 0x07 */ - SIOC_WP_TDM_GET_POWER_LEVEL, /* 0x08 */ - - SIOC_WP_TDM_TOGGLE_RX, /* 0x09 */ - SIOC_WP_TDM_TOGGLE_TX, /* 0x0A */ - - SIOC_WP_TDM_GET_HW_CODING, /* 0x0B */ - SIOC_WP_TDM_SET_HW_CODING, /* 0x0C */ - - SIOC_WP_TDM_GET_FULL_CFG, /* 0x0D */ - - SIOC_WP_TDM_SET_EC_TAP, /* 0x0E */ - SIOC_WP_TDM_GET_EC_TAP, /* 0x0F */ - - SIOC_WP_TDM_ENABLE_RBS_EVENTS, /* 0x10 */ - SIOC_WP_TDM_DISABLE_RBS_EVENTS, /* 0x11 */ - SIOC_WP_TDM_WRITE_RBS_BITS, /* 0x12 */ - - SIOC_WP_TDM_GET_STATS, /* 0x13 */ - SIOC_WP_TDM_FLUSH_BUFFERS, /* 0x14 */ - - SIOC_WP_TDM_READ_EVENT, /* 0x15 */ - - SIOC_WP_TDM_SET_EVENT, /* 0x16 */ - - SIOC_WP_TDM_SET_RX_GAINS, /* 0x17 */ - SIOC_WP_TDM_SET_TX_GAINS, /* 0x18 */ - SIOC_WP_TDM_CLEAR_RX_GAINS, /* 0x19 */ - SIOC_WP_TDM_CLEAR_TX_GAINS, /* 0x1A */ - - SIOC_WP_TDM_GET_FE_ALARMS, /* 0x1B */ - - SIOC_WP_TDM_ENABLE_HWEC, /* 0x1C */ - SIOC_WP_TDM_DISABLE_HWEC, /* 0x1D */ - - SIOC_WP_TDM_SET_FE_STATUS, /* 0x1E */ - SIOC_WP_TDM_GET_FE_STATUS, /* 0x1F */ - - SIOC_WP_TDM_GET_HW_DTMF, /* 0x20 */ - - SIOC_WP_TDM_NOTSUPP /* */ - -}; - -#define SIOC_WP_TDM_GET_LINK_STATUS SIOC_WP_TDM_GET_FE_STATUS - -enum wanpipe_tdm_api_events { - WP_TDMAPI_EVENT_NONE, - WP_TDMAPI_EVENT_RBS, - WP_TDMAPI_EVENT_ALARM, - WP_TDMAPI_EVENT_DTMF, - WP_TDMAPI_EVENT_RM_DTMF, - WP_TDMAPI_EVENT_RXHOOK, - WP_TDMAPI_EVENT_RING, - WP_TDMAPI_EVENT_RING_DETECT, - WP_TDMAPI_EVENT_RING_TRIP_DETECT, - WP_TDMAPI_EVENT_TONE, - WP_TDMAPI_EVENT_TXSIG_KEWL, - WP_TDMAPI_EVENT_TXSIG_START, - WP_TDMAPI_EVENT_TXSIG_OFFHOOK, - WP_TDMAPI_EVENT_TXSIG_ONHOOK, - WP_TDMAPI_EVENT_ONHOOKTRANSFER, - WP_TDMAPI_EVENT_SETPOLARITY, - WP_TDMAPI_EVENT_BRI_CHAN_LOOPBACK, - WP_TDMAPI_EVENT_LINK_STATUS -}; - -#define WP_TDMAPI_EVENT_FE_ALARM WP_TDMAPI_EVENT_ALARM - - -#define WP_TDMAPI_EVENT_ENABLE 0x01 -#define WP_TDMAPI_EVENT_DISABLE 0x02 -#define WP_TDMAPI_EVENT_MODE_DECODE(mode) \ - ((mode) == WP_TDMAPI_EVENT_ENABLE) ? "Enable" : \ - ((mode) == WP_TDMAPI_EVENT_DISABLE) ? "Disable" : \ - "(Unknown mode)" - -#define WPTDM_A_BIT WAN_RBS_SIG_A -#define WPTDM_B_BIT WAN_RBS_SIG_B -#define WPTDM_C_BIT WAN_RBS_SIG_C -#define WPTDM_D_BIT WAN_RBS_SIG_D - -#define WP_TDMAPI_EVENT_RXHOOK_OFF 0x01 -#define WP_TDMAPI_EVENT_RXHOOK_ON 0x02 -#define WP_TDMAPI_EVENT_RXHOOK_DECODE(state) \ - ((state) == WP_TDMAPI_EVENT_RXHOOK_OFF) ? "Off-hook" : \ - ((state) == WP_TDMAPI_EVENT_RXHOOK_ON) ? "On-hook" : \ - "(Unknown state)" - -#define WP_TDMAPI_EVENT_RING_PRESENT 0x01 -#define WP_TDMAPI_EVENT_RING_STOP 0x02 -#define WP_TDMAPI_EVENT_RING_DECODE(state) \ - ((state) == WP_TDMAPI_EVENT_RING_PRESENT) ? "Ring Present" : \ - ((state) == WP_TDMAPI_EVENT_RING_STOP) ? "Ring Stop" : \ - "(Unknown state)" - -#define WP_TDMAPI_EVENT_RING_TRIP_PRESENT 0x01 -#define WP_TDMAPI_EVENT_RING_TRIP_STOP 0x02 -#define WP_TDMAPI_EVENT_RING_TRIP_DECODE(state) \ - ((state) == WP_TDMAPI_EVENT_RING_TRIP_PRESENT) ? "Ring Present" : \ - ((state) == WP_TDMAPI_EVENT_RING_TRIP_STOP) ? "Ring Stop" : \ - "(Unknown state)" -/*Link Status */ -#define WP_TDMAPI_EVENT_LINK_STATUS_CONNECTED 0x01 -#define WP_TDMAPI_EVENT_LINK_STATUS_DISCONNECTED 0x02 -#define WP_TDMAPI_EVENT_LINK_STATUS_DECODE(status) \ - ((status) == WP_TDMAPI_EVENT_LINK_STATUS_CONNECTED) ? "Connected" : \ - ((status) == WP_TDMAPI_EVENT_LINK_STATUS_DISCONNECTED) ? "Disconnected" : \ - "Unknown" -#define WP_TDMAPI_EVENT_TONE_DIAL 0x01 -#define WP_TDMAPI_EVENT_TONE_BUSY 0x02 -#define WP_TDMAPI_EVENT_TONE_RING 0x03 -#define WP_TDMAPI_EVENT_TONE_CONGESTION 0x04 - -/* BRI channels list */ -#define WAN_BRI_BCHAN1 0x01 -#define WAN_BRI_BCHAN2 0x02 -#define WAN_BRI_DCHAN 0x03 - - -typedef struct { - - u_int8_t type; - u_int8_t mode; - u_int32_t time_stamp; - u_int8_t channel; - u_int32_t chan_map; - u_int8_t span; - union { - struct { - u_int8_t alarm; - } te1_alarm; - struct { - u_int8_t rbs_bits; - } te1_rbs; - struct { - u_int8_t state; - u_int8_t sig; - } rm_hook; - struct { - u_int8_t state; - } rm_ring; - struct { - u_int8_t type; - } rm_tone; - struct { - u_int8_t digit; /* DTMF: digit */ - u_int8_t port; /* DTMF: SOUT/ROUT */ - u_int8_t type; /* DTMF: PRESET/STOP */ - } dtmf; - struct { - u_int16_t polarity; - u_int16_t ohttimer; - } rm_common; - struct{ - u_int16_t status; - } linkstatus; - } wp_tdm_api_event_u; -#define wp_tdm_api_event_type type -#define wp_tdm_api_event_mode mode -#define wp_tdm_api_event_alarm wp_tdm_api_event_u.te1_alarm.alarm -#define wp_tdm_api_event_alarm wp_tdm_api_event_u.te1_alarm.alarm -#define wp_tdm_api_event_rbs_bits wp_tdm_api_event_u.te1_rbs.rbs_bits -#define wp_tdm_api_event_hook_state wp_tdm_api_event_u.rm_hook.state -#define wp_tdm_api_event_hook_sig wp_tdm_api_event_u.rm_hook.sig -#define wp_tdm_api_event_ring_state wp_tdm_api_event_u.rm_ring.state -#define wp_tdm_api_event_tone_type wp_tdm_api_event_u.rm_tone.type -#define wp_tdm_api_event_dtmf_digit wp_tdm_api_event_u.dtmf.digit -#define wp_tdm_api_event_dtmf_type wp_tdm_api_event_u.dtmf.type -#define wp_tdm_api_event_dtmf_port wp_tdm_api_event_u.dtmf.port -#define wp_tdm_api_event_ohttimer wp_tdm_api_event_u.rm_common.ohttimer -#define wp_tdm_api_event_polarity wp_tdm_api_event_u.rm_common.polarity -#define wp_tdm_api_event_link_status wp_tdm_api_event_u.linkstatus.status -} wp_tdm_api_event_t; - -typedef struct { - union { - unsigned char reserved[16]; - }wp_rx_hdr_u; -} wp_tdm_api_rx_hdr_t; - -typedef struct { - wp_tdm_api_rx_hdr_t hdr; - unsigned char data[1]; -} wp_tdm_api_rx_element_t; - -typedef struct { - union { - struct { - unsigned char _rbs_rx_bits; - unsigned int _time_stamp; - }wp_tx; - unsigned char reserved[16]; - }wp_tx_hdr_u; -#define wp_api_time_stamp wp_tx_hdr_u.wp_tx._time_stamp -} wp_tdm_api_tx_hdr_t; - -typedef struct { - wp_tdm_api_tx_hdr_t hdr; - unsigned char data[1]; -} wp_tdm_api_tx_element_t; - - - -typedef struct wp_tdm_chan_stats -{ - unsigned int rx_packets; /* total packets received */ - unsigned int tx_packets; /* total packets transmitted */ - unsigned int rx_bytes; /* total bytes received */ - unsigned int tx_bytes; /* total bytes transmitted */ - unsigned int rx_errors; /* bad packets received */ - unsigned int tx_errors; /* packet transmit problems */ - unsigned int rx_dropped; /* no space in linux buffers */ - unsigned int tx_dropped; /* no space available in linux */ - unsigned int multicast; /* multicast packets received */ -#if !defined(__WINDOWS__) - unsigned int collisions; -#endif - /* detailed rx_errors: */ - unsigned int rx_length_errors; - unsigned int rx_over_errors; /* receiver ring buff overflow */ - unsigned int rx_crc_errors; /* recved pkt with crc error */ - unsigned int rx_frame_errors; /* recv'd frame alignment error */ -#if !defined(__WINDOWS__) - unsigned int rx_fifo_errors; /* recv'r fifo overrun */ -#endif - unsigned int rx_missed_errors; /* receiver missed packet */ - - /* detailed tx_errors */ -#if !defined(__WINDOWS__) - unsigned int tx_aborted_errors; - unsigned int tx_carrier_errors; -#endif - unsigned int tx_fifo_errors; - unsigned int tx_heartbeat_errors; - unsigned int tx_window_errors; - -}wp_tdm_chan_stats_t; - - - -typedef struct wanpipe_tdm_api_cmd{ - unsigned int cmd; - unsigned int hw_tdm_coding; /* Set/Get HW TDM coding: uLaw muLaw */ - unsigned int hw_mtu_mru; /* Set/Get HW TDM MTU/MRU */ - unsigned int usr_period; /* Set/Get User Period in ms */ - unsigned int tdm_codec; /* Set/Get TDM Codec: SLinear */ - unsigned int power_level; /* Set/Get Power level treshold */ - unsigned int rx_disable; /* Enable/Disable Rx */ - unsigned int tx_disable; /* Enable/Disable Tx */ - unsigned int usr_mtu_mru; /* Set/Get User TDM MTU/MRU */ - unsigned int ec_tap; /* Echo Cancellation Tap */ - unsigned int rbs_poll; /* Enable/Disable RBS Polling */ - unsigned int rbs_rx_bits; /* Rx RBS Bits */ - unsigned int rbs_tx_bits; /* Tx RBS Bits */ - unsigned int hdlc; /* HDLC based device */ - unsigned int idle_flag; /* IDLE flag to Tx */ - unsigned int fe_alarms; /* FE Alarms detected */ - wp_tdm_chan_stats_t stats; /* TDM Statistics */ - /* Do NOT add anything above this! Important for binary backward compatibility. */ - wp_tdm_api_event_t event; /* TDM Event */ - unsigned int data_len; - void *data; - unsigned char fe_status; /* FE status - Connected or Disconnected */ - unsigned int hw_dtmf; /* HW DTMF enabled */ -}wanpipe_tdm_api_cmd_t; - -typedef struct wanpipe_tdm_api_event{ - int (*wp_rbs_event)(sng_fd_t fd, unsigned char rbs_bits); - int (*wp_dtmf_event)(sng_fd_t fd, unsigned char dtmf, unsigned char type, unsigned char port); - int (*wp_rxhook_event)(sng_fd_t fd, unsigned char hook_state); - int (*wp_ring_detect_event)(sng_fd_t fd, unsigned char ring_state); - int (*wp_ring_trip_detect_event)(sng_fd_t fd, unsigned char ring_state); - int (*wp_fe_alarm_event)(sng_fd_t fd, unsigned char fe_alarm_event); - int (*wp_link_status_event)(sng_fd_t fd, unsigned char link_status_event); -}wanpipe_tdm_api_event_t; - -typedef struct wanpipe_tdm_api{ - wanpipe_tdm_api_cmd_t wp_tdm_cmd; - wanpipe_tdm_api_event_t wp_tdm_event; -}wanpipe_tdm_api_t; - - -#endif From 7a7a387f551a8b2a52a64dd3590f73e29ee5112e Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Fri, 26 Nov 2010 15:49:18 -0500 Subject: [PATCH 114/237] freetdm: improve IO stats (cherry picked from R2 branch) --- .../ftmod_sangoma_isdn_stack_out.c | 14 +- .../src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c | 131 ++++++++++++++---- libs/freetdm/src/include/private/ftdm_core.h | 44 +++--- 3 files changed, 132 insertions(+), 57 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c index 1b906a2004..62d6d023b8 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c @@ -655,32 +655,32 @@ void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len) memcpy(&l1_frame.data, data, len); - if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_CRC)) { + if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_CRC)) { l1_frame.flags |= SNG_L1FRAME_ERROR_CRC; } - if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_FRAME)) { + if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_FRAME)) { l1_frame.flags |= SNG_L1FRAME_ERROR_FRAME; } - if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_ABORT)) { + if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_ABORT)) { l1_frame.flags |= SNG_L1FRAME_ERROR_ABORT; } - if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_FIFO)) { + if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_FIFO)) { l1_frame.flags |= SNG_L1FRAME_ERROR_FIFO; } - if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_DMA)) { + if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_DMA)) { l1_frame.flags |= SNG_L1FRAME_ERROR_DMA; } - if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES)) { + if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES)) { /* Should we trigger congestion here? */ l1_frame.flags |= SNG_L1FRAME_QUEUE_THRES; } - if (ftdm_test_flag(&(dchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL)) { + if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL)) { /* Should we trigger congestion here? */ l1_frame.flags |= SNG_L1FRAME_QUEUE_FULL; } diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c index c13455dd21..c20ad82a3b 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c @@ -513,7 +513,10 @@ static FIO_OPEN_FUNCTION(wanpipe_open) wanpipe_tdm_api_t tdm_api; memset(&tdm_api,0,sizeof(tdm_api)); + sangoma_tdm_flush_bufs(ftdmchan->sockfd, &tdm_api); + sangoma_flush_stats(ftdmchan->sockfd, &tdm_api); + memset(&ftdmchan->iostats, 0, sizeof(ftdmchan->iostats)); if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921 || ftdmchan->type == FTDM_CHAN_TYPE_DQ931) { ftdmchan->native_codec = ftdmchan->effective_codec = FTDM_CODEC_NONE; @@ -750,6 +753,7 @@ static FIO_COMMAND_FUNCTION(wanpipe_command) case FTDM_COMMAND_FLUSH_IOSTATS: { err = sangoma_flush_stats(ftdmchan->sockfd, &tdm_api); + memset(&ftdmchan->iostats, 0, sizeof(ftdmchan->iostats)); } break; case FTDM_COMMAND_SET_RX_QUEUE_SIZE: @@ -777,44 +781,110 @@ static FIO_COMMAND_FUNCTION(wanpipe_command) return FTDM_SUCCESS; } +static void wanpipe_write_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_tx_hdr_t *tx_stats) +{ + ftdmchan->iostats.tx.errors = tx_stats->wp_api_tx_hdr_errors; + ftdmchan->iostats.tx.queue_size = tx_stats->wp_api_tx_hdr_max_queue_length; + ftdmchan->iostats.tx.queue_len = tx_stats->wp_api_tx_hdr_number_of_frames_in_queue; + + if (ftdmchan->iostats.tx.queue_len >= (0.8 * ftdmchan->iostats.tx.queue_size)) { + ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Tx Queue length exceeded 80% threshold (%d/%d)\n", + ftdmchan->iostats.tx.queue_len, ftdmchan->iostats.tx.queue_size); + ftdm_set_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_THRES); + } else if (ftdm_test_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_THRES)){ + ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Tx Queue length reduced 80% threshold (%d/%d)\n", + ftdmchan->iostats.tx.queue_len, ftdmchan->iostats.tx.queue_size); + ftdm_clear_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_THRES); + } + + if (ftdmchan->iostats.tx.queue_len >= ftdmchan->iostats.rx.queue_size) { + ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Tx Queue Full (%d/%d)\n", + ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); + ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL); + } else if (ftdm_test_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_FULL)){ + ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Tx Queue no longer full (%d/%d)\n", + ftdmchan->iostats.tx.queue_len, ftdmchan->iostats.tx.queue_size); + ftdm_clear_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_FULL); + } + + if (ftdmchan->iostats.tx.idle_packets < tx_stats->wp_api_tx_hdr_number_of_frames_in_queue) { + ftdmchan->iostats.tx.idle_packets = tx_stats->wp_api_tx_hdr_tx_idle_packets; + ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Tx idle: %d\n", ftdmchan->iostats.tx.idle_packets); + } + + if (!ftdmchan->iostats.tx.packets) { + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "First packet write stats: Tx queue len: %d, Tx queue size: %d, Tx idle: %d\n", + ftdmchan->iostats.tx.queue_len, + ftdmchan->iostats.tx.queue_size, + ftdmchan->iostats.tx.idle_packets); + } + + ftdmchan->iostats.tx.packets++; +} + static void wanpipe_read_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_rx_hdr_t *rx_stats) { - ftdmchan->iostats.stats.rx.flags = 0; - - ftdmchan->iostats.stats.rx.errors = rx_stats->wp_api_rx_hdr_errors; - ftdmchan->iostats.stats.rx.rx_queue_size = rx_stats->wp_api_rx_hdr_max_queue_length; - ftdmchan->iostats.stats.rx.rx_queue_len = rx_stats->wp_api_rx_hdr_number_of_frames_in_queue; + ftdmchan->iostats.rx.errors = rx_stats->wp_api_rx_hdr_errors; + ftdmchan->iostats.rx.queue_size = rx_stats->wp_api_rx_hdr_max_queue_length; + ftdmchan->iostats.rx.queue_len = rx_stats->wp_api_rx_hdr_number_of_frames_in_queue; - if (rx_stats->wp_api_rx_hdr_error_map & (1<iostats.stats.rx), FTDM_IOSTATS_ERROR_ABORT); - } - if (rx_stats->wp_api_rx_hdr_error_map & (1<iostats.stats.rx), FTDM_IOSTATS_ERROR_DMA); - } - if (rx_stats->wp_api_rx_hdr_error_map & (1<iostats.stats.rx), FTDM_IOSTATS_ERROR_FIFO); - } - if (rx_stats->wp_api_rx_hdr_error_map & (1<iostats.stats.rx), FTDM_IOSTATS_ERROR_CRC); - } - if (rx_stats->wp_api_rx_hdr_error_map & (1<iostats.stats.rx), FTDM_IOSTATS_ERROR_FRAME); + if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_ABORT_ERROR_BIT))) { + ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_ABORT); + } else { + ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_ABORT); } - if (ftdmchan->iostats.stats.rx.rx_queue_len >= (0.8*ftdmchan->iostats.stats.rx.rx_queue_size)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Rx Queue length exceeded threshold (%d/%d)\n", - ftdmchan->iostats.stats.rx.rx_queue_len, ftdmchan->iostats.stats.rx.rx_queue_size); - - ftdm_set_flag(&(ftdmchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES); + if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_DMA_ERROR_BIT))) { + ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_DMA); + } else { + ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_DMA); + } + + if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_FIFO_ERROR_BIT))) { + ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_FIFO); + } else { + ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_FIFO); + } + + if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_CRC_ERROR_BIT))) { + ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_CRC); + } else { + ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_CRC); + } + + if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_FRAME_ERROR_BIT))) { + ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_FRAME); + } else { + ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_FRAME); + } + + if (ftdmchan->iostats.rx.queue_len >= (0.8 * ftdmchan->iostats.rx.queue_size)) { + ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Rx Queue length exceeded 80% threshold (%d/%d)\n", + ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); + ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES); + } else if (ftdm_test_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES)){ + /* any reason we have wanpipe_tdm_api_iface.h in ftmod_wanpipe/ dir? */ + ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Rx Queue length reduced 80% threshold (%d/%d)\n", + ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); + ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES); } - if (ftdmchan->iostats.stats.rx.rx_queue_len >= ftdmchan->iostats.stats.rx.rx_queue_size) { + if (ftdmchan->iostats.rx.queue_len >= ftdmchan->iostats.rx.queue_size) { ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Rx Queue Full (%d/%d)\n", - ftdmchan->iostats.stats.rx.rx_queue_len, ftdmchan->iostats.stats.rx.rx_queue_size); - - ftdm_set_flag(&(ftdmchan->iostats.stats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL); + ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); + ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL); + } else if (ftdm_test_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL)){ + ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Rx Queue no longer full (%d/%d)\n", + ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); + ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL); } - return; + + if (!ftdmchan->iostats.rx.packets) { + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "First packet read stats: Rx queue len: %d, Rx queue size: %d\n", + ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); + } + + ftdmchan->iostats.rx.packets++; } /** @@ -875,6 +945,9 @@ static FIO_WRITE_FUNCTION(wanpipe_write) /* should we be checking if bsent == *datalen here? */ if (bsent > 0) { *datalen = bsent; + if (ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS)) { + wanpipe_write_stats(ftdmchan, &hdrframe); + } return FTDM_SUCCESS; } diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h index 06f899c8c9..7683ec7145 100644 --- a/libs/freetdm/src/include/private/ftdm_core.h +++ b/libs/freetdm/src/include/private/ftdm_core.h @@ -368,30 +368,32 @@ typedef struct { } ftdm_channel_history_entry_t; typedef enum { - FTDM_IOSTATS_ERROR_CRC = (1<<0), - FTDM_IOSTATS_ERROR_FRAME = (1<<1), - FTDM_IOSTATS_ERROR_ABORT = (1<<2), - FTDM_IOSTATS_ERROR_FIFO = (1<<3), - FTDM_IOSTATS_ERROR_DMA = (1<<4), - FTDM_IOSTATS_ERROR_QUEUE_THRES = (1<<5), /* Queue reached high threshold */ - FTDM_IOSTATS_ERROR_QUEUE_FULL = (1<<6), /* Queue is full */ + FTDM_IOSTATS_ERROR_CRC = (1 << 0), + FTDM_IOSTATS_ERROR_FRAME = (1 << 1), + FTDM_IOSTATS_ERROR_ABORT = (1 << 2), + FTDM_IOSTATS_ERROR_FIFO = (1 << 3), + FTDM_IOSTATS_ERROR_DMA = (1 << 4), + FTDM_IOSTATS_ERROR_QUEUE_THRES = (1 << 5), /* Queue reached high threshold */ + FTDM_IOSTATS_ERROR_QUEUE_FULL = (1 << 6), /* Queue is full */ } ftdm_iostats_error_type_t; typedef struct { - union { - struct { - uint32_t errors; - uint16_t flags; - uint8_t rx_queue_size; /* max queue size configured */ - uint8_t rx_queue_len; /* Current number of elements in queue */ - } rx; - struct { - uint32_t errors; - uint16_t flags; - uint8_t tx_queue_size; /* max queue size configured */ - uint8_t tx_queue_len; /* Current number of elements in queue */ - } tx; - } stats; + struct { + uint32_t errors; + uint16_t flags; + uint8_t queue_size; /* max queue size configured */ + uint8_t queue_len; /* Current number of elements in queue */ + uint64_t packets; + } rx; + + struct { + uint32_t errors; + uint16_t flags; + uint8_t idle_packets; + uint8_t queue_size; /* max queue size configured */ + uint8_t queue_len; /* Current number of elements in queue */ + uint64_t packets; + } tx; } ftdm_channel_iostats_t; /* 2^8 table size, one for each byte (sample) value */ From f7279386e423d7f525211f9f929242ca1e4baf1b Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Fri, 26 Nov 2010 22:10:33 -0200 Subject: [PATCH 115/237] freetdm: ftmod_r2 - replaced deprecated ftdm_r2_configure_span() by ftdm_r2_configure_span_signaling(), all r2 default params now stays on ftmod_r2 --- libs/freetdm/mod_freetdm/mod_freetdm.c | 94 ++-------------- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 122 ++++++++++++--------- 2 files changed, 80 insertions(+), 136 deletions(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 8d961123cb..18c1d4aebe 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -3212,29 +3212,6 @@ static switch_status_t load_config(void) char *name = (char *) switch_xml_attr(myspan, "name"); ftdm_status_t zstatus = FTDM_FAIL; - /* strings */ - const char *variant = "itu"; - const char *category = "national_subscriber"; - const char *logdir = "/usr/local/freeswitch/log/"; /* FIXME: get PREFIX variable */ - const char *logging = "notice,warning,error"; - const char *advanced_protocol_file = ""; - - /* booleans */ - int call_files = 0; - int get_ani_first = -1; - int immediate_accept = -1; - int double_answer = -1; - int skip_category = -1; - int forced_release = -1; - int charge_calls = -1; - - /* integers */ - int mfback_timeout = -1; - int metering_pulse_timeout = -1; - int allow_collect_calls = -1; - int max_ani = 10; - int max_dnis = 4; - /* common non r2 stuff */ const char *context = "default"; const char *dialplan = "XML"; @@ -3243,53 +3220,16 @@ static switch_status_t load_config(void) uint32_t span_id = 0; ftdm_span_t *span = NULL; + ftdm_conf_parameter_t spanparameters[30]; + unsigned paramindex = 0; + memset(spanparameters, 0, sizeof(spanparameters)); for (param = switch_xml_child(myspan, "param"); param; param = param->next) { char *var = (char *) switch_xml_attr_soft(param, "name"); char *val = (char *) switch_xml_attr_soft(param, "value"); /* string parameters */ - if (!strcasecmp(var, "variant")) { - variant = val; - } else if (!strcasecmp(var, "category")) { - category = val; - } else if (!strcasecmp(var, "logdir")) { - logdir = val; - } else if (!strcasecmp(var, "logging")) { - logging = val; - } else if (!strcasecmp(var, "advanced_protocol_file")) { - advanced_protocol_file = val; - - /* booleans */ - } else if (!strcasecmp(var, "allow_collect_calls")) { - allow_collect_calls = switch_true(val); - } else if (!strcasecmp(var, "immediate_accept")) { - immediate_accept = switch_true(val); - } else if (!strcasecmp(var, "double_answer")) { - double_answer = switch_true(val); - } else if (!strcasecmp(var, "skip_category")) { - skip_category = switch_true(var); - } else if (!strcasecmp(var, "forced_release")) { - forced_release = switch_true(val); - } else if (!strcasecmp(var, "charge_calls")) { - charge_calls = switch_true(val); - } else if (!strcasecmp(var, "get_ani_first")) { - get_ani_first = switch_true(val); - } else if (!strcasecmp(var, "call_files")) { - call_files = switch_true(val); - - /* integers */ - } else if (!strcasecmp(var, "mfback_timeout")) { - mfback_timeout = atoi(val); - } else if (!strcasecmp(var, "metering_pulse_timeout")) { - metering_pulse_timeout = atoi(val); - } else if (!strcasecmp(var, "max_ani")) { - max_ani = atoi(val); - } else if (!strcasecmp(var, "max_dnis")) { - max_dnis = atoi(val); - - /* common non r2 stuff */ - } else if (!strcasecmp(var, "context")) { + if (!strcasecmp(var, "context")) { context = val; } else if (!strcasecmp(var, "dialplan")) { dialplan = val; @@ -3297,11 +3237,15 @@ static switch_status_t load_config(void) dial_regex = val; } else if (!strcasecmp(var, "fail-dial-regex")) { fail_dial_regex = val; + } else { + spanparameters[paramindex].var = var; + spanparameters[paramindex].val = val; + paramindex++; } } if (!id && !name) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "span missing required param 'id'\n"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "either 'id' or 'name' required params are missing\n"); continue; } @@ -3327,25 +3271,7 @@ static switch_status_t load_config(void) span_id = ftdm_span_get_id(span); } - if (ftdm_configure_span(span, "r2", on_r2_signal, - "variant", variant, - "max_ani", max_ani, - "max_dnis", max_dnis, - "category", category, - "logdir", logdir, - "logging", logging, - "advanced_protocol_file", advanced_protocol_file, - "allow_collect_calls", allow_collect_calls, - "immediate_accept", immediate_accept, - "double_answer", double_answer, - "skip_category", skip_category, - "forced_release", forced_release, - "charge_calls", charge_calls, - "get_ani_first", get_ani_first, - "call_files", call_files, - "mfback_timeout", mfback_timeout, - "metering_pulse_timeout", metering_pulse_timeout, - FTDM_TAG_END) != FTDM_SUCCESS) { + if (ftdm_configure_span_signaling(span, "r2", on_r2_signal, spanparameters) != FTDM_SUCCESS) { ftdm_log(FTDM_LOG_ERROR, "Error configuring R2 FreeTDM span %d, error: %s\n", span_id, ftdm_span_get_last_error(span)); continue; diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index c8d669ca5c..ffc39e8884 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -892,27 +892,50 @@ static openr2_io_interface_t ftdm_r2_io_iface = { /* .get_oob_event */ ftdm_r2_io_get_oob_event /* never called */ }; -static FIO_SIG_CONFIGURE_FUNCTION(ftdm_r2_configure_span) - //ftdm_status_t (ftdm_span_t *span, fio_signal_cb_t sig_cb, va_list ap) +/* resolve a loglevel string, such as "debug,notice,warning", to an openr2 log level integer */ +static openr2_log_level_t ftdm_r2_loglevel_from_string(const char *level) +{ + openr2_log_level_t tmplevel; + openr2_log_level_t newlevel = 0; + char *clevel = NULL; + char *logval = NULL; + + logval = ftdm_malloc(strlen(level)+1); /* alloca man page scared me, so better to use good ol' malloc */ + if (!logval) { + ftdm_log(FTDM_LOG_WARNING, "Ignoring R2 logging parameter: '%s', failed to alloc memory\n", level); + return newlevel; + } + strcpy(logval, level); + while (logval) { + clevel = strsep(&logval, ","); + if (-1 == (tmplevel = openr2_log_get_level(clevel))) { + ftdm_log(FTDM_LOG_WARNING, "Ignoring invalid R2 logging level: '%s'\n", clevel); + continue; + } + newlevel |= tmplevel; + } + ftdm_safe_free(logval); + return newlevel; +} + +static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_r2_configure_span_signaling) { unsigned int i = 0; int conf_failure = 0; - char *var = NULL; - char *val = NULL; + const char *var = NULL, *val = NULL; + const char *log_level = "notice,warning,error"; /* default loglevel, if none is read from conf */ ftdm_r2_data_t *r2data = NULL; ftdm_r2_span_pvt_t *spanpvt = NULL; ftdm_r2_call_t *r2call = NULL; openr2_chan_t *r2chan = NULL; - openr2_log_level_t tmplevel; - char *clevel = NULL; - char *logval = NULL; + unsigned paramindex = 0; ft_r2_conf_t r2conf = { /* .variant */ OR2_VAR_ITU, /* .category */ OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER, /* .loglevel */ OR2_LOG_ERROR | OR2_LOG_WARNING, - /* .logdir */ NULL, + /* .logdir */ (char *)"/usr/local/freeswitch/log/", /* FIXME: get PREFIX variable */ /* .advanced_protocol_file */ NULL, /* .max_ani */ 10, /* .max_dnis */ 4, @@ -923,7 +946,7 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_r2_configure_span) /* .get_ani_first */ -1, /* .call_files */ 0, /* .mf_files */ 0, - /* .double_answer */ 0, + /* .double_answer */ -1, /* .charge_calls */ -1, /* .forced_release */ -1, /* .allow_collect_calls */ -1 @@ -936,10 +959,12 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_r2_configure_span) return FTDM_FAIL; } - while ((var = va_arg(ap, char *))) { + for (; ftdm_parameters[paramindex].var; paramindex++) { + var = ftdm_parameters[paramindex].var; + val = ftdm_parameters[paramindex].val; ftdm_log(FTDM_LOG_DEBUG, "Reading R2 parameter %s for span %d\n", var, span->span_id); if (!strcasecmp(var, "variant")) { - if (!(val = va_arg(ap, char *))) { + if (!val) { break; } if (ftdm_strlen_zero_buf(val)) { @@ -954,7 +979,7 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_r2_configure_span) } ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d for variant %s\n", span->span_id, val); } else if (!strcasecmp(var, "category")) { - if (!(val = va_arg(ap, char *))) { + if (!val) { break; } if (ftdm_strlen_zero_buf(val)) { @@ -969,87 +994,72 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_r2_configure_span) } ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with default category %s\n", span->span_id, val); } else if (!strcasecmp(var, "logdir")) { - if (!(val = va_arg(ap, char *))) { + if (!val) { break; } if (ftdm_strlen_zero_buf(val)) { ftdm_log(FTDM_LOG_NOTICE, "Ignoring empty R2 logdir parameter\n"); continue; } - r2conf.logdir = val; + r2conf.logdir = (char *)val; ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with logdir %s\n", span->span_id, val); } else if (!strcasecmp(var, "logging")) { - if (!(val = va_arg(ap, char *))) { + if (!val) { break; } if (ftdm_strlen_zero_buf(val)) { ftdm_log(FTDM_LOG_NOTICE, "Ignoring empty R2 logging parameter\n"); continue; } - logval = ftdm_malloc(strlen(val)+1); /* alloca man page scared me, so better to use good ol' malloc */ - if (!logval) { - ftdm_log(FTDM_LOG_WARNING, "Ignoring R2 logging parameter: '%s', failed to alloc memory\n", val); - continue; - } - strcpy(logval, val); - while (logval) { - clevel = strsep(&logval, ","); - if (-1 == (tmplevel = openr2_log_get_level(clevel))) { - ftdm_log(FTDM_LOG_WARNING, "Ignoring invalid R2 logging level: '%s'\n", clevel); - continue; - } - r2conf.loglevel |= tmplevel; - ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with loglevel %s\n", span->span_id, clevel); - } - ftdm_safe_free(logval); + log_level = val; } else if (!strcasecmp(var, "advanced_protocol_file")) { - if (!(val = va_arg(ap, char *))) { + if (!val) { break; } if (ftdm_strlen_zero_buf(val)) { ftdm_log(FTDM_LOG_NOTICE, "Ignoring empty R2 advanced_protocol_file parameter\n"); continue; } - r2conf.advanced_protocol_file = val; + r2conf.advanced_protocol_file = (char *)val; ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with advanced protocol file %s\n", span->span_id, val); } else if (!strcasecmp(var, "allow_collect_calls")) { - r2conf.allow_collect_calls = va_arg(ap, int); + r2conf.allow_collect_calls = ftdm_true(val); ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with allow collect calls max ani = %d\n", span->span_id, r2conf.allow_collect_calls); } else if (!strcasecmp(var, "double_answer")) { - r2conf.double_answer = va_arg(ap, int); + r2conf.double_answer = ftdm_true(val); ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with double answer = %d\n", span->span_id, r2conf.double_answer); } else if (!strcasecmp(var, "immediate_accept")) { - r2conf.immediate_accept = va_arg(ap, int); + r2conf.immediate_accept = ftdm_true(val); ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with immediate accept = %d\n", span->span_id, r2conf.immediate_accept); } else if (!strcasecmp(var, "skip_category")) { - r2conf.skip_category = va_arg(ap, int); + r2conf.skip_category = ftdm_true(val); ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with skip category = %d\n", span->span_id, r2conf.skip_category); } else if (!strcasecmp(var, "forced_release")) { - r2conf.forced_release = va_arg(ap, int); + r2conf.forced_release = ftdm_true(val); ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with forced release = %d\n", span->span_id, r2conf.forced_release); } else if (!strcasecmp(var, "charge_calls")) { - r2conf.charge_calls = va_arg(ap, int); + r2conf.charge_calls = ftdm_true(val); ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with charge calls = %d\n", span->span_id, r2conf.charge_calls); } else if (!strcasecmp(var, "get_ani_first")) { - r2conf.get_ani_first = va_arg(ap, int); + r2conf.get_ani_first = ftdm_true(val); ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with get ani first = %d\n", span->span_id, r2conf.get_ani_first); } else if (!strcasecmp(var, "call_files")) { - r2conf.call_files = va_arg(ap, int); + r2conf.call_files = ftdm_true(val); ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with call files = %d\n", span->span_id, r2conf.call_files); } else if (!strcasecmp(var, "mf_files")) { - r2conf.mf_files = va_arg(ap, int); + r2conf.mf_files = ftdm_true(val); ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with mf files = %d\n", span->span_id, r2conf.mf_files); } else if (!strcasecmp(var, "mfback_timeout")) { - r2conf.mfback_timeout = va_arg(ap, int); + r2conf.mfback_timeout = atoi(val); ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with MF backward timeout = %dms\n", span->span_id, r2conf.mfback_timeout); } else if (!strcasecmp(var, "metering_pulse_timeout")) { - r2conf.metering_pulse_timeout = va_arg(ap, int); + r2conf.metering_pulse_timeout = atoi(val); ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with metering pulse timeout = %dms\n", span->span_id, r2conf.metering_pulse_timeout); } else if (!strcasecmp(var, "max_ani")) { - r2conf.max_ani = va_arg(ap, int); + r2conf.max_ani = atoi(val); ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with max ani = %d\n", span->span_id, r2conf.max_ani); } else if (!strcasecmp(var, "max_dnis")) { - r2conf.max_dnis = va_arg(ap, int); + r2conf.max_dnis = atoi(val); ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with max dnis = %d\n", span->span_id, r2conf.max_dnis); } else { snprintf(span->last_error, sizeof(span->last_error), "Unknown R2 parameter [%s]", var); @@ -1062,6 +1072,10 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_r2_configure_span) return FTDM_FAIL; } + /* set span log level */ + r2conf.loglevel = ftdm_r2_loglevel_from_string(log_level); + ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %d with loglevel %s\n", span->span_id, log_level); + r2data = ftdm_malloc(sizeof(*r2data)); if (!r2data) { snprintf(span->last_error, sizeof(span->last_error), "Failed to allocate R2 data."); @@ -1387,6 +1401,9 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) r2chan = R2CALL(span->channels[i])->r2chan; openr2_chan_set_idle(r2chan); openr2_chan_process_cas_signaling(r2chan); + + ftdmchan = openr2_chan_get_client_data(r2chan); + ftdm_channel_set_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS); } memset(&start, 0, sizeof(start)); @@ -1762,12 +1779,13 @@ static FIO_SIG_UNLOAD_FUNCTION(ftdm_r2_destroy) } EX_DECLARE_DATA ftdm_module_t ftdm_module = { - "r2", - ftdm_r2_io_init, - NULL, - ftdm_r2_init, - ftdm_r2_configure_span, - ftdm_r2_destroy + /* .name */ "r2", + /* .io_load */ ftdm_r2_io_init, + /* .io_unload */ NULL, + /* .sig_load */ ftdm_r2_init, + /* .sig_configure */ NULL, + /* .sig_unload */ ftdm_r2_destroy, + /* .configure_span_signaling */ ftdm_r2_configure_span_signaling }; From 80174cf39fa6b29c45232b231f7f169224f975a7 Mon Sep 17 00:00:00 2001 From: Marc Olivier Chouinard Date: Fri, 26 Nov 2010 20:38:46 -0500 Subject: [PATCH 116/237] mod_callcenter: Add new eventsocket agent-offering. Plus some documentation and better handeling of bad agent type -- FS-2869 --- .../mod_callcenter/mod_callcenter.c | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/mod/applications/mod_callcenter/mod_callcenter.c b/src/mod/applications/mod_callcenter/mod_callcenter.c index 1b0ba1331a..ca92b17fa4 100644 --- a/src/mod/applications/mod_callcenter/mod_callcenter.c +++ b/src/mod/applications/mod_callcenter/mod_callcenter.c @@ -1346,6 +1346,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa switch_time_t t_agent_called = 0; switch_time_t t_agent_answered = 0; switch_time_t t_member_called = atoi(h->member_joined_epoch); + switch_event_t *event = NULL; switch_mutex_lock(globals.mutex); globals.threads++; @@ -1360,6 +1361,21 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa switch_safe_free(sql); goto done; } + + /* Proceed contact the agent to offer the member */ + if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Queue", h->queue_name); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "agent-offering"); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent", h->agent_name); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-Type", h->agent_type); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-System", h->agent_system); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", h->member_uuid); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", h->member_caller_name); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", h->member_caller_number); + switch_event_fire(&event); + } + + /* CallBack Mode */ if (!strcasecmp(h->agent_type, CC_AGENT_TYPE_CALLBACK)) { switch_event_create(&ovars, SWITCH_EVENT_REQUEST_PARAMS); switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_queue", "%s", h->queue_name); @@ -1375,6 +1391,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa switch_safe_free(dialstr); switch_event_destroy(&ovars); + /* UUID Standby Mode */ } else if (!strcasecmp(h->agent_type, CC_AGENT_TYPE_UUID_STANDBY)) { agent_session = switch_core_session_locate(h->agent_uuid); if (agent_session) { @@ -1400,14 +1417,17 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa cc_agent_update("status", cc_agent_status2str(CC_AGENT_STATUS_LOGGED_OUT), h->agent_name); cc_agent_update("uuid", "", h->agent_name); } + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Invalid agent type '%s' for agent '%s', aborting member offering", h->agent_type, h->agent_name); + status = SWITCH_CAUSE_USER_NOT_REGISTERED; } + /* Originate/Bridge is not finished, processing the return value */ if (status == SWITCH_STATUS_SUCCESS) { /* Agent Answered */ const char *agent_uuid = switch_core_session_get_uuid(agent_session); switch_channel_t *member_channel = switch_core_session_get_channel(member_session); switch_channel_t *agent_channel = switch_core_session_get_channel(agent_session); - switch_event_t *event; switch_channel_set_variable(agent_channel, "cc_member_pre_answer_uuid", NULL); From 9a9373c0bb42cf0e57c1b08e661a14b2a7760369 Mon Sep 17 00:00:00 2001 From: Marc Olivier Chouinard Date: Sun, 28 Nov 2010 17:07:54 -0500 Subject: [PATCH 117/237] mod_sofia: Fix malformed Presense SQL Query --- src/mod/endpoints/mod_sofia/sofia_presence.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index 95ea913a61..9d0b23a06d 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -1927,7 +1927,7 @@ static void sync_sla(sofia_profile_t *profile, const char *to_user, const char * switch_core_hash_init(&sh->hash, sh->pool); sql = switch_mprintf("select sip_from_user,sip_from_host,call_info,call_info_state,uuid from sip_dialogs " - "where hostname='%q' " "and ((sip_from_user='%q' and sip_from_host='%q) or presence_id='%q@%q')' ", + "where hostname='%q' and ((sip_from_user='%q' and sip_from_host='%q) or presence_id='%q@%q')", mod_sofia_globals.hostname, to_user, to_host, to_user, to_host); From 8825b6eac893b8280e7323133469eb24b79ed8db Mon Sep 17 00:00:00 2001 From: Marc Olivier Chouinard Date: Sun, 28 Nov 2010 17:15:39 -0500 Subject: [PATCH 118/237] mod_sofia: Fix in previous commit incompleted, this one should do it (sofia presence related) --- src/mod/endpoints/mod_sofia/sofia_presence.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index 9d0b23a06d..5c2517db61 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -1927,7 +1927,7 @@ static void sync_sla(sofia_profile_t *profile, const char *to_user, const char * switch_core_hash_init(&sh->hash, sh->pool); sql = switch_mprintf("select sip_from_user,sip_from_host,call_info,call_info_state,uuid from sip_dialogs " - "where hostname='%q' and ((sip_from_user='%q' and sip_from_host='%q) or presence_id='%q@%q')", + "where hostname='%q' and ((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q')", mod_sofia_globals.hostname, to_user, to_host, to_user, to_host); From ac2998b61f74e06100ca988eefdb608d312d1098 Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Mon, 29 Nov 2010 16:48:01 -0200 Subject: [PATCH 119/237] freetdm: ftmod_r2 - set feature FTDM_CHANNEL_FEATURE_IO_STATS just when the channel is in FTDM_CHANNEL_STATE_UP state --- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index ffc39e8884..b9e0e1378f 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -1403,7 +1403,6 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) openr2_chan_process_cas_signaling(r2chan); ftdmchan = openr2_chan_get_client_data(r2chan); - ftdm_channel_set_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS); } memset(&start, 0, sizeof(start)); @@ -1462,6 +1461,12 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) ftdmchan = openr2_chan_get_client_data(r2chan); r2call = R2CALL(ftdmchan); + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_UP)) { + ftdm_channel_set_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS); + } else { + ftdm_channel_clear_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS); + } + ftdm_mutex_lock(ftdmchan->mutex); ftdm_r2_state_advance_all(ftdmchan); openr2_chan_process_signaling(r2chan); From 2572621bc914e30cc22e79749264d67882d0aaf8 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 29 Nov 2010 13:00:19 -0600 Subject: [PATCH 120/237] FS-2368 --- src/switch_core_session.c | 14 ++++-- src/switch_ivr_bridge.c | 92 ++++++++++++++++++++++----------------- 2 files changed, 61 insertions(+), 45 deletions(-) diff --git a/src/switch_core_session.c b/src/switch_core_session.c index b3bb638c76..eca2f8daf2 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -1831,10 +1831,16 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application_get_flag switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Application %s Requires media on channel %s!\n", app, switch_channel_get_name(session->channel)); } else if (!switch_test_flag(application_interface, SAF_SUPPORT_NOMEDIA) && !switch_channel_media_ready(session->channel)) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Application %s Requires media! pre_answering channel %s\n", - app, switch_channel_get_name(session->channel)); - if (switch_channel_pre_answer(session->channel) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Well, that didn't work very well did it? ...\n"); + if (switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_INBOUND) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Application %s Requires media! pre_answering channel %s\n", + app, switch_channel_get_name(session->channel)); + if (switch_channel_pre_answer(session->channel) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Well, that didn't work very well did it? ...\n"); + switch_goto_status(SWITCH_STATUS_FALSE, done); + } + } else { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, + "Cannot execute app '%s' media required on an outbound channel that does not have media established\n", app); switch_goto_status(SWITCH_STATUS_FALSE, done); } } diff --git a/src/switch_ivr_bridge.c b/src/switch_ivr_bridge.c index b6363ffa53..64a5f8d7c9 100644 --- a/src/switch_ivr_bridge.c +++ b/src/switch_ivr_bridge.c @@ -155,7 +155,6 @@ struct switch_ivr_bridge_data { switch_input_callback_function_t input_callback; void *session_data; int clean_exit; - uint32_t skip_frames; }; typedef struct switch_ivr_bridge_data switch_ivr_bridge_data_t; @@ -169,7 +168,7 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj) switch_channel_t *chan_a, *chan_b; switch_frame_t *read_frame; switch_core_session_t *session_a, *session_b; - uint32_t loop_count = 0; + uint32_t read_frame_count = 0; const char *app_name = NULL, *app_arg = NULL; const char *hook_var = NULL; int inner_bridge = 0; @@ -181,6 +180,8 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj) const char *bridge_answer_timeout = NULL; int answer_timeout, sent_update = 0; time_t answer_limit = 0; + const char *exec_app = NULL; + const char *exec_data = NULL; #ifdef SWITCH_VIDEO_IN_THREADS switch_thread_t *vid_thread = NULL; @@ -201,6 +202,10 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj) chan_a = switch_core_session_get_channel(session_a); chan_b = switch_core_session_get_channel(session_b); + if ((exec_app = switch_channel_get_variable(chan_a, "bridge_pre_execute_app"))) { + exec_data = switch_channel_get_variable(chan_a, "bridge_pre_execute_data"); + } + bypass_media_after_bridge = switch_channel_test_flag(chan_a, CF_BYPASS_MEDIA_AFTER_BRIDGE); switch_channel_clear_flag(chan_a, CF_BYPASS_MEDIA_AFTER_BRIDGE); @@ -212,7 +217,7 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj) } inner_bridge = switch_channel_test_flag(chan_a, CF_INNER_BRIDGE); - + if (!switch_channel_test_flag(chan_a, CF_ANSWERED) && (bridge_answer_timeout = switch_channel_get_variable(chan_a, "bridge_answer_timeout"))) { if ((answer_timeout = atoi(bridge_answer_timeout)) < 0) { answer_timeout = 0; @@ -285,7 +290,6 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj) switch_channel_state_t b_state; switch_status_t status; switch_event_t *event; - loop_count++; if (switch_channel_test_flag(chan_a, CF_TRANSFER)) { data->clean_exit = 1; @@ -309,7 +313,7 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj) goto end_of_bridge_loop; } - if (loop_count > DEFAULT_LEAD_FRAMES && switch_channel_media_ack(chan_a) && switch_core_session_private_event_count(session_a)) { + if (read_frame_count > DEFAULT_LEAD_FRAMES && switch_channel_media_ack(chan_a) && switch_core_session_private_event_count(session_a)) { switch_channel_set_flag(chan_b, CF_SUSPEND); msg.string_arg = data->b_uuid; msg.message_id = SWITCH_MESSAGE_INDICATE_UNBRIDGE; @@ -341,13 +345,34 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj) } #endif - if (loop_count > DEFAULT_LEAD_FRAMES && switch_channel_media_ack(chan_a) && - (bypass_media_after_bridge || switch_channel_test_flag(chan_a, CF_BYPASS_MEDIA_AFTER_BRIDGE)) && switch_channel_test_flag(chan_a, CF_ANSWERED) - && switch_channel_test_flag(chan_b, CF_ANSWERED)) { - switch_ivr_nomedia(switch_core_session_get_uuid(session_a), SMF_REBRIDGE); - bypass_media_after_bridge = 0; - switch_channel_clear_flag(chan_a, CF_BYPASS_MEDIA_AFTER_BRIDGE); - goto end_of_bridge_loop; + if (read_frame_count > DEFAULT_LEAD_FRAMES && switch_channel_media_ack(chan_a)) { + + if (exec_app) { + switch_event_t *execute_event; + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session_a), SWITCH_LOG_CRIT, "%s Bridge execute app %s(%s)\n", + switch_channel_get_name(chan_a), exec_app, exec_data); + + if (switch_event_create(&execute_event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "call-command", "execute"); + switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-name", exec_app); + if (exec_data) { + switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-arg", exec_data); + } + //switch_event_add_header(execute_event, SWITCH_STACK_BOTTOM, "lead-frames", "%d", 5); + switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "event-lock", "true"); + switch_core_session_queue_private_event(session_a, &execute_event, SWITCH_FALSE); + } + exec_app = exec_data = NULL; + } + + + if ((bypass_media_after_bridge || switch_channel_test_flag(chan_a, CF_BYPASS_MEDIA_AFTER_BRIDGE)) && switch_channel_test_flag(chan_a, CF_ANSWERED) + && switch_channel_test_flag(chan_b, CF_ANSWERED)) { + switch_ivr_nomedia(switch_core_session_get_uuid(session_a), SMF_REBRIDGE); + bypass_media_after_bridge = 0; + switch_channel_clear_flag(chan_a, CF_BYPASS_MEDIA_AFTER_BRIDGE); + goto end_of_bridge_loop; + } } /* if 1 channel has DTMF pass it to the other */ @@ -454,6 +479,7 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj) status = switch_core_session_read_frame(session_a, &read_frame, SWITCH_IO_FLAG_NONE, stream_id); if (SWITCH_READ_ACCEPTABLE(status)) { + read_frame_count++; if (switch_test_flag(read_frame, SFF_CNG)) { if (silence_val) { switch_generate_sln_silence((int16_t *) silence_frame.data, silence_frame.samples, silence_val); @@ -463,11 +489,6 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj) } } - if (data->skip_frames) { - data->skip_frames--; - continue; - } - if (switch_channel_test_flag(chan_a, CF_BRIDGE_NOWRITE)) { continue; } @@ -1193,35 +1214,24 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_multi_threaded_bridge(switch_core_ses switch_channel_set_variable(peer_channel, SWITCH_SIGNAL_BOND_VARIABLE, switch_core_session_get_uuid(session)); if ((app = switch_channel_get_variable(caller_channel, "bridge_pre_execute_aleg_app"))) { - switch_event_t *execute_event; - - data = switch_channel_get_variable(caller_channel, "bridge_pre_execute_aleg_data"); - if (switch_event_create(&execute_event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "call-command", "execute"); - switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-name", app); - switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-arg", data); - switch_event_add_header(execute_event, SWITCH_STACK_BOTTOM, "lead-frames", "%d", 5); - switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "event-lock", "true"); - switch_core_session_queue_private_event(session, &execute_event, SWITCH_FALSE); - a_leg->skip_frames = DEFAULT_LEAD_FRAMES; + switch_channel_set_variable(caller_channel, "bridge_pre_execute_app", app); + + if ((data = switch_channel_get_variable(caller_channel, "bridge_pre_execute_aleg_data"))) { + switch_channel_set_variable(caller_channel, "bridge_pre_execute_data", data); } - } if ((app = switch_channel_get_variable(caller_channel, "bridge_pre_execute_bleg_app"))) { - switch_event_t *execute_event; - data = switch_channel_get_variable(caller_channel, "bridge_pre_execute_bleg_data"); - if (switch_event_create(&execute_event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "call-command", "execute"); - switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-name", app); - switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-arg", data); - switch_event_add_header(execute_event, SWITCH_STACK_BOTTOM, "lead-frames", "%d", 5); - switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "event-lock", "true"); - switch_core_session_queue_private_event(peer_session, &execute_event, SWITCH_FALSE); - b_leg->skip_frames = DEFAULT_LEAD_FRAMES; - } - } + switch_channel_set_variable(peer_channel, "bridge_pre_execute_app", app); + if ((data = switch_channel_get_variable(caller_channel, "bridge_pre_execute_bleg_data"))) { + switch_channel_set_variable(peer_channel, "bridge_pre_execute_data", data); + } + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "APP [%s][%s]\n", app, switch_str_nil(data)); + + } + switch_channel_set_private(peer_channel, "_bridge_", b_leg); switch_channel_set_state(peer_channel, CS_EXCHANGE_MEDIA); audio_bridge_thread(NULL, (void *) a_leg); From 9a25519496cf5299b0d4d59ea1ca9da56b008432 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 29 Nov 2010 13:02:48 -0600 Subject: [PATCH 121/237] FS-2368 forgot one debug line --- src/switch_ivr_bridge.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/switch_ivr_bridge.c b/src/switch_ivr_bridge.c index 64a5f8d7c9..4cae1a67e2 100644 --- a/src/switch_ivr_bridge.c +++ b/src/switch_ivr_bridge.c @@ -349,7 +349,7 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj) if (exec_app) { switch_event_t *execute_event; - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session_a), SWITCH_LOG_CRIT, "%s Bridge execute app %s(%s)\n", + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session_a), SWITCH_LOG_DEBUG, "%s Bridge execute app %s(%s)\n", switch_channel_get_name(chan_a), exec_app, exec_data); if (switch_event_create(&execute_event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) { @@ -1228,8 +1228,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_multi_threaded_bridge(switch_core_ses switch_channel_set_variable(peer_channel, "bridge_pre_execute_data", data); } - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "APP [%s][%s]\n", app, switch_str_nil(data)); - } switch_channel_set_private(peer_channel, "_bridge_", b_leg); From 74f04959b4e27f4af677c960c82637e874920395 Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Mon, 29 Nov 2010 19:27:49 -0200 Subject: [PATCH 122/237] freetdm: ftmod_r2 - reverted last commit --- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index b9e0e1378f..ffc39e8884 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -1403,6 +1403,7 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) openr2_chan_process_cas_signaling(r2chan); ftdmchan = openr2_chan_get_client_data(r2chan); + ftdm_channel_set_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS); } memset(&start, 0, sizeof(start)); @@ -1461,12 +1462,6 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) ftdmchan = openr2_chan_get_client_data(r2chan); r2call = R2CALL(ftdmchan); - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_UP)) { - ftdm_channel_set_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS); - } else { - ftdm_channel_clear_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS); - } - ftdm_mutex_lock(ftdmchan->mutex); ftdm_r2_state_advance_all(ftdmchan); openr2_chan_process_signaling(r2chan); From ed5266d3ca944036165a26d06eac3a3fcd0b88a5 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 29 Nov 2010 15:34:27 -0600 Subject: [PATCH 123/237] don't parse events for b legs from a leg thread in case they are using a monolothic python script as a group_confirm exec over socket to send it messages while the call is ringing --- src/switch_ivr_originate.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/switch_ivr_originate.c b/src/switch_ivr_originate.c index da76cf6cbc..f99ac69188 100644 --- a/src/switch_ivr_originate.c +++ b/src/switch_ivr_originate.c @@ -635,8 +635,15 @@ static uint8_t check_channel_status(originate_global_t *oglobals, originate_stat } } } - - switch_ivr_parse_all_events(originate_status[i].peer_session); + + if (!switch_channel_test_flag(originate_status[i].peer_channel, CF_PARK) && + !switch_channel_test_flag(originate_status[i].peer_channel, CF_CONSUME_ON_ORIGINATE)) { + if (switch_channel_test_flag(originate_status[i].peer_channel, CF_THREAD_SLEEPING)) { + switch_core_session_wake_session_thread(originate_status[i].peer_session); + } else { + switch_ivr_parse_all_events(originate_status[i].peer_session); + } + } state = switch_channel_get_state(originate_status[i].peer_channel); if (state >= CS_HANGUP || state == CS_RESET || switch_channel_test_flag(originate_status[i].peer_channel, CF_TRANSFER) || From 7630d47e0e9efb0cea1f2a2ae7f908fee43d80a3 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Mon, 29 Nov 2010 21:55:34 -0600 Subject: [PATCH 124/237] VS2010 Initial version for freetdm --- libs/freetdm/freetdm.2010.sln | 137 +++++++++++ libs/freetdm/msvc/freetdm.2010.vcxproj | 223 ++++++++++++++++++ .../freetdm/msvc/freetdm.2010.vcxproj.filters | 128 ++++++++++ .../msvc/testanalog/testanalog.2010.vcxproj | 213 +++++++++++++++++ .../testanalog.2010.vcxproj.filters | 14 ++ .../msvc/testboost/testboost.2010.vcxproj | 218 +++++++++++++++++ .../testboost/testboost.2010.vcxproj.filters | 14 ++ .../testboost/testsangomaboost.2010.vcxproj | 218 +++++++++++++++++ .../testsangomaboost.2010.vcxproj.filters | 14 ++ .../msvc/testisdn/testisdn.2010.vcxproj | 213 +++++++++++++++++ .../testisdn/testisdn.2010.vcxproj.filters | 14 ++ .../ftmod_analog/ftmod_analog.2010.vcxproj | 198 ++++++++++++++++ .../ftmod_analog.2010.vcxproj.filters | 23 ++ .../ftmod_analog_em.2010.vcxproj | 198 ++++++++++++++++ .../ftmod_analog_em.2010.vcxproj.filters | 23 ++ .../ftmod/ftmod_isdn/ftmod_isdn.2010.vcxproj | 223 ++++++++++++++++++ .../ftmod_isdn.2010.vcxproj.filters | 110 +++++++++ .../ftmod/ftmod_pika/ftmod_pika.2010.vcxproj | 198 ++++++++++++++++ .../ftmod_pika.2010.vcxproj.filters | 23 ++ .../src/ftmod/ftmod_r2/ftmod_r2.2010.vcxproj | 95 ++++++++ .../ftmod_r2/ftmod_r2.2010.vcxproj.filters | 22 ++ .../ftmod_sangoma_boost.2010.vcxproj | 206 ++++++++++++++++ .../ftmod_sangoma_boost.2010.vcxproj.filters | 35 +++ .../ftmod_sangoma_isdn.2010.vcxproj | 121 ++++++++++ .../ftmod_sangoma_isdn.2010.vcxproj.filters | 57 +++++ .../ftmod_wanpipe/ftmod_wanpipe.2010.vcxproj | 201 ++++++++++++++++ .../ftmod_wanpipe.2010.vcxproj.filters | 18 ++ 27 files changed, 3157 insertions(+) create mode 100644 libs/freetdm/freetdm.2010.sln create mode 100644 libs/freetdm/msvc/freetdm.2010.vcxproj create mode 100644 libs/freetdm/msvc/freetdm.2010.vcxproj.filters create mode 100644 libs/freetdm/msvc/testanalog/testanalog.2010.vcxproj create mode 100644 libs/freetdm/msvc/testanalog/testanalog.2010.vcxproj.filters create mode 100644 libs/freetdm/msvc/testboost/testboost.2010.vcxproj create mode 100644 libs/freetdm/msvc/testboost/testboost.2010.vcxproj.filters create mode 100644 libs/freetdm/msvc/testboost/testsangomaboost.2010.vcxproj create mode 100644 libs/freetdm/msvc/testboost/testsangomaboost.2010.vcxproj.filters create mode 100644 libs/freetdm/msvc/testisdn/testisdn.2010.vcxproj create mode 100644 libs/freetdm/msvc/testisdn/testisdn.2010.vcxproj.filters create mode 100644 libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.2010.vcxproj create mode 100644 libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.2010.vcxproj.filters create mode 100644 libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.2010.vcxproj create mode 100644 libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.2010.vcxproj.filters create mode 100644 libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.2010.vcxproj create mode 100644 libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.2010.vcxproj.filters create mode 100644 libs/freetdm/src/ftmod/ftmod_pika/ftmod_pika.2010.vcxproj create mode 100644 libs/freetdm/src/ftmod/ftmod_pika/ftmod_pika.2010.vcxproj.filters create mode 100644 libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2010.vcxproj create mode 100644 libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2010.vcxproj.filters create mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2010.vcxproj create mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2010.vcxproj.filters create mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2010.vcxproj create mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2010.vcxproj.filters create mode 100644 libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2010.vcxproj create mode 100644 libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2010.vcxproj.filters diff --git a/libs/freetdm/freetdm.2010.sln b/libs/freetdm/freetdm.2010.sln new file mode 100644 index 0000000000..1806e9ea23 --- /dev/null +++ b/libs/freetdm/freetdm.2010.sln @@ -0,0 +1,137 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "freetdm", "msvc\freetdm.2010.vcxproj", "{93B8812C-3EC4-4F78-8970-FFBFC99E167D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testanalog", "msvc\testanalog\testanalog.2010.vcxproj", "{BB833648-BAFF-4BE2-94DB-F8BB043C588C}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testisdn", "msvc\testisdn\testisdn.2010.vcxproj", "{6DA6FD42-641D-4147-92F5-3BC4AAA6589B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_freetdm", "mod_freetdm\mod_freetdm.2010.vcxproj", "{FE3540C5-3303-46E0-A69E-D92F775687F1}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_analog", "src\ftmod\ftmod_analog\ftmod_analog.2010.vcxproj", "{37C94798-6E33-4B4F-8EE0-C72A7DC91157}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_analog_em", "src\ftmod\ftmod_analog_em\ftmod_analog_em.2010.vcxproj", "{B3F49375-2834-4937-9D8C-4AC2EC911010}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_isdn", "src\ftmod\ftmod_isdn\ftmod_isdn.2010.vcxproj", "{729344A5-D5E9-434D-8EE8-AF8C6C795D15}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_pika", "src\ftmod\ftmod_pika\ftmod_pika.2010.vcxproj", "{E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_wanpipe", "src\ftmod\ftmod_wanpipe\ftmod_wanpipe.2010.vcxproj", "{1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_sangoma_boost", "src\ftmod\ftmod_sangoma_boost\ftmod_sangoma_boost.2010.vcxproj", "{D021EF2A-460D-4827-A0F7-41FDECF46F1B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testboost", "msvc\testboost\testboost.2010.vcxproj", "{2B1BAF36-0241-43E7-B865-A8338AD48E2E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testsangomaboost", "msvc\testboost\testsangomaboost.2010.vcxproj", "{0DA69C18-4FA1-4E8C-89CE-12498637C5BE}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_sangoma_isdn", "src\ftmod\ftmod_sangoma_isdn\ftmod_sangoma_isdn.2010.vcxproj", "{B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_r2", "src\ftmod\ftmod_r2\ftmod_r2.2010.vcxproj", "{08C3EA27-A51D-47F8-B47D-B189C649CF30}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Debug|Win32.ActiveCfg = Debug|Win32 + {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Debug|Win32.Build.0 = Debug|Win32 + {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Debug|x64.ActiveCfg = Debug|x64 + {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Debug|x64.Build.0 = Debug|x64 + {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Release|Win32.ActiveCfg = Release|Win32 + {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Release|Win32.Build.0 = Release|Win32 + {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Release|x64.ActiveCfg = Release|x64 + {93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Release|x64.Build.0 = Release|x64 + {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Debug|Win32.ActiveCfg = Debug|Win32 + {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Debug|Win32.Build.0 = Debug|Win32 + {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Debug|x64.ActiveCfg = Debug|x64 + {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Debug|x64.Build.0 = Debug|x64 + {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Release|Win32.ActiveCfg = Release|Win32 + {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Release|Win32.Build.0 = Release|Win32 + {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Release|x64.ActiveCfg = Release|x64 + {BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Release|x64.Build.0 = Release|x64 + {6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Debug|Win32.ActiveCfg = Debug|Win32 + {6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Debug|x64.ActiveCfg = Debug|x64 + {6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Release|Win32.ActiveCfg = Release|Win32 + {6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Release|x64.ActiveCfg = Release|x64 + {FE3540C5-3303-46E0-A69E-D92F775687F1}.Debug|Win32.ActiveCfg = Debug|Win32 + {FE3540C5-3303-46E0-A69E-D92F775687F1}.Debug|Win32.Build.0 = Debug|Win32 + {FE3540C5-3303-46E0-A69E-D92F775687F1}.Debug|x64.ActiveCfg = Debug|x64 + {FE3540C5-3303-46E0-A69E-D92F775687F1}.Debug|x64.Build.0 = Debug|x64 + {FE3540C5-3303-46E0-A69E-D92F775687F1}.Release|Win32.ActiveCfg = Release|Win32 + {FE3540C5-3303-46E0-A69E-D92F775687F1}.Release|Win32.Build.0 = Release|Win32 + {FE3540C5-3303-46E0-A69E-D92F775687F1}.Release|x64.ActiveCfg = Release|x64 + {FE3540C5-3303-46E0-A69E-D92F775687F1}.Release|x64.Build.0 = Release|x64 + {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Debug|Win32.ActiveCfg = Debug|Win32 + {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Debug|Win32.Build.0 = Debug|Win32 + {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Debug|x64.ActiveCfg = Debug|x64 + {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Debug|x64.Build.0 = Debug|x64 + {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Release|Win32.ActiveCfg = Release|Win32 + {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Release|Win32.Build.0 = Release|Win32 + {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Release|x64.ActiveCfg = Release|x64 + {37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Release|x64.Build.0 = Release|x64 + {B3F49375-2834-4937-9D8C-4AC2EC911010}.Debug|Win32.ActiveCfg = Debug|Win32 + {B3F49375-2834-4937-9D8C-4AC2EC911010}.Debug|Win32.Build.0 = Debug|Win32 + {B3F49375-2834-4937-9D8C-4AC2EC911010}.Debug|x64.ActiveCfg = Debug|x64 + {B3F49375-2834-4937-9D8C-4AC2EC911010}.Debug|x64.Build.0 = Debug|x64 + {B3F49375-2834-4937-9D8C-4AC2EC911010}.Release|Win32.ActiveCfg = Release|Win32 + {B3F49375-2834-4937-9D8C-4AC2EC911010}.Release|Win32.Build.0 = Release|Win32 + {B3F49375-2834-4937-9D8C-4AC2EC911010}.Release|x64.ActiveCfg = Release|x64 + {B3F49375-2834-4937-9D8C-4AC2EC911010}.Release|x64.Build.0 = Release|x64 + {729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Debug|Win32.ActiveCfg = Debug|Win32 + {729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Debug|x64.ActiveCfg = Debug|x64 + {729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Release|Win32.ActiveCfg = Release|Win32 + {729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Release|x64.ActiveCfg = Release|x64 + {E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}.Debug|Win32.ActiveCfg = Debug|Win32 + {E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}.Debug|x64.ActiveCfg = Debug|x64 + {E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}.Release|Win32.ActiveCfg = Release|Win32 + {E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}.Release|x64.ActiveCfg = Release|x64 + {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Debug|Win32.ActiveCfg = Debug|Win32 + {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Debug|Win32.Build.0 = Debug|Win32 + {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Debug|x64.ActiveCfg = Debug|x64 + {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Release|Win32.ActiveCfg = Release|Win32 + {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Release|x64.ActiveCfg = Release|x64 + {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Debug|Win32.ActiveCfg = Debug|Win32 + {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Debug|Win32.Build.0 = Debug|Win32 + {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Debug|x64.ActiveCfg = Debug|x64 + {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Debug|x64.Build.0 = Debug|x64 + {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Release|Win32.ActiveCfg = Release|Win32 + {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Release|Win32.Build.0 = Release|Win32 + {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Release|x64.ActiveCfg = Release|x64 + {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Release|x64.Build.0 = Release|x64 + {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Debug|Win32.ActiveCfg = Debug|Win32 + {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Debug|Win32.Build.0 = Debug|Win32 + {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Debug|x64.ActiveCfg = Debug|x64 + {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Debug|x64.Build.0 = Debug|x64 + {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Release|Win32.ActiveCfg = Release|Win32 + {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Release|Win32.Build.0 = Release|Win32 + {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Release|x64.ActiveCfg = Release|x64 + {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Release|x64.Build.0 = Release|x64 + {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Debug|Win32.ActiveCfg = Debug|Win32 + {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Debug|Win32.Build.0 = Debug|Win32 + {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Debug|x64.ActiveCfg = Debug|x64 + {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Debug|x64.Build.0 = Debug|x64 + {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|Win32.ActiveCfg = Release|Win32 + {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|Win32.Build.0 = Release|Win32 + {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|x64.ActiveCfg = Release|x64 + {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|x64.Build.0 = Release|x64 + {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Debug|Win32.ActiveCfg = Debug|Win32 + {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Debug|Win32.Build.0 = Debug|Win32 + {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Debug|x64.ActiveCfg = Debug|Win32 + {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|Win32.ActiveCfg = Release|Win32 + {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|Win32.Build.0 = Release|Win32 + {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|x64.ActiveCfg = Release|Win32 + {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Debug|Win32.ActiveCfg = Debug|Win32 + {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Debug|Win32.Build.0 = Debug|Win32 + {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Debug|x64.ActiveCfg = Debug|Win32 + {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Release|Win32.ActiveCfg = Release|Win32 + {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Release|Win32.Build.0 = Release|Win32 + {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Release|x64.ActiveCfg = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/libs/freetdm/msvc/freetdm.2010.vcxproj b/libs/freetdm/msvc/freetdm.2010.vcxproj new file mode 100644 index 0000000000..71eb6dbf22 --- /dev/null +++ b/libs/freetdm/msvc/freetdm.2010.vcxproj @@ -0,0 +1,223 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + freetdm + {93B8812C-3EC4-4F78-8970-FFBFC99E167D} + freetdm + Win32Proj + + + + DynamicLibrary + MultiByte + true + + + DynamicLibrary + MultiByte + + + DynamicLibrary + MultiByte + true + + + DynamicLibrary + MultiByte + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + $(IntDir)BuildLog-freetdm.htm + + + Disabled + ../src/include;../src/include/private;../src/isdn/include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;FREETDM_EXPORTS;TELETONE_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + false + false + + + Level4 + true + ProgramDatabase + CompileAsC + + + true + + + + + $(IntDir)BuildLog-freetdm.htm + + + ../src/include;../src/include/private;../src/isdn/include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;FREETDM_EXPORTS;TELETONE_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDLL + false + false + + + Level4 + true + ProgramDatabase + CompileAsC + + + + + $(IntDir)BuildLog-freetdm.htm + + + X64 + + + Disabled + ../src/include;../src/include/private;../src/isdn/include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;FREETDM_EXPORTS;TELETONE_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + false + false + + + Level4 + true + ProgramDatabase + CompileAsC + + + true + MachineX64 + + + + + $(IntDir)BuildLog-freetdm.htm + + + X64 + + + ../src/include;../src/include/private;../src/isdn/include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;FREETDM_EXPORTS;TELETONE_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDLL + false + false + + + Level4 + true + ProgramDatabase + CompileAsC + + + MachineX64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/freetdm/msvc/freetdm.2010.vcxproj.filters b/libs/freetdm/msvc/freetdm.2010.vcxproj.filters new file mode 100644 index 0000000000..ed642baf3d --- /dev/null +++ b/libs/freetdm/msvc/freetdm.2010.vcxproj.filters @@ -0,0 +1,128 @@ + + + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/libs/freetdm/msvc/testanalog/testanalog.2010.vcxproj b/libs/freetdm/msvc/testanalog/testanalog.2010.vcxproj new file mode 100644 index 0000000000..719dc618a9 --- /dev/null +++ b/libs/freetdm/msvc/testanalog/testanalog.2010.vcxproj @@ -0,0 +1,213 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + testanalog + {BB833648-BAFF-4BE2-94DB-F8BB043C588C} + testanalog + Win32Proj + + + + Application + Unicode + true + + + Application + Unicode + + + Application + Unicode + true + + + Application + Unicode + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + $(IntDir)BuildLog-testanalog.htm + + + Disabled + ../../src/include;../../src/isdn/include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + true + EditAndContinue + 4100;%(DisableSpecificWarnings) + + + true + Console + false + + + MachineX86 + + + + + $(IntDir)BuildLog-testanalog.htm + + + ../../src/include;../../src/isdn/include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + + + Level4 + true + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + true + Console + true + true + false + + + MachineX86 + + + + + $(IntDir)BuildLog-testanalog.htm + + + X64 + + + Disabled + ../../src/include;../../src/isdn/include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + true + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + true + Console + false + + + MachineX64 + + + + + $(IntDir)BuildLog-testanalog.htm + + + X64 + + + ../../src/include;../../src/isdn/include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + + + Level4 + true + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + true + Console + true + true + false + + + MachineX64 + + + + + + + + {93b8812c-3ec4-4f78-8970-ffbfc99e167d} + false + + + + + + \ No newline at end of file diff --git a/libs/freetdm/msvc/testanalog/testanalog.2010.vcxproj.filters b/libs/freetdm/msvc/testanalog/testanalog.2010.vcxproj.filters new file mode 100644 index 0000000000..7ac3635cc5 --- /dev/null +++ b/libs/freetdm/msvc/testanalog/testanalog.2010.vcxproj.filters @@ -0,0 +1,14 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Source Files + + + \ No newline at end of file diff --git a/libs/freetdm/msvc/testboost/testboost.2010.vcxproj b/libs/freetdm/msvc/testboost/testboost.2010.vcxproj new file mode 100644 index 0000000000..62061485c2 --- /dev/null +++ b/libs/freetdm/msvc/testboost/testboost.2010.vcxproj @@ -0,0 +1,218 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + testboost + {2B1BAF36-0241-43E7-B865-A8338AD48E2E} + testboost + Win32Proj + + + + Application + Unicode + true + + + Application + Unicode + + + Application + Unicode + true + + + Application + Unicode + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\testboost\$(Configuration)\ + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\testboost\$(Configuration)\ + false + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\testboost\$(Configuration)\ + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\testboost\$(Configuration)\ + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + $(IntDir)BuildLog-testboost.htm + + + Disabled + ../../src/include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + true + EditAndContinue + 4100;%(DisableSpecificWarnings) + + + ..\..\debug\freetdm.lib;%(AdditionalDependencies) + true + Console + false + + + MachineX86 + + + + + $(IntDir)BuildLog-testboost.htm + + + ../../src/include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + + + Level4 + true + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + true + Console + true + true + false + + + MachineX86 + + + + + $(IntDir)BuildLog-testboost.htm + + + X64 + + + Disabled + ../../src/include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + true + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + freetdm.lib;%(AdditionalDependencies) + true + Console + false + + + MachineX64 + ../../$(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories) + + + + + $(IntDir)BuildLog-testboost.htm + + + X64 + + + ../../src/include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + + + Level4 + true + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + true + Console + true + true + false + + + MachineX64 + freetdm.lib;%(AdditionalDependencies) + ../../$(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories) + + + + + + + + {93b8812c-3ec4-4f78-8970-ffbfc99e167d} + false + + + + + + \ No newline at end of file diff --git a/libs/freetdm/msvc/testboost/testboost.2010.vcxproj.filters b/libs/freetdm/msvc/testboost/testboost.2010.vcxproj.filters new file mode 100644 index 0000000000..74181d60a8 --- /dev/null +++ b/libs/freetdm/msvc/testboost/testboost.2010.vcxproj.filters @@ -0,0 +1,14 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Source Files + + + \ No newline at end of file diff --git a/libs/freetdm/msvc/testboost/testsangomaboost.2010.vcxproj b/libs/freetdm/msvc/testboost/testsangomaboost.2010.vcxproj new file mode 100644 index 0000000000..b6c0518883 --- /dev/null +++ b/libs/freetdm/msvc/testboost/testsangomaboost.2010.vcxproj @@ -0,0 +1,218 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + testsangomaboost + {0DA69C18-4FA1-4E8C-89CE-12498637C5BE} + testsangomaboost + Win32Proj + + + + Application + Unicode + true + + + Application + Unicode + + + Application + Unicode + true + + + Application + Unicode + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + $(IntDir)BuildLog-testsangomaboost.htm + + + Disabled + ../../src/include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + true + EditAndContinue + 4100;%(DisableSpecificWarnings) + + + ..\..\debug\freetdm.lib;%(AdditionalDependencies) + true + Console + false + + + MachineX86 + + + + + $(IntDir)BuildLog-testsangomaboost.htm + + + ../../src/include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + + + Level4 + true + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + true + Console + true + true + false + + + MachineX86 + + + + + $(IntDir)BuildLog-testsangomaboost.htm + + + X64 + + + Disabled + ../../src/include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + false + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + freetdm.lib;%(AdditionalDependencies) + true + Console + false + + + MachineX64 + ../../$(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories) + + + + + $(IntDir)BuildLog-testsangomaboost.htm + + + X64 + + + ../../src/include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + + + Level4 + true + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + true + Console + true + true + false + + + MachineX64 + freetdm.lib;%(AdditionalDependencies) + ../../$(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories) + + + + + + + + {93b8812c-3ec4-4f78-8970-ffbfc99e167d} + false + + + + + + \ No newline at end of file diff --git a/libs/freetdm/msvc/testboost/testsangomaboost.2010.vcxproj.filters b/libs/freetdm/msvc/testboost/testsangomaboost.2010.vcxproj.filters new file mode 100644 index 0000000000..e72f14e161 --- /dev/null +++ b/libs/freetdm/msvc/testboost/testsangomaboost.2010.vcxproj.filters @@ -0,0 +1,14 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Source Files + + + \ No newline at end of file diff --git a/libs/freetdm/msvc/testisdn/testisdn.2010.vcxproj b/libs/freetdm/msvc/testisdn/testisdn.2010.vcxproj new file mode 100644 index 0000000000..2dfdeb042f --- /dev/null +++ b/libs/freetdm/msvc/testisdn/testisdn.2010.vcxproj @@ -0,0 +1,213 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + testisdn + {6DA6FD42-641D-4147-92F5-3BC4AAA6589B} + testisdn + Win32Proj + + + + Application + Unicode + true + + + Application + Unicode + + + Application + Unicode + true + + + Application + Unicode + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + $(IntDir)BuildLog-testisdn.htm + + + Disabled + ../../src/include;../../src/isdn/include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + true + EditAndContinue + 4100;%(DisableSpecificWarnings) + + + true + Console + false + + + MachineX86 + + + + + $(IntDir)BuildLog-testisdn.htm + + + ../../src/include;../../src/isdn/include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + + + Level4 + true + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + true + Console + true + true + false + + + MachineX86 + + + + + $(IntDir)BuildLog-testisdn.htm + + + X64 + + + Disabled + ../../src/include;../../src/isdn/include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + true + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + true + Console + false + + + MachineX64 + + + + + $(IntDir)BuildLog-testisdn.htm + + + X64 + + + ../../src/include;../../src/isdn/include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + + + Level4 + true + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + true + Console + true + true + false + + + MachineX64 + + + + + + + + {93b8812c-3ec4-4f78-8970-ffbfc99e167d} + false + + + + + + \ No newline at end of file diff --git a/libs/freetdm/msvc/testisdn/testisdn.2010.vcxproj.filters b/libs/freetdm/msvc/testisdn/testisdn.2010.vcxproj.filters new file mode 100644 index 0000000000..9d48828d4a --- /dev/null +++ b/libs/freetdm/msvc/testisdn/testisdn.2010.vcxproj.filters @@ -0,0 +1,14 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Source Files + + + \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.2010.vcxproj b/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.2010.vcxproj new file mode 100644 index 0000000000..81cb93fa44 --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.2010.vcxproj @@ -0,0 +1,198 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + ftmod_analog + {37C94798-6E33-4B4F-8EE0-C72A7DC91157} + ftmod_analog + Win32Proj + + + + DynamicLibrary + Unicode + true + + + DynamicLibrary + Unicode + + + DynamicLibrary + Unicode + true + + + DynamicLibrary + Unicode + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\include;..\..\isdn\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + true + EditAndContinue + 4100;%(DisableSpecificWarnings) + + + true + Windows + MachineX86 + + + + + MaxSpeed + true + ..\..\include;..\..\isdn\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + Level4 + true + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + true + Windows + true + true + MachineX86 + + + + + X64 + + + Disabled + ..\..\include;..\..\isdn\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + false + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + true + Windows + MachineX64 + + + + + X64 + + + MaxSpeed + true + ..\..\include;..\..\isdn\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + Level4 + true + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + true + Windows + true + true + MachineX64 + + + + + + + + + + + {93b8812c-3ec4-4f78-8970-ffbfc99e167d} + false + + + + + + \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.2010.vcxproj.filters b/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.2010.vcxproj.filters new file mode 100644 index 0000000000..b6fed5927a --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.2010.vcxproj.filters @@ -0,0 +1,23 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.2010.vcxproj b/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.2010.vcxproj new file mode 100644 index 0000000000..44792df89f --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.2010.vcxproj @@ -0,0 +1,198 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + ftmod_analog_em + {B3F49375-2834-4937-9D8C-4AC2EC911010} + ftmod_analog_em + Win32Proj + + + + DynamicLibrary + Unicode + true + + + DynamicLibrary + Unicode + + + DynamicLibrary + Unicode + true + + + DynamicLibrary + Unicode + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\include;..\..\isdn\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EM_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + true + EditAndContinue + 4100;%(DisableSpecificWarnings) + + + true + Windows + MachineX86 + + + + + MaxSpeed + true + ..\..\include;..\..\isdn\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EM_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + Level4 + true + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + true + Windows + true + true + MachineX86 + + + + + X64 + + + Disabled + ..\..\include;..\..\isdn\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EM_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + false + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + true + Windows + MachineX64 + + + + + X64 + + + MaxSpeed + true + ..\..\include;..\..\isdn\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EM_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + Level4 + true + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + true + Windows + true + true + MachineX64 + + + + + + + + + + + {93b8812c-3ec4-4f78-8970-ffbfc99e167d} + false + + + + + + \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.2010.vcxproj.filters b/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.2010.vcxproj.filters new file mode 100644 index 0000000000..3326f9fd16 --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.2010.vcxproj.filters @@ -0,0 +1,23 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.2010.vcxproj b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.2010.vcxproj new file mode 100644 index 0000000000..bd2e2fe4f0 --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.2010.vcxproj @@ -0,0 +1,223 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + ftmod_isdn + {729344A5-D5E9-434D-8EE8-AF8C6C795D15} + ftmod_isdn + Win32Proj + + + + DynamicLibrary + Unicode + true + + + DynamicLibrary + Unicode + + + DynamicLibrary + Unicode + true + + + DynamicLibrary + Unicode + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + true + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + false + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\isdn\include;..\..\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_ISDN_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + true + EditAndContinue + + + true + Windows + MachineX86 + + + + + MaxSpeed + true + ..\..\isdn\include;..\..\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_ISDN_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + Level4 + true + ProgramDatabase + + + true + Windows + true + true + MachineX86 + + + + + X64 + + + Disabled + ..\..\isdn\include;..\..\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_ISDN_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + true + ProgramDatabase + + + true + Windows + MachineX64 + + + + + X64 + + + MaxSpeed + true + ..\..\isdn\include;..\..\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_ISDN_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + Level4 + true + ProgramDatabase + + + true + Windows + true + true + MachineX64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {93b8812c-3ec4-4f78-8970-ffbfc99e167d} + false + + + + + + \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.2010.vcxproj.filters b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.2010.vcxproj.filters new file mode 100644 index 0000000000..30824888fc --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.2010.vcxproj.filters @@ -0,0 +1,110 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_pika/ftmod_pika.2010.vcxproj b/libs/freetdm/src/ftmod/ftmod_pika/ftmod_pika.2010.vcxproj new file mode 100644 index 0000000000..c4004bda21 --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_pika/ftmod_pika.2010.vcxproj @@ -0,0 +1,198 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + ftmod_pika + {E886B4D5-AB4F-4092-B8F4-3B06E1E462EF} + ftmod_pika + Win32Proj + + + + DynamicLibrary + Unicode + true + + + DynamicLibrary + Unicode + + + DynamicLibrary + Unicode + true + + + DynamicLibrary + Unicode + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + true + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + false + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\isdn\include;..\..\include;..\..\..\pika\aoh\inc;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_PIKA_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level3 + EditAndContinue + + + pikahmpapi.lib;%(AdditionalDependencies) + ..\..\..\pika\aoh\lib;%(AdditionalLibraryDirectories) + true + Windows + MachineX86 + + + + + MaxSpeed + true + ..\..\isdn\include;..\..\include;..\..\..\pika\aoh\inc;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_PIKA_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + Level3 + ProgramDatabase + + + pikahmpapi.lib;%(AdditionalDependencies) + ..\..\..\pika\aoh\lib;%(AdditionalLibraryDirectories) + true + Windows + true + true + MachineX86 + + + + + X64 + + + Disabled + ..\..\isdn\include;..\..\include;..\..\..\pika\aoh\inc;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_PIKA_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level3 + ProgramDatabase + + + pikahmpapi.lib;%(AdditionalDependencies) + ..\..\..\pika\aoh\lib;%(AdditionalLibraryDirectories) + true + Windows + MachineX64 + + + + + X64 + + + MaxSpeed + true + ..\..\isdn\include;..\..\include;..\..\..\pika\aoh\inc;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_PIKA_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + Level3 + ProgramDatabase + + + pikahmpapi.lib;%(AdditionalDependencies) + ..\..\..\pika\aoh\lib;%(AdditionalLibraryDirectories) + true + Windows + true + true + MachineX64 + + + + + + + + + + + {93b8812c-3ec4-4f78-8970-ffbfc99e167d} + false + + + + + + \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_pika/ftmod_pika.2010.vcxproj.filters b/libs/freetdm/src/ftmod/ftmod_pika/ftmod_pika.2010.vcxproj.filters new file mode 100644 index 0000000000..4d4cec4668 --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_pika/ftmod_pika.2010.vcxproj.filters @@ -0,0 +1,23 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2010.vcxproj b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2010.vcxproj new file mode 100644 index 0000000000..f66f5afc0d --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2010.vcxproj @@ -0,0 +1,95 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + ftmod_r2 + {08C3EA27-A51D-47F8-B47D-B189C649CF30} + Win32Proj + + + + DynamicLibrary + + + DynamicLibrary + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + true + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + true + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\include;c:\Program Files\openr2\include\openr2;C:\Program Files\openr2\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_R2_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level3 + EditAndContinue + + + freetdm.lib;openr2.lib;%(AdditionalDependencies) + C:\Program Files\openr2\lib;$(OutDir);%(AdditionalLibraryDirectories) + true + Windows + MachineX86 + + + + + ..\..\include;C:\Program Files\openr2\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_R2_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDLL + + + Level3 + ProgramDatabase + + + true + Windows + true + true + MachineX86 + + + + + + + + + \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2010.vcxproj.filters b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2010.vcxproj.filters new file mode 100644 index 0000000000..9c91228e09 --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2010.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Source Files + + + \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2010.vcxproj b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2010.vcxproj new file mode 100644 index 0000000000..1dd09211e2 --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2010.vcxproj @@ -0,0 +1,206 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + ftmod_sangoma_boost + {D021EF2A-460D-4827-A0F7-41FDECF46F1B} + ftmod_sangoma_boost + Win32Proj + + + + DynamicLibrary + Unicode + true + + + DynamicLibrary + Unicode + + + DynamicLibrary + Unicode + true + + + DynamicLibrary + Unicode + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + true + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + false + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\include;..\..\isdn\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_SANGOMA_BOOST_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + true + EditAndContinue + 4100;%(DisableSpecificWarnings) + + + freetdm.lib;%(AdditionalDependencies) + $(OutDir);%(AdditionalLibraryDirectories) + true + Windows + MachineX86 + + + + + MaxSpeed + true + ..\..\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_SANGOMA_BOOST_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + Level4 + true + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + true + Windows + true + true + MachineX86 + + + + + X64 + + + Disabled + ..\..\include;..\..\isdn\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_SANGOMA_BOOST_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + true + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + freetdm.lib;%(AdditionalDependencies) + $(OutDir);%(AdditionalLibraryDirectories) + true + Windows + MachineX64 + + + + + X64 + + + MaxSpeed + true + ..\..\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_SANGOMA_BOOST_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + Level4 + true + ProgramDatabase + 4100;%(DisableSpecificWarnings) + + + true + Windows + true + true + MachineX64 + + + + + + + + + + + + + + + {93b8812c-3ec4-4f78-8970-ffbfc99e167d} + false + + + + + + \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2010.vcxproj.filters b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2010.vcxproj.filters new file mode 100644 index 0000000000..2aeed155cd --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2010.vcxproj.filters @@ -0,0 +1,35 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2010.vcxproj b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2010.vcxproj new file mode 100644 index 0000000000..b4d234cc7d --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2010.vcxproj @@ -0,0 +1,121 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + ftmod_sangoma_isdn + {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395} + ftmod_sangoma_isdn + Win32Proj + + + + DynamicLibrary + true + + + DynamicLibrary + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + true + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + true + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + C:\Program Files\libsng_isdn\include;C:\Program Files\libsng_isdn\include\sng_isdn;../../include;C:\Program Files\Sangoma\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + EnableFastChecks + + + Level3 + EditAndContinue + + + freetdm.lib;libsng_isdn.lib;%(AdditionalDependencies) + $(OutDir);C:\Program Files\libsng_isdn\lib;C:\Program Files\Sangoma\api\lib\x86;%(AdditionalLibraryDirectories) + true + Console + false + + + MachineX86 + + + + + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level3 + ProgramDatabase + + + true + Windows + true + true + MachineX86 + + + + + + + + + + + + + + + + + + + + + {93b8812c-3ec4-4f78-8970-ffbfc99e167d} + false + + + + + + \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2010.vcxproj.filters b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2010.vcxproj.filters new file mode 100644 index 0000000000..5f592fa9ef --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2010.vcxproj.filters @@ -0,0 +1,57 @@ + + + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2010.vcxproj b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2010.vcxproj new file mode 100644 index 0000000000..b165ac82d3 --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2010.vcxproj @@ -0,0 +1,201 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + ftmod_wanpipe + {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD} + ftmod_wanpipe + Win32Proj + + + + DynamicLibrary + MultiByte + true + + + DynamicLibrary + MultiByte + + + DynamicLibrary + MultiByte + true + + + DynamicLibrary + MultiByte + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + true + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + false + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ../../include;C:\Program Files\Sangoma\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level3 + EditAndContinue + + + freetdm.lib;libsangoma.lib;%(AdditionalDependencies) + $(OutDir);C:\Program Files\Sangoma\api\lib\x86;%(AdditionalLibraryDirectories) + true + Console + false + + + MachineX86 + + + + + X64 + + + Disabled + ../../include;C:\Program Files\Sangoma\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level3 + ProgramDatabase + + + freetdm.lib;libsangoma.lib;%(AdditionalDependencies) + $(OutDir);C:\Program Files\Sangoma\api\lib\x64;%(AdditionalLibraryDirectories) + true + Console + false + + + MachineX64 + + + + + ../../include;C:\Program Files\Sangoma\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + + + Level3 + ProgramDatabase + + + freetdm.lib;libsangoma.lib;%(AdditionalDependencies) + $(OutDir);C:\Program Files\Sangoma\api\lib\x86;%(AdditionalLibraryDirectories) + true + Console + true + true + false + + + MachineX86 + + + + + X64 + + + ../../include;C:\Program Files\Sangoma\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + + + Level3 + ProgramDatabase + + + freetdm.lib;libsangoma.lib;%(AdditionalDependencies) + $(OutDir);C:\Program Files\Sangoma\api\lib\x64;%(AdditionalLibraryDirectories) + true + Console + true + true + false + + + MachineX64 + + + + + + + + {93b8812c-3ec4-4f78-8970-ffbfc99e167d} + false + + + + + + \ No newline at end of file diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2010.vcxproj.filters b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2010.vcxproj.filters new file mode 100644 index 0000000000..15a8bc3d35 --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2010.vcxproj.filters @@ -0,0 +1,18 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + + + Source Files + + + \ No newline at end of file From 8b0421ff6815457ac9b21223db2bbe338cd782f0 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 30 Nov 2010 09:49:12 -0600 Subject: [PATCH 125/237] add new function to check when messages need parsing to improve performance on parsing messages during originate --- src/include/switch_core.h | 5 +++++ src/switch_core_session.c | 15 +++++++++++++++ src/switch_ivr_originate.c | 10 ++++++---- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 3f636d00c4..231b26f269 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -1024,6 +1024,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_queue_event(_In_ switch_core */ SWITCH_DECLARE(uint32_t) switch_core_session_event_count(_In_ switch_core_session_t *session); +/* + Number of parsable messages waiting on the session. + */ +SWITCH_DECLARE(uint32_t) switch_core_session_messages_waiting(switch_core_session_t *session); + /*! \brief DE-Queue an event on a given session \param session the session to de-queue the message on diff --git a/src/switch_core_session.c b/src/switch_core_session.c index eca2f8daf2..aaa47cc696 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -861,6 +861,21 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_queue_event(switch_core_sess return status; } +SWITCH_DECLARE(uint32_t) switch_core_session_messages_waiting(switch_core_session_t *session) +{ + int x = 0; + + if (session->private_event_queue) { + x += switch_queue_size(session->private_event_queue); + } + + if (session->message_queue) { + x += switch_queue_size(session->message_queue); + } + + return x; +} + SWITCH_DECLARE(uint32_t) switch_core_session_event_count(switch_core_session_t *session) { if (session->event_queue) { diff --git a/src/switch_ivr_originate.c b/src/switch_ivr_originate.c index f99ac69188..e61534798b 100644 --- a/src/switch_ivr_originate.c +++ b/src/switch_ivr_originate.c @@ -638,10 +638,12 @@ static uint8_t check_channel_status(originate_global_t *oglobals, originate_stat if (!switch_channel_test_flag(originate_status[i].peer_channel, CF_PARK) && !switch_channel_test_flag(originate_status[i].peer_channel, CF_CONSUME_ON_ORIGINATE)) { - if (switch_channel_test_flag(originate_status[i].peer_channel, CF_THREAD_SLEEPING)) { - switch_core_session_wake_session_thread(originate_status[i].peer_session); - } else { - switch_ivr_parse_all_events(originate_status[i].peer_session); + if (switch_core_session_messages_waiting(originate_status[i].peer_session)) { + if (switch_channel_test_flag(originate_status[i].peer_channel, CF_THREAD_SLEEPING)) { + switch_core_session_wake_session_thread(originate_status[i].peer_session); + } else { + switch_ivr_parse_all_events(originate_status[i].peer_session); + } } } From bce61e7f926ca424c04340d217ac5ee3246fe454 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Tue, 30 Nov 2010 10:49:23 -0500 Subject: [PATCH 126/237] freetdm: ftmod_wanpipe - use SANGOMA_WAIT_INFINITE instead of -1 --- libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c index c20ad82a3b..65c587c350 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c @@ -121,6 +121,10 @@ static __inline__ int tdmv_api_wait_socket(ftdm_channel_t *ftdmchan, int timeout uint32_t outflags = 0; sangoma_wait_obj_t *sangoma_wait_obj = ftdmchan->io_data; + if (timeout == -1) { + timeout = SANGOMA_WAIT_INFINITE; + } + err = sangoma_waitfor(sangoma_wait_obj, inflags, &outflags, timeout); *flags = 0; if (err == SANG_STATUS_SUCCESS) { From 136fc8aa954cf7154b75a72297e76b94cb92e3c3 Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Tue, 30 Nov 2010 13:56:29 -0200 Subject: [PATCH 127/237] freetdm: ftmod_wanpipe - removed 80% tx/rx queue warnings --- .../src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c index 804c6cfe8f..17f0219b1f 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c @@ -789,16 +789,6 @@ static void wanpipe_write_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_tx_hdr_t *t ftdmchan->iostats.tx.queue_size = tx_stats->wp_api_tx_hdr_max_queue_length; ftdmchan->iostats.tx.queue_len = tx_stats->wp_api_tx_hdr_number_of_frames_in_queue; - if (ftdmchan->iostats.tx.queue_len >= (0.8 * ftdmchan->iostats.tx.queue_size)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Tx Queue length exceeded 80% threshold (%d/%d)\n", - ftdmchan->iostats.tx.queue_len, ftdmchan->iostats.tx.queue_size); - ftdm_set_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_THRES); - } else if (ftdm_test_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_THRES)){ - ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Tx Queue length reduced 80% threshold (%d/%d)\n", - ftdmchan->iostats.tx.queue_len, ftdmchan->iostats.tx.queue_size); - ftdm_clear_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_THRES); - } - if (ftdmchan->iostats.tx.queue_len >= ftdmchan->iostats.rx.queue_size) { ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Tx Queue Full (%d/%d)\n", ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); @@ -860,17 +850,6 @@ static void wanpipe_read_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_rx_hdr_t *rx ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_FRAME); } - if (ftdmchan->iostats.rx.queue_len >= (0.8 * ftdmchan->iostats.rx.queue_size)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Rx Queue length exceeded 80% threshold (%d/%d)\n", - ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); - ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES); - } else if (ftdm_test_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES)){ - /* any reason we have wanpipe_tdm_api_iface.h in ftmod_wanpipe/ dir? */ - ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Rx Queue length reduced 80% threshold (%d/%d)\n", - ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); - ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES); - } - if (ftdmchan->iostats.rx.queue_len >= ftdmchan->iostats.rx.queue_size) { ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Rx Queue Full (%d/%d)\n", ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); From a523e7755c111023ec767e298206fd7657693b94 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Tue, 30 Nov 2010 11:07:40 -0500 Subject: [PATCH 128/237] freetdm: get rid of Linux warnings in testsangomaboost.c --- libs/freetdm/src/testsangomaboost.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libs/freetdm/src/testsangomaboost.c b/libs/freetdm/src/testsangomaboost.c index 38eac3c190..85b5332635 100644 --- a/libs/freetdm/src/testsangomaboost.c +++ b/libs/freetdm/src/testsangomaboost.c @@ -45,10 +45,14 @@ #include -#include "freetdm.h" #include #include #include +#ifdef __linux__ +#define __USE_BSD +#include +#endif +#include "freetdm.h" /* arbitrary limit for max calls in this sample program */ @@ -338,9 +342,9 @@ int main(int argc, char *argv[]) exit(-1); } - if (!strcasecmp(argv[2], "cpe")) { + if (!strcmp(argv[2], "cpe")) { sigtype = "pri_cpe"; - } else if (!strcasecmp(argv[2], "net")) { + } else if (!strcmp(argv[2], "net")) { sigtype = "pri_net"; } else { fprintf(stderr, "Valid signaling types are cpe and net only\n"); From 006b3165cf7d0e512e4b3d7ed23c92f2bedb1d22 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 30 Nov 2010 19:35:38 +0300 Subject: [PATCH 129/237] fix issues with Progress message type if pre_answer enabled --- src/mod/endpoints/mod_h323/changes.txt | 1 + src/mod/endpoints/mod_h323/mod_h323.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_h323/changes.txt b/src/mod/endpoints/mod_h323/changes.txt index 19aca46dc8..c01542e2d3 100644 --- a/src/mod/endpoints/mod_h323/changes.txt +++ b/src/mod/endpoints/mod_h323/changes.txt @@ -1,3 +1,4 @@ +fix issues with Progress message type if pre_answer enabled fix crashes on FSH323Connection calls in on_hangup routine in different threads. move PTrace level set to FSH323EndPoint::Initialise partially apply patch from from Peter Olsson, Remove UnLock() when TryLock() failed and DEBUG_RTP_PACKETS directive. diff --git a/src/mod/endpoints/mod_h323/mod_h323.cpp b/src/mod/endpoints/mod_h323/mod_h323.cpp index 142506dd92..6365f9cc0c 100644 --- a/src/mod/endpoints/mod_h323/mod_h323.cpp +++ b/src/mod/endpoints/mod_h323/mod_h323.cpp @@ -1148,7 +1148,7 @@ void FSH323Connection::AnsweringCall(AnswerCallResponse response) if (!mediaWaitForConnect) { // create a new facility PDU if doing AnswerDeferredWithMedia H323SignalPDU want245PDU; - //H225_Progress_UUIE & prog = want245PDU.BuildProgress(*this); + want245PDU.BuildProgress(*this); PBoolean sendPDU = TRUE; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE,"mediaWaitForConnect = FALSE\n"); /* if (SendFastStartAcknowledge(prog.m_fastStart)){ From 469728a8656431e334e77d92d398cca05fa6c4a0 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Tue, 30 Nov 2010 11:38:38 -0500 Subject: [PATCH 130/237] freetdm: clear out wait flags in the core on timeout --- libs/freetdm/src/ftdm_io.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 6f543304a2..4df4d81fe1 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -2828,21 +2828,17 @@ done: FT_DECLARE(ftdm_status_t) ftdm_channel_wait(ftdm_channel_t *ftdmchan, ftdm_wait_flag_t *flags, int32_t to) { - assert(ftdmchan != NULL); - assert(ftdmchan->fio != NULL); + ftdm_status_t status = FTDM_FAIL; + ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "Null channel\n"); + ftdm_assert_return(ftdmchan->fio != NULL, FTDM_FAIL, "Null io interface\n"); + ftdm_assert_return(ftdmchan->fio->wait != NULL, FTDM_NOTIMPL, "wait method not implemented\n"); - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "channel not open"); - return FTDM_FAIL; - } - - if (!ftdmchan->fio->wait) { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "method not implemented"); - return FTDM_FAIL; + status = ftdmchan->fio->wait(ftdmchan, flags, to); + if (status == FTDM_TIMEOUT) { + /* make sure the flags are cleared on timeout */ + *flags = 0; } - - return ftdmchan->fio->wait(ftdmchan, flags, to); - + return status; } /*******************************/ From ef4a4ed03498769c34bfbb22fce1e100a3e3b5e8 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 30 Nov 2010 11:01:54 -0600 Subject: [PATCH 131/237] run execute_on_answer on_media _on_ring apps async --- src/include/switch_core.h | 2 ++ src/switch_channel.c | 21 ++++++++++++++++++--- src/switch_core_session.c | 26 ++++++++++++++++++++++++++ src/switch_ivr_bridge.c | 12 +----------- 4 files changed, 47 insertions(+), 14 deletions(-) diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 231b26f269..33df7e31dd 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -882,6 +882,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_exec(_In_ switch_core_sessio SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application_get_flags(_In_ switch_core_session_t *session, _In_ const char *app, _In_opt_z_ const char *arg, _Out_opt_ int32_t *flags); +SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application_async(switch_core_session_t *session, const char *app, const char *arg); + SWITCH_DECLARE(switch_status_t) switch_core_session_get_app_flags(const char *app, int32_t *flags); /*! diff --git a/src/switch_channel.c b/src/switch_channel.c index c63a1aadb9..a9c87c5954 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -2518,7 +2518,12 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_ring_ready_value(swi if ((arg = strchr(app, ' '))) { *arg++ = '\0'; } - switch_core_session_execute_application(channel->session, app, arg); + + if (switch_core_session_in_thread(channel->session)) { + switch_core_session_execute_application(channel->session, app, arg); + } else { + switch_core_session_execute_application_async(channel->session, app, arg); + } } return SWITCH_STATUS_SUCCESS; @@ -2571,7 +2576,12 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_pre_answered(switch_ if ((arg = strchr(app, ' '))) { *arg++ = '\0'; } - switch_core_session_execute_application(channel->session, app, arg); + + if (switch_core_session_in_thread(channel->session)) { + switch_core_session_execute_application(channel->session, app, arg); + } else { + switch_core_session_execute_application_async(channel->session, app, arg); + } } if ((var = switch_channel_get_variable(channel, SWITCH_PASSTHRU_PTIME_MISMATCH_VARIABLE))) { @@ -2750,7 +2760,12 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_answered(switch_chan } switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "%s execute on answer: %s(%s)\n", channel->name, app, switch_str_nil(arg)); - switch_core_session_execute_application(channel->session, app, arg); + + if (switch_core_session_in_thread(channel->session)) { + switch_core_session_execute_application(channel->session, app, arg); + } else { + switch_core_session_execute_application_async(channel->session, app, arg); + } } } diff --git a/src/switch_core_session.c b/src/switch_core_session.c index aaa47cc696..a84bfabaf0 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -855,6 +855,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_queue_event(switch_core_sess if (switch_queue_trypush(session->event_queue, *event) == SWITCH_STATUS_SUCCESS) { *event = NULL; status = SWITCH_STATUS_SUCCESS; + + if (switch_channel_test_flag(session->channel, CF_PROXY_MODE) || switch_channel_test_flag(session->channel, CF_THREAD_SLEEPING)) { + switch_core_session_wake_session_thread(session); + } } } @@ -1814,6 +1818,28 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_get_app_flags(const char *ap } +SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application_async(switch_core_session_t *session, const char *app, const char *arg) +{ + switch_event_t *execute_event; + + if (switch_event_create(&execute_event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "call-command", "execute"); + switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-name", app); + + if (arg) { + switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-arg", arg); + } + + switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "event-lock", "true"); + switch_core_session_queue_private_event(session, &execute_event, SWITCH_FALSE); + + return SWITCH_STATUS_SUCCESS; + } + + return SWITCH_STATUS_FALSE; +} + + SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application_get_flags(switch_core_session_t *session, const char *app, const char *arg, int32_t *flags) { diff --git a/src/switch_ivr_bridge.c b/src/switch_ivr_bridge.c index 4cae1a67e2..4d320d0e5c 100644 --- a/src/switch_ivr_bridge.c +++ b/src/switch_ivr_bridge.c @@ -348,20 +348,10 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj) if (read_frame_count > DEFAULT_LEAD_FRAMES && switch_channel_media_ack(chan_a)) { if (exec_app) { - switch_event_t *execute_event; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session_a), SWITCH_LOG_DEBUG, "%s Bridge execute app %s(%s)\n", switch_channel_get_name(chan_a), exec_app, exec_data); - if (switch_event_create(&execute_event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "call-command", "execute"); - switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-name", exec_app); - if (exec_data) { - switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-arg", exec_data); - } - //switch_event_add_header(execute_event, SWITCH_STACK_BOTTOM, "lead-frames", "%d", 5); - switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "event-lock", "true"); - switch_core_session_queue_private_event(session_a, &execute_event, SWITCH_FALSE); - } + switch_core_session_execute_application_async(session_a, exec_app, exec_data); exec_app = exec_data = NULL; } From 5b15e03f30eabcba91b0c1bec09a489221bbaaaa Mon Sep 17 00:00:00 2001 From: Brian West Date: Tue, 30 Nov 2010 11:24:59 -0600 Subject: [PATCH 132/237] swigall --- .../languages/mod_managed/freeswitch_wrap.cxx | 28 +++++++++++++++++++ src/mod/languages/mod_managed/managed/swig.cs | 16 +++++++++++ 2 files changed, 44 insertions(+) diff --git a/src/mod/languages/mod_managed/freeswitch_wrap.cxx b/src/mod/languages/mod_managed/freeswitch_wrap.cxx index ca001f64b1..d2f63b1006 100644 --- a/src/mod/languages/mod_managed/freeswitch_wrap.cxx +++ b/src/mod/languages/mod_managed/freeswitch_wrap.cxx @@ -7626,6 +7626,22 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_session_execute_application_get_fl } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_session_execute_application_async(void * jarg1, char * jarg2, char * jarg3) { + int jresult ; + switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; + char *arg2 = (char *) 0 ; + char *arg3 = (char *) 0 ; + switch_status_t result; + + arg1 = (switch_core_session_t *)jarg1; + arg2 = (char *)jarg2; + arg3 = (char *)jarg3; + result = (switch_status_t)switch_core_session_execute_application_async(arg1,(char const *)arg2,(char const *)arg3); + jresult = result; + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_session_get_app_flags(char * jarg1, void * jarg2) { int jresult ; char *arg1 = (char *) 0 ; @@ -7856,6 +7872,18 @@ SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_core_session_event_count(void } +SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_core_session_messages_waiting(void * jarg1) { + unsigned long jresult ; + switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; + uint32_t result; + + arg1 = (switch_core_session_t *)jarg1; + result = (uint32_t)switch_core_session_messages_waiting(arg1); + jresult = (unsigned long)result; + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_session_dequeue_event(void * jarg1, void * jarg2, int jarg3) { int jresult ; switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; diff --git a/src/mod/languages/mod_managed/managed/swig.cs b/src/mod/languages/mod_managed/managed/swig.cs index bd901911ed..fd4915f013 100644 --- a/src/mod/languages/mod_managed/managed/swig.cs +++ b/src/mod/languages/mod_managed/managed/swig.cs @@ -1439,6 +1439,11 @@ public class freeswitch { return ret; } + public static switch_status_t switch_core_session_execute_application_async(SWIGTYPE_p_switch_core_session session, string app, string arg) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_session_execute_application_async(SWIGTYPE_p_switch_core_session.getCPtr(session), app, arg); + return ret; + } + public static switch_status_t switch_core_session_get_app_flags(string app, SWIGTYPE_p_int flags) { switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_session_get_app_flags(app, SWIGTYPE_p_int.getCPtr(flags)); return ret; @@ -1518,6 +1523,11 @@ public class freeswitch { return ret; } + public static uint switch_core_session_messages_waiting(SWIGTYPE_p_switch_core_session session) { + uint ret = freeswitchPINVOKE.switch_core_session_messages_waiting(SWIGTYPE_p_switch_core_session.getCPtr(session)); + return ret; + } + public static switch_status_t switch_core_session_dequeue_event(SWIGTYPE_p_switch_core_session session, SWIGTYPE_p_p_switch_event arg1, switch_bool_t force) { switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_session_dequeue_event(SWIGTYPE_p_switch_core_session.getCPtr(session), SWIGTYPE_p_p_switch_event.getCPtr(arg1), (int)force); return ret; @@ -7449,6 +7459,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_execute_application_get_flags")] public static extern int switch_core_session_execute_application_get_flags(HandleRef jarg1, string jarg2, string jarg3, HandleRef jarg4); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_execute_application_async")] + public static extern int switch_core_session_execute_application_async(HandleRef jarg1, string jarg2, string jarg3); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_get_app_flags")] public static extern int switch_core_session_get_app_flags(string jarg1, HandleRef jarg2); @@ -7497,6 +7510,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_event_count")] public static extern uint switch_core_session_event_count(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_messages_waiting")] + public static extern uint switch_core_session_messages_waiting(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_dequeue_event")] public static extern int switch_core_session_dequeue_event(HandleRef jarg1, HandleRef jarg2, int jarg3); From 302d5bb18f5604c180d1eb3c48b80929e1b306ae Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Thu, 25 Nov 2010 19:19:32 -0500 Subject: [PATCH 133/237] Changes for ftdm variables --- libs/freetdm/mod_freetdm/mod_freetdm.c | 73 +++-- libs/freetdm/src/ftdm_call_utils.c | 135 +++++---- libs/freetdm/src/ftdm_io.c | 20 +- .../ftmod_sangoma_boost/ftdm_sangoma_boost.h | 2 +- .../ftmod_sangoma_boost/ftmod_sangoma_boost.c | 14 +- .../ftmod_sangoma_isdn/ftmod_sangoma_isdn.c | 11 +- .../ftmod_sangoma_isdn/ftmod_sangoma_isdn.h | 72 +++-- .../ftmod_sangoma_isdn_cfg.c | 97 +++--- .../ftmod_sangoma_isdn_stack_hndl.c | 99 +++--- .../ftmod_sangoma_isdn_stack_out.c | 90 ++---- .../ftmod_sangoma_isdn_support.c | 285 ++++++++++++++++-- .../ftmod_sangoma_isdn_trace.c | 15 + .../ftmod_sangoma_isdn_trace.h | 6 + libs/freetdm/src/include/freetdm.h | 82 +++-- libs/freetdm/src/include/ftdm_call_utils.h | 118 ++++++++ libs/freetdm/src/include/ftdm_declare.h | 17 ++ .../src/include/private/ftdm_call_utils.h | 47 --- 17 files changed, 792 insertions(+), 391 deletions(-) create mode 100644 libs/freetdm/src/include/ftdm_call_utils.h delete mode 100644 libs/freetdm/src/include/private/ftdm_call_utils.h diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 27dc8d8c92..07d4e88f33 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -149,6 +149,7 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id); static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id); static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig); +static const char* channel_get_variable(switch_core_session_t *session, switch_event_t *var_event, const char *variable_name); ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session_t **sp); void dump_chan(ftdm_span_t *span, uint32_t chan_id, switch_stream_handle_t *stream); void dump_chan_xml(ftdm_span_t *span, uint32_t chan_id, switch_stream_handle_t *stream); @@ -1049,6 +1050,27 @@ switch_io_routines_t freetdm_io_routines = { /*.receive_message*/ channel_receive_message }; +static const char* channel_get_variable(switch_core_session_t *session, switch_event_t *var_event, const char *variable_name) +{ + const char *variable = NULL; + + if (var_event) { + if ((variable = switch_event_get_header(var_event, variable_name))) { + return variable; + } + } + if (session) { + switch_channel_t *channel = switch_core_session_get_channel(session); + if ((variable = switch_channel_get_variable(channel, variable_name))) { + return variable; + } + } + if ((variable = switch_core_get_variable(variable_name))) { + return variable; + } + return NULL; +} + /* Make sure when you have 2 sessions in the same scope that you pass the appropriate one to the routines that allocate memory or you will have 1 channel with memory allocated from another channel's pool! */ @@ -1226,20 +1248,6 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi } } - if (session) { - /* take out some other values from the session if they're present */ - switch_channel_t *channel = switch_core_session_get_channel(session); - const char *freetdmvar; - freetdmvar = switch_channel_get_variable(channel, "freetdm_bearer_capability"); - if (freetdmvar) { - caller_data.bearer_capability = (uint8_t)atoi(freetdmvar); - } - freetdmvar = switch_channel_get_variable(channel, "freetdm_bearer_layer1"); - if (freetdmvar) { - caller_data.bearer_layer1 = (uint8_t)atoi(freetdmvar); - } - } - if (switch_test_flag(outbound_profile, SWITCH_CPF_SCREEN)) { caller_data.screen = 1; } @@ -1248,29 +1256,37 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi caller_data.pres = 1; } - if (!zstr(dest)) { - ftdm_set_string(caller_data.dnis.digits, dest); + if ((var = channel_get_variable(session, var_event, "freetdm_bearer_capability"))) { + caller_data.bearer_capability = (uint8_t)atoi(var); } - if ((var = switch_event_get_header(var_event, "freetdm_outbound_ton")) || (var = switch_core_get_variable("freetdm_outbound_ton"))) { - if (!strcasecmp(var, "national")) { - caller_data.dnis.type = FTDM_TON_NATIONAL; - } else if (!strcasecmp(var, "international")) { - caller_data.dnis.type = FTDM_TON_INTERNATIONAL; - } else if (!strcasecmp(var, "local")) { - caller_data.dnis.type = FTDM_TON_SUBSCRIBER_NUMBER; - } else if (!strcasecmp(var, "unknown")) { - caller_data.dnis.type = FTDM_TON_UNKNOWN; - } + if ((var = channel_get_variable(session, var_event, "freetdm_bearer_layer1"))) { + caller_data.bearer_layer1 = (uint8_t)atoi(var); + } + + if ((var = channel_get_variable(session, var_event, "freetdm_screening_ind"))) { + ftdm_set_screening_ind(var, &caller_data.screen); + } + + if ((var = channel_get_variable(session, var_event, "freetdm_presentation_ind"))) { + ftdm_set_presentation_ind(var, &caller_data.pres); + } + + if ((var = channel_get_variable(session, var_event, "freetdm_outbound_ton"))) { + ftdm_set_ton(var, &caller_data.dnis.type); } else { caller_data.dnis.type = outbound_profile->destination_number_ton; } - if ((var = switch_event_get_header(var_event, "freetdm_custom_call_data")) || (var = switch_core_get_variable("freetdm_custom_call_data"))) { + if ((var = channel_get_variable(session, var_event, "freetdm_custom_call_data"))) { ftdm_set_string(caller_data.raw_data, var); caller_data.raw_data_len = (uint32_t)strlen(var); } + if (!zstr(dest)) { + ftdm_set_string(caller_data.dnis.digits, dest); + } + caller_data.dnis.plan = outbound_profile->destination_number_numplan; /* blindly copy data from outbound_profile. They will be overwritten @@ -2074,6 +2090,9 @@ static FIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal) switch(sigmsg->event_id) { case FTDM_SIGEVENT_START: { + ftdm_channel_add_var(sigmsg->channel, "screening_ind", ftdm_screening2str(caller_data->screen)); + ftdm_channel_add_var(sigmsg->channel, "presentation_ind", ftdm_presentation2str(caller_data->pres)); + ftdm_enable_channel_dtmf(sigmsg->channel, NULL); return ftdm_channel_from_event(sigmsg, &session); } diff --git a/libs/freetdm/src/ftdm_call_utils.c b/libs/freetdm/src/ftdm_call_utils.c index d91b3bc9e2..52d2557a01 100644 --- a/libs/freetdm/src/ftdm_call_utils.c +++ b/libs/freetdm/src/ftdm_call_utils.c @@ -36,80 +36,101 @@ #include -FT_DECLARE(ftdm_status_t) ftdm_span_set_npi(const char *npi_string, uint8_t *target) +FT_DECLARE(ftdm_status_t) ftdm_set_npi(const char *string, uint8_t *target) { - if (!strcasecmp(npi_string, "isdn") || !strcasecmp(npi_string, "e164")) { - *target = FTDM_NPI_ISDN; - } else if (!strcasecmp(npi_string, "data")) { - *target = FTDM_NPI_DATA; - } else if (!strcasecmp(npi_string, "telex")) { - *target = FTDM_NPI_TELEX; - } else if (!strcasecmp(npi_string, "national")) { - *target = FTDM_NPI_NATIONAL; - } else if (!strcasecmp(npi_string, "private")) { - *target = FTDM_NPI_PRIVATE; - } else if (!strcasecmp(npi_string, "reserved")) { - *target = FTDM_NPI_RESERVED; - } else if (!strcasecmp(npi_string, "unknown")) { - *target = FTDM_NPI_UNKNOWN; - } else { - ftdm_log(FTDM_LOG_WARNING, "Invalid NPI value (%s)\n", npi_string); - *target = FTDM_NPI_UNKNOWN; - return FTDM_FAIL; + int val; + ftdm_status_t status = FTDM_SUCCESS; + + val = ftdm_str2ftdm_npi(string); + if (val == FTDM_NPI_INVALID) { + ftdm_log(FTDM_LOG_WARNING, "Invalid NPI string (%s)\n", string); + status = FTDM_FAIL; + val = FTDM_NPI_UNKNOWN; } - return FTDM_SUCCESS; + *target = val; + return status; } -FT_DECLARE(ftdm_status_t) ftdm_span_set_ton(const char *ton_string, uint8_t *target) +FT_DECLARE(ftdm_status_t) ftdm_set_ton(const char *string, uint8_t *target) { - if (!strcasecmp(ton_string, "national")) { - *target = FTDM_TON_NATIONAL; - } else if (!strcasecmp(ton_string, "international")) { - *target = FTDM_TON_INTERNATIONAL; - } else if (!strcasecmp(ton_string, "local")) { - *target = FTDM_TON_SUBSCRIBER_NUMBER; - } else if (!strcasecmp(ton_string, "unknown")) { - *target = FTDM_TON_UNKNOWN; - } else { - ftdm_log(FTDM_LOG_WARNING, "Invalid TON value (%s)\n", ton_string); - *target = FTDM_TON_UNKNOWN; - return FTDM_FAIL; + int val; + ftdm_status_t status = FTDM_SUCCESS; + + val = ftdm_str2ftdm_ton(string); + if (val == FTDM_TON_INVALID) { + ftdm_log(FTDM_LOG_WARNING, "Invalid TON string (%s)\n", string); + status = FTDM_FAIL; + val = FTDM_TON_UNKNOWN; } - return FTDM_SUCCESS; + *target = val; + return status; } -FT_DECLARE(ftdm_status_t) ftdm_span_set_bearer_capability(const char *bc_string, ftdm_bearer_cap_t *target) +FT_DECLARE(ftdm_status_t) ftdm_set_bearer_capability(const char *string, uint8_t *target) { - if (!strcasecmp(bc_string, "speech")) { - *target = FTDM_BEARER_CAP_SPEECH; - } else if (!strcasecmp(bc_string, "unrestricted-digital")) { - *target = FTDM_BEARER_CAP_64K_UNRESTRICTED; - } else if (!strcasecmp(bc_string, "3.1Khz")) { - *target = FTDM_BEARER_CAP_3_1KHZ_AUDIO; - } else { - ftdm_log(FTDM_LOG_WARNING, "Unsupported Bearer Capability value (%s)\n", bc_string); - return FTDM_FAIL; + int val; + ftdm_status_t status = FTDM_SUCCESS; + + val = ftdm_str2ftdm_bearer_cap(string); + if (val == FTDM_NPI_INVALID) { + ftdm_log(FTDM_LOG_WARNING, "Invalid Bearer-Capability string (%s)\n", string); + status = FTDM_FAIL; + val = FTDM_BEARER_CAP_SPEECH; } - return FTDM_SUCCESS; + + *target = val; + return status; } -FT_DECLARE(ftdm_status_t) ftdm_span_set_bearer_layer1(const char *bc_string, ftdm_user_layer1_prot_t *target) +FT_DECLARE(ftdm_status_t) ftdm_set_bearer_layer1(const char *string, uint8_t *target) { - if (!strcasecmp(bc_string, "v110")) { - *target = FTDM_USER_LAYER1_PROT_V110; - } else if (!strcasecmp(bc_string, "ulaw")) { - *target = FTDM_USER_LAYER1_PROT_ULAW; - } else if (!strcasecmp(bc_string, "alaw")) { - *target =FTDM_USER_LAYER1_PROT_ALAW ; - } else { - ftdm_log(FTDM_LOG_WARNING, "Unsupported Bearer Layer1 Prot value (%s)\n", bc_string); - return FTDM_FAIL; + int val; + ftdm_status_t status = FTDM_SUCCESS; + + val = ftdm_str2ftdm_usr_layer1_prot(string); + if (val == FTDM_USER_LAYER1_PROT_INVALID) { + ftdm_log(FTDM_LOG_WARNING, "Invalid Bearer Layer 1 Protocol string (%s)\n", string); + status = FTDM_FAIL; + val = FTDM_USER_LAYER1_PROT_ULAW; } - return FTDM_SUCCESS; + + *target = val; + return status; } +FT_DECLARE(ftdm_status_t) ftdm_set_screening_ind(const char *string, uint8_t *target) +{ + int val; + ftdm_status_t status = FTDM_SUCCESS; -FT_DECLARE(ftdm_status_t) ftdm_is_number(char *number) + val = ftdm_str2ftdm_screening(string); + if (val == FTDM_SCREENING_INVALID) { + ftdm_log(FTDM_LOG_WARNING, "Invalid screening indicator string (%s)\n", string); + status = FTDM_FAIL; + val = FTDM_SCREENING_NOT_SCREENED; + } + + *target = val; + return status; +} + +FT_DECLARE(ftdm_status_t) ftdm_set_presentation_ind(const char *string, uint8_t *target) +{ + int val; + ftdm_status_t status = FTDM_SUCCESS; + + val = ftdm_str2ftdm_presentation(string); + if (val == FTDM_PRES_INVALID) { + ftdm_log(FTDM_LOG_WARNING, "Invalid presentation string (%s)\n", string); + status = FTDM_FAIL; + val = FTDM_PRES_ALLOWED; + } + + *target = val; + return status; +} + +FT_DECLARE(ftdm_status_t) ftdm_is_number(const char *number) { if (!number) { return FTDM_FAIL; diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index ede3ff8fc8..3e48586a4e 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -150,6 +150,24 @@ FTDM_STR2ENUM(ftdm_str2ftdm_chan_type, ftdm_chan_type2str, ftdm_chan_type_t, CHA FTDM_ENUM_NAMES(SIGNALING_STATUS_NAMES, SIGSTATUS_STRINGS) FTDM_STR2ENUM(ftdm_str2ftdm_signaling_status, ftdm_signaling_status2str, ftdm_signaling_status_t, SIGNALING_STATUS_NAMES, FTDM_SIG_STATE_INVALID) +FTDM_ENUM_NAMES(TON_NAMES, TON_STRINGS) +FTDM_STR2ENUM(ftdm_str2ftdm_ton, ftdm_ton2str, ftdm_ton_t, TON_NAMES, FTDM_TON_INVALID) + +FTDM_ENUM_NAMES(NPI_NAMES, NPI_STRINGS) +FTDM_STR2ENUM(ftdm_str2ftdm_npi, ftdm_npi2str, ftdm_npi_t, NPI_NAMES, FTDM_NPI_INVALID) + +FTDM_ENUM_NAMES(PRESENTATION_NAMES, PRESENTATION_STRINGS) +FTDM_STR2ENUM(ftdm_str2ftdm_presentation, ftdm_presentation2str, ftdm_presentation_t, PRESENTATION_NAMES, FTDM_PRES_INVALID) + +FTDM_ENUM_NAMES(SCREENING_NAMES, SCREENING_STRINGS) +FTDM_STR2ENUM(ftdm_str2ftdm_screening, ftdm_screening2str, ftdm_screening_t, SCREENING_NAMES, FTDM_SCREENING_INVALID) + +FTDM_ENUM_NAMES(BEARER_CAP_NAMES, BEARER_CAP_STRINGS) +FTDM_STR2ENUM(ftdm_str2ftdm_bearer_cap, ftdm_bearer_cap2str, ftdm_bearer_cap_t, BEARER_CAP_NAMES, FTDM_BEARER_CAP_INVALID) + +FTDM_ENUM_NAMES(USER_LAYER1_PROT_NAMES, USER_LAYER1_PROT_STRINGS) +FTDM_STR2ENUM(ftdm_str2ftdm_usr_layer1_prot, ftdm_user_layer1_prot2str, ftdm_user_layer1_prot_t, USER_LAYER1_PROT_NAMES, FTDM_USER_LAYER1_PROT_INVALID) + static ftdm_status_t ftdm_group_add_channels(ftdm_span_t* span, int currindex, const char* name); static const char *cut_path(const char *in) @@ -4822,7 +4840,7 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t if (sigmsg->channel) { ftdm_mutex_lock(sigmsg->channel->mutex); } - + /* some core things to do on special events */ switch (sigmsg->event_id) { diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftdm_sangoma_boost.h b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftdm_sangoma_boost.h index 5a3ca76c56..6fbf272d07 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftdm_sangoma_boost.h +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftdm_sangoma_boost.h @@ -58,7 +58,7 @@ typedef struct ftdm_sangoma_boost_trunkgroup { ftdm_size_t size; /* Number of b-channels in group */ unsigned int last_used_index; /* index of last b-channel used */ ftdm_channel_t* ftdmchans[MAX_CHANS_PER_TRUNKGROUP]; - //DAVIDY need to merge congestion timeouts to this struct + //TODO need to merge congestion timeouts to this struct } ftdm_sangoma_boost_trunkgroup_t; #endif diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c index c9691e232b..50a01cc0ec 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c @@ -55,7 +55,7 @@ ftdm_mutex_t *g_boost_modules_mutex = NULL; ftdm_hash_t *g_boost_modules_hash = NULL; #define MAX_TRUNK_GROUPS 64 -//DAVIDY need to merge congestion_timeouts with ftdm_sangoma_boost_trunkgroups +//TODO need to merge congestion_timeouts with ftdm_sangoma_boost_trunkgroups static time_t congestion_timeouts[MAX_TRUNK_GROUPS]; static ftdm_sangoma_boost_trunkgroup_t *g_trunkgroups[MAX_TRUNK_GROUPS]; @@ -2582,17 +2582,17 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_boost_configure_span) } else if (!strcasecmp(var, "remote_port")) { remote_port = atoi(val); } else if (!strcasecmp(var, "outbound-called-ton")) { - ftdm_span_set_ton(val, &span->default_caller_data.dnis.type); + ftdm_set_ton(val, &span->default_caller_data.dnis.type); } else if (!strcasecmp(var, "outbound-called-npi")) { - ftdm_span_set_npi(val, &span->default_caller_data.dnis.plan); + ftdm_set_npi(val, &span->default_caller_data.dnis.plan); } else if (!strcasecmp(var, "outbound-calling-ton")) { - ftdm_span_set_ton(val, &span->default_caller_data.cid_num.type); + ftdm_set_ton(val, &span->default_caller_data.cid_num.type); } else if (!strcasecmp(var, "outbound-calling-npi")) { - ftdm_span_set_npi(val, &span->default_caller_data.cid_num.plan); + ftdm_set_npi(val, &span->default_caller_data.cid_num.plan); } else if (!strcasecmp(var, "outbound-rdnis-ton")) { - ftdm_span_set_ton(val, &span->default_caller_data.rdnis.type); + ftdm_set_ton(val, &span->default_caller_data.rdnis.type); } else if (!strcasecmp(var, "outbound-rdnis-npi")) { - ftdm_span_set_npi(val, &span->default_caller_data.rdnis.plan); + ftdm_set_npi(val, &span->default_caller_data.rdnis.plan); } else if (!sigmod) { snprintf(span->last_error, sizeof(span->last_error), "Unknown parameter [%s]", var); FAIL_CONFIG_RETURN(FTDM_FAIL); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c index 6f5f838590..8831ac4185 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c @@ -40,8 +40,8 @@ #include #endif -static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj); +static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj); static ftdm_status_t ftdm_sangoma_isdn_stop(ftdm_span_t *span); static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span); @@ -673,7 +673,8 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan) break; case FTDM_CHANNEL_STATE_RINGING: { - sngisdn_snd_alert(ftdmchan, SNGISDN_PROGIND_NETE_ISDN); + ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_NETE_ISDN}; + sngisdn_snd_alert(ftdmchan, prog_ind); } break; case FTDM_CHANNEL_STATE_PROGRESS: @@ -687,7 +688,8 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan) /* If we already sent a PROCEED before, do not send a PROGRESS as there is nothing to indicate to the remote switch */ if (ftdmchan->last_state != FTDM_CHANNEL_STATE_PROCEED) { /* Send a progress message, indicating: Call is not end-to-end ISDN, further call progress may be available */ - sngisdn_snd_progress(ftdmchan, SNGISDN_PROGIND_NETE_ISDN); + ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_NETE_ISDN}; + sngisdn_snd_progress(ftdmchan, prog_ind); } } } @@ -699,7 +701,8 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan) ftdm_span_send_signal(ftdmchan->span, &sigev); } else { /* Send a progress message, indicating: In-band information/pattern available */ - sngisdn_snd_progress(ftdmchan, SNGISDN_PROGIND_IB_AVAIL); + ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_IB_AVAIL}; + sngisdn_snd_progress(ftdmchan, prog_ind); } } break; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h index a82ed283e1..6957f9925e 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h @@ -138,17 +138,47 @@ typedef enum { typedef enum { /* Call is not end-to-end ISDN */ - SNGISDN_PROGIND_NETE_ISDN = 1, + SNGISDN_PROGIND_DESCR_NETE_ISDN, /* Destination address is non-ISDN */ - SNGISDN_PROGIND_DEST_NISDN, + SNGISDN_PROGIND_DESCR_DEST_NISDN, /* Origination address is non-ISDN */ - SNGISDN_PROGIND_ORIG_NISDN, + SNGISDN_PROGIND_DESCR_ORIG_NISDN, /* Call has returned to the ISDN */ - SNGISDN_PROGIND_RET_ISDN, + SNGISDN_PROGIND_DESCR_RET_ISDN, /* Interworking as occured and has resulted in a telecommunication service change */ - SNGISDN_PROGIND_SERV_CHANGE, - /* In-band information or an appropriate pattern is now available */ - SNGISDN_PROGIND_IB_AVAIL, + SNGISDN_PROGIND_DESCR_SERV_CHANGE, + /* In-band information or an appropriate pattern is now available */ + SNGISDN_PROGIND_DESCR_IB_AVAIL, + /* Invalid */ + SNGISDN_PROGIND_DESCR_INVALID, +} ftdm_sngisdn_progind_descr_t; +#define SNGISDN_PROGIND_DESCR_STRINGS "not-end-to-end-isdn", "destination-is-non-isdn", "origination-is-non-isdn", "call-returned-to-isdn", "service-change", "inband-info-available", "invalid" +FTDM_STR2ENUM_P(ftdm_str2ftdm_sngisdn_progind_descr, ftdm_sngisdn_progind_descr2str, ftdm_sngisdn_progind_descr_t); + +typedef enum { + /* User */ + SNGISDN_PROGIND_LOC_USER, + /* Private network serving the local user */ + SNGISDN_PROGIND_LOC_PRIV_NET_LOCAL_USR, + /* Public network serving the local user */ + SNGISDN_PROGIND_LOC_PUB_NET_LOCAL_USR, + /* Transit network */ + SNGISDN_PROGIND_LOC_TRANSIT_NET, + /* Public network serving remote user */ + SNGISDN_PROGIND_LOC_PUB_NET_REMOTE_USR, + /* Private network serving remote user */ + SNGISDN_PROGIND_LOC_PRIV_NET_REMOTE_USR, + /* Network beyond the interworking point */ + SNGISDN_PROGIND_LOC_NET_BEYOND_INTRW, + /* Invalid */ + SNGISDN_PROGIND_LOC_INVALID, +} ftdm_sngisdn_progind_loc_t; +#define SNGISDN_PROGIND_LOC_STRINGS "user", "private-net-local-user", "public-net-local-user", "transit-network", "public-net-remote-user", "private-net-remote-user", "beyond-interworking", "invalid" +FTDM_STR2ENUM_P(ftdm_str2ftdm_sngisdn_progind_loc, ftdm_sngisdn_progind_loc2str, ftdm_sngisdn_progind_loc_t); + +typedef struct ftdm_sngisdn_prog_ind { + ftdm_sngisdn_progind_loc_t loc; /* location */ + ftdm_sngisdn_progind_descr_t descr; /* description */ } ftdm_sngisdn_progind_t; /* Only timers that can be cancelled are listed here */ @@ -201,6 +231,7 @@ typedef struct sngisdn_span_data { uint8_t facility; int8_t facility_timeout; uint8_t num_local_numbers; + uint8_t ignore_cause_value; uint8_t timer_t3; char* local_numbers[SNGISDN_NUM_LOCAL_NUMBERS]; ftdm_sched_t *sched; @@ -376,18 +407,25 @@ void sngisdn_rcv_cc_ind(CcMngmt *status); void sngisdn_rcv_sng_log(uint8_t level, char *fmt,...); void sngisdn_rcv_sng_assert(char *message); -ftdm_status_t get_calling_num(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb); -ftdm_status_t get_called_num(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb); -ftdm_status_t get_redir_num(ftdm_caller_data_t *ftdm, RedirNmb *redirNmb); -ftdm_status_t get_calling_name_from_display(ftdm_caller_data_t *ftdm, Display *display); -ftdm_status_t get_calling_name_from_usr_usr(ftdm_caller_data_t *ftdm, UsrUsr *usrUsr); -ftdm_status_t get_facility_ie(ftdm_caller_data_t *ftdm, uint8_t *data, uint32_t data_len); +ftdm_status_t get_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb); +ftdm_status_t get_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb); +ftdm_status_t get_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb); +ftdm_status_t get_calling_name_from_display(ftdm_channel_t *ftdmchan, Display *display); +ftdm_status_t get_calling_name_from_usr_usr(ftdm_channel_t *ftdmchan, UsrUsr *usrUsr); +ftdm_status_t get_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad); +ftdm_status_t get_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd); +ftdm_status_t get_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr); +ftdm_status_t get_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, ftdm_size_t data_len); -ftdm_status_t set_calling_num(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *ftdm); -ftdm_status_t set_called_num(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *ftdm); -ftdm_status_t set_redir_num(RedirNmb *redirNmb, ftdm_caller_data_t *ftdm); -ftdm_status_t set_calling_name(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan); +ftdm_status_t set_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb); +ftdm_status_t set_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb); +ftdm_status_t set_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb); +ftdm_status_t set_calling_name(ftdm_channel_t *ftdmchan, ConEvnt *conEvnt); +ftdm_status_t set_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad); +ftdm_status_t set_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd, ftdm_sngisdn_progind_t prog_ind); ftdm_status_t set_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr); +ftdm_status_t set_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, ftdm_size_t *data_len); + uint8_t sngisdn_get_infoTranCap_from_stack(ftdm_bearer_cap_t bearer_capability); uint8_t sngisdn_get_usrInfoLyr1Prot_from_stack(ftdm_user_layer1_prot_t layer1_prot); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c index 657aa5e206..6b4e73ab25 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c @@ -34,13 +34,24 @@ #include "ftmod_sangoma_isdn.h" -ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span); -ftdm_status_t parse_signalling(const char* signalling, ftdm_span_t *span); -ftdm_status_t add_local_number(const char* val, ftdm_span_t *span); +static ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span); +static ftdm_status_t parse_signalling(const char* signalling, ftdm_span_t *span); +static ftdm_status_t add_local_number(const char* val, ftdm_span_t *span); +static ftdm_status_t parse_yesno(const char* var, const char* val, uint8_t *target); extern ftdm_sngisdn_data_t g_sngisdn_data; -ftdm_status_t add_local_number(const char* val, ftdm_span_t *span) +static ftdm_status_t parse_yesno(const char* var, const char* val, uint8_t *target) +{ + if (ftdm_true(val)) { + *target = SNGISDN_OPT_TRUE; + } else { + *target = SNGISDN_OPT_FALSE; + } + return FTDM_SUCCESS; +} + +static ftdm_status_t add_local_number(const char* val, ftdm_span_t *span) { sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data; @@ -53,7 +64,7 @@ ftdm_status_t add_local_number(const char* val, ftdm_span_t *span) return FTDM_SUCCESS; } -ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span) +static ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span) { unsigned i; ftdm_iterator_t *chaniter = NULL; @@ -160,7 +171,7 @@ ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span) return FTDM_SUCCESS; } -ftdm_status_t parse_signalling(const char* signalling, ftdm_span_t *span) +static ftdm_status_t parse_signalling(const char* signalling, ftdm_span_t *span) { sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data; if (!strcasecmp(signalling, "net") || @@ -190,7 +201,8 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_ signal_data->min_digits = 8; signal_data->overlap_dial = SNGISDN_OPT_DEFAULT; signal_data->setup_arb = SNGISDN_OPT_DEFAULT; - signal_data->facility_ie_decode = SNGISDN_OPT_TRUE; + signal_data->facility_ie_decode = SNGISDN_OPT_DEFAULT; + signal_data->ignore_cause_value = SNGISDN_OPT_DEFAULT; signal_data->timer_t3 = 8; signal_data->link_id = span->span_id; @@ -202,20 +214,19 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_ if (span->trunk_type == FTDM_TRUNK_BRI || span->trunk_type == FTDM_TRUNK_BRI_PTMP) { - - ftdm_span_set_npi("unknown", &span->default_caller_data.dnis.plan); - ftdm_span_set_ton("unknown", &span->default_caller_data.dnis.type); - ftdm_span_set_npi("unknown", &span->default_caller_data.cid_num.plan); - ftdm_span_set_ton("unknown", &span->default_caller_data.cid_num.type); - ftdm_span_set_npi("unknown", &span->default_caller_data.rdnis.plan); - ftdm_span_set_ton("unknown", &span->default_caller_data.rdnis.type); + ftdm_set_npi("unknown", &span->default_caller_data.dnis.plan); + ftdm_set_ton("unknown", &span->default_caller_data.dnis.type); + ftdm_set_npi("unknown", &span->default_caller_data.cid_num.plan); + ftdm_set_ton("unknown", &span->default_caller_data.cid_num.type); + ftdm_set_npi("unknown", &span->default_caller_data.rdnis.plan); + ftdm_set_ton("unknown", &span->default_caller_data.rdnis.type); } else { - ftdm_span_set_npi("e164", &span->default_caller_data.dnis.plan); - ftdm_span_set_ton("national", &span->default_caller_data.dnis.type); - ftdm_span_set_npi("e164", &span->default_caller_data.cid_num.plan); - ftdm_span_set_ton("national", &span->default_caller_data.cid_num.type); - ftdm_span_set_npi("e164", &span->default_caller_data.rdnis.plan); - ftdm_span_set_ton("national", &span->default_caller_data.rdnis.type); + ftdm_set_npi("isdn", &span->default_caller_data.dnis.plan); + ftdm_set_ton("national", &span->default_caller_data.dnis.type); + ftdm_set_npi("isdn", &span->default_caller_data.cid_num.plan); + ftdm_set_ton("national", &span->default_caller_data.cid_num.type); + ftdm_set_npi("isdn", &span->default_caller_data.rdnis.plan); + ftdm_set_ton("national", &span->default_caller_data.rdnis.type); } for (paramindex = 0; ftdm_parameters[paramindex].var; paramindex++) { @@ -247,41 +258,29 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_ } else { ftdm_log(FTDM_LOG_ERROR, "Invalid value for parameter:%s:%s\n", var, val); } - } else if (!strcasecmp(var, "setup arbitration")) { - if (!strcasecmp(val, "yes")) { - signal_data->setup_arb = SNGISDN_OPT_TRUE; - } else if (!strcasecmp(val, "no")) { - signal_data->setup_arb = SNGISDN_OPT_FALSE; - } else { - ftdm_log(FTDM_LOG_ERROR, "Invalid value for parameter:%s:%s\n", var, val); - } + } else if (!strcasecmp(var, "setup-arbitration")) { + parse_yesno(var, val, &signal_data->setup_arb); } else if (!strcasecmp(var, "facility")) { - if (!strcasecmp(val, "yes")) { - signal_data->facility = SNGISDN_OPT_TRUE; - } else if (!strcasecmp(val, "no")) { - signal_data->facility = SNGISDN_OPT_FALSE; - } else { - ftdm_log(FTDM_LOG_ERROR, "Invalid value for parameter:%s:%s\n", var, val); - } + parse_yesno(var, val, &signal_data->facility); } else if (!strcasecmp(var, "min_digits")) { signal_data->min_digits = atoi(val); } else if (!strcasecmp(var, "outbound-called-ton")) { - ftdm_span_set_ton(val, &span->default_caller_data.dnis.type); + ftdm_set_ton(val, &span->default_caller_data.dnis.type); } else if (!strcasecmp(var, "outbound-called-npi")) { - ftdm_span_set_npi(val, &span->default_caller_data.dnis.plan); + ftdm_set_npi(val, &span->default_caller_data.dnis.plan); } else if (!strcasecmp(var, "outbound-calling-ton")) { - ftdm_span_set_ton(val, &span->default_caller_data.cid_num.type); + ftdm_set_ton(val, &span->default_caller_data.cid_num.type); } else if (!strcasecmp(var, "outbound-calling-npi")) { - ftdm_span_set_npi(val, &span->default_caller_data.cid_num.plan); + ftdm_set_npi(val, &span->default_caller_data.cid_num.plan); } else if (!strcasecmp(var, "outbound-rdnis-ton")) { - ftdm_span_set_ton(val, &span->default_caller_data.rdnis.type); + ftdm_set_ton(val, &span->default_caller_data.rdnis.type); } else if (!strcasecmp(var, "outbound-rdnis-npi")) { - ftdm_span_set_npi(val, &span->default_caller_data.rdnis.plan); + ftdm_set_npi(val, &span->default_caller_data.rdnis.plan); } else if (!strcasecmp(var, "outbound-bearer_cap")) { - ftdm_span_set_bearer_capability(val, &span->default_caller_data.bearer_capability); + ftdm_set_bearer_capability(val, (uint8_t*)&span->default_caller_data.bearer_capability); } else if (!strcasecmp(var, "outbound-bearer_layer1")) { - ftdm_span_set_bearer_layer1(val, &span->default_caller_data.bearer_layer1); - } else if (!strcasecmp(var, "local-number")) { + ftdm_set_bearer_layer1(val, (uint8_t*)&span->default_caller_data.bearer_layer1); + } else if (!strcasecmp(var, "local-number")) { if (add_local_number(val, span) != FTDM_SUCCESS) { return FTDM_FAIL; } @@ -291,13 +290,9 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_ signal_data->facility_timeout = 0; } } else if (!strcasecmp(var, "facility-ie-decode")) { - if (!strcasecmp(val, "yes")) { - signal_data->facility_ie_decode = SNGISDN_OPT_TRUE; - } else if (!strcasecmp(val, "no")) { - signal_data->facility_ie_decode = SNGISDN_OPT_FALSE; - } else { - ftdm_log(FTDM_LOG_ERROR, "Invalid value for parameter:%s:%s\n", var, val); - } + parse_yesno(var, val, &signal_data->facility_ie_decode); + } else if (!strcasecmp(var, "ignore-cause-value")) { + parse_yesno(var, val, &signal_data->ignore_cause_value); } else { ftdm_log(FTDM_LOG_WARNING, "Ignoring unknown parameter %s\n", ftdm_parameters[paramindex].var); } diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c index a541a655d8..6bf0c25212 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c @@ -127,13 +127,15 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event) ftdm_channel_add_var(ftdmchan, "isdn_specific_var", "1"); #endif /* Fill in call information */ - get_calling_num(&ftdmchan->caller_data, &conEvnt->cgPtyNmb); - get_called_num(&ftdmchan->caller_data, &conEvnt->cdPtyNmb); - get_redir_num(&ftdmchan->caller_data, &conEvnt->redirNmb); + get_calling_num(ftdmchan, &conEvnt->cgPtyNmb); + get_called_num(ftdmchan, &conEvnt->cdPtyNmb); + get_redir_num(ftdmchan, &conEvnt->redirNmb); + get_calling_subaddr(ftdmchan, &conEvnt->cgPtySad); - if (get_calling_name_from_display(&ftdmchan->caller_data, &conEvnt->display) != FTDM_SUCCESS) { - get_calling_name_from_usr_usr(&ftdmchan->caller_data, &conEvnt->usrUsr); + if (get_calling_name_from_display(ftdmchan, &conEvnt->display) != FTDM_SUCCESS) { + get_calling_name_from_usr_usr(ftdmchan, &conEvnt->usrUsr); } + get_prog_ind_ie(ftdmchan, &conEvnt->progInd); ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Incoming call: Called No:[%s] Calling No:[%s]\n", ftdmchan->caller_data.dnis.digits, ftdmchan->caller_data.cid_num.digits); @@ -148,35 +150,35 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event) snprintf(ftdmchan->caller_data.aniII, 5, "%.2d", conEvnt->ni2OctStr.str.val[3]); } } + } - if (conEvnt->facilityStr.eh.pres) { - if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) { - get_facility_ie(&ftdmchan->caller_data, conEvnt->facilityStr.facilityStr.val, conEvnt->facilityStr.facilityStr.len); - } else if (signal_data->facility == SNGISDN_OPT_TRUE) { - /* Verify whether the Caller Name will come in a subsequent FACILITY message */ - uint16_t ret_val; - char retrieved_str[255]; - - ret_val = sng_isdn_retrieve_facility_caller_name(conEvnt->facilityStr.facilityStr.val, conEvnt->facilityStr.facilityStr.len, retrieved_str); - /* - return values for "sng_isdn_retrieve_facility_information_following": - If there will be no information following, or fails to decode IE, returns -1 - If there will be no information following, but current FACILITY IE contains a caller name, returns 0 - If there will be information following, returns 1 - */ + if (conEvnt->facilityStr.eh.pres) { + if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) { + get_facility_ie(ftdmchan, &conEvnt->facilityStr); + } else if (signal_data->facility == SNGISDN_OPT_TRUE) { + /* Verify whether the Caller Name will come in a subsequent FACILITY message */ + uint16_t ret_val; + char retrieved_str[255]; - if (ret_val == 1) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Expecting Caller name in FACILITY\n"); - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_GET_CALLERID); - /* Launch timer in case we never get a FACILITY msg */ - if (signal_data->facility_timeout) { - ftdm_sched_timer(signal_data->sched, "facility_timeout", signal_data->facility_timeout, - sngisdn_facility_timeout, (void*) sngisdn_info, &sngisdn_info->timers[SNGISDN_TIMER_FACILITY]); - } - break; - } else if (ret_val == 0) { - strcpy(ftdmchan->caller_data.cid_name, retrieved_str); + ret_val = sng_isdn_retrieve_facility_caller_name(conEvnt->facilityStr.facilityStr.val, conEvnt->facilityStr.facilityStr.len, retrieved_str); + /* + return values for "sng_isdn_retrieve_facility_information_following": + If there will be no information following, or fails to decode IE, returns -1 + If there will be no information following, but current FACILITY IE contains a caller name, returns 0 + If there will be information following, returns 1 + */ + + if (ret_val == 1) { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Expecting Caller name in FACILITY\n"); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_GET_CALLERID); + /* Launch timer in case we never get a FACILITY msg */ + if (signal_data->facility_timeout) { + ftdm_sched_timer(signal_data->sched, "facility_timeout", signal_data->facility_timeout, + sngisdn_facility_timeout, (void*) sngisdn_info, &sngisdn_info->timers[SNGISDN_TIMER_FACILITY]); } + break; + } else if (ret_val == 0) { + strcpy(ftdmchan->caller_data.cid_name, retrieved_str); } } } @@ -254,8 +256,7 @@ void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event) ISDN_FUNC_TRACE_ENTER(__FUNCTION__); - /* Function does not require any info from conStEvnt struct for now */ - /* CnStEvnt *cnStEvnt = &sngisdn_event->event.cnStEvnt; */ + CnStEvnt *cnStEvnt = &sngisdn_event->event.cnStEvnt; ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n"); @@ -281,6 +282,7 @@ void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event) case FTDM_CHANNEL_STATE_PROGRESS: case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: case FTDM_CHANNEL_STATE_DIALING: + get_prog_ind_ie(ftdmchan, &cnStEvnt->progInd); ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP); break; case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: @@ -344,9 +346,13 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event) suId, suInstId, spInstId, ces); switch(evntType) { + case MI_CALLPROC: case MI_PROGRESS: - if (signal_data->switchtype == SNGISDN_SWITCH_NI2 && - cnStEvnt->causeDgn[0].eh.pres && cnStEvnt->causeDgn[0].causeVal.pres) { + case MI_ALERTING: + get_prog_ind_ie(ftdmchan, &cnStEvnt->progInd); + + if (signal_data->ignore_cause_value != SNGISDN_OPT_TRUE && + cnStEvnt->causeDgn[0].eh.pres && cnStEvnt->causeDgn[0].causeVal.pres) { switch(cnStEvnt->causeDgn[0].causeVal.val) { case 17: /* User Busy */ @@ -371,24 +377,17 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event) goto sngisdn_process_cnst_ind_end; } } - /* fall-through */ - case MI_ALERTING: - case MI_CALLPROC: - + switch(ftdmchan->state) { case FTDM_CHANNEL_STATE_DIALING: - if (evntType == MI_CALLPROC) { - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROCEED); - } else if (evntType == MI_PROGRESS || - (cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL)) { + case FTDM_CHANNEL_STATE_PROCEED: + if (cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL) { ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); } else { ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS); } - break; case FTDM_CHANNEL_STATE_PROGRESS: - if (evntType == MI_PROGRESS || - (cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL)) { + if (cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL) { ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); } break; @@ -417,7 +416,7 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event) ftdm_size_t min_digits = ((sngisdn_span_data_t*)ftdmchan->span->signal_data)->min_digits; ftdm_size_t num_digits; - get_called_num(&ftdmchan->caller_data, &cnStEvnt->cdPtyNmb); + get_called_num(ftdmchan, &cnStEvnt->cdPtyNmb); num_digits = strlen(ftdmchan->caller_data.dnis.digits); if (cnStEvnt->sndCmplt.eh.pres || num_digits >= min_digits) { @@ -476,7 +475,7 @@ void sngisdn_process_disc_ind (sngisdn_event_data_t *sngisdn_event) case FTDM_CHANNEL_STATE_UP: if (discEvnt->facilityStr.eh.pres) { if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) { - get_facility_ie(&ftdmchan->caller_data, discEvnt->facilityStr.facilityStr.val, discEvnt->facilityStr.facilityStr.len); + get_facility_ie(ftdmchan, &discEvnt->facilityStr); } else { /* Call libsng_isdn facility decode function and copy variables here */ } @@ -573,7 +572,7 @@ void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event) if (relEvnt->facilityStr.eh.pres) { if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) { - get_facility_ie(&ftdmchan->caller_data, relEvnt->facilityStr.facilityStr.val, relEvnt->facilityStr.facilityStr.len); + get_facility_ie(ftdmchan, &relEvnt->facilityStr); } else { /* Call libsng_isdn facility decode function and copy variables here */ } @@ -789,7 +788,7 @@ void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event) ftdm_sigmsg_t sigev; if (facEvnt->facElmt.facStr.pres) { if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) { - get_facility_ie(&ftdmchan->caller_data, &facEvnt->facElmt.facStr.val[2], facEvnt->facElmt.facStr.len); + get_facility_ie_str(ftdmchan, &facEvnt->facElmt.facStr.val[2], facEvnt->facElmt.facStr.len); } else { /* Call libsng_isdn facility decode function and copy variables here */ } diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c index 36c6782a97..e91f21f55e 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c @@ -34,13 +34,12 @@ #include "ftmod_sangoma_isdn.h" -static void sngisdn_set_prog_desc(ProgInd *progInd, ftdm_sngisdn_progind_t prod_ind); - void sngisdn_snd_setup(ftdm_channel_t *ftdmchan) { - ConEvnt conEvnt; + ConEvnt conEvnt; sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data; - sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; + sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; + ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_NETE_ISDN}; ftdm_assert((!sngisdn_info->suInstId && !sngisdn_info->spInstId), "Trying to call out, but call data was not cleared\n"); @@ -118,14 +117,6 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan) conEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id; } - conEvnt.progInd.eh.pres = PRSNT_NODEF; - conEvnt.progInd.location.pres = PRSNT_NODEF; - conEvnt.progInd.location.val = IN_LOC_USER; - conEvnt.progInd.codeStand0.pres = PRSNT_NODEF; - conEvnt.progInd.codeStand0.val = IN_CSTD_CCITT; - conEvnt.progInd.progDesc.pres = PRSNT_NODEF; - conEvnt.progInd.progDesc.val = IN_PD_NOTETEISDN; /* Not end-to-end ISDN */ - if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN) { conEvnt.sndCmplt.eh.pres = PRSNT_NODEF; } @@ -135,11 +126,13 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan) } ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Outgoing call: Called No:[%s] Calling No:[%s]\n", ftdmchan->caller_data.dnis.digits, ftdmchan->caller_data.cid_num.digits); - set_called_num(&conEvnt.cdPtyNmb, &ftdmchan->caller_data); - set_calling_num(&conEvnt.cgPtyNmb, &ftdmchan->caller_data); - set_redir_num(&conEvnt.redirNmb, &ftdmchan->caller_data); - set_calling_name(&conEvnt, ftdmchan); + set_called_num(ftdmchan, &conEvnt.cdPtyNmb); + set_calling_num(ftdmchan, &conEvnt.cgPtyNmb); + set_calling_subaddr(ftdmchan, &conEvnt.cgPtySad); + set_redir_num(ftdmchan, &conEvnt.redirNmb); + set_calling_name(ftdmchan, &conEvnt); set_facility_ie(ftdmchan, &conEvnt.facilityStr); + set_prog_ind_ie(ftdmchan, &conEvnt.progInd, prog_ind); ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending SETUP (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces); @@ -347,15 +340,7 @@ void sngisdn_snd_progress(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ } memset(&cnStEvnt, 0, sizeof(cnStEvnt)); - - cnStEvnt.progInd.eh.pres = PRSNT_NODEF; - cnStEvnt.progInd.location.pres = PRSNT_NODEF; - cnStEvnt.progInd.location.val = IN_LOC_USER; - cnStEvnt.progInd.codeStand0.pres = PRSNT_NODEF; - cnStEvnt.progInd.codeStand0.val = IN_CSTD_CCITT; - cnStEvnt.progInd.progDesc.pres = PRSNT_NODEF; - - sngisdn_set_prog_desc(&cnStEvnt.progInd, prog_ind); + set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind); ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending PROGRESS (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces); if(sng_isdn_con_status(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId,&cnStEvnt, MI_PROGRESS, signal_data->dchan_id, sngisdn_info->ces)) { @@ -380,13 +365,7 @@ void sngisdn_snd_alert(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind memset(&cnStEvnt, 0, sizeof(cnStEvnt)); - cnStEvnt.progInd.eh.pres = PRSNT_NODEF; - cnStEvnt.progInd.location.pres = PRSNT_NODEF; - cnStEvnt.progInd.location.val = IN_LOC_USER; - cnStEvnt.progInd.codeStand0.pres = PRSNT_NODEF; - cnStEvnt.progInd.codeStand0.val = IN_CSTD_CCITT; - cnStEvnt.progInd.progDesc.pres = PRSNT_NODEF; - sngisdn_set_prog_desc(&cnStEvnt.progInd, prog_ind); + set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind); ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending ALERT (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces); @@ -398,10 +377,10 @@ void sngisdn_snd_alert(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind void sngisdn_snd_connect(ftdm_channel_t *ftdmchan) { - CnStEvnt cnStEvnt; - + CnStEvnt cnStEvnt; sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data; sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; + ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_NETE_ISDN}; if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) { ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending CONNECT, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId); @@ -444,14 +423,8 @@ void sngisdn_snd_connect(ftdm_channel_t *ftdmchan) cnStEvnt.chanId.chanNmbSlotMap.len = 1; cnStEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id; } - - cnStEvnt.progInd.eh.pres = PRSNT_NODEF; - cnStEvnt.progInd.location.pres = PRSNT_NODEF; - cnStEvnt.progInd.location.val = IN_LOC_USER; - cnStEvnt.progInd.codeStand0.pres = PRSNT_NODEF; - cnStEvnt.progInd.codeStand0.val = IN_CSTD_CCITT; - cnStEvnt.progInd.progDesc.pres = PRSNT_NODEF; - cnStEvnt.progInd.progDesc.val = IN_PD_NOTETEISDN; /* Not end-to-end ISDN */ + + set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind); ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending CONNECT (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces); if (sng_isdn_con_response(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &cnStEvnt, signal_data->dchan_id, sngisdn_info->ces)) { @@ -473,7 +446,12 @@ void sngisdn_snd_fac_req(ftdm_channel_t *ftdmchan) } memset(&facEvnt, 0, sizeof(facEvnt)); - + + set_facility_ie_str(ftdmchan, &facEvnt.facElmt.facStr.val[2], (ftdm_size_t*)&facEvnt.facElmt.facStr.len); + + facEvnt.facElmt.facStr.val[0] = 0x1C; + facEvnt.facElmt.facStr.val[1] = facEvnt.facElmt.facStr.len; + ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending FACILITY (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces); if (sng_isdn_facility_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &facEvnt, MI_FACIL, signal_data->dchan_id, sngisdn_info->ces)) { @@ -619,32 +597,6 @@ void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare) return; } -static void sngisdn_set_prog_desc(ProgInd *progInd, ftdm_sngisdn_progind_t prog_ind) -{ - switch(prog_ind) { - case SNGISDN_PROGIND_NETE_ISDN: - progInd->progDesc.val = IN_PD_NOTETEISDN; - break; - case SNGISDN_PROGIND_DEST_NISDN: - progInd->progDesc.val = IN_PD_DSTNOTISDN; - break; - case SNGISDN_PROGIND_ORIG_NISDN: - progInd->progDesc.val = IN_PD_ORGNOTISDN; - break; - case SNGISDN_PROGIND_RET_ISDN: - progInd->progDesc.val = IN_PD_CALLRET; - break; - case SNGISDN_PROGIND_SERV_CHANGE: - /* Trillium defines do not match ITU-T Q931 Progress descriptions, - indicate a delayed response for now */ - progInd->progDesc.val = IN_PD_DELRESP; - break; - case SNGISDN_PROGIND_IB_AVAIL: - progInd->progDesc.val = IN_PD_IBAVAIL; - break; - } - return; -} /* We received an incoming frame on the d-channel, send data to the stack */ void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len) diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c index 4ddb90bbd3..964d06caaf 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c @@ -33,6 +33,15 @@ */ #include "ftmod_sangoma_isdn.h" +#define SNGISDN_Q931_FACILITY_IE_ID 0x1C + +/* ftmod_sangoma_isdn specific enum look-up functions */ + +FTDM_ENUM_NAMES(SNGISDN_PROGIND_DESCR_NAMES, SNGISDN_PROGIND_DESCR_STRINGS) +FTDM_STR2ENUM(ftdm_str2ftdm_sngisdn_progind_descr, ftdm_sngisdn_progind_descr2str, ftdm_sngisdn_progind_descr_t, SNGISDN_PROGIND_DESCR_NAMES, SNGISDN_PROGIND_DESCR_INVALID) + +FTDM_ENUM_NAMES(SNGISDN_PROGIND_LOC_NAMES, SNGISDN_PROGIND_LOC_STRINGS) +FTDM_STR2ENUM(ftdm_str2ftdm_sngisdn_progind_loc, ftdm_sngisdn_progind_loc2str, ftdm_sngisdn_progind_loc_t, SNGISDN_PROGIND_LOC_NAMES, SNGISDN_PROGIND_LOC_INVALID) ftdm_status_t sngisdn_check_free_ids(void); @@ -129,7 +138,6 @@ ftdm_status_t get_ftdmchan_by_spInstId(int16_t cc_id, uint32_t spInstId, sngisdn ftdm_status_t sngisdn_set_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail) { - if (span->trunk_type == FTDM_TRUNK_BRI || span->trunk_type == FTDM_TRUNK_BRI_PTMP) { @@ -147,8 +155,9 @@ ftdm_status_t sngisdn_set_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail) return FTDM_SUCCESS; } -ftdm_status_t get_calling_num(ftdm_caller_data_t *caller_data, CgPtyNmb *cgPtyNmb) +ftdm_status_t get_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb) { + ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; if (cgPtyNmb->eh.pres != PRSNT_NODEF) { return FTDM_FAIL; } @@ -176,8 +185,9 @@ ftdm_status_t get_calling_num(ftdm_caller_data_t *caller_data, CgPtyNmb *cgPtyNm return FTDM_SUCCESS; } -ftdm_status_t get_called_num(ftdm_caller_data_t *caller_data, CdPtyNmb *cdPtyNmb) +ftdm_status_t get_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb) { + ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; if (cdPtyNmb->eh.pres != PRSNT_NODEF) { return FTDM_FAIL; } @@ -199,8 +209,9 @@ ftdm_status_t get_called_num(ftdm_caller_data_t *caller_data, CdPtyNmb *cdPtyNmb return FTDM_SUCCESS; } -ftdm_status_t get_redir_num(ftdm_caller_data_t *caller_data, RedirNmb *redirNmb) +ftdm_status_t get_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb) { + ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; if (redirNmb->eh.pres != PRSNT_NODEF) { return FTDM_FAIL; } @@ -219,8 +230,9 @@ ftdm_status_t get_redir_num(ftdm_caller_data_t *caller_data, RedirNmb *redirNmb) return FTDM_SUCCESS; } -ftdm_status_t get_calling_name_from_display(ftdm_caller_data_t *caller_data, Display *display) +ftdm_status_t get_calling_name_from_display(ftdm_channel_t *ftdmchan, Display *display) { + ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; if (display->eh.pres != PRSNT_NODEF) { return FTDM_FAIL; } @@ -232,8 +244,9 @@ ftdm_status_t get_calling_name_from_display(ftdm_caller_data_t *caller_data, Dis return FTDM_SUCCESS; } -ftdm_status_t get_calling_name_from_usr_usr(ftdm_caller_data_t *caller_data, UsrUsr *usrUsr) +ftdm_status_t get_calling_name_from_usr_usr(ftdm_channel_t *ftdmchan, UsrUsr *usrUsr) { + ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; if (usrUsr->eh.pres != PRSNT_NODEF) { return FTDM_FAIL; } @@ -250,26 +263,124 @@ ftdm_status_t get_calling_name_from_usr_usr(ftdm_caller_data_t *caller_data, Usr return FTDM_SUCCESS; } -ftdm_status_t get_facility_ie(ftdm_caller_data_t *caller_data, uint8_t *data, uint32_t data_len) +ftdm_status_t get_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad) { + char subaddress[100]; + + if (cgPtySad->eh.pres != PRSNT_NODEF) { + return FTDM_FAIL; + } + memset(subaddress, 0, sizeof(subaddress)); + if(cgPtySad->sadInfo.len >= sizeof(subaddress)) { + ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Calling Party Subaddress exceeds local size limit (len:%d max:%d)\n", cgPtySad->sadInfo.len, sizeof(subaddress)); + cgPtySad->sadInfo.len = sizeof(subaddress)-1; + } + + memcpy(subaddress, (char*)cgPtySad->sadInfo.val, cgPtySad->sadInfo.len); + subaddress[cgPtySad->sadInfo.len] = '\0'; + ftdm_channel_add_var(ftdmchan, "isdn.calling_subaddr", subaddress); + return FTDM_SUCCESS; +} + +ftdm_status_t get_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr) +{ + if (!facilityStr->eh.pres) { + return FTDM_FAIL; + } + + return get_facility_ie_str(ftdmchan, facilityStr->facilityStr.val, facilityStr->facilityStr.len); +} + +ftdm_status_t get_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, ftdm_size_t data_len) +{ + ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; if (data_len > sizeof(caller_data->raw_data)-2) { ftdm_log(FTDM_LOG_CRIT, "Length of Facility IE exceeds maximum length\n"); return FTDM_FAIL; } - + memset(caller_data->raw_data, 0, sizeof(caller_data->raw_data)); /* Always include Facility IE identifier + len so this can be used as a sanity check by the user */ - caller_data->raw_data[0] = 0x1C; + caller_data->raw_data[0] = SNGISDN_Q931_FACILITY_IE_ID; caller_data->raw_data[1] = data_len; memcpy(&caller_data->raw_data[2], data, data_len); caller_data->raw_data_len = data_len+2; - return FTDM_SUCCESS; } -ftdm_status_t set_calling_num(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *caller_data) +ftdm_status_t get_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd) { + uint8_t val; + if (!progInd->eh.pres) { + return FTDM_FAIL; + } + + if (progInd->progDesc.pres) { + switch (progInd->progDesc.val) { + case IN_PD_NOTETEISDN: + val = SNGISDN_PROGIND_DESCR_NETE_ISDN; + break; + case IN_PD_DSTNOTISDN: + val = SNGISDN_PROGIND_DESCR_DEST_NISDN; + break; + case IN_PD_ORGNOTISDN: + val = SNGISDN_PROGIND_DESCR_ORIG_NISDN; + break; + case IN_PD_CALLRET: + val = SNGISDN_PROGIND_DESCR_RET_ISDN; + break; + case IN_PD_DELRESP: + val = SNGISDN_PROGIND_DESCR_SERV_CHANGE; + break; + case IN_PD_IBAVAIL: + val = SNGISDN_PROGIND_DESCR_IB_AVAIL; + break; + default: + ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Unknown Progress Indicator Description (%d)\n", progInd->progDesc.val); + val = SNGISDN_PROGIND_DESCR_INVALID; + break; + } + ftdm_channel_add_var(ftdmchan, "isdn.prog_ind.descr", ftdm_sngisdn_progind_descr2str(val)); + } + + if (progInd->location.pres) { + switch (progInd->location.val) { + case IN_LOC_USER: + val = SNGISDN_PROGIND_LOC_USER; + break; + case IN_LOC_PRIVNETLU: + val = SNGISDN_PROGIND_LOC_PRIV_NET_LOCAL_USR; + break; + case IN_LOC_PUBNETLU: + val = SNGISDN_PROGIND_LOC_PUB_NET_LOCAL_USR; + break; + case IN_LOC_TRANNET: + val = SNGISDN_PROGIND_LOC_TRANSIT_NET; + break; + case IN_LOC_PUBNETRU: + val = SNGISDN_PROGIND_LOC_PUB_NET_REMOTE_USR; + break; + case IN_LOC_PRIVNETRU: + val = SNGISDN_PROGIND_LOC_PRIV_NET_REMOTE_USR; + break; + case IN_LOC_NETINTER: + val = SNGISDN_PROGIND_LOC_NET_BEYOND_INTRW; + break; + default: + ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Unknown Progress Indicator Location (%d)", progInd->location.val); + val = SNGISDN_PROGIND_LOC_INVALID; + break; + } + ftdm_channel_add_var(ftdmchan, "isdn.prog_ind.loc", ftdm_sngisdn_progind_loc2str(val)); + } + return FTDM_SUCCESS; +} + + +ftdm_status_t set_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb) +{ + ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; uint8_t len = strlen(caller_data->cid_num.digits); if (!len) { return FTDM_SUCCESS; @@ -296,9 +407,11 @@ ftdm_status_t set_calling_num(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *caller_dat return FTDM_SUCCESS; } -ftdm_status_t set_called_num(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *caller_data) +ftdm_status_t set_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb) { + ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; uint8_t len = strlen(caller_data->dnis.digits); + if (!len) { return FTDM_SUCCESS; } @@ -326,8 +439,9 @@ ftdm_status_t set_called_num(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *caller_data return FTDM_SUCCESS; } -ftdm_status_t set_redir_num(RedirNmb *redirNmb, ftdm_caller_data_t *caller_data) +ftdm_status_t set_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb) { + ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; uint8_t len = strlen(caller_data->rdnis.digits); if (!len) { return FTDM_SUCCESS; @@ -358,7 +472,7 @@ ftdm_status_t set_redir_num(RedirNmb *redirNmb, ftdm_caller_data_t *caller_data) } -ftdm_status_t set_calling_name(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan) +ftdm_status_t set_calling_name(ftdm_channel_t *ftdmchan, ConEvnt *conEvnt) { uint8_t len; ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; @@ -411,20 +525,139 @@ ftdm_status_t set_calling_name(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan) return FTDM_SUCCESS; } +ftdm_status_t set_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad) +{ + const char* clg_subaddr = NULL; + clg_subaddr = ftdm_channel_get_var(ftdmchan, "isdn.calling_subaddr"); + if ((clg_subaddr != NULL) && (*clg_subaddr)) { + unsigned len = strlen (clg_subaddr); + cgPtySad->eh.pres = PRSNT_NODEF; + cgPtySad->typeSad.pres = 1; + cgPtySad->typeSad.val = 0; /* NSAP */ + cgPtySad->oddEvenInd.pres = 1; + cgPtySad->oddEvenInd.val = 0; + + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending Calling Party Subaddress:%s\n", clg_subaddr); + cgPtySad->sadInfo.pres = 1; + cgPtySad->sadInfo.len = len; + memcpy(cgPtySad->sadInfo.val, clg_subaddr, len); + } + return FTDM_SUCCESS; +} + + ftdm_status_t set_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr) { - const char *facility_str = NULL; - - facility_str = ftdm_channel_get_var(ftdmchan, "isdn.facility.val"); - if (facility_str) { + ftdm_status_t status; + status = set_facility_ie_str(ftdmchan, facilityStr->facilityStr.val, (ftdm_size_t*)&facilityStr->facilityStr.len); + if (status == FTDM_SUCCESS) { facilityStr->eh.pres = PRSNT_NODEF; - facilityStr->facilityStr.len = strlen(facility_str); - memcpy(facilityStr->facilityStr.val, facility_str, facilityStr->facilityStr.len); - return FTDM_SUCCESS; + facilityStr->facilityStr.pres = PRSNT_NODEF; } + return status; +} + +ftdm_status_t set_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, ftdm_size_t *data_len) +{ + ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; + + if (caller_data->raw_data_len > 0 && caller_data->raw_data[0] == SNGISDN_Q931_FACILITY_IE_ID) { + + *data_len = caller_data->raw_data[1]; + memcpy(data, &caller_data->raw_data[2], *data_len); + return FTDM_SUCCESS; + } return FTDM_FAIL; } +ftdm_status_t set_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd, ftdm_sngisdn_progind_t prog_ind) +{ + const char *str = NULL; + int descr = prog_ind.descr; + int loc = prog_ind.loc; + + str = ftdm_channel_get_var(ftdmchan, "isdn.prog_ind.descr"); + if (str && *str) { + /* User wants to override progress indicator */ + descr = ftdm_str2ftdm_sngisdn_progind_descr(str); + } + + if (descr == SNGISDN_PROGIND_DESCR_INVALID) { + /* User does not want to send progress indicator */ + return FTDM_SUCCESS; + } + + str = ftdm_channel_get_var(ftdmchan, "isdn.prog_ind.loc"); + if (str && *str) { + loc = ftdm_str2ftdm_sngisdn_progind_loc(str); + } + if (loc == SNGISDN_PROGIND_LOC_INVALID) { + loc = SNGISDN_PROGIND_LOC_USER; + } + + progInd->eh.pres = PRSNT_NODEF; + progInd->codeStand0.pres = PRSNT_NODEF; + progInd->codeStand0.val = IN_CSTD_CCITT; + + progInd->progDesc.pres = PRSNT_NODEF; + switch(descr) { + case SNGISDN_PROGIND_DESCR_NETE_ISDN: + progInd->progDesc.val = IN_PD_NOTETEISDN; + break; + case SNGISDN_PROGIND_DESCR_DEST_NISDN: + progInd->progDesc.val = IN_PD_DSTNOTISDN; + break; + case SNGISDN_PROGIND_DESCR_ORIG_NISDN: + progInd->progDesc.val = IN_PD_ORGNOTISDN; + break; + case SNGISDN_PROGIND_DESCR_RET_ISDN: + progInd->progDesc.val = IN_PD_CALLRET; + break; + case SNGISDN_PROGIND_DESCR_SERV_CHANGE: + /* Trillium defines do not match ITU-T Q931 Progress descriptions, + indicate a delayed response for now */ + progInd->progDesc.val = IN_PD_DELRESP; + break; + case SNGISDN_PROGIND_DESCR_IB_AVAIL: + progInd->progDesc.val = IN_PD_IBAVAIL; + break; + default: + ftdm_log(FTDM_LOG_WARNING, "Invalid prog_ind description:%d\n", descr); + progInd->progDesc.val = IN_PD_NOTETEISDN; + break; + } + + progInd->location.pres = PRSNT_NODEF; + switch (loc) { + case SNGISDN_PROGIND_LOC_USER: + progInd->location.val = IN_LOC_USER; + break; + case SNGISDN_PROGIND_LOC_PRIV_NET_LOCAL_USR: + progInd->location.val = IN_LOC_PRIVNETLU; + break; + case SNGISDN_PROGIND_LOC_PUB_NET_LOCAL_USR: + progInd->location.val = IN_LOC_PUBNETLU; + break; + case SNGISDN_PROGIND_LOC_TRANSIT_NET: + progInd->location.val = IN_LOC_TRANNET; + break; + case SNGISDN_PROGIND_LOC_PUB_NET_REMOTE_USR: + progInd->location.val = IN_LOC_PUBNETRU; + break; + case SNGISDN_PROGIND_LOC_PRIV_NET_REMOTE_USR: + progInd->location.val = IN_LOC_PRIVNETRU; + break; + case SNGISDN_PROGIND_LOC_NET_BEYOND_INTRW: + progInd->location.val = IN_LOC_NETINTER; + break; + default: + ftdm_log(FTDM_LOG_WARNING, "Invalid prog_ind location:%d\n", loc); + progInd->location.val = IN_PD_NOTETEISDN; + } + return FTDM_SUCCESS; +} + + void sngisdn_t3_timeout(void* p_sngisdn_info) { sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info; @@ -581,13 +814,12 @@ uint8_t sngisdn_get_infoTranCap_from_stack(ftdm_bearer_cap_t bearer_capability) switch(bearer_capability) { case FTDM_BEARER_CAP_SPEECH: return IN_ITC_SPEECH; - case FTDM_BEARER_CAP_64K_UNRESTRICTED: return IN_ITC_UNRDIG; - case FTDM_BEARER_CAP_3_1KHZ_AUDIO: return IN_ITC_A31KHZ; - + case FTDM_BEARER_CAP_INVALID: + return IN_ITC_SPEECH; /* Do not put a default case here, so we can see compile warnings if we have unhandled cases */ } return FTDM_BEARER_CAP_SPEECH; @@ -598,13 +830,12 @@ uint8_t sngisdn_get_usrInfoLyr1Prot_from_stack(ftdm_user_layer1_prot_t layer1_pr switch(layer1_prot) { case FTDM_USER_LAYER1_PROT_V110: return IN_UIL1_CCITTV110; - case FTDM_USER_LAYER1_PROT_ULAW: return IN_UIL1_G711ULAW; - case FTDM_USER_LAYER1_PROT_ALAW: return IN_UIL1_G711ALAW; - + case FTDM_USER_LAYER1_PROT_INVALID: + return IN_UIL1_G711ULAW; /* Do not put a default case here, so we can see compile warnings if we have unhandled cases */ } return IN_UIL1_G711ULAW; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c index 624d35c147..e5167164b3 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c @@ -613,6 +613,21 @@ uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset return 0; break; case PROT_Q931_IE_CALLED_PARTY_SUBADDRESS: + { + uint8_t type; + uint8_t currentOct, j=0; + char calling_subaddr_string[82]; + memset(calling_subaddr_string, 0, sizeof(calling_subaddr_string)); + type = get_bits(OCTET(3),5,7); + currentOct = 3; + while(currentOct++ <= len+1) { + calling_subaddr_string[j++]=ia5[get_bits(OCTET(currentOct),1,4)][get_bits(OCTET(currentOct),5,8)]; + } + calling_subaddr_string[j++]='\0'; + *str_len += sprintf(&str[*str_len], "%s (l:%d) type:%s(%d) \n", + calling_subaddr_string, (j-1), get_code_2_str(type, dcodQ931TypeOfSubaddressTable), type); + } + break; case PROT_Q931_IE_REDIRECTION_NUMBER: case PROT_Q931_IE_NOTIFICATION_IND: case PROT_Q931_IE_DATE_TIME: diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.h b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.h index d210c50db9..f054de9377 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.h +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.h @@ -544,5 +544,11 @@ struct code2str dcodQ931GenDigitsTypeTable[] = { {-1, "Invalid"}, }; +struct code2str dcodQ931TypeOfSubaddressTable[] = { + { 0x00, "NSAP"}, + { 0x02, "User-specified"}, + { -1, "Invalid"}, +}; + #endif /* __FTMOD_SANGOMA_ISDN_TRACE_H__ */ diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index 014eeef852..45254e817f 100644 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -41,6 +41,7 @@ #include "ftdm_declare.h" +#include "ftdm_call_utils.h" /*! \brief Max number of channels per physical span */ #define FTDM_MAX_CHANNELS_PHYSICAL_SPAN 32 @@ -62,23 +63,6 @@ #define FTDM_INVALID_INT_PARM 0xFF -/*! \brief FreeTDM APIs possible return codes */ -typedef enum { - FTDM_SUCCESS, /*!< Success */ - FTDM_FAIL, /*!< Failure, generic error return code, use ftdm_channel_get_last_error or ftdm_span_get_last_error for details */ - FTDM_MEMERR, /*!< Memory error, most likely allocation failure */ - FTDM_TIMEOUT, /*!< Operation timed out (ie: polling on a device)*/ - FTDM_NOTIMPL, /*!< Operation not implemented */ - FTDM_BREAK, /*!< Request the caller to perform a break (context-dependant, ie: stop getting DNIS/ANI) */ - FTDM_EINVAL /*!< Invalid argument */ -} ftdm_status_t; - -/*! \brief FreeTDM bool type. */ -typedef enum { - FTDM_FALSE, - FTDM_TRUE -} ftdm_bool_t; - /*! \brief Thread/Mutex OS abstraction API. */ #include "ftdm_os.h" @@ -220,8 +204,10 @@ typedef enum { FTDM_TON_SUBSCRIBER_NUMBER, FTDM_TON_ABBREVIATED_NUMBER, FTDM_TON_RESERVED, - FTDM_TON_INVALID = 255 + FTDM_TON_INVALID } ftdm_ton_t; +#define TON_STRINGS "unknown", "international", "national", "network-specific", "subscriber-number", "abbreviated-number", "reserved", "invalid" +FTDM_STR2ENUM_P(ftdm_str2ftdm_ton, ftdm_ton2str, ftdm_ton_t) /*! Numbering Plan Identification (NPI) */ typedef enum { @@ -232,8 +218,52 @@ typedef enum { FTDM_NPI_NATIONAL = 8, FTDM_NPI_PRIVATE = 9, FTDM_NPI_RESERVED = 10, - FTDM_NPI_INVALID = 255 + FTDM_NPI_INVALID } ftdm_npi_t; +#define NPI_STRINGS "unknown", "ISDN", "data", "telex", "national", "private", "reserved", "invalid" +FTDM_STR2ENUM_P(ftdm_str2ftdm_npi, ftdm_npi2str, ftdm_npi_t) + +/*! Presentation Ind */ +typedef enum { + FTDM_PRES_ALLOWED, + FTDM_PRES_RESTRICTED, + FTDM_PRES_NOT_AVAILABLE, + FTDM_PRES_RESERVED, + FTDM_PRES_INVALID +} ftdm_presentation_t; +#define PRESENTATION_STRINGS "presentation-allowed", "presentation-restricted", "number-not-available", "reserved", "Invalid" +FTDM_STR2ENUM_P(ftdm_str2ftdm_presentation, ftdm_presentation2str, ftdm_presentation_t) + +/*! Screening Ind */ +typedef enum { + FTDM_SCREENING_NOT_SCREENED, + FTDM_SCREENING_VERIFIED_PASSED, + FTDM_SCREENING_VERIFIED_FAILED, + FTDM_SCREENING_NETWORK_PROVIDED, + FTDM_SCREENING_INVALID +} ftdm_screening_t; +#define SCREENING_STRINGS "user-provided-not-screened", "user-provided-verified-and-passed", "user-provided-verified-and-failed", "network-provided", "invalid" +FTDM_STR2ENUM_P(ftdm_str2ftdm_screening, ftdm_screening2str, ftdm_screening_t) + +/*! \brief bearer capability */ +typedef enum { + FTDM_BEARER_CAP_SPEECH = 0x00, + FTDM_BEARER_CAP_64K_UNRESTRICTED = 0x02, + FTDM_BEARER_CAP_3_1KHZ_AUDIO = 0x03, + FTDM_BEARER_CAP_INVALID +} ftdm_bearer_cap_t; +#define BEARER_CAP_STRINGS "speech", "unrestricted-digital-information", "3.1-Khz-audio", "invalid" +FTDM_STR2ENUM_P(ftdm_str2ftdm_bearer_cap, ftdm_bearer_cap2str, ftdm_bearer_cap_t) + +/*! \brief user information layer 1 protocol */ +typedef enum { + FTDM_USER_LAYER1_PROT_V110 = 0x01, + FTDM_USER_LAYER1_PROT_ULAW = 0x02, + FTDM_USER_LAYER1_PROT_ALAW = 0x03, + FTDM_USER_LAYER1_PROT_INVALID +} ftdm_user_layer1_prot_t; +#define USER_LAYER1_PROT_STRINGS "V.110", "u-law", "a-law", "Invalid" +FTDM_STR2ENUM_P(ftdm_str2ftdm_usr_layer1_prot, ftdm_user_layer1_prot2str, ftdm_user_layer1_prot_t) /*! \brief Number abstraction */ typedef struct { @@ -242,20 +272,6 @@ typedef struct { uint8_t plan; } ftdm_number_t; -/*! \brief bearer capability */ -typedef enum { - FTDM_BEARER_CAP_SPEECH = 0x00, - FTDM_BEARER_CAP_64K_UNRESTRICTED = 0x02, - FTDM_BEARER_CAP_3_1KHZ_AUDIO = 0x03 -} ftdm_bearer_cap_t; - -/*! \brief user information layer 1 protocol */ -typedef enum { - FTDM_USER_LAYER1_PROT_V110 = 0x01, - FTDM_USER_LAYER1_PROT_ULAW = 0x02, - FTDM_USER_LAYER1_PROT_ALAW = 0x03, -} ftdm_user_layer1_prot_t; - /*! \brief Caller information */ typedef struct ftdm_caller_data { char cid_date[8]; /*!< Caller ID date */ diff --git a/libs/freetdm/src/include/ftdm_call_utils.h b/libs/freetdm/src/include/ftdm_call_utils.h new file mode 100644 index 0000000000..835a5c6cdc --- /dev/null +++ b/libs/freetdm/src/include/ftdm_call_utils.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2010, Sangoma Technologies + * David Yat Sin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of the original author; nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __FTDM_CALL_UTILS_H__ +#define __FTDM_CALL_UTILS_H__ + +/*! + * \brief Set the Numbering Plan Identification from a string + * + * \param npi_string string value + * \param target the target to set value to + * + * \retval FTDM_SUCCESS success + * \retval FTDM_FAIL failure + */ +FT_DECLARE(ftdm_status_t) ftdm_set_npi(const char *npi_string, uint8_t *target); + + +/*! + * \brief Set the Type of number from a string + * + * \param ton_string string value + * \param target the target to set value to + * + * \retval FTDM_SUCCESS success + * \retval FTDM_FAIL failure + */ +FT_DECLARE(ftdm_status_t) ftdm_set_ton(const char *ton_string, uint8_t *target); + +/*! + * \brief Set the Bearer Capability from a string + * + * \param bc_string string value + * \param target the target to set value to + * + * \retval FTDM_SUCCESS success + * \retval FTDM_FAIL failure + */ +FT_DECLARE(ftdm_status_t) ftdm_set_bearer_capability(const char *bc_string, uint8_t *target); + +/*! + * \brief Set the Bearer Capability - Layer 1 from a string + * + * \param bc_string string value + * \param target the target to set value to + * + * \retval FTDM_SUCCESS success + * \retval FTDM_FAIL failure + */ +FT_DECLARE(ftdm_status_t) ftdm_set_bearer_layer1(const char *bc_string, uint8_t *target); + +/*! + * \brief Set the Screening Ind from a string + * + * \param screen_string string value + * \param target the target to set value to + * + * \retval FTDM_SUCCESS success + * \retval FTDM_FAIL failure + */ +FT_DECLARE(ftdm_status_t) ftdm_set_screening_ind(const char *string, uint8_t *target); + + +/*! + * \brief Set the Presentation Ind from an enum + * + * \param screen_string string value + * \param target the target to set value to + * + * \retval FTDM_SUCCESS success + * \retval FTDM_FAIL failure + */ +FT_DECLARE(ftdm_status_t) ftdm_set_presentation_ind(const char *string, uint8_t *target); + + +/*! + * \brief Checks whether a string contains only numbers + * + * \param number string value + * + * \retval FTDM_SUCCESS success + * \retval FTDM_FAIL failure + */ +FT_DECLARE(ftdm_status_t) ftdm_is_number(const char *number); + +#endif /* __FTDM_CALL_UTILS_H__ */ + diff --git a/libs/freetdm/src/include/ftdm_declare.h b/libs/freetdm/src/include/ftdm_declare.h index ab3b5c8966..4aba703f28 100644 --- a/libs/freetdm/src/include/ftdm_declare.h +++ b/libs/freetdm/src/include/ftdm_declare.h @@ -171,6 +171,23 @@ typedef int ftdm_socket_t; #include #endif +/*! \brief FreeTDM APIs possible return codes */ +typedef enum { + FTDM_SUCCESS, /*!< Success */ + FTDM_FAIL, /*!< Failure, generic error return code, use ftdm_channel_get_last_error or ftdm_span_get_last_error for details */ + FTDM_MEMERR, /*!< Memory error, most likely allocation failure */ + FTDM_TIMEOUT, /*!< Operation timed out (ie: polling on a device)*/ + FTDM_NOTIMPL, /*!< Operation not implemented */ + FTDM_BREAK, /*!< Request the caller to perform a break (context-dependant, ie: stop getting DNIS/ANI) */ + FTDM_EINVAL /*!< Invalid argument */ +} ftdm_status_t; + +/*! \brief FreeTDM bool type. */ +typedef enum { + FTDM_FALSE, + FTDM_TRUE +} ftdm_bool_t; + /*! * \brief FreeTDM channel. * This is the basic data structure used to place calls and I/O operations diff --git a/libs/freetdm/src/include/private/ftdm_call_utils.h b/libs/freetdm/src/include/private/ftdm_call_utils.h deleted file mode 100644 index 782abde927..0000000000 --- a/libs/freetdm/src/include/private/ftdm_call_utils.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2010, Sangoma Technologies - * David Yat Sin - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __FTDM_CALL_UTILS_H__ -#define __FTDM_CALL_UTILS_H__ - -#include "freetdm.h" - -FT_DECLARE(ftdm_status_t) ftdm_span_set_npi(const char *npi_string, uint8_t *target); -FT_DECLARE(ftdm_status_t) ftdm_span_set_ton(const char *ton_string, uint8_t *target); -FT_DECLARE(ftdm_status_t) ftdm_span_set_bearer_capability(const char *bc_string, ftdm_bearer_cap_t *target); -FT_DECLARE(ftdm_status_t) ftdm_span_set_bearer_layer1(const char *bc_string, ftdm_user_layer1_prot_t *target); -FT_DECLARE(ftdm_status_t) ftdm_is_number(char *number); - -#endif /* __FTDM_CALL_UTILS_H__ */ - From 3934682e9b616f9117d70f05965e8c5f3bbc3269 Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Tue, 30 Nov 2010 16:01:08 -0200 Subject: [PATCH 134/237] freetdm: ftmod_r2 - rename ftdm_started flag to ftdm_call_started --- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index ffc39e8884..b98f7db99c 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -68,7 +68,7 @@ typedef struct ftdm_r2_call_t { int accepted:1; int answer_pending:1; int disconnect_rcvd:1; - int ftdm_started:1; + int ftdm_call_started:1; int protocol_error:1; ftdm_channel_state_t chanstate; ftdm_size_t dnis_index; @@ -357,7 +357,7 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(r2_outgoing_call) } ft_r2_clean_call(ftdmchan->call_data); - R2CALL(ftdmchan)->ftdm_started = 1; + R2CALL(ftdmchan)->ftdm_call_started = 1; R2CALL(ftdmchan)->chanstate = FTDM_CHANNEL_STATE_DOWN; ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DIALING); @@ -503,7 +503,7 @@ static void ftdm_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_discon } /* if the call has not been started yet we must go to HANGUP right here */ - if (!R2CALL(ftdmchan)->ftdm_started) { + if (!R2CALL(ftdmchan)->ftdm_call_started) { ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); return; } @@ -567,7 +567,7 @@ static void ftdm_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_err R2CALL(ftdmchan)->disconnect_rcvd = 1; R2CALL(ftdmchan)->protocol_error = 1; - if (!R2CALL(ftdmchan)->ftdm_started) { + if (!R2CALL(ftdmchan)->ftdm_call_started) { ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); return; } @@ -1260,7 +1260,7 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan) ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL); break; } - R2CALL(ftdmchan)->ftdm_started = 1; + R2CALL(ftdmchan)->ftdm_call_started = 1; break; From e3b070c88fa02406890b35e554f5c0ac1ad6aa36 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Tue, 30 Nov 2010 13:21:47 -0500 Subject: [PATCH 135/237] freetdm: ftmod_wanpipe - do not test 80% tx queue full --- libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c index fbb827e27f..0ac628a260 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c @@ -791,16 +791,7 @@ static void wanpipe_write_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_tx_hdr_t *t ftdmchan->iostats.tx.queue_size = tx_stats->wp_api_tx_hdr_max_queue_length; ftdmchan->iostats.tx.queue_len = tx_stats->wp_api_tx_hdr_number_of_frames_in_queue; - if (ftdmchan->iostats.tx.queue_len >= (0.8 * ftdmchan->iostats.tx.queue_size)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Tx Queue length exceeded 80% threshold (%d/%d)\n", - ftdmchan->iostats.tx.queue_len, ftdmchan->iostats.tx.queue_size); - ftdm_set_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_THRES); - } else if (ftdm_test_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_THRES)){ - ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Tx Queue length reduced 80% threshold (%d/%d)\n", - ftdmchan->iostats.tx.queue_len, ftdmchan->iostats.tx.queue_size); - ftdm_clear_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_THRES); - } - + /* we don't test for 80% full in tx since is typically full for voice channels, should we test tx 80% full for D-channels? */ if (ftdmchan->iostats.tx.queue_len >= ftdmchan->iostats.tx.queue_size) { ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Tx Queue Full (%d/%d)\n", ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.tx.queue_size); From 1f329ad521926c5af22a710a7e473daec0177f3e Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Tue, 30 Nov 2010 13:28:14 -0500 Subject: [PATCH 136/237] set the right configs in sync with mainstream --- conf/autoload_configs/callcenter.conf.xml | 1 + conf/autoload_configs/erlang_event.conf.xml | 9 ++ conf/autoload_configs/modules.conf.xml | 96 +++++++++++++++++++++ conf/autoload_configs/switch.conf.xml | 6 ++ conf/autoload_configs/voicemail.conf.xml | 7 +- conf/sip_profiles/internal.xml | 20 +++++ conf/skinny_profiles/internal.xml | 2 +- conf/vars.xml | 2 +- 8 files changed, 138 insertions(+), 5 deletions(-) diff --git a/conf/autoload_configs/callcenter.conf.xml b/conf/autoload_configs/callcenter.conf.xml index 9140193b22..a069413ac6 100644 --- a/conf/autoload_configs/callcenter.conf.xml +++ b/conf/autoload_configs/callcenter.conf.xml @@ -13,6 +13,7 @@ + diff --git a/conf/autoload_configs/erlang_event.conf.xml b/conf/autoload_configs/erlang_event.conf.xml index ec14e21a25..62deb84f67 100644 --- a/conf/autoload_configs/erlang_event.conf.xml +++ b/conf/autoload_configs/erlang_event.conf.xml @@ -2,7 +2,16 @@ + + + + + diff --git a/conf/autoload_configs/modules.conf.xml b/conf/autoload_configs/modules.conf.xml index 90d66f5798..f5627fe965 100644 --- a/conf/autoload_configs/modules.conf.xml +++ b/conf/autoload_configs/modules.conf.xml @@ -1,17 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/conf/autoload_configs/switch.conf.xml b/conf/autoload_configs/switch.conf.xml index 7a68a7f2bd..896dd0e712 100644 --- a/conf/autoload_configs/switch.conf.xml +++ b/conf/autoload_configs/switch.conf.xml @@ -15,6 +15,11 @@ + + + + + @@ -81,6 +86,7 @@ + diff --git a/conf/autoload_configs/voicemail.conf.xml b/conf/autoload_configs/voicemail.conf.xml index 14ad98b41c..06bd6f6dca 100644 --- a/conf/autoload_configs/voicemail.conf.xml +++ b/conf/autoload_configs/voicemail.conf.xml @@ -33,9 +33,10 @@ - - - + --> + + + diff --git a/conf/sip_profiles/internal.xml b/conf/sip_profiles/internal.xml index 69b0d15be4..3e756a85c0 100644 --- a/conf/sip_profiles/internal.xml +++ b/conf/sip_profiles/internal.xml @@ -42,6 +42,26 @@ + + + + + + diff --git a/conf/skinny_profiles/internal.xml b/conf/skinny_profiles/internal.xml index 5feac1ffbf..52da89741d 100644 --- a/conf/skinny_profiles/internal.xml +++ b/conf/skinny_profiles/internal.xml @@ -16,7 +16,7 @@ - + diff --git a/conf/vars.xml b/conf/vars.xml index c638a80582..fced2ef139 100644 --- a/conf/vars.xml +++ b/conf/vars.xml @@ -195,7 +195,7 @@ - + From cefedc0da9a8248cbebde655ecc73701d7cfcd1d Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Tue, 30 Nov 2010 13:30:37 -0500 Subject: [PATCH 137/237] sync .sln file with mainstream, ppl stop blindly using git commit -a! --- Freeswitch.2008.sln | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/Freeswitch.2008.sln b/Freeswitch.2008.sln index 4ffd66abac..01a4cf43c1 100644 --- a/Freeswitch.2008.sln +++ b/Freeswitch.2008.sln @@ -36,6 +36,7 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Default", "Default", "{3B08FEFD-4D3D-4C16-BA94-EE83509E32A0}" ProjectSection(SolutionItems) = preProject conf\freeswitch.xml = conf\freeswitch.xml + conf\vars.xml = conf\vars.xml EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Release", "Release", "{7BFD517E-7F8F-4A40-A78E-8D3632738227}" @@ -56,6 +57,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_Build System", "_Build Sys bootstrap.sh = bootstrap.sh build\buildlib.sh = build\buildlib.sh configure.in = configure.in + Makefile.am = Makefile.am build\modmake.rules.in = build\modmake.rules.in build\modules.conf.in = build\modules.conf.in libs\win32\util.vbs = libs\win32\util.vbs @@ -90,12 +92,15 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "autoload_configs", "autoloa conf\autoload_configs\limit.conf.xml = conf\autoload_configs\limit.conf.xml conf\autoload_configs\local_stream.conf.xml = conf\autoload_configs\local_stream.conf.xml conf\autoload_configs\logfile.conf.xml = conf\autoload_configs\logfile.conf.xml + conf\autoload_configs\modules.conf.xml = conf\autoload_configs\modules.conf.xml conf\autoload_configs\openmrcp.conf.xml = conf\autoload_configs\openmrcp.conf.xml conf\autoload_configs\portaudio.conf.xml = conf\autoload_configs\portaudio.conf.xml conf\autoload_configs\rss.conf.xml = conf\autoload_configs\rss.conf.xml conf\autoload_configs\sofia.conf.xml = conf\autoload_configs\sofia.conf.xml conf\autoload_configs\spidermonkey.conf.xml = conf\autoload_configs\spidermonkey.conf.xml + conf\autoload_configs\switch.conf.xml = conf\autoload_configs\switch.conf.xml conf\autoload_configs\syslog.conf.xml = conf\autoload_configs\syslog.conf.xml + conf\autoload_configs\voicemail.conf.xml = conf\autoload_configs\voicemail.conf.xml conf\autoload_configs\wanpipe.conf.xml = conf\autoload_configs\wanpipe.conf.xml conf\autoload_configs\woomera.conf.xml = conf\autoload_configs\woomera.conf.xml conf\autoload_configs\xml_cdr.conf.xml = conf\autoload_configs\xml_cdr.conf.xml @@ -106,6 +111,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "autoload_configs", "autoloa EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dialplan", "dialplan", "{C7E2382E-2C22-4D18-BF93-80C6A1FFA7AC}" ProjectSection(SolutionItems) = preProject + conf\dialplan\default.xml = conf\dialplan\default.xml conf\dialplan\public.xml = conf\dialplan\public.xml EndProjectSection EndProject @@ -117,6 +123,7 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sip_profiles", "sip_profiles", "{8E2E8798-8B6F-4A55-8E4F-4E6FDE40ED26}" ProjectSection(SolutionItems) = preProject conf\sip_profiles\external.xml = conf\sip_profiles\external.xml + conf\sip_profiles\internal.xml = conf\sip_profiles\internal.xml conf\sip_profiles\nat.xml = conf\sip_profiles\nat.xml EndProjectSection EndProject @@ -301,6 +308,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "autoload_configs", "autoloa EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dialplan", "dialplan", "{23874F4B-C0AF-4587-9F7E-DB0F06DE8CB4}" + ProjectSection(SolutionItems) = preProject + conf\dialplan\default.xml = conf\dialplan\default.xml + EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "directory", "directory", "{19ED97F6-30D8-4FCE-AE1D-8B7FCB170D40}" ProjectSection(SolutionItems) = preProject @@ -1261,15 +1271,15 @@ Global {89385C74-5860-4174-9CAF-A39E7C48909C}.Release|Win32.Build.0 = Release|Win32 {89385C74-5860-4174-9CAF-A39E7C48909C}.Release|x64.ActiveCfg = Release|x64 {89385C74-5860-4174-9CAF-A39E7C48909C}.Release|x64.Build.0 = Release|x64 - {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.All|Win32.ActiveCfg = Release|Win32 - {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.All|Win32.Build.0 = Release|Win32 - {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.All|x64.ActiveCfg = Release|Win32 + {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.All|Win32.ActiveCfg = Release|x64 + {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.All|x64.ActiveCfg = Release|x64 + {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.All|x64.Build.0 = Release|x64 {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Debug|Win32.ActiveCfg = Debug|Win32 {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Debug|Win32.Build.0 = Debug|Win32 - {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Debug|x64.ActiveCfg = Debug|Win32 + {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Debug|x64.ActiveCfg = Debug|x64 {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Release|Win32.ActiveCfg = Release|Win32 {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Release|Win32.Build.0 = Release|Win32 - {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Release|x64.ActiveCfg = Release|Win32 + {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Release|x64.ActiveCfg = Release|x64 {692F6330-4D87-4C82-81DF-40DB5892636E}.All|Win32.ActiveCfg = Release|x64 {692F6330-4D87-4C82-81DF-40DB5892636E}.All|x64.ActiveCfg = Release|x64 {692F6330-4D87-4C82-81DF-40DB5892636E}.All|x64.Build.0 = Release|x64 From c4369fc84dc00348169f0e7adc9a0169d864ac96 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 30 Nov 2010 15:34:22 -0600 Subject: [PATCH 138/237] add uuid_fileman : <-- same vals as the callbacks in js and lua to control the currently playing file of a channel from the cli or ESL (for the people who were ignoring me on the conference call so I decided to implement it instead of try to explain it ) --- src/include/private/switch_core_pvt.h | 1 + src/include/switch_core.h | 5 + src/include/switch_ivr.h | 5 + .../applications/mod_commands/mod_commands.c | 43 +++++++ src/switch_core_rwlock.c | 40 ++++++ src/switch_core_session.c | 1 + src/switch_cpp.cpp | 115 +---------------- src/switch_ivr.c | 118 ++++++++++++++++++ src/switch_ivr_play_say.c | 44 +++++++ 9 files changed, 258 insertions(+), 114 deletions(-) diff --git a/src/include/private/switch_core_pvt.h b/src/include/private/switch_core_pvt.h index 3df9001b0c..13410a00ae 100644 --- a/src/include/private/switch_core_pvt.h +++ b/src/include/private/switch_core_pvt.h @@ -135,6 +135,7 @@ struct switch_core_session { switch_mutex_t *frame_read_mutex; switch_thread_rwlock_t *rwlock; + switch_thread_rwlock_t *io_rwlock; void *streams[SWITCH_MAX_STREAMS]; int stream_count; diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 33df7e31dd..840a06c204 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -354,6 +354,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_destroy(void); ///\ingroup core1 ///\{ + +SWITCH_DECLARE(switch_status_t) switch_core_session_io_read_lock(switch_core_session_t *session); +SWITCH_DECLARE(switch_status_t) switch_core_session_io_write_lock(switch_core_session_t *session); +SWITCH_DECLARE(switch_status_t) switch_core_session_io_rwunlock(switch_core_session_t *session); + #ifdef SWITCH_DEBUG_RWLOCKS SWITCH_DECLARE(switch_status_t) switch_core_session_perform_read_lock(_In_ switch_core_session_t *session, const char *file, const char *func, int line); #endif diff --git a/src/include/switch_ivr.h b/src/include/switch_ivr.h index 249ac63a58..d277bd030f 100644 --- a/src/include/switch_ivr.h +++ b/src/include/switch_ivr.h @@ -874,6 +874,11 @@ SWITCH_DECLARE(void) switch_ivr_dmachine_set_input_timeout_ms(switch_ivr_dmachin SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_clear_realm(switch_ivr_dmachine_t *dmachine, const char *realm); SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_set_realm(switch_ivr_dmachine_t *dmachine, const char *realm); + +SWITCH_DECLARE(switch_status_t) switch_ivr_get_file_handle(switch_core_session_t *session, switch_file_handle_t **fh); +SWITCH_DECLARE(switch_status_t) switch_ivr_release_file_handle(switch_core_session_t *session, switch_file_handle_t **fh); +SWITCH_DECLARE(switch_status_t) switch_ivr_process_fh(switch_core_session_t *session, const char *cmd, switch_file_handle_t *fhp); + /** @} */ SWITCH_END_EXTERN_C diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c index ba4b6d310d..c7edfd5420 100644 --- a/src/mod/applications/mod_commands/mod_commands.c +++ b/src/mod/applications/mod_commands/mod_commands.c @@ -3968,6 +3968,47 @@ SWITCH_STANDARD_API(uuid_getvar_function) return SWITCH_STATUS_SUCCESS; } + +#define FILEMAN_SYNTAX " :" +SWITCH_STANDARD_API(uuid_fileman_function) +{ + switch_core_session_t *psession = NULL; + char *mycmd = NULL, *argv[4] = { 0 }; + int argc = 0; + + if (!zstr(cmd) && (mycmd = strdup(cmd))) { + argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); + if (argc >= 2 && !zstr(argv[0])) { + char *uuid = argv[0]; + char *cmd = argv[1]; + + if ((psession = switch_core_session_locate(uuid))) { + switch_channel_t *channel; + switch_file_handle_t *fh = NULL; + + channel = switch_core_session_get_channel(psession); + + if (switch_ivr_get_file_handle(psession, &fh) == SWITCH_STATUS_SUCCESS) { + switch_ivr_process_fh(psession, cmd, fh); + switch_ivr_release_file_handle(psession, &fh); + } + + switch_core_session_rwunlock(psession); + + } else { + stream->write_function(stream, "-ERR No Such Channel!\n"); + } + goto done; + } + } + + stream->write_function(stream, "-USAGE: %s\n", GETVAR_SYNTAX); + + done: + switch_safe_free(mycmd); + return SWITCH_STATUS_SUCCESS; +} + #define UUID_SEND_DTMF_SYNTAX " " SWITCH_STANDARD_API(uuid_send_dtmf_function) { @@ -4674,6 +4715,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load) SWITCH_ADD_API(commands_api_interface, "uuid_display", "change display", uuid_display_function, DISPLAY_SYNTAX); SWITCH_ADD_API(commands_api_interface, "uuid_dump", "uuid_dump", uuid_dump_function, DUMP_SYNTAX); SWITCH_ADD_API(commands_api_interface, "uuid_exists", "see if a uuid exists", uuid_exists_function, EXISTS_SYNTAX); + SWITCH_ADD_API(commands_api_interface, "uuid_fileman", "uuid_fileman", uuid_fileman_function, FILEMAN_SYNTAX); SWITCH_ADD_API(commands_api_interface, "uuid_flush_dtmf", "Flush dtmf on a given uuid", uuid_flush_dtmf_function, ""); SWITCH_ADD_API(commands_api_interface, "uuid_getvar", "uuid_getvar", uuid_getvar_function, GETVAR_SYNTAX); SWITCH_ADD_API(commands_api_interface, "uuid_hold", "hold", uuid_hold_function, HOLD_SYNTAX); @@ -4785,6 +4827,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load) switch_console_set_complete("add uuid_display ::console::list_uuid"); switch_console_set_complete("add uuid_dump ::console::list_uuid"); switch_console_set_complete("add uuid_exists ::console::list_uuid"); + switch_console_set_complete("add uuid_fileman ::console::list_uuid"); switch_console_set_complete("add uuid_flush_dtmf ::console::list_uuid"); switch_console_set_complete("add uuid_getvar ::console::list_uuid"); switch_console_set_complete("add uuid_hold ::console::list_uuid"); diff --git a/src/switch_core_rwlock.c b/src/switch_core_rwlock.c index 4285491dc1..57168d9a29 100644 --- a/src/switch_core_rwlock.c +++ b/src/switch_core_rwlock.c @@ -36,6 +36,46 @@ #include "private/switch_core_pvt.h" +SWITCH_DECLARE(switch_status_t) switch_core_session_io_read_lock(switch_core_session_t *session) +{ + switch_status_t status = SWITCH_STATUS_FALSE; + + if (session->io_rwlock) { + if (switch_thread_rwlock_tryrdlock(session->io_rwlock) == SWITCH_STATUS_SUCCESS) { + status = SWITCH_STATUS_SUCCESS; + } + } + + return status; +} + +SWITCH_DECLARE(switch_status_t) switch_core_session_io_write_lock(switch_core_session_t *session) +{ + switch_status_t status = SWITCH_STATUS_FALSE; + + if (session->io_rwlock) { + switch_thread_rwlock_wrlock(session->io_rwlock); + status = SWITCH_STATUS_SUCCESS; + } + + return status; +} + + +SWITCH_DECLARE(switch_status_t) switch_core_session_io_rwunlock(switch_core_session_t *session) +{ + switch_status_t status = SWITCH_STATUS_FALSE; + + if (session->io_rwlock) { + switch_thread_rwlock_unlock(session->io_rwlock); + status = SWITCH_STATUS_SUCCESS; + } + + return status; +} + + + #ifdef SWITCH_DEBUG_RWLOCKS SWITCH_DECLARE(switch_status_t) switch_core_session_perform_read_lock(switch_core_session_t *session, const char *file, const char *func, int line) #else diff --git a/src/switch_core_session.c b/src/switch_core_session.c index a84bfabaf0..fc7648155a 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -1667,6 +1667,7 @@ SWITCH_DECLARE(switch_core_session_t *) switch_core_session_request_uuid(switch_ switch_thread_rwlock_create(&session->bug_rwlock, session->pool); switch_thread_cond_create(&session->cond, session->pool); switch_thread_rwlock_create(&session->rwlock, session->pool); + switch_thread_rwlock_create(&session->io_rwlock, session->pool); switch_queue_create(&session->message_queue, SWITCH_MESSAGE_QUEUE_LEN, session->pool); switch_queue_create(&session->event_queue, SWITCH_EVENT_QUEUE_LEN, session->pool); switch_queue_create(&session->private_event_queue, SWITCH_EVENT_QUEUE_LEN, session->pool); diff --git a/src/switch_cpp.cpp b/src/switch_cpp.cpp index 469ae18c4b..40462db567 100644 --- a/src/switch_cpp.cpp +++ b/src/switch_cpp.cpp @@ -1269,120 +1269,7 @@ SWITCH_DECLARE(switch_status_t) CoreSession::process_callback_result(char *resul this_check(SWITCH_STATUS_FALSE); sanity_check(SWITCH_STATUS_FALSE); - if (zstr(result)) { - return SWITCH_STATUS_SUCCESS; - } - - if (fhp) { - if (!switch_test_flag(fhp, SWITCH_FILE_OPEN)) { - return SWITCH_STATUS_FALSE; - } - - if (!strncasecmp(result, "speed", 5)) { - char *p; - - if ((p = strchr(result, ':'))) { - p++; - if (*p == '+' || *p == '-') { - int step; - if (!(step = atoi(p))) { - step = 1; - } - fhp->speed += step; - } else { - int speed = atoi(p); - fhp->speed = speed; - } - return SWITCH_STATUS_SUCCESS; - } - - return SWITCH_STATUS_FALSE; - - } else if (!strncasecmp(result, "volume", 6)) { - char *p; - - if ((p = strchr(result, ':'))) { - p++; - if (*p == '+' || *p == '-') { - int step; - if (!(step = atoi(p))) { - step = 1; - } - fhp->vol += step; - } else { - int vol = atoi(p); - fhp->vol = vol; - } - return SWITCH_STATUS_SUCCESS; - } - - if (fhp->vol) { - switch_normalize_volume(fhp->vol); - } - - return SWITCH_STATUS_FALSE; - } else if (!strcasecmp(result, "pause")) { - if (switch_test_flag(fhp, SWITCH_FILE_PAUSE)) { - switch_clear_flag(fhp, SWITCH_FILE_PAUSE); - } else { - switch_set_flag(fhp, SWITCH_FILE_PAUSE); - } - return SWITCH_STATUS_SUCCESS; - } else if (!strcasecmp(result, "stop")) { - return SWITCH_STATUS_FALSE; - } else if (!strcasecmp(result, "truncate")) { - switch_core_file_truncate(fhp, 0); - } else if (!strcasecmp(result, "restart")) { - unsigned int pos = 0; - fhp->speed = 0; - switch_core_file_seek(fhp, &pos, 0, SEEK_SET); - return SWITCH_STATUS_SUCCESS; - } else if (!strncasecmp(result, "seek", 4)) { - switch_codec_t *codec; - unsigned int samps = 0; - unsigned int pos = 0; - char *p; - codec = switch_core_session_get_read_codec(session); - - if ((p = strchr(result, ':'))) { - p++; - if (*p == '+' || *p == '-') { - int step; - int32_t target; - if (!(step = atoi(p))) { - step = 1000; - } - - samps = step * (codec->implementation->samples_per_second / 1000); - target = (int32_t)fhp->pos + samps; - - if (target < 0) { - target = 0; - } - - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "seek to position %d\n", target); - switch_core_file_seek(fhp, &pos, target, SEEK_SET); - - } else { - samps = atoi(p) * (codec->implementation->samples_per_second / 1000); - if (samps < 0) { - samps = 0; - } - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "seek to position %d\n", samps); - switch_core_file_seek(fhp, &pos, samps, SEEK_SET); - } - } - - return SWITCH_STATUS_SUCCESS; - } - } - - if (!strcmp(result, "true") || !strcmp(result, "undefined")) { - return SWITCH_STATUS_SUCCESS; - } - - - return SWITCH_STATUS_FALSE; + return switch_ivr_process_fh(session, result, fhp); } /* For Emacs: diff --git a/src/switch_ivr.c b/src/switch_ivr.c index df88451a3d..00917adc34 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -2563,6 +2563,124 @@ SWITCH_DECLARE(switch_bool_t) switch_ivr_uuid_exists(const char *uuid) return exists; } +SWITCH_DECLARE(switch_status_t) switch_ivr_process_fh(switch_core_session_t *session, const char *cmd, switch_file_handle_t *fhp) +{ + if (zstr(cmd)) { + return SWITCH_STATUS_SUCCESS; + } + + if (fhp) { + if (!switch_test_flag(fhp, SWITCH_FILE_OPEN)) { + return SWITCH_STATUS_FALSE; + } + + if (!strncasecmp(cmd, "speed", 5)) { + char *p; + + if ((p = strchr(cmd, ':'))) { + p++; + if (*p == '+' || *p == '-') { + int step; + if (!(step = atoi(p))) { + step = 1; + } + fhp->speed += step; + } else { + int speed = atoi(p); + fhp->speed = speed; + } + return SWITCH_STATUS_SUCCESS; + } + + return SWITCH_STATUS_FALSE; + + } else if (!strncasecmp(cmd, "volume", 6)) { + char *p; + + if ((p = strchr(cmd, ':'))) { + p++; + if (*p == '+' || *p == '-') { + int step; + if (!(step = atoi(p))) { + step = 1; + } + fhp->vol += step; + } else { + int vol = atoi(p); + fhp->vol = vol; + } + return SWITCH_STATUS_SUCCESS; + } + + if (fhp->vol) { + switch_normalize_volume(fhp->vol); + } + + return SWITCH_STATUS_FALSE; + } else if (!strcasecmp(cmd, "pause")) { + if (switch_test_flag(fhp, SWITCH_FILE_PAUSE)) { + switch_clear_flag(fhp, SWITCH_FILE_PAUSE); + } else { + switch_set_flag(fhp, SWITCH_FILE_PAUSE); + } + return SWITCH_STATUS_SUCCESS; + } else if (!strcasecmp(cmd, "stop")) { + return SWITCH_STATUS_FALSE; + } else if (!strcasecmp(cmd, "truncate")) { + switch_core_file_truncate(fhp, 0); + } else if (!strcasecmp(cmd, "restart")) { + unsigned int pos = 0; + fhp->speed = 0; + switch_core_file_seek(fhp, &pos, 0, SEEK_SET); + return SWITCH_STATUS_SUCCESS; + } else if (!strncasecmp(cmd, "seek", 4)) { + switch_codec_t *codec; + unsigned int samps = 0; + unsigned int pos = 0; + char *p; + codec = switch_core_session_get_read_codec(session); + + if ((p = strchr(cmd, ':'))) { + p++; + if (*p == '+' || *p == '-') { + int step; + int32_t target; + if (!(step = atoi(p))) { + step = 1000; + } + + samps = step * (codec->implementation->samples_per_second / 1000); + target = (int32_t)fhp->pos + samps; + + if (target < 0) { + target = 0; + } + + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "seek to position %d\n", target); + switch_core_file_seek(fhp, &pos, target, SEEK_SET); + + } else { + samps = atoi(p) * (codec->implementation->samples_per_second / 1000); + if (samps < 0) { + samps = 0; + } + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "seek to position %d\n", samps); + switch_core_file_seek(fhp, &pos, samps, SEEK_SET); + } + } + + return SWITCH_STATUS_SUCCESS; + } + } + + if (!strcmp(cmd, "true") || !strcmp(cmd, "undefined")) { + return SWITCH_STATUS_SUCCESS; + } + + return SWITCH_STATUS_FALSE; + +} + /* For Emacs: * Local Variables: diff --git a/src/switch_ivr_play_say.c b/src/switch_ivr_play_say.c index 7285b894ea..3c8fa5e10f 100644 --- a/src/switch_ivr_play_say.c +++ b/src/switch_ivr_play_say.c @@ -913,6 +913,31 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_gentones(switch_core_session_t *sessi return SWITCH_STATUS_SUCCESS; } +SWITCH_DECLARE(switch_status_t) switch_ivr_get_file_handle(switch_core_session_t *session, switch_file_handle_t **fh) +{ + switch_file_handle_t *fhp; + switch_channel_t *channel = switch_core_session_get_channel(session); + + *fh = NULL; + switch_core_session_io_read_lock(session); + + if ((fhp = switch_channel_get_private(channel, "__fh"))) { + *fh = fhp; + return SWITCH_STATUS_SUCCESS; + } + + switch_core_session_io_rwunlock(session); + + return SWITCH_STATUS_FALSE; +} + +SWITCH_DECLARE(switch_status_t) switch_ivr_release_file_handle(switch_core_session_t *session, switch_file_handle_t **fh) +{ + *fh = NULL; + switch_core_session_io_rwunlock(session); + + return SWITCH_STATUS_SUCCESS; +} #define FILE_STARTSAMPLES 1024 * 32 #define FILE_BLOCKSIZE 1024 * 8 @@ -994,6 +1019,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess } + + if (play_delimiter) { file_dup = switch_core_session_strdup(session, file); argc = switch_separate_string(file_dup, play_delimiter, argv, (sizeof(argv) / sizeof(argv[0]))); @@ -1134,6 +1161,11 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess status = SWITCH_STATUS_NOTFOUND; continue; } + + switch_core_session_io_write_lock(session); + switch_channel_set_private(channel, "__fh", fh); + switch_core_session_io_rwunlock(session); + if (switch_test_flag(fh, SWITCH_FILE_NATIVE)) { asis = 1; } @@ -1208,7 +1240,12 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Raw Codec Activation Failed %s@%uhz %u channels %dms\n", codec_name, fh->samplerate, fh->channels, interval); + switch_core_session_io_write_lock(session); + switch_channel_set_private(channel, "__fh", NULL); + switch_core_session_io_rwunlock(session); + switch_core_file_close(fh); + switch_core_session_reset(session, SWITCH_TRUE, SWITCH_FALSE); status = SWITCH_STATUS_GENERR; continue; @@ -1228,6 +1265,9 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess if (switch_core_timer_init(&timer, timer_name, interval, samples, pool) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Setup timer failed!\n"); switch_core_codec_destroy(&codec); + switch_core_session_io_write_lock(session); + switch_channel_set_private(channel, "__fh", NULL); + switch_core_session_io_rwunlock(session); switch_core_file_close(fh); switch_core_session_reset(session, SWITCH_TRUE, SWITCH_FALSE); status = SWITCH_STATUS_GENERR; @@ -1538,6 +1578,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess } switch_channel_set_variable_printf(channel, "playback_samples", "%d", fh->samples_out); + switch_core_session_io_write_lock(session); + switch_channel_set_private(channel, "__fh", NULL); + switch_core_session_io_rwunlock(session); + switch_core_file_close(fh); if (fh->audio_buffer) { From 15b5170b14396e1e17b6f75a3da01695cb49eff3 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Tue, 30 Nov 2010 16:42:58 -0500 Subject: [PATCH 139/237] freetdm: ftmod_libpri - add support for RINGING state --- libs/freetdm/mod_freetdm/mod_freetdm.c | 12 ++++++------ libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c | 6 ++++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 07d4e88f33..b5c8b84c0c 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -841,9 +841,9 @@ static switch_status_t channel_receive_message_b(switch_core_session_t *session, assert(tech_pvt != NULL); if (switch_test_flag(tech_pvt, TFLAG_DEAD)) { - switch_channel_hangup(channel, SWITCH_CAUSE_LOSE_RACE); - return SWITCH_STATUS_FALSE; - } + switch_channel_hangup(channel, SWITCH_CAUSE_LOSE_RACE); + return SWITCH_STATUS_FALSE; + } if (ftdm_channel_call_check_hangup(tech_pvt->ftdmchan)) { return SWITCH_STATUS_SUCCESS; @@ -888,9 +888,9 @@ static switch_status_t channel_receive_message_fxo(switch_core_session_t *sessio assert(tech_pvt != NULL); if (switch_test_flag(tech_pvt, TFLAG_DEAD)) { - switch_channel_hangup(channel, SWITCH_CAUSE_LOSE_RACE); - return SWITCH_STATUS_FALSE; - } + switch_channel_hangup(channel, SWITCH_CAUSE_LOSE_RACE); + return SWITCH_STATUS_FALSE; + } if (switch_channel_test_flag(channel, CF_OUTBOUND)) { return SWITCH_STATUS_SUCCESS; diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c index c8e865214c..68f0e9e5a4 100644 --- a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c +++ b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c @@ -462,7 +462,7 @@ static ftdm_state_map_t isdn_state_map = { ZSD_INBOUND, ZSM_UNACCEPTABLE, {FTDM_CHANNEL_STATE_RING, FTDM_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END} + {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END} }, { ZSD_INBOUND, @@ -479,7 +479,7 @@ static ftdm_state_map_t isdn_state_map = { { ZSD_INBOUND, ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END}, + {FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END}, {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_UP, FTDM_END}, }, @@ -537,6 +537,8 @@ static __inline__ void state_advance(ftdm_channel_t *chan) break; case FTDM_CHANNEL_STATE_PROGRESS: + /* RINGING is an alias for PROGRESS state in inbound calls ATM */ + case FTDM_CHANNEL_STATE_RINGING: { if (ftdm_test_flag(chan, FTDM_CHANNEL_OUTBOUND)) { sig.event_id = FTDM_SIGEVENT_PROGRESS; From a1d6596ea627285828e5425282c60052c4a88b27 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 30 Nov 2010 15:50:15 -0600 Subject: [PATCH 140/237] swigall --- .../languages/mod_managed/freeswitch_wrap.cxx | 80 +++++++++++++++++++ src/mod/languages/mod_managed/managed/swig.cs | 78 ++++++++++++++++++ src/mod/languages/mod_perl/mod_perl_wrap.cpp | 6 +- 3 files changed, 161 insertions(+), 3 deletions(-) diff --git a/src/mod/languages/mod_managed/freeswitch_wrap.cxx b/src/mod/languages/mod_managed/freeswitch_wrap.cxx index d2f63b1006..f4bf780086 100644 --- a/src/mod/languages/mod_managed/freeswitch_wrap.cxx +++ b/src/mod/languages/mod_managed/freeswitch_wrap.cxx @@ -6744,6 +6744,42 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_destroy() { } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_session_io_read_lock(void * jarg1) { + int jresult ; + switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; + switch_status_t result; + + arg1 = (switch_core_session_t *)jarg1; + result = (switch_status_t)switch_core_session_io_read_lock(arg1); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_session_io_write_lock(void * jarg1) { + int jresult ; + switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; + switch_status_t result; + + arg1 = (switch_core_session_t *)jarg1; + result = (switch_status_t)switch_core_session_io_write_lock(arg1); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_session_io_rwunlock(void * jarg1) { + int jresult ; + switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; + switch_status_t result; + + arg1 = (switch_core_session_t *)jarg1; + result = (switch_status_t)switch_core_session_io_rwunlock(arg1); + jresult = result; + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_session_read_lock(void * jarg1) { int jresult ; switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; @@ -28317,6 +28353,50 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_dmachine_set_realm(void * jarg1, ch } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_get_file_handle(void * jarg1, void * jarg2) { + int jresult ; + switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; + switch_file_handle_t **arg2 = (switch_file_handle_t **) 0 ; + switch_status_t result; + + arg1 = (switch_core_session_t *)jarg1; + arg2 = (switch_file_handle_t **)jarg2; + result = (switch_status_t)switch_ivr_get_file_handle(arg1,arg2); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_release_file_handle(void * jarg1, void * jarg2) { + int jresult ; + switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; + switch_file_handle_t **arg2 = (switch_file_handle_t **) 0 ; + switch_status_t result; + + arg1 = (switch_core_session_t *)jarg1; + arg2 = (switch_file_handle_t **)jarg2; + result = (switch_status_t)switch_ivr_release_file_handle(arg1,arg2); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_process_fh(void * jarg1, char * jarg2, void * jarg3) { + int jresult ; + switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; + char *arg2 = (char *) 0 ; + switch_file_handle_t *arg3 = (switch_file_handle_t *) 0 ; + switch_status_t result; + + arg1 = (switch_core_session_t *)jarg1; + arg2 = (char *)jarg2; + arg3 = (switch_file_handle_t *)jarg3; + result = (switch_status_t)switch_ivr_process_fh(arg1,(char const *)arg2,arg3); + jresult = result; + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_SWITCH_RTP_MAX_BUF_LEN_get() { int jresult ; int result; diff --git a/src/mod/languages/mod_managed/managed/swig.cs b/src/mod/languages/mod_managed/managed/swig.cs index fd4915f013..10fd3c6bc6 100644 --- a/src/mod/languages/mod_managed/managed/swig.cs +++ b/src/mod/languages/mod_managed/managed/swig.cs @@ -1103,6 +1103,21 @@ public class freeswitch { return ret; } + public static switch_status_t switch_core_session_io_read_lock(SWIGTYPE_p_switch_core_session session) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_session_io_read_lock(SWIGTYPE_p_switch_core_session.getCPtr(session)); + return ret; + } + + public static switch_status_t switch_core_session_io_write_lock(SWIGTYPE_p_switch_core_session session) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_session_io_write_lock(SWIGTYPE_p_switch_core_session.getCPtr(session)); + return ret; + } + + public static switch_status_t switch_core_session_io_rwunlock(SWIGTYPE_p_switch_core_session session) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_session_io_rwunlock(SWIGTYPE_p_switch_core_session.getCPtr(session)); + return ret; + } + public static switch_status_t switch_core_session_read_lock(SWIGTYPE_p_switch_core_session session) { switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_session_read_lock(SWIGTYPE_p_switch_core_session.getCPtr(session)); return ret; @@ -4471,6 +4486,21 @@ public class freeswitch { return ret; } + public static switch_status_t switch_ivr_get_file_handle(SWIGTYPE_p_switch_core_session session, SWIGTYPE_p_p_switch_file_handle fh) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_ivr_get_file_handle(SWIGTYPE_p_switch_core_session.getCPtr(session), SWIGTYPE_p_p_switch_file_handle.getCPtr(fh)); + return ret; + } + + public static switch_status_t switch_ivr_release_file_handle(SWIGTYPE_p_switch_core_session session, SWIGTYPE_p_p_switch_file_handle fh) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_ivr_release_file_handle(SWIGTYPE_p_switch_core_session.getCPtr(session), SWIGTYPE_p_p_switch_file_handle.getCPtr(fh)); + return ret; + } + + public static switch_status_t switch_ivr_process_fh(SWIGTYPE_p_switch_core_session session, string cmd, switch_file_handle fhp) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_ivr_process_fh(SWIGTYPE_p_switch_core_session.getCPtr(session), cmd, switch_file_handle.getCPtr(fhp)); + return ret; + } + public static switch_status_t switch_rtp_add_crypto_key(SWIGTYPE_p_switch_rtp rtp_session, switch_rtp_crypto_direction_t direction, uint index, switch_rtp_crypto_key_type_t type, SWIGTYPE_p_unsigned_char key, SWIGTYPE_p_switch_size_t keylen) { switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_rtp_add_crypto_key(SWIGTYPE_p_switch_rtp.getCPtr(rtp_session), (int)direction, index, (int)type, SWIGTYPE_p_unsigned_char.getCPtr(key), SWIGTYPE_p_switch_size_t.getCPtr(keylen)); if (freeswitchPINVOKE.SWIGPendingException.Pending) throw freeswitchPINVOKE.SWIGPendingException.Retrieve(); @@ -7255,6 +7285,15 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_core_destroy")] public static extern int switch_core_destroy(); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_io_read_lock")] + public static extern int switch_core_session_io_read_lock(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_io_write_lock")] + public static extern int switch_core_session_io_write_lock(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_io_rwunlock")] + public static extern int switch_core_session_io_rwunlock(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_read_lock")] public static extern int switch_core_session_read_lock(HandleRef jarg1); @@ -12244,6 +12283,15 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_dmachine_set_realm")] public static extern int switch_ivr_dmachine_set_realm(HandleRef jarg1, string jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_get_file_handle")] + public static extern int switch_ivr_get_file_handle(HandleRef jarg1, HandleRef jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_release_file_handle")] + public static extern int switch_ivr_release_file_handle(HandleRef jarg1, HandleRef jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_process_fh")] + public static extern int switch_ivr_process_fh(HandleRef jarg1, string jarg2, HandleRef jarg3); + [DllImport("mod_managed", EntryPoint="CSharp_SWITCH_RTP_MAX_BUF_LEN_get")] public static extern int SWITCH_RTP_MAX_BUF_LEN_get(); @@ -17119,6 +17167,36 @@ namespace FreeSWITCH.Native { using System; using System.Runtime.InteropServices; +public class SWIGTYPE_p_p_switch_file_handle { + private HandleRef swigCPtr; + + internal SWIGTYPE_p_p_switch_file_handle(IntPtr cPtr, bool futureUse) { + swigCPtr = new HandleRef(this, cPtr); + } + + protected SWIGTYPE_p_p_switch_file_handle() { + swigCPtr = new HandleRef(null, IntPtr.Zero); + } + + internal static HandleRef getCPtr(SWIGTYPE_p_p_switch_file_handle obj) { + return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; + } +} + +} +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 1.3.35 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +namespace FreeSWITCH.Native { + +using System; +using System.Runtime.InteropServices; + public class SWIGTYPE_p_p_switch_frame { private HandleRef swigCPtr; diff --git a/src/mod/languages/mod_perl/mod_perl_wrap.cpp b/src/mod/languages/mod_perl/mod_perl_wrap.cpp index 370c88bc99..2efbdf1abc 100644 --- a/src/mod/languages/mod_perl/mod_perl_wrap.cpp +++ b/src/mod/languages/mod_perl/mod_perl_wrap.cpp @@ -9732,17 +9732,17 @@ XS(SWIG_init) { SWIG_TypeClientData(SWIGTYPE_p_IVRMenu, (void*) "freeswitch::IVRMenu"); SWIG_TypeClientData(SWIGTYPE_p_API, (void*) "freeswitch::API"); SWIG_TypeClientData(SWIGTYPE_p_input_callback_state, (void*) "freeswitch::input_callback_state_t"); - /*@SWIG:/usr/share/swig/1.3.35/perl5/perltypemaps.swg,64,%set_constant@*/ do { + /*@SWIG:/usr/local/share/swig/1.3.35/perl5/perltypemaps.swg,64,%set_constant@*/ do { SV *sv = get_sv((char*) SWIG_prefix "S_HUP", TRUE | 0x2 | GV_ADDMULTI); sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1(static_cast< int >(S_HUP))); SvREADONLY_on(sv); } while(0) /*@SWIG@*/; - /*@SWIG:/usr/share/swig/1.3.35/perl5/perltypemaps.swg,64,%set_constant@*/ do { + /*@SWIG:/usr/local/share/swig/1.3.35/perl5/perltypemaps.swg,64,%set_constant@*/ do { SV *sv = get_sv((char*) SWIG_prefix "S_FREE", TRUE | 0x2 | GV_ADDMULTI); sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1(static_cast< int >(S_FREE))); SvREADONLY_on(sv); } while(0) /*@SWIG@*/; - /*@SWIG:/usr/share/swig/1.3.35/perl5/perltypemaps.swg,64,%set_constant@*/ do { + /*@SWIG:/usr/local/share/swig/1.3.35/perl5/perltypemaps.swg,64,%set_constant@*/ do { SV *sv = get_sv((char*) SWIG_prefix "S_RDLOCK", TRUE | 0x2 | GV_ADDMULTI); sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1(static_cast< int >(S_RDLOCK))); SvREADONLY_on(sv); From 086245a70103f87fc16eb294e23738cca95b1817 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Tue, 30 Nov 2010 17:21:48 -0500 Subject: [PATCH 141/237] freetdm: do not skip states if FREETDM_SKIP_SIG_STATES is not defined --- libs/freetdm/src/ftdm_io.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index cffd98203b..bcaa15a77c 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -2051,10 +2051,10 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_answer(const char *file, const char goto done; } -#if 0 - /* DAVIDY - We will fail RFC's if we do that, but some modules apart from ftmod_sangoma_isdn +#ifndef FREETDM_SKIP_SIG_STATES + /* We will fail RFC's if we not skip states, but some modules apart from ftmod_sangoma_isdn * expect the call to always to go PROGRESS and PROGRESS MEDIA state before going to UP, so - * remove this only in netborder branch for now */ + * remove this only in netborder branch for now while we update the sig modules */ if (ftdmchan->state < FTDM_CHANNEL_STATE_PROGRESS) { ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS, 1); From 35ba58e64994efa0a2c97a08b5164a5ea9f20679 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Tue, 30 Nov 2010 16:45:05 -0500 Subject: [PATCH 142/237] freetdm - ISDN:Fix for windows compilation issues --- libs/freetdm/src/ftdm_call_utils.c | 12 +++---- libs/freetdm/src/ftdm_io.c | 2 -- .../ftmod_sangoma_isdn/ftmod_sangoma_isdn.c | 4 +-- .../ftmod_sangoma_isdn/ftmod_sangoma_isdn.h | 31 +++++++++++++++++-- .../ftmod_sangoma_isdn_stack_hndl.c | 5 ++- .../ftmod_sangoma_isdn_support.c | 8 ++--- 6 files changed, 42 insertions(+), 20 deletions(-) diff --git a/libs/freetdm/src/ftdm_call_utils.c b/libs/freetdm/src/ftdm_call_utils.c index 52d2557a01..69f2fb4fff 100644 --- a/libs/freetdm/src/ftdm_call_utils.c +++ b/libs/freetdm/src/ftdm_call_utils.c @@ -38,7 +38,7 @@ FT_DECLARE(ftdm_status_t) ftdm_set_npi(const char *string, uint8_t *target) { - int val; + uint8_t val; ftdm_status_t status = FTDM_SUCCESS; val = ftdm_str2ftdm_npi(string); @@ -53,7 +53,7 @@ FT_DECLARE(ftdm_status_t) ftdm_set_npi(const char *string, uint8_t *target) FT_DECLARE(ftdm_status_t) ftdm_set_ton(const char *string, uint8_t *target) { - int val; + uint8_t val; ftdm_status_t status = FTDM_SUCCESS; val = ftdm_str2ftdm_ton(string); @@ -68,7 +68,7 @@ FT_DECLARE(ftdm_status_t) ftdm_set_ton(const char *string, uint8_t *target) FT_DECLARE(ftdm_status_t) ftdm_set_bearer_capability(const char *string, uint8_t *target) { - int val; + uint8_t val; ftdm_status_t status = FTDM_SUCCESS; val = ftdm_str2ftdm_bearer_cap(string); @@ -84,7 +84,7 @@ FT_DECLARE(ftdm_status_t) ftdm_set_bearer_capability(const char *string, uint8_t FT_DECLARE(ftdm_status_t) ftdm_set_bearer_layer1(const char *string, uint8_t *target) { - int val; + uint8_t val; ftdm_status_t status = FTDM_SUCCESS; val = ftdm_str2ftdm_usr_layer1_prot(string); @@ -100,7 +100,7 @@ FT_DECLARE(ftdm_status_t) ftdm_set_bearer_layer1(const char *string, uint8_t *ta FT_DECLARE(ftdm_status_t) ftdm_set_screening_ind(const char *string, uint8_t *target) { - int val; + uint8_t val; ftdm_status_t status = FTDM_SUCCESS; val = ftdm_str2ftdm_screening(string); @@ -116,7 +116,7 @@ FT_DECLARE(ftdm_status_t) ftdm_set_screening_ind(const char *string, uint8_t *ta FT_DECLARE(ftdm_status_t) ftdm_set_presentation_ind(const char *string, uint8_t *target) { - int val; + uint8_t val; ftdm_status_t status = FTDM_SUCCESS; val = ftdm_str2ftdm_presentation(string); diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index bcaa15a77c..5ba7e389f8 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -38,8 +38,6 @@ */ #define _GNU_SOURCE -#ifndef WIN32 -#endif #include "private/ftdm_core.h" #include #ifdef WIN32 diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c index 02927d7c88..03b5a5fb1d 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c @@ -799,9 +799,7 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan) break; case FTDM_CHANNEL_STATE_DOWN: /* the call is finished and removed */ { - uint8_t glare = 0; - - glare = sngisdn_test_flag(sngisdn_info, FLAG_GLARE); + uint8_t glare = sngisdn_test_flag(sngisdn_info, FLAG_GLARE); /* clear all of the call specific data store in the channel structure */ clear_call_data(sngisdn_info); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h index 9cddecb04e..b9ab3395ae 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h @@ -64,6 +64,33 @@ /* TODO: rename all *_cc_* to *_an_* */ +#define SNGISDN_ENUM_NAMES(_NAME, _STRINGS) static const char * _NAME [] = { _STRINGS , NULL }; +#define SNGISDN_STR2ENUM_P(_FUNC1, _FUNC2, _TYPE) _TYPE _FUNC1 (const char *name); const char * _FUNC2 (_TYPE type); +#define SNGISDN_STR2ENUM(_FUNC1, _FUNC2, _TYPE, _STRINGS, _MAX) \ + _TYPE _FUNC1 (const char *name) \ +{ \ + int i; \ + _TYPE t = _MAX ; \ + \ + for (i = 0; i < _MAX ; i++) { \ + if (!strcasecmp(name, _STRINGS[i])) { \ + t = (_TYPE) i; \ + break; \ +} \ +} \ + \ + return t; \ +} \ + const char * _FUNC2 (_TYPE type) \ +{ \ + if (type > _MAX) { \ + type = _MAX; \ +} \ + return _STRINGS[(int)type]; \ +} \ + + + typedef enum { FLAG_RESET_RX = (1 << 0), FLAG_RESET_TX = (1 << 1), @@ -153,7 +180,7 @@ typedef enum { SNGISDN_PROGIND_DESCR_INVALID, } ftdm_sngisdn_progind_descr_t; #define SNGISDN_PROGIND_DESCR_STRINGS "not-end-to-end-isdn", "destination-is-non-isdn", "origination-is-non-isdn", "call-returned-to-isdn", "service-change", "inband-info-available", "invalid" -FTDM_STR2ENUM_P(ftdm_str2ftdm_sngisdn_progind_descr, ftdm_sngisdn_progind_descr2str, ftdm_sngisdn_progind_descr_t); +SNGISDN_STR2ENUM_P(ftdm_str2ftdm_sngisdn_progind_descr, ftdm_sngisdn_progind_descr2str, ftdm_sngisdn_progind_descr_t); typedef enum { /* User */ @@ -174,7 +201,7 @@ typedef enum { SNGISDN_PROGIND_LOC_INVALID, } ftdm_sngisdn_progind_loc_t; #define SNGISDN_PROGIND_LOC_STRINGS "user", "private-net-local-user", "public-net-local-user", "transit-network", "public-net-remote-user", "private-net-remote-user", "beyond-interworking", "invalid" -FTDM_STR2ENUM_P(ftdm_str2ftdm_sngisdn_progind_loc, ftdm_sngisdn_progind_loc2str, ftdm_sngisdn_progind_loc_t); +SNGISDN_STR2ENUM_P(ftdm_str2ftdm_sngisdn_progind_loc, ftdm_sngisdn_progind_loc2str, ftdm_sngisdn_progind_loc_t); typedef struct ftdm_sngisdn_prog_ind { ftdm_sngisdn_progind_loc_t loc; /* location */ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c index c4e9f4a33f..d557ca3ba0 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c @@ -255,10 +255,9 @@ void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event) uint8_t ces = sngisdn_event->ces; sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info; ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; - - ISDN_FUNC_TRACE_ENTER(__FUNCTION__); - CnStEvnt *cnStEvnt = &sngisdn_event->event.cnStEvnt; + + ISDN_FUNC_TRACE_ENTER(__FUNCTION__); ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n"); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c index 964d06caaf..42bcd1e20a 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c @@ -37,11 +37,11 @@ /* ftmod_sangoma_isdn specific enum look-up functions */ -FTDM_ENUM_NAMES(SNGISDN_PROGIND_DESCR_NAMES, SNGISDN_PROGIND_DESCR_STRINGS) -FTDM_STR2ENUM(ftdm_str2ftdm_sngisdn_progind_descr, ftdm_sngisdn_progind_descr2str, ftdm_sngisdn_progind_descr_t, SNGISDN_PROGIND_DESCR_NAMES, SNGISDN_PROGIND_DESCR_INVALID) +SNGISDN_ENUM_NAMES(SNGISDN_PROGIND_DESCR_NAMES, SNGISDN_PROGIND_DESCR_STRINGS) +SNGISDN_STR2ENUM(ftdm_str2ftdm_sngisdn_progind_descr, ftdm_sngisdn_progind_descr2str, ftdm_sngisdn_progind_descr_t, SNGISDN_PROGIND_DESCR_NAMES, SNGISDN_PROGIND_DESCR_INVALID) -FTDM_ENUM_NAMES(SNGISDN_PROGIND_LOC_NAMES, SNGISDN_PROGIND_LOC_STRINGS) -FTDM_STR2ENUM(ftdm_str2ftdm_sngisdn_progind_loc, ftdm_sngisdn_progind_loc2str, ftdm_sngisdn_progind_loc_t, SNGISDN_PROGIND_LOC_NAMES, SNGISDN_PROGIND_LOC_INVALID) +SNGISDN_ENUM_NAMES(SNGISDN_PROGIND_LOC_NAMES, SNGISDN_PROGIND_LOC_STRINGS) +SNGISDN_STR2ENUM(ftdm_str2ftdm_sngisdn_progind_loc, ftdm_sngisdn_progind_loc2str, ftdm_sngisdn_progind_loc_t, SNGISDN_PROGIND_LOC_NAMES, SNGISDN_PROGIND_LOC_INVALID) ftdm_status_t sngisdn_check_free_ids(void); From a669f76f786e2a74d3621cf5d4f9b0ad30d7e89a Mon Sep 17 00:00:00 2001 From: Brian West Date: Tue, 30 Nov 2010 17:38:44 -0600 Subject: [PATCH 143/237] Fix issue when fs_path is used so we pick the correct media IP in our outbound invite this was soemthing that wouldn't work correctly over ATT on the iphone. --- src/mod/endpoints/mod_sofia/mod_sofia.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 3bb926adf3..74c4c0897e 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -3900,7 +3900,26 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session switch_channel_set_variable_printf(nchannel, "sip_local_network_addr", "%s", profile->extsipip ? profile->extsipip : profile->sipip); switch_channel_set_variable(nchannel, "sip_profile_name", profile_name); - switch_split_user_domain(switch_core_session_strdup(nsession, tech_pvt->dest), NULL, &tech_pvt->remote_ip); + if (switch_stristr("fs_path", tech_pvt->dest)) { + char *remote_host = NULL; + const char *s; + + if ((s = switch_stristr("fs_path=", tech_pvt->dest))) { + s += 8; + } + + if (s) { + remote_host = switch_core_session_strdup(nsession, s); + switch_url_decode(remote_host); + } + if (!zstr(remote_host)) { + switch_split_user_domain(remote_host, NULL, &tech_pvt->remote_ip); + } + } + + if (zstr(tech_pvt->remote_ip)) { + switch_split_user_domain(switch_core_session_strdup(nsession, tech_pvt->dest), NULL, &tech_pvt->remote_ip); + } if (dest_to) { if (strchr(dest_to, '@')) { From 82394b37687cb43ae3805d14a7ed9ca20da95a63 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 30 Nov 2010 18:22:12 -0600 Subject: [PATCH 144/237] add switch_ivr_insert_file to insert one file into another at an arbitrary sample point --- src/include/switch_ivr.h | 1 + src/switch_ivr.c | 156 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 157 insertions(+) diff --git a/src/include/switch_ivr.h b/src/include/switch_ivr.h index d277bd030f..da366c5b8d 100644 --- a/src/include/switch_ivr.h +++ b/src/include/switch_ivr.h @@ -878,6 +878,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_set_realm(switch_ivr_dmachin SWITCH_DECLARE(switch_status_t) switch_ivr_get_file_handle(switch_core_session_t *session, switch_file_handle_t **fh); SWITCH_DECLARE(switch_status_t) switch_ivr_release_file_handle(switch_core_session_t *session, switch_file_handle_t **fh); SWITCH_DECLARE(switch_status_t) switch_ivr_process_fh(switch_core_session_t *session, const char *cmd, switch_file_handle_t *fhp); +SWITCH_DECLARE(switch_status_t) switch_ivr_insert_file(switch_core_session_t *session, const char *file, const char *insert_file, switch_size_t sample_point); /** @} */ diff --git a/src/switch_ivr.c b/src/switch_ivr.c index 00917adc34..46ba4e6659 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -2681,6 +2681,162 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_process_fh(switch_core_session_t *ses } +#define START_SAMPLES 32768 + +SWITCH_DECLARE(switch_status_t) switch_ivr_insert_file(switch_core_session_t *session, const char *file, const char *insert_file, switch_size_t sample_point) +{ + switch_file_handle_t orig_fh = { 0 }; + switch_file_handle_t new_fh = { 0 }; + switch_codec_implementation_t read_impl = { 0 }; + char *tmp_file; + switch_uuid_t uuid; + char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1]; + int16_t *abuf = NULL; + switch_size_t olen = 0; + int asis = 0; + switch_channel_t *channel = switch_core_session_get_channel(session); + switch_size_t sample_count = 0; + uint32_t pos = 0; + char *ext; + + switch_uuid_get(&uuid); + switch_uuid_format(uuid_str, &uuid); + + if ((ext = strrchr(file, '.'))) { + ext++; + } else { + ext = "wav"; + } + + tmp_file = switch_core_session_sprintf(session, "%s%smsg_%s.%s", + SWITCH_GLOBAL_dirs.temp_dir, SWITCH_PATH_SEPARATOR, uuid_str, ext); + + switch_core_session_get_read_impl(session, &read_impl); + + new_fh.channels = read_impl.number_of_channels; + new_fh.native_rate = read_impl.actual_samples_per_second; + + + if (switch_core_file_open(&new_fh, + tmp_file, + new_fh.channels, + read_impl.actual_samples_per_second, SWITCH_FILE_FLAG_WRITE | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failed to open file %s\n", tmp_file); + goto end; + } + + + if (switch_core_file_open(&orig_fh, + file, + new_fh.channels, + read_impl.actual_samples_per_second, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failed to open file %s\n", file); + goto end; + } + + + switch_zmalloc(abuf, START_SAMPLES * sizeof(*abuf)); + + if (switch_test_flag((&orig_fh), SWITCH_FILE_NATIVE)) { + asis = 1; + } + + while (switch_channel_ready(channel)) { + olen = START_SAMPLES; + + if (!asis) { + olen /= 2; + } + + if ((sample_count + olen) > sample_point) { + olen = sample_point - sample_count; + } + + if (!olen || switch_core_file_read(&orig_fh, abuf, &olen) != SWITCH_STATUS_SUCCESS || !olen) { + break; + } + + sample_count += olen; + + switch_core_file_write(&new_fh, abuf, &olen); + } + + switch_core_file_close(&orig_fh); + + + if (switch_core_file_open(&orig_fh, + insert_file, + new_fh.channels, + read_impl.actual_samples_per_second, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failed to open file %s\n", file); + goto end; + } + + + while (switch_channel_ready(channel)) { + olen = START_SAMPLES; + + if (!asis) { + olen /= 2; + } + + if (switch_core_file_read(&orig_fh, abuf, &olen) != SWITCH_STATUS_SUCCESS || !olen) { + break; + } + + sample_count += olen; + + switch_core_file_write(&new_fh, abuf, &olen); + } + + switch_core_file_close(&orig_fh); + + if (switch_core_file_open(&orig_fh, + file, + new_fh.channels, + read_impl.actual_samples_per_second, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failed to open file %s\n", file); + goto end; + } + + pos = 0; + switch_core_file_seek(&orig_fh, &pos, sample_point, SEEK_SET); + + while (switch_channel_ready(channel)) { + olen = START_SAMPLES; + + if (!asis) { + olen /= 2; + } + + if (switch_core_file_read(&orig_fh, abuf, &olen) != SWITCH_STATUS_SUCCESS || !olen) { + break; + } + + sample_count += olen; + + switch_core_file_write(&new_fh, abuf, &olen); + } + + end: + + if (switch_test_flag((&orig_fh), SWITCH_FILE_OPEN)) { + switch_core_file_close(&orig_fh); + } + + if (switch_test_flag((&new_fh), SWITCH_FILE_OPEN)) { + switch_core_file_close(&new_fh); + } + + switch_file_rename(tmp_file, file, switch_core_session_get_pool(session)); + unlink(tmp_file); + + switch_safe_free(abuf); + + return SWITCH_STATUS_SUCCESS; +} + + /* For Emacs: * Local Variables: From 77a7f93d6799ebf7cfb433af7a78b2c7b6ace60d Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 30 Nov 2010 18:23:01 -0600 Subject: [PATCH 145/237] reswig --- .../languages/mod_managed/freeswitch_wrap.cxx | 24 +++++++++++++++++++ src/mod/languages/mod_managed/managed/swig.cs | 9 +++++++ 2 files changed, 33 insertions(+) diff --git a/src/mod/languages/mod_managed/freeswitch_wrap.cxx b/src/mod/languages/mod_managed/freeswitch_wrap.cxx index f4bf780086..a65d82d9cb 100644 --- a/src/mod/languages/mod_managed/freeswitch_wrap.cxx +++ b/src/mod/languages/mod_managed/freeswitch_wrap.cxx @@ -28397,6 +28397,30 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_process_fh(void * jarg1, char * jar } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_insert_file(void * jarg1, char * jarg2, char * jarg3, void * jarg4) { + int jresult ; + switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; + char *arg2 = (char *) 0 ; + char *arg3 = (char *) 0 ; + switch_size_t arg4 ; + switch_status_t result; + switch_size_t *argp4 ; + + arg1 = (switch_core_session_t *)jarg1; + arg2 = (char *)jarg2; + arg3 = (char *)jarg3; + argp4 = (switch_size_t *)jarg4; + if (!argp4) { + SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "Attempt to dereference null switch_size_t", 0); + return 0; + } + arg4 = *argp4; + result = (switch_status_t)switch_ivr_insert_file(arg1,(char const *)arg2,(char const *)arg3,arg4); + jresult = result; + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_SWITCH_RTP_MAX_BUF_LEN_get() { int jresult ; int result; diff --git a/src/mod/languages/mod_managed/managed/swig.cs b/src/mod/languages/mod_managed/managed/swig.cs index 10fd3c6bc6..e024c586f8 100644 --- a/src/mod/languages/mod_managed/managed/swig.cs +++ b/src/mod/languages/mod_managed/managed/swig.cs @@ -4501,6 +4501,12 @@ public class freeswitch { return ret; } + public static switch_status_t switch_ivr_insert_file(SWIGTYPE_p_switch_core_session session, string file, string insert_file, SWIGTYPE_p_switch_size_t sample_point) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_ivr_insert_file(SWIGTYPE_p_switch_core_session.getCPtr(session), file, insert_file, SWIGTYPE_p_switch_size_t.getCPtr(sample_point)); + if (freeswitchPINVOKE.SWIGPendingException.Pending) throw freeswitchPINVOKE.SWIGPendingException.Retrieve(); + return ret; + } + public static switch_status_t switch_rtp_add_crypto_key(SWIGTYPE_p_switch_rtp rtp_session, switch_rtp_crypto_direction_t direction, uint index, switch_rtp_crypto_key_type_t type, SWIGTYPE_p_unsigned_char key, SWIGTYPE_p_switch_size_t keylen) { switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_rtp_add_crypto_key(SWIGTYPE_p_switch_rtp.getCPtr(rtp_session), (int)direction, index, (int)type, SWIGTYPE_p_unsigned_char.getCPtr(key), SWIGTYPE_p_switch_size_t.getCPtr(keylen)); if (freeswitchPINVOKE.SWIGPendingException.Pending) throw freeswitchPINVOKE.SWIGPendingException.Retrieve(); @@ -12292,6 +12298,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_process_fh")] public static extern int switch_ivr_process_fh(HandleRef jarg1, string jarg2, HandleRef jarg3); + [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_insert_file")] + public static extern int switch_ivr_insert_file(HandleRef jarg1, string jarg2, string jarg3, HandleRef jarg4); + [DllImport("mod_managed", EntryPoint="CSharp_SWITCH_RTP_MAX_BUF_LEN_get")] public static extern int SWITCH_RTP_MAX_BUF_LEN_get(); From bc34a24d4c7a70f5b526252495a19ba5f3d2de86 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 30 Nov 2010 18:35:43 -0600 Subject: [PATCH 146/237] get ready for ClueCon 11 --- build/Makefile.am | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/build/Makefile.am b/build/Makefile.am index 4b426ef6e3..1d57dad528 100644 --- a/build/Makefile.am +++ b/build/Makefile.am @@ -6,8 +6,13 @@ all: @echo " + Install by running: +" @echo " + +" @echo " + $(MK) install +" + @echo " + +" + @echo " + While you're waiting, register for ClueCon! +" + @echo " + http://www.cluecon.com +" + @echo " + +" @echo " +-----------------------------------------------+" + install: @echo " +---------- FreeSWITCH install Complete ----------+" @echo " + FreeSWITCH has been successfully installed. +" From 2343f68597f7f5d2986aeef1f85f579add45b0c4 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Tue, 30 Nov 2010 21:43:28 -0600 Subject: [PATCH 147/237] VS2010 reswig --- .../mod_managed/freeswitch_wrap.2010.cxx | 132 ++++++++++++++++++ .../mod_managed/managed/swig.2010.cs | 103 ++++++++++++++ 2 files changed, 235 insertions(+) diff --git a/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx b/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx index 4a0b52efec..8033a8faa5 100644 --- a/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx +++ b/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx @@ -6454,6 +6454,42 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_destroy() { } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_session_io_read_lock(void * jarg1) { + int jresult ; + switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; + switch_status_t result; + + arg1 = (switch_core_session_t *)jarg1; + result = (switch_status_t)switch_core_session_io_read_lock(arg1); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_session_io_write_lock(void * jarg1) { + int jresult ; + switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; + switch_status_t result; + + arg1 = (switch_core_session_t *)jarg1; + result = (switch_status_t)switch_core_session_io_write_lock(arg1); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_session_io_rwunlock(void * jarg1) { + int jresult ; + switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; + switch_status_t result; + + arg1 = (switch_core_session_t *)jarg1; + result = (switch_status_t)switch_core_session_io_rwunlock(arg1); + jresult = result; + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_session_read_lock(void * jarg1) { int jresult ; switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; @@ -7336,6 +7372,22 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_session_execute_application_get_fl } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_session_execute_application_async(void * jarg1, char * jarg2, char * jarg3) { + int jresult ; + switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; + char *arg2 = (char *) 0 ; + char *arg3 = (char *) 0 ; + switch_status_t result; + + arg1 = (switch_core_session_t *)jarg1; + arg2 = (char *)jarg2; + arg3 = (char *)jarg3; + result = (switch_status_t)switch_core_session_execute_application_async(arg1,(char const *)arg2,(char const *)arg3); + jresult = result; + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_session_get_app_flags(char * jarg1, void * jarg2) { int jresult ; char *arg1 = (char *) 0 ; @@ -7566,6 +7618,18 @@ SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_core_session_event_count(void } +SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_core_session_messages_waiting(void * jarg1) { + unsigned long jresult ; + switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; + uint32_t result; + + arg1 = (switch_core_session_t *)jarg1; + result = (uint32_t)switch_core_session_messages_waiting(arg1); + jresult = (unsigned long)result; + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_session_dequeue_event(void * jarg1, void * jarg2, int jarg3) { int jresult ; switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; @@ -27597,6 +27661,74 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_dmachine_set_realm(void * jarg1, ch } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_get_file_handle(void * jarg1, void * jarg2) { + int jresult ; + switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; + switch_file_handle_t **arg2 = (switch_file_handle_t **) 0 ; + switch_status_t result; + + arg1 = (switch_core_session_t *)jarg1; + arg2 = (switch_file_handle_t **)jarg2; + result = (switch_status_t)switch_ivr_get_file_handle(arg1,arg2); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_release_file_handle(void * jarg1, void * jarg2) { + int jresult ; + switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; + switch_file_handle_t **arg2 = (switch_file_handle_t **) 0 ; + switch_status_t result; + + arg1 = (switch_core_session_t *)jarg1; + arg2 = (switch_file_handle_t **)jarg2; + result = (switch_status_t)switch_ivr_release_file_handle(arg1,arg2); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_process_fh(void * jarg1, char * jarg2, void * jarg3) { + int jresult ; + switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; + char *arg2 = (char *) 0 ; + switch_file_handle_t *arg3 = (switch_file_handle_t *) 0 ; + switch_status_t result; + + arg1 = (switch_core_session_t *)jarg1; + arg2 = (char *)jarg2; + arg3 = (switch_file_handle_t *)jarg3; + result = (switch_status_t)switch_ivr_process_fh(arg1,(char const *)arg2,arg3); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_insert_file(void * jarg1, char * jarg2, char * jarg3, void * jarg4) { + int jresult ; + switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; + char *arg2 = (char *) 0 ; + char *arg3 = (char *) 0 ; + switch_size_t arg4 ; + switch_size_t *argp4 ; + switch_status_t result; + + arg1 = (switch_core_session_t *)jarg1; + arg2 = (char *)jarg2; + arg3 = (char *)jarg3; + argp4 = (switch_size_t *)jarg4; + if (!argp4) { + SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "Attempt to dereference null switch_size_t", 0); + return 0; + } + arg4 = *argp4; + result = (switch_status_t)switch_ivr_insert_file(arg1,(char const *)arg2,(char const *)arg3,arg4); + jresult = result; + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_SWITCH_RTP_MAX_BUF_LEN_get() { int jresult ; int result; diff --git a/src/mod/languages/mod_managed/managed/swig.2010.cs b/src/mod/languages/mod_managed/managed/swig.2010.cs index 2897fef1e5..4d14f10879 100644 --- a/src/mod/languages/mod_managed/managed/swig.2010.cs +++ b/src/mod/languages/mod_managed/managed/swig.2010.cs @@ -1113,6 +1113,21 @@ public class freeswitch { return ret; } + public static switch_status_t switch_core_session_io_read_lock(SWIGTYPE_p_switch_core_session session) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_session_io_read_lock(SWIGTYPE_p_switch_core_session.getCPtr(session)); + return ret; + } + + public static switch_status_t switch_core_session_io_write_lock(SWIGTYPE_p_switch_core_session session) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_session_io_write_lock(SWIGTYPE_p_switch_core_session.getCPtr(session)); + return ret; + } + + public static switch_status_t switch_core_session_io_rwunlock(SWIGTYPE_p_switch_core_session session) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_session_io_rwunlock(SWIGTYPE_p_switch_core_session.getCPtr(session)); + return ret; + } + public static switch_status_t switch_core_session_read_lock(SWIGTYPE_p_switch_core_session session) { switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_session_read_lock(SWIGTYPE_p_switch_core_session.getCPtr(session)); return ret; @@ -1449,6 +1464,11 @@ public class freeswitch { return ret; } + public static switch_status_t switch_core_session_execute_application_async(SWIGTYPE_p_switch_core_session session, string app, string arg) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_session_execute_application_async(SWIGTYPE_p_switch_core_session.getCPtr(session), app, arg); + return ret; + } + public static switch_status_t switch_core_session_get_app_flags(string app, SWIGTYPE_p_int flags) { switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_session_get_app_flags(app, SWIGTYPE_p_int.getCPtr(flags)); return ret; @@ -1528,6 +1548,11 @@ public class freeswitch { return ret; } + public static uint switch_core_session_messages_waiting(SWIGTYPE_p_switch_core_session session) { + uint ret = freeswitchPINVOKE.switch_core_session_messages_waiting(SWIGTYPE_p_switch_core_session.getCPtr(session)); + return ret; + } + public static switch_status_t switch_core_session_dequeue_event(SWIGTYPE_p_switch_core_session session, SWIGTYPE_p_p_switch_event arg1, switch_bool_t force) { switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_session_dequeue_event(SWIGTYPE_p_switch_core_session.getCPtr(session), SWIGTYPE_p_p_switch_event.getCPtr(arg1), (int)force); return ret; @@ -4471,6 +4496,27 @@ public class freeswitch { return ret; } + public static switch_status_t switch_ivr_get_file_handle(SWIGTYPE_p_switch_core_session session, SWIGTYPE_p_p_switch_file_handle fh) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_ivr_get_file_handle(SWIGTYPE_p_switch_core_session.getCPtr(session), SWIGTYPE_p_p_switch_file_handle.getCPtr(fh)); + return ret; + } + + public static switch_status_t switch_ivr_release_file_handle(SWIGTYPE_p_switch_core_session session, SWIGTYPE_p_p_switch_file_handle fh) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_ivr_release_file_handle(SWIGTYPE_p_switch_core_session.getCPtr(session), SWIGTYPE_p_p_switch_file_handle.getCPtr(fh)); + return ret; + } + + public static switch_status_t switch_ivr_process_fh(SWIGTYPE_p_switch_core_session session, string cmd, switch_file_handle fhp) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_ivr_process_fh(SWIGTYPE_p_switch_core_session.getCPtr(session), cmd, switch_file_handle.getCPtr(fhp)); + return ret; + } + + public static switch_status_t switch_ivr_insert_file(SWIGTYPE_p_switch_core_session session, string file, string insert_file, SWIGTYPE_p_switch_size_t sample_point) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_ivr_insert_file(SWIGTYPE_p_switch_core_session.getCPtr(session), file, insert_file, SWIGTYPE_p_switch_size_t.getCPtr(sample_point)); + if (freeswitchPINVOKE.SWIGPendingException.Pending) throw freeswitchPINVOKE.SWIGPendingException.Retrieve(); + return ret; + } + public static switch_status_t switch_rtp_add_crypto_key(SWIGTYPE_p_switch_rtp rtp_session, switch_rtp_crypto_direction_t direction, uint index, switch_rtp_crypto_key_type_t type, SWIGTYPE_p_unsigned_char key, SWIGTYPE_p_switch_size_t keylen) { switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_rtp_add_crypto_key(SWIGTYPE_p_switch_rtp.getCPtr(rtp_session), (int)direction, index, (int)type, SWIGTYPE_p_unsigned_char.getCPtr(key), SWIGTYPE_p_switch_size_t.getCPtr(keylen)); if (freeswitchPINVOKE.SWIGPendingException.Pending) throw freeswitchPINVOKE.SWIGPendingException.Retrieve(); @@ -7259,6 +7305,15 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_core_destroy")] public static extern int switch_core_destroy(); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_io_read_lock")] + public static extern int switch_core_session_io_read_lock(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_io_write_lock")] + public static extern int switch_core_session_io_write_lock(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_io_rwunlock")] + public static extern int switch_core_session_io_rwunlock(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_read_lock")] public static extern int switch_core_session_read_lock(HandleRef jarg1); @@ -7463,6 +7518,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_execute_application_get_flags")] public static extern int switch_core_session_execute_application_get_flags(HandleRef jarg1, string jarg2, string jarg3, HandleRef jarg4); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_execute_application_async")] + public static extern int switch_core_session_execute_application_async(HandleRef jarg1, string jarg2, string jarg3); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_get_app_flags")] public static extern int switch_core_session_get_app_flags(string jarg1, HandleRef jarg2); @@ -7511,6 +7569,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_event_count")] public static extern uint switch_core_session_event_count(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_messages_waiting")] + public static extern uint switch_core_session_messages_waiting(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_dequeue_event")] public static extern int switch_core_session_dequeue_event(HandleRef jarg1, HandleRef jarg2, int jarg3); @@ -12242,6 +12303,18 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_dmachine_set_realm")] public static extern int switch_ivr_dmachine_set_realm(HandleRef jarg1, string jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_get_file_handle")] + public static extern int switch_ivr_get_file_handle(HandleRef jarg1, HandleRef jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_release_file_handle")] + public static extern int switch_ivr_release_file_handle(HandleRef jarg1, HandleRef jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_process_fh")] + public static extern int switch_ivr_process_fh(HandleRef jarg1, string jarg2, HandleRef jarg3); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_insert_file")] + public static extern int switch_ivr_insert_file(HandleRef jarg1, string jarg2, string jarg3, HandleRef jarg4); + [DllImport("mod_managed", EntryPoint="CSharp_SWITCH_RTP_MAX_BUF_LEN_get")] public static extern int SWITCH_RTP_MAX_BUF_LEN_get(); @@ -17157,6 +17230,36 @@ namespace FreeSWITCH.Native { using System; using System.Runtime.InteropServices; +public class SWIGTYPE_p_p_switch_file_handle { + private HandleRef swigCPtr; + + internal SWIGTYPE_p_p_switch_file_handle(IntPtr cPtr, bool futureUse) { + swigCPtr = new HandleRef(this, cPtr); + } + + protected SWIGTYPE_p_p_switch_file_handle() { + swigCPtr = new HandleRef(null, IntPtr.Zero); + } + + internal static HandleRef getCPtr(SWIGTYPE_p_p_switch_file_handle obj) { + return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; + } +} + +} +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 2.0.1 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +namespace FreeSWITCH.Native { + +using System; +using System.Runtime.InteropServices; + public class SWIGTYPE_p_p_switch_frame { private HandleRef swigCPtr; From 92f43440729f16831fa9a3e840843486a942906e Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 1 Dec 2010 09:46:06 -0600 Subject: [PATCH 148/237] FS-2892 --- src/mod/endpoints/mod_sofia/sofia_glue.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 57a2bfaa6a..451d7881b7 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -3732,6 +3732,14 @@ static switch_t38_options_t *tech_process_udptl(private_object_t *tech_pvt, sdp_ if (!t38_options) { t38_options = switch_core_session_alloc(tech_pvt->session, sizeof(switch_t38_options_t)); + + // set some default value + t38_options->T38FaxVersion = 0; + t38_options->T38MaxBitRate = 9600; + t38_options->T38FaxRateManagement = switch_core_session_strdup(tech_pvt->session, "transferredTCF"); + t38_options->T38FaxUdpEC = switch_core_session_strdup(tech_pvt->session, "t38UDPRedundancy"); + t38_options->T38FaxMaxBuffer = 500; + t38_options->T38FaxMaxDatagram = 500; } t38_options->remote_port = (switch_port_t)m->m_port; From 6b611662c26fbdd1ae96d71dadd243c48b725ab6 Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Wed, 1 Dec 2010 13:47:17 -0200 Subject: [PATCH 149/237] freetdm: removed ftmod_sangoma_boost, testboost, testsangomaboost, ftmod_sangoma_isdn and ftmod_r2 from default msvc 2008 build --- libs/freetdm/freetdm.2008.sln | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/libs/freetdm/freetdm.2008.sln b/libs/freetdm/freetdm.2008.sln index f059d941d3..c7207a6216 100644 --- a/libs/freetdm/freetdm.2008.sln +++ b/libs/freetdm/freetdm.2008.sln @@ -64,6 +64,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_sangoma_isdn", "src\f EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_r2", "src\ftmod\ftmod_r2\ftmod_r2.2008.vcproj", "{08C3EA27-A51D-47F8-B47D-B189C649CF30}" + ProjectSection(ProjectDependencies) = postProject + {93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D} + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -131,7 +134,6 @@ Global {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Release|Win32.ActiveCfg = Release|Win32 {1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Release|x64.ActiveCfg = Release|x64 {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Debug|Win32.ActiveCfg = Debug|Win32 - {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Debug|Win32.Build.0 = Debug|Win32 {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Debug|x64.ActiveCfg = Debug|x64 {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Debug|x64.Build.0 = Debug|x64 {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Release|Win32.ActiveCfg = Release|Win32 @@ -139,7 +141,6 @@ Global {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Release|x64.ActiveCfg = Release|x64 {D021EF2A-460D-4827-A0F7-41FDECF46F1B}.Release|x64.Build.0 = Release|x64 {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Debug|Win32.ActiveCfg = Debug|Win32 - {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Debug|Win32.Build.0 = Debug|Win32 {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Debug|x64.ActiveCfg = Debug|x64 {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Debug|x64.Build.0 = Debug|x64 {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Release|Win32.ActiveCfg = Release|Win32 @@ -147,7 +148,6 @@ Global {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Release|x64.ActiveCfg = Release|x64 {2B1BAF36-0241-43E7-B865-A8338AD48E2E}.Release|x64.Build.0 = Release|x64 {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Debug|Win32.ActiveCfg = Debug|Win32 - {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Debug|Win32.Build.0 = Debug|Win32 {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Debug|x64.ActiveCfg = Debug|x64 {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Debug|x64.Build.0 = Debug|x64 {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|Win32.ActiveCfg = Release|Win32 @@ -155,13 +155,11 @@ Global {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|x64.ActiveCfg = Release|x64 {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|x64.Build.0 = Release|x64 {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Debug|Win32.ActiveCfg = Debug|Win32 - {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Debug|Win32.Build.0 = Debug|Win32 {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Debug|x64.ActiveCfg = Debug|Win32 {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|Win32.ActiveCfg = Release|Win32 {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|Win32.Build.0 = Release|Win32 {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|x64.ActiveCfg = Release|Win32 {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Debug|Win32.ActiveCfg = Debug|Win32 - {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Debug|Win32.Build.0 = Debug|Win32 {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Debug|x64.ActiveCfg = Debug|Win32 {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Release|Win32.ActiveCfg = Release|Win32 {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Release|Win32.Build.0 = Release|Win32 From 1ba98b02b9b2a44d1504f5c4546a7088907ed4eb Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 1 Dec 2010 09:54:28 -0600 Subject: [PATCH 150/237] FS-2852 --- src/switch_xml.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/switch_xml.c b/src/switch_xml.c index a7bfe413d0..05cfe9fd4c 100644 --- a/src/switch_xml.c +++ b/src/switch_xml.c @@ -1980,19 +1980,16 @@ static char not_so_threadsafe_error_buffer[256] = ""; SWITCH_DECLARE(switch_xml_t) switch_xml_open_root(uint8_t reload, const char **err) { char path_buf[1024]; - uint8_t hasmain = 0, errcnt = 0; + uint8_t errcnt = 0; switch_xml_t new_main, r = NULL; switch_mutex_lock(XML_LOCK); if (MAIN_XML_ROOT) { - hasmain++; - if (!reload) { r = switch_xml_root(); goto done; } - switch_thread_rwlock_wrlock(RWLOCK); } switch_snprintf(path_buf, sizeof(path_buf), "%s%s%s", SWITCH_GLOBAL_dirs.conf_dir, SWITCH_PATH_SEPARATOR, "freeswitch.xml"); @@ -2007,9 +2004,15 @@ SWITCH_DECLARE(switch_xml_t) switch_xml_open_root(uint8_t reload, const char **e } else { switch_xml_t old_root; *err = "Success"; + + switch_thread_rwlock_wrlock(RWLOCK); + old_root = MAIN_XML_ROOT; MAIN_XML_ROOT = new_main; switch_set_flag(MAIN_XML_ROOT, SWITCH_XML_ROOT); + + switch_thread_rwlock_unlock(RWLOCK); + switch_xml_free(old_root); /* switch_xml_free_in_thread(old_root); */ } @@ -2018,10 +2021,6 @@ SWITCH_DECLARE(switch_xml_t) switch_xml_open_root(uint8_t reload, const char **e errcnt++; } - if (hasmain) { - switch_thread_rwlock_unlock(RWLOCK); - } - if (errcnt == 0) { switch_event_t *event; if (switch_event_create(&event, SWITCH_EVENT_RELOADXML) == SWITCH_STATUS_SUCCESS) { From 43c91d5fce868bc7a6b9055494cd3e0d46ade964 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Wed, 1 Dec 2010 10:25:02 -0600 Subject: [PATCH 151/237] misc windows x64 fixes --- libs/freetdm/freetdm.2008.sln | 2 - .../msvc/testboost/testboost.2008.vcproj | 160 ++-- .../testboost/testsangomaboost.2008.vcproj | 156 ++-- .../ftmod_analog/ftmod_analog.2008.vcproj | 706 +++++++++--------- .../ftmod_analog_em.2008.vcproj | 706 +++++++++--------- .../ftmod_sangoma_boost.2008.vcproj | 156 ++-- 6 files changed, 942 insertions(+), 944 deletions(-) diff --git a/libs/freetdm/freetdm.2008.sln b/libs/freetdm/freetdm.2008.sln index f059d941d3..2e8c7c4adb 100644 --- a/libs/freetdm/freetdm.2008.sln +++ b/libs/freetdm/freetdm.2008.sln @@ -161,10 +161,8 @@ Global {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|Win32.Build.0 = Release|Win32 {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|x64.ActiveCfg = Release|Win32 {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Debug|Win32.ActiveCfg = Debug|Win32 - {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Debug|Win32.Build.0 = Debug|Win32 {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Debug|x64.ActiveCfg = Debug|Win32 {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Release|Win32.ActiveCfg = Release|Win32 - {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Release|Win32.Build.0 = Release|Win32 {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Release|x64.ActiveCfg = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution diff --git a/libs/freetdm/msvc/testboost/testboost.2008.vcproj b/libs/freetdm/msvc/testboost/testboost.2008.vcproj index afb44b6469..5707033f33 100644 --- a/libs/freetdm/msvc/testboost/testboost.2008.vcproj +++ b/libs/freetdm/msvc/testboost/testboost.2008.vcproj @@ -22,7 +22,7 @@ - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + diff --git a/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.2008.vcproj b/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.2008.vcproj index 448f03a545..09349fc05f 100644 --- a/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.2008.vcproj +++ b/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.2008.vcproj @@ -1,353 +1,353 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.2008.vcproj b/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.2008.vcproj index 8ad183797a..837ba7de0f 100644 --- a/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.2008.vcproj +++ b/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.2008.vcproj @@ -1,353 +1,353 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2008.vcproj b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2008.vcproj index e7fc1d6549..73e421818f 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2008.vcproj +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.2008.vcproj @@ -95,83 +95,6 @@ Name="VCPostBuildEventTool" /> - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + From ca28a80658d50a9fab14f3022c40536b385b6b9b Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 1 Dec 2010 10:31:28 -0600 Subject: [PATCH 152/237] update caller_profile to have correct uuid when using custom uuid from originate string --- src/switch_core_session.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/switch_core_session.c b/src/switch_core_session.c index fc7648155a..2567d17712 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -1327,6 +1327,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_set_uuid(switch_core_session { switch_event_t *event; switch_core_session_message_t msg = { 0 }; + switch_caller_profile_t *profile; switch_assert(use_uuid); @@ -1343,6 +1344,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_set_uuid(switch_core_session msg.string_array_arg[1] = use_uuid; switch_core_session_receive_message(session, &msg); + if ((profile = switch_channel_get_caller_profile(session->channel))) { + profile->uuid = switch_core_strdup(profile->pool, use_uuid); + } + switch_event_create(&event, SWITCH_EVENT_CHANNEL_UUID); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Old-Unique-ID", session->uuid_str); switch_core_hash_delete(session_manager.session_table, session->uuid_str); From 6b52a43314824943a3ef19b86bd577d5729416eb Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Wed, 1 Dec 2010 11:55:05 -0600 Subject: [PATCH 153/237] fix build warnings --- libs/freetdm/src/ftdm_call_utils.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libs/freetdm/src/ftdm_call_utils.c b/libs/freetdm/src/ftdm_call_utils.c index 52d2557a01..69f2fb4fff 100644 --- a/libs/freetdm/src/ftdm_call_utils.c +++ b/libs/freetdm/src/ftdm_call_utils.c @@ -38,7 +38,7 @@ FT_DECLARE(ftdm_status_t) ftdm_set_npi(const char *string, uint8_t *target) { - int val; + uint8_t val; ftdm_status_t status = FTDM_SUCCESS; val = ftdm_str2ftdm_npi(string); @@ -53,7 +53,7 @@ FT_DECLARE(ftdm_status_t) ftdm_set_npi(const char *string, uint8_t *target) FT_DECLARE(ftdm_status_t) ftdm_set_ton(const char *string, uint8_t *target) { - int val; + uint8_t val; ftdm_status_t status = FTDM_SUCCESS; val = ftdm_str2ftdm_ton(string); @@ -68,7 +68,7 @@ FT_DECLARE(ftdm_status_t) ftdm_set_ton(const char *string, uint8_t *target) FT_DECLARE(ftdm_status_t) ftdm_set_bearer_capability(const char *string, uint8_t *target) { - int val; + uint8_t val; ftdm_status_t status = FTDM_SUCCESS; val = ftdm_str2ftdm_bearer_cap(string); @@ -84,7 +84,7 @@ FT_DECLARE(ftdm_status_t) ftdm_set_bearer_capability(const char *string, uint8_t FT_DECLARE(ftdm_status_t) ftdm_set_bearer_layer1(const char *string, uint8_t *target) { - int val; + uint8_t val; ftdm_status_t status = FTDM_SUCCESS; val = ftdm_str2ftdm_usr_layer1_prot(string); @@ -100,7 +100,7 @@ FT_DECLARE(ftdm_status_t) ftdm_set_bearer_layer1(const char *string, uint8_t *ta FT_DECLARE(ftdm_status_t) ftdm_set_screening_ind(const char *string, uint8_t *target) { - int val; + uint8_t val; ftdm_status_t status = FTDM_SUCCESS; val = ftdm_str2ftdm_screening(string); @@ -116,7 +116,7 @@ FT_DECLARE(ftdm_status_t) ftdm_set_screening_ind(const char *string, uint8_t *ta FT_DECLARE(ftdm_status_t) ftdm_set_presentation_ind(const char *string, uint8_t *target) { - int val; + uint8_t val; ftdm_status_t status = FTDM_SUCCESS; val = ftdm_str2ftdm_presentation(string); From 85d2395d26135a862b3bed07b316c0ebbf14b725 Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Wed, 1 Dec 2010 16:23:21 -0200 Subject: [PATCH 154/237] freetdm: ftmod_r2 - now clearing FTDM_CHANNEL_STATE_CHANGE flag when needed --- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 54 ++++++++++++++++------ 1 file changed, 41 insertions(+), 13 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index b98f7db99c..73856f000c 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -56,15 +56,10 @@ typedef enum { FTDM_R2_RUNNING = (1 << 0), } ftdm_r2_flag_t; -typedef enum { - FTDM_R2_WAITING_ACK = (1 << 0), -} ftdm_r2_call_flag_t; - /* private call information stored in ftdmchan->call_data void* ptr */ #define R2CALL(ftdmchan) ((ftdm_r2_call_t*)((ftdmchan)->call_data)) typedef struct ftdm_r2_call_t { openr2_chan_t *r2chan; - ftdm_r2_call_flag_t flags; int accepted:1; int answer_pending:1; int disconnect_rcvd:1; @@ -154,6 +149,12 @@ static ftdm_io_interface_t g_ftdm_r2_interface; static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan); static void ftdm_r2_state_advance_all(ftdm_channel_t *ftdmchan); +/* whether R2 call accept process is pending */ +#define IS_ACCEPTING_PENDING(ftdmchan) \ + ( (!ftdm_test_flag((ftdmchan), FTDM_CHANNEL_OUTBOUND)) && !R2CALL((ftdmchan))->accepted && \ + ((ftdmchan)->state == FTDM_CHANNEL_STATE_PROGRESS || \ + (ftdmchan)->state == FTDM_CHANNEL_STATE_PROGRESS_MEDIA || \ + (ftdmchan)->state == FTDM_CHANNEL_STATE_UP) ) /* functions not available on windows */ #ifdef WIN32 @@ -374,7 +375,6 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(r2_outgoing_call) if (ftdmchan->state != FTDM_CHANNEL_STATE_DIALING) { ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Collision after call attempt, try another channel, new state = %s\n", ftdm_channel_state2str(ftdmchan->state)); - ftdm_clear_flag(R2CALL(ftdmchan), FTDM_R2_WAITING_ACK); return FTDM_BREAK; } @@ -451,16 +451,43 @@ static void ftdm_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, cons ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING); } +/* + * Accepting a call in R2 is a lengthy process due to MF tones, + * when the user sends PROGRESS indication (implicitly moving the + * ftdm channel to PROGRESS state) the R2 processing loop + * does not clear FTDM_CHANNEL_STATE_CHANGE immediately as it does + * for all the other states, instead has to wait for on_call_accepted + * callback from openr2, which means the MF has ended and the progress + * indication is done, in order to clear the flag. However, if + * a protocol error or call disconnection (which is indicated using CAS bits) + * occurrs while accepting, we must clear the pending flag, this function + * takes care of that + * */ +static void clear_accept_pending(ftdm_channel_t *fchan) +{ + if (IS_ACCEPTING_PENDING(fchan)) { + ftdm_clear_flag(fchan, FTDM_CHANNEL_STATE_CHANGE); + ftdm_channel_complete_state(fchan); + } else if (ftdm_test_flag(fchan, FTDM_CHANNEL_STATE_CHANGE)) { + ftdm_log_chan(fchan, FTDM_LOG_CRIT, "State change flag set in state %s, last state = %s\n", + ftdm_channel_state2str(fchan->state), ftdm_channel_state2str(fchan->last_state)); + ftdm_clear_flag(fchan, FTDM_CHANNEL_STATE_CHANGE); + ftdm_channel_complete_state(fchan); + } +} + static void ftdm_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode) { ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan); ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Call accepted\n"); + + clear_accept_pending(ftdmchan); + /* at this point the MF signaling has ended and there is no point on keep reading */ openr2_chan_disable_read(r2chan); R2CALL(ftdmchan)->accepted = 1; + if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) { - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE); - ftdm_channel_complete_state(ftdmchan); if (R2CALL(ftdmchan)->answer_pending) { ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Answer was pending, answering now.\n"); ft_r2_answer_call(ftdmchan); @@ -493,6 +520,8 @@ static void ftdm_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_discon ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Got openr2 disconnection, clearing call\n"); + clear_accept_pending(ftdmchan); + R2CALL(ftdmchan)->disconnect_rcvd = 1; if (ftdmchan->state == FTDM_CHANNEL_STATE_HANGUP) { @@ -564,6 +593,8 @@ static void ftdm_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_err ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Protocol error\n"); + clear_accept_pending(ftdmchan); + R2CALL(ftdmchan)->disconnect_rcvd = 1; R2CALL(ftdmchan)->protocol_error = 1; @@ -1204,12 +1235,9 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan) ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Executing state handler for %s\n", ftdm_channel_state2str(ftdmchan->state)); R2CALL(ftdmchan)->chanstate = ftdmchan->state; - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) && !R2CALL(ftdmchan)->accepted && - (ftdmchan->state == FTDM_CHANNEL_STATE_PROGRESS || - ftdmchan->state == FTDM_CHANNEL_STATE_PROGRESS_MEDIA || - ftdmchan->state == FTDM_CHANNEL_STATE_UP) ) { + if (IS_ACCEPTING_PENDING(ftdmchan)) { /* - Moving to PROGRESS, PROGRESS_MEDIA or UP means that we must accept the call, and accepting + Moving to PROGRESS, PROGRESS_MEDIA or UP means that we must accept the call first, and accepting the call in R2 means sending a tone, then waiting for the acknowledge from the other end, since all of that requires sending and detecting tones, it takes a few milliseconds (I'd say around 100) which means during that time the user should not try to perform any operations like answer, hangup or anything From 5df1683c38851b71ac0f74fbf058e32437140c55 Mon Sep 17 00:00:00 2001 From: Geovani Ricardo Wiedenhoft Date: Wed, 1 Dec 2010 16:40:35 -0200 Subject: [PATCH 155/237] - Notifies the pre_answer - Dialplan examples - New version of commons - Priority of contexts - New K3L install script - getk3l.sh - CLI return in XML - More options in GET and SET commands - Events (ESL) to send/receive SMS. - fax-adjustment-timeout implemented - accountcode and language - Owner destroy - Destroy wait for resources release - static const expression - Hangup cause --- build/modules.conf.in | 2 +- conf/autoload_configs/modules.conf.xml | 1 + .../mod_khomp/Install/files/khomp.conf.xml | 61 +- src/mod/endpoints/mod_khomp/Makefile | 20 +- .../mod_khomp/commons/{ => base}/atomic.hpp | 24 +- .../commons/{ => base}/config_commons.hpp | 9 +- .../mod_khomp/commons/base/config_options.cpp | 302 ++++ .../mod_khomp/commons/base/config_options.hpp | 772 +++++++++++ .../commons/base/configurator/configfile.cpp | 241 ++++ .../{ => base}/configurator/configfile.hpp | 70 +- .../commons/base/configurator/option.cpp | 186 +++ .../{ => base}/configurator/option.hpp | 112 +- .../commons/base/configurator/restriction.cpp | 358 +++++ .../commons/base/configurator/restriction.hpp | 269 ++++ .../{ => base}/configurator/section.cpp | 100 +- .../commons/base/configurator/section.hpp | 260 ++++ .../mod_khomp/commons/base/const_this.hpp | 15 + .../mod_khomp/commons/{ => base}/flagger.hpp | 0 .../mod_khomp/commons/{ => base}/format.cpp | 138 +- .../mod_khomp/commons/{ => base}/format.hpp | 505 +++---- .../mod_khomp/commons/{ => base}/function.hpp | 140 +- .../commons/{ => base}/initializer.hpp | 16 +- .../mod_khomp/commons/{ => base}/k3lapi.cpp | 70 +- .../mod_khomp/commons/{ => base}/k3lapi.hpp | 470 ++++--- .../mod_khomp/commons/{ => base}/k3lutil.cpp | 50 +- .../mod_khomp/commons/{ => base}/k3lutil.hpp | 6 +- .../mod_khomp/commons/{ => base}/logger.hpp | 56 +- .../commons/{ => base}/noncopyable.hpp | 0 .../commons/{ => base}/refcounter.hpp | 11 +- .../mod_khomp/commons/{ => base}/regex.cpp | 5 +- .../mod_khomp/commons/{ => base}/regex.hpp | 77 +- .../mod_khomp/commons/base/ringbuffer.cpp | 485 +++++++ .../commons/{ => base}/ringbuffer.hpp | 62 +- .../commons/{ => base}/saved_condition.cpp | 0 .../commons/{ => base}/saved_condition.hpp | 0 .../commons/{ => base}/scoped_lock.hpp | 0 .../commons/{ => base}/simple_lock.hpp | 4 +- .../mod_khomp/commons/{ => base}/strings.cpp | 56 +- .../mod_khomp/commons/{ => base}/strings.hpp | 19 +- .../system}/freeswitch/saved_condition.cpp | 46 +- .../system}/freeswitch/saved_condition.hpp | 32 +- .../system}/freeswitch/simple_lock.hpp | 32 +- .../{ => base/system}/freeswitch/thread.hpp | 66 +- .../commons/{ => base}/tagged_union.hpp | 62 +- .../mod_khomp/commons/{ => base}/thread.hpp | 0 .../mod_khomp/commons/{ => base}/timer.cpp | 14 + .../mod_khomp/commons/{ => base}/timer.hpp | 11 +- .../mod_khomp/commons/{ => base}/types.hpp | 24 +- .../{variant.hpp => base/variable.hpp} | 127 +- .../mod_khomp/commons/{ => base}/verbose.cpp | 980 ++++++------- .../mod_khomp/commons/base/verbose.hpp | 303 ++++ .../mod_khomp/commons/config_options.cpp | 710 ---------- .../mod_khomp/commons/config_options.hpp | 286 ---- .../commons/configurator/configfile.cpp | 241 ---- .../mod_khomp/commons/configurator/option.cpp | 185 --- .../commons/configurator/restriction.cpp | 353 ----- .../commons/configurator/restriction.hpp | 321 ----- .../commons/configurator/section.hpp | 226 --- .../mod_khomp/commons/ringbuffer.cpp | 575 -------- .../commons/tools/generate-verbose-headers.sh | 183 +++ .../endpoints/mod_khomp/commons/verbose.hpp | 505 ------- src/mod/endpoints/mod_khomp/docs/Manual.html | 16 +- src/mod/endpoints/mod_khomp/docs/Manual.pdf | Bin 469674 -> 470343 bytes src/mod/endpoints/mod_khomp/docs/README.pdf | Bin 399120 -> 399119 bytes .../endpoints/mod_khomp/docs/README_en.pdf | Bin 314414 -> 314413 bytes .../endpoints/mod_khomp/docs/User_Guide.html | 18 +- .../endpoints/mod_khomp/docs/User_Guide.pdf | Bin 509356 -> 509260 bytes .../mod_khomp/examples/intercept.xml | 26 + .../endpoints/mod_khomp/examples/transfer.xml | 43 + .../mod_khomp/include/applications.h | 83 +- src/mod/endpoints/mod_khomp/include/cli.h | 254 ++-- src/mod/endpoints/mod_khomp/include/defs.h | 4 +- src/mod/endpoints/mod_khomp/include/frame.h | 2 +- src/mod/endpoints/mod_khomp/include/globals.h | 4 +- .../endpoints/mod_khomp/include/khomp_pvt.h | 66 +- .../mod_khomp/include/khomp_pvt_fxo.h | 6 +- .../mod_khomp/include/khomp_pvt_gsm.h | 4 +- .../mod_khomp/include/khomp_pvt_kxe1.h | 29 +- .../mod_khomp/include/khomp_pvt_passive.h | 8 +- src/mod/endpoints/mod_khomp/include/opt.h | 316 ++--- .../endpoints/mod_khomp/include/revision.h | 2 +- src/mod/endpoints/mod_khomp/include/spec.h | 7 - src/mod/endpoints/mod_khomp/include/utils.h | 90 ++ src/mod/endpoints/mod_khomp/mod_khomp.cpp | 77 +- .../endpoints/mod_khomp/src/applications.cpp | 15 +- src/mod/endpoints/mod_khomp/src/cli.cpp | 1214 +++++++++++++---- src/mod/endpoints/mod_khomp/src/globals.cpp | 4 +- src/mod/endpoints/mod_khomp/src/khomp_pvt.cpp | 270 +++- .../endpoints/mod_khomp/src/khomp_pvt_fxo.cpp | 51 +- .../endpoints/mod_khomp/src/khomp_pvt_gsm.cpp | 31 +- .../mod_khomp/src/khomp_pvt_kxe1.cpp | 187 +-- .../mod_khomp/src/khomp_pvt_passive.cpp | 7 +- src/mod/endpoints/mod_khomp/src/opt.cpp | 416 +++--- src/mod/endpoints/mod_khomp/src/spec.cpp | 40 +- src/mod/endpoints/mod_khomp/src/utils.cpp | 78 +- .../mod_khomp/support/klog-config.cpp | 4 + .../mod_khomp/support/klog-config.hpp | 6 + .../mod_khomp/{install.sh => tools/getk3l.sh} | 12 +- 98 files changed, 7491 insertions(+), 6153 deletions(-) rename src/mod/endpoints/mod_khomp/commons/{ => base}/atomic.hpp (90%) rename src/mod/endpoints/mod_khomp/commons/{ => base}/config_commons.hpp (92%) create mode 100644 src/mod/endpoints/mod_khomp/commons/base/config_options.cpp create mode 100644 src/mod/endpoints/mod_khomp/commons/base/config_options.hpp create mode 100644 src/mod/endpoints/mod_khomp/commons/base/configurator/configfile.cpp rename src/mod/endpoints/mod_khomp/commons/{ => base}/configurator/configfile.hpp (65%) create mode 100644 src/mod/endpoints/mod_khomp/commons/base/configurator/option.cpp rename src/mod/endpoints/mod_khomp/commons/{ => base}/configurator/option.hpp (52%) create mode 100644 src/mod/endpoints/mod_khomp/commons/base/configurator/restriction.cpp create mode 100644 src/mod/endpoints/mod_khomp/commons/base/configurator/restriction.hpp rename src/mod/endpoints/mod_khomp/commons/{ => base}/configurator/section.cpp (59%) create mode 100644 src/mod/endpoints/mod_khomp/commons/base/configurator/section.hpp create mode 100644 src/mod/endpoints/mod_khomp/commons/base/const_this.hpp rename src/mod/endpoints/mod_khomp/commons/{ => base}/flagger.hpp (100%) rename src/mod/endpoints/mod_khomp/commons/{ => base}/format.cpp (89%) rename src/mod/endpoints/mod_khomp/commons/{ => base}/format.hpp (81%) rename src/mod/endpoints/mod_khomp/commons/{ => base}/function.hpp (65%) rename src/mod/endpoints/mod_khomp/commons/{ => base}/initializer.hpp (86%) rename src/mod/endpoints/mod_khomp/commons/{ => base}/k3lapi.cpp (77%) rename src/mod/endpoints/mod_khomp/commons/{ => base}/k3lapi.hpp (50%) rename src/mod/endpoints/mod_khomp/commons/{ => base}/k3lutil.cpp (83%) rename src/mod/endpoints/mod_khomp/commons/{ => base}/k3lutil.hpp (95%) rename src/mod/endpoints/mod_khomp/commons/{ => base}/logger.hpp (89%) rename src/mod/endpoints/mod_khomp/commons/{ => base}/noncopyable.hpp (100%) rename src/mod/endpoints/mod_khomp/commons/{ => base}/refcounter.hpp (94%) rename src/mod/endpoints/mod_khomp/commons/{ => base}/regex.cpp (94%) rename src/mod/endpoints/mod_khomp/commons/{ => base}/regex.hpp (78%) create mode 100644 src/mod/endpoints/mod_khomp/commons/base/ringbuffer.cpp rename src/mod/endpoints/mod_khomp/commons/{ => base}/ringbuffer.hpp (88%) rename src/mod/endpoints/mod_khomp/commons/{ => base}/saved_condition.cpp (100%) rename src/mod/endpoints/mod_khomp/commons/{ => base}/saved_condition.hpp (100%) rename src/mod/endpoints/mod_khomp/commons/{ => base}/scoped_lock.hpp (100%) rename src/mod/endpoints/mod_khomp/commons/{ => base}/simple_lock.hpp (96%) rename src/mod/endpoints/mod_khomp/commons/{ => base}/strings.cpp (87%) rename src/mod/endpoints/mod_khomp/commons/{ => base}/strings.hpp (81%) rename src/mod/endpoints/mod_khomp/commons/{ => base/system}/freeswitch/saved_condition.cpp (83%) rename src/mod/endpoints/mod_khomp/commons/{ => base/system}/freeswitch/saved_condition.hpp (94%) rename src/mod/endpoints/mod_khomp/commons/{ => base/system}/freeswitch/simple_lock.hpp (96%) rename src/mod/endpoints/mod_khomp/commons/{ => base/system}/freeswitch/thread.hpp (94%) rename src/mod/endpoints/mod_khomp/commons/{ => base}/tagged_union.hpp (84%) rename src/mod/endpoints/mod_khomp/commons/{ => base}/thread.hpp (100%) rename src/mod/endpoints/mod_khomp/commons/{ => base}/timer.cpp (96%) rename src/mod/endpoints/mod_khomp/commons/{ => base}/timer.hpp (93%) rename src/mod/endpoints/mod_khomp/commons/{ => base}/types.hpp (88%) rename src/mod/endpoints/mod_khomp/commons/{variant.hpp => base/variable.hpp} (53%) rename src/mod/endpoints/mod_khomp/commons/{ => base}/verbose.cpp (82%) create mode 100644 src/mod/endpoints/mod_khomp/commons/base/verbose.hpp delete mode 100644 src/mod/endpoints/mod_khomp/commons/config_options.cpp delete mode 100644 src/mod/endpoints/mod_khomp/commons/config_options.hpp delete mode 100644 src/mod/endpoints/mod_khomp/commons/configurator/configfile.cpp delete mode 100644 src/mod/endpoints/mod_khomp/commons/configurator/option.cpp delete mode 100644 src/mod/endpoints/mod_khomp/commons/configurator/restriction.cpp delete mode 100644 src/mod/endpoints/mod_khomp/commons/configurator/restriction.hpp delete mode 100644 src/mod/endpoints/mod_khomp/commons/configurator/section.hpp delete mode 100644 src/mod/endpoints/mod_khomp/commons/ringbuffer.cpp create mode 100755 src/mod/endpoints/mod_khomp/commons/tools/generate-verbose-headers.sh delete mode 100644 src/mod/endpoints/mod_khomp/commons/verbose.hpp create mode 100644 src/mod/endpoints/mod_khomp/examples/intercept.xml create mode 100644 src/mod/endpoints/mod_khomp/examples/transfer.xml rename src/mod/endpoints/mod_khomp/{install.sh => tools/getk3l.sh} (93%) diff --git a/build/modules.conf.in b/build/modules.conf.in index 37244a188a..13e655672c 100644 --- a/build/modules.conf.in +++ b/build/modules.conf.in @@ -62,6 +62,7 @@ endpoints/mod_loopback #endpoints/mod_skinny #endpoints/mod_skypopen #endpoints/mod_h323 +#endpoints/mod_khomp #../../libs/openzap/mod_openzap #../../libs/freetdm/mod_freetdm #asr_tts/mod_unimrcp @@ -105,5 +106,4 @@ say/mod_say_ru #say/mod_say_th ## Experimental Modules (don't cry if they're broken) -#endpoints/mod_khomp #../../contrib/mod/xml_int/mod_xml_odbc diff --git a/conf/autoload_configs/modules.conf.xml b/conf/autoload_configs/modules.conf.xml index f5627fe965..118d7c4d81 100644 --- a/conf/autoload_configs/modules.conf.xml +++ b/conf/autoload_configs/modules.conf.xml @@ -38,6 +38,7 @@ + diff --git a/src/mod/endpoints/mod_khomp/Install/files/khomp.conf.xml b/src/mod/endpoints/mod_khomp/Install/files/khomp.conf.xml index 45268f304b..79c00516b9 100644 --- a/src/mod/endpoints/mod_khomp/Install/files/khomp.conf.xml +++ b/src/mod/endpoints/mod_khomp/Install/files/khomp.conf.xml @@ -95,16 +95,6 @@ should be opened for the channel. Limited to 25ms min, 500ms max. --> - - - - - - - - - - diff --git a/src/mod/endpoints/mod_khomp/Makefile b/src/mod/endpoints/mod_khomp/Makefile index 94923c7cda..db1a6fe4e4 100644 --- a/src/mod/endpoints/mod_khomp/Makefile +++ b/src/mod/endpoints/mod_khomp/Makefile @@ -1,6 +1,9 @@ MODNAME := mod_khomp VERBOSE := 1 +#FreeSWITCH source PATH is needed: +# Set FREESWITCH_PATH + ifeq ($(strip $(FREESWITCH_PATH)),) BASE := ../../../../ else @@ -11,12 +14,12 @@ curr_dir := $(shell pwd) versions := -DFS_VERSION_MAJOR=$(shell bash $(curr_dir)/tools/getversion.sh "SWITCH_VERSION_MAJOR" $(BASE)) -DFS_VERSION_MINOR=$(shell bash $(curr_dir)/tools/getversion.sh "SWITCH_VERSION_MINOR" $(BASE)) -DFS_VERSION_MICRO=$(shell bash $(curr_dir)/tools/getversion.sh "SWITCH_VERSION_MICRO" $(BASE)) -LOCAL_CFLAGS = -I./ -I./include -I./commons -I./support -D_REENTRANT -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -DK3L_HOSTSYSTEM -DCOMMONS_LIBRARY_USING_FREESWITCH -g -ggdb #-DDEBUG_FLAGS +LOCAL_CFLAGS = -I./ -I./include -I./commons -I./commons/base -I./support -D_REENTRANT -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -DK3L_HOSTSYSTEM -DCOMMONS_LIBRARY_USING_FREESWITCH -g -ggdb #-DDEBUG_FLAGS LOCAL_CFLAGS += $(versions) LOCAL_LDFLAGS = -lk3l -LOCAL_OBJS = ./commons/k3lapi.o ./commons/k3lutil.o ./commons/config_options.o ./commons/format.o ./commons/strings.o ./commons/ringbuffer.o ./commons/verbose.o ./commons/saved_condition.o ./commons/regex.o ./commons/timer.o ./commons/configurator/configfile.o ./commons/configurator/option.o ./commons/configurator/section.o ./commons/configurator/restriction.o +LOCAL_OBJS = ./commons/base/k3lapi.o ./commons/base/k3lutil.o ./commons/base/config_options.o ./commons/base/format.o ./commons/base/strings.o ./commons/base/ringbuffer.o ./commons/base/verbose.o ./commons/base/saved_condition.o ./commons/base/regex.o ./commons/base/timer.o ./commons/base/configurator/configfile.o ./commons/base/configurator/option.o ./commons/base/configurator/section.o ./commons/base/configurator/restriction.o ./commons/base/verbose_traits.o LOCAL_OBJS += ./support/klog-config.o ./support/klog-options.o ./support/config_defaults.o LOCAL_OBJS += ./src/globals.o ./src/opt.o ./src/frame.o ./src/utils.o ./src/lock.o ./src/spec.o ./src/applications.o ./src/khomp_pvt_fxo.o ./src/khomp_pvt_gsm.o ./src/khomp_pvt_kxe1.o ./src/khomp_pvt_passive.o ./src/khomp_pvt.o ./src/logger.o ./src/cli.o @@ -27,7 +30,20 @@ conf_file_install = $(sysconfdir)/autoload_configs include $(BASE)/build/modmake.rules +local_depend: + @if test ! -f $(curr_dir)/commons/base/verbose_traits.hpp || test ! -f $(curr_dir)/commons/base/verbose_traits.cpp ; then \ + echo "Generating verbose_traits" ;\ + bash $(curr_dir)/commons/tools/generate-verbose-headers.sh commons/base/ include/k3l.h ;\ + fi; + depend_install: + @if test "w`kserver --version 2>/dev/null | grep 2.1`" == "w" ; then \ + echo "###############################################################################" ;\ + echo "Install k3l from KHOMP." ;\ + echo "Run: $(curr_dir)/tools/getk3l.sh" ;\ + echo "###############################################################################" ;\ + exit 1;\ + fi; @echo "Copy $(conf_file_name)" @if test -d $(conf_file_install) ; then \ if test -f $(conf_file_dir)/$(conf_file_name) ; then \ diff --git a/src/mod/endpoints/mod_khomp/commons/atomic.hpp b/src/mod/endpoints/mod_khomp/commons/base/atomic.hpp similarity index 90% rename from src/mod/endpoints/mod_khomp/commons/atomic.hpp rename to src/mod/endpoints/mod_khomp/commons/base/atomic.hpp index daa598c9b4..02278b390c 100644 --- a/src/mod/endpoints/mod_khomp/commons/atomic.hpp +++ b/src/mod/endpoints/mod_khomp/commons/base/atomic.hpp @@ -64,17 +64,31 @@ namespace Atomic PunnedType pval; pval.valtype = VAL; \ unsigned long long vexp = *(pexp.podtype); \ unsigned long long vval = *(pval.podtype); \ - unsigned long long res = (unsigned long long)exp; \ + unsigned long vval32 = (unsigned long)vval; \ unsigned char chg = 0; \ - asm volatile("lock; cmpxchg8b %2; sete %1;" \ + asm volatile( \ + "xchgl %%ebx, %4;" \ + "lock; cmpxchg8b %2; sete %1;" \ + "movl %4, %%ebx; " \ : "+A" (vexp), /* 0 (result) */ \ - "=q" (chg) /* 1 */ \ + "=c" (chg) /* 1 */ \ : "m" (*(unsigned char**)(PTR)), /* 2 */ \ - "b" ((unsigned long)(vval)), \ - "c" ((unsigned long)(vval >> 32))); \ + "c" ((unsigned long)(vval >> 32)), \ + "m" (vval32)); \ *(pexp.podtype) = vexp; \ return (chg != 0 ? true : false); +// "movl %%ecx, %4;" +// +// "m" (*((unsigned long*)(*(pval.podtype)))), +// "m" ((unsigned long)(vval >> 32)) +// +// "m" (*((unsigned long*)(&vval))), +// "m" ((unsigned long)(vval >> 32)) +// +// unsigned long long vval = *(pval.podtype); +// unsigned long long res = (unsigned long long)exp; +// // Types used for making CMPXCHG instructions independent from base type. template < typename ValType, typename PodType > diff --git a/src/mod/endpoints/mod_khomp/commons/config_commons.hpp b/src/mod/endpoints/mod_khomp/commons/base/config_commons.hpp similarity index 92% rename from src/mod/endpoints/mod_khomp/commons/config_commons.hpp rename to src/mod/endpoints/mod_khomp/commons/base/config_commons.hpp index de8f327df4..dad16f4e92 100644 --- a/src/mod/endpoints/mod_khomp/commons/config_commons.hpp +++ b/src/mod/endpoints/mod_khomp/commons/base/config_commons.hpp @@ -63,7 +63,12 @@ #error Unknown implementation selected. Please define COMMONS_LIBRARY_USING_* correctly. #endif -#define COMMONS_INCLUDE(file) +#define COMMONS_INCLUDE(file) + +#define COMMONS_VERSION_MAJOR 1 +#define COMMONS_VERSION_MINOR 1 + +#define COMMONS_AT_LEAST(x,y) \ + (COMMONS_VERSION_MAJOR > x || (COMMONS_VERSION_MAJOR == x && COMMONS_VERSION_MINOR >= y)) #endif /* _CONFIG_COMMONS_HPP_ */ - diff --git a/src/mod/endpoints/mod_khomp/commons/base/config_options.cpp b/src/mod/endpoints/mod_khomp/commons/base/config_options.cpp new file mode 100644 index 0000000000..7412b4b1a0 --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/base/config_options.cpp @@ -0,0 +1,302 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include + +void Config::Restriction::checkRange(const std::string & name, const SIntType value, const Range < SIntType > & range) +{ + if (value < range.minimum) + throw Failure(STG(FMT("value '%d' out-of-range for option '%s' (too low)") % value % name)); + + if (value > range.maximum) + throw Failure(STG(FMT("value '%d' out-of-range for option '%s' (too high)") % value % name)); + + if (((value - range.minimum) % range.step) != 0) + throw Failure(STG(FMT("value '%d' out-of-range for option '%s' (outside allowed step)") % value % name)); +} + +void Config::Restriction::checkRange(const std::string & name, const UIntType value, const Range < UIntType > & range) +{ + if (value < range.minimum) + throw Failure(STG(FMT("value '%d' out-of-range for option '%s' (too low)") % value % name)); + + if (value > range.maximum) + throw Failure(STG(FMT("value '%d' out-of-range for option '%s' (too high)") % value % name)); + + if (((value - range.minimum) % range.step) != 0) + throw Failure(STG(FMT("value '%d' out-of-range for option '%s' (outside allowed step)") % value % name)); +} + +void Config::Restriction::checkStringSet(const std::string & name, const StringType & value, const StringSet & allowed) +{ + if (allowed.empty()) + return; + + if (allowed.find(value) != allowed.end()) + return; + + std::string strlist; + + for (StringSet::const_iterator i = allowed.begin(); i != allowed.end(); i++) + { + strlist += " '"; + strlist += (*i); + strlist += "'"; + } + + throw Failure(STG(FMT("value '%s' not allowed for option '%s' (allowed values:%s)") + % value % name % strlist)); +} + +Config::Option::Option(std::string name, Config::Option::StringMemberType value, const StringType defvalue, StringSet & allowed, bool listme) +: _myname(name), _option(InnerStringType(name, value, defvalue, allowed)), _listme(listme), _values(NULL) +{}; + +Config::Option::Option(std::string name, Config::Option::StringMemberType value, const StringType defvalue, bool listme) +: _myname(name), _option(InnerStringType(name, value, defvalue)), _listme(listme), _values(NULL) +{}; + +Config::Option::Option(std::string name, Config::Option::BooleanMemberType value, const BooleanType defvalue, bool listme) +: _myname(name), _option(InnerBooleanType(name, value, defvalue)), _listme(listme), _values(NULL) +{}; + +Config::Option::Option(std::string name, Config::Option::SIntMemberType value, const SIntType defvalue, + SIntType min, SIntType max, SIntType step, bool listme) +: _myname(name), _option(InnerSIntType(name, value, defvalue, min, max, step)), _listme(listme), _values(NULL) +{}; + +Config::Option::Option(std::string name, Config::Option::UIntMemberType value, const UIntType defvalue, + UIntType min, UIntType max, UIntType step, bool listme) +: _myname(name), _option(InnerUIntType(name, value, defvalue, min, max, step)), _listme(listme), _values(NULL) +{}; + +Config::Option::Option(const Config::Option & o) +: _myname(o._myname), _option(o._option), _listme(o._listme), _values(o._values) +{}; + +Config::Option::Option(std::string name, Config::Option::FunctionMemberType value, const StringType defvalue, StringSet & allowed, bool listme) +: _myname(name), _option(InnerFunctionType(name, value, defvalue, allowed)), _listme(listme), _values(NULL) +{}; + +Config::Option::Option(std::string name, Config::Option::FunctionMemberType value, const StringType defvalue, bool listme) +: _myname(name), _option(InnerFunctionType(name, value, defvalue)), _listme(listme), _values(NULL) +{}; + +Config::Option::~Option(void) +{ + if (_values) + { + for (unsigned int i = 0; _values[i] != NULL; i++) + delete _values[i]; + + delete[] _values; + _values = NULL; + } +}; + +const char ** Config::Option::values(void) +{ + if (_values != NULL) + return _values; + + /**/ if (_option.check()) + { + _values = new const char*[3]; + + _values[0] = strdup("yes"); + _values[1] = strdup("no"); + _values[2] = NULL; + + } + else if (_option.check()) + { + const InnerSIntType & tmp = _option.get(); + + unsigned int count = ((tmp._range.maximum - tmp._range.minimum) / tmp._range.step) + 1; + unsigned int index = 0; + + _values = new const char*[count + 1]; + + for (SIntType i = tmp._range.minimum; i <= tmp._range.maximum; i += tmp._range.step, ++index) + _values[index] = strdup(STG(FMT("%d") % i).c_str()); + + _values[index] = NULL; + } + else if (_option.check()) + { + const InnerUIntType & tmp = _option.get(); + + unsigned int count = ((tmp._range.maximum - tmp._range.minimum) / tmp._range.step) + 1; + unsigned int index = 0; + + _values = new const char*[count + 1]; + + for (UIntType i = tmp._range.minimum; i <= tmp._range.maximum; i += tmp._range.step, ++index) + _values[index] = strdup(STG(FMT("%d") % i).c_str()); + + _values[index] = NULL; + } + else if (_option.check()) + { + const InnerStringType & tmp = _option.get(); + + _values = new const char*[ tmp._allowed.size() + 1 ]; + + unsigned int index = 0; + + for (StringSet::iterator i = tmp._allowed.begin(); i != tmp._allowed.end(); ++i, ++index) + _values[index] = strdup((*i).c_str()); + + _values[index] = NULL; + } + else if (_option.check()) + { + const InnerFunctionType & tmp = _option.get(); + + _values = new const char*[ tmp._allowed.size() + 1 ]; + + unsigned int index = 0; + + for (StringSet::iterator i = tmp._allowed.begin(); i != tmp._allowed.end(); ++i, ++index) + _values[index] = strdup((*i).c_str()); + + _values[index] = NULL; + } + else + { + throw Failure(STG(FMT("values() not implemented for type used in option '%s'") % _myname)); + } + + return _values; +}; + +/*********************************/ + +Config::Options::Options(void) +: _values(NULL) +{}; + +Config::Options::~Options() +{ + if (_values) + { + for (unsigned int i = 0; _values[i] != NULL; i++) + free((void*)(_values[i])); + + delete[] _values; + _values = NULL; + } +}; + +bool Config::Options::add(Config::Option option) +{ + std::pair ret = _map.insert(OptionPair(option.name(), option)); + + return ret.second; +} + +bool Config::Options::synonym(std::string equiv_opt, std::string main_opt) +{ + std::pair ret = _syn_map.insert(SynOptionPair(equiv_opt, main_opt)); + + return ret.second; +} + +Config::StringSet Config::Options::options(void) +{ + StringSet res; + + for (OptionMap::iterator i = _map.begin(); i != _map.end(); i++) + res.insert(i->first); + + return res; +} + +const char ** Config::Options::values(const char * name) +{ + OptionMap::iterator iter = find_option(name); + + if (iter == _map.end()) + throw Failure(STG(FMT("unknown option '%s'") % name)); + + return iter->second.values(); +} + +const char ** Config::Options::values(void) +{ + if (_values != NULL) + return _values; + + unsigned int count = 0; + + for (OptionMap::iterator i = _map.begin(); i != _map.end(); ++i) + if (i->second.listme()) + ++count; + + _values = new const char*[ count + 1 ]; + + unsigned int index = 0; + + for (OptionMap::iterator i = _map.begin(); i != _map.end(); ++i) + { + if (i->second.listme()) + { + _values[index] = strdup(i->first.c_str()); + ++index; + } + } + + _values[index] = NULL; + + return _values; +} + +Config::Options::OptionMap::iterator Config::Options::find_option(std::string name) +{ + SynOptionMap::iterator syn_iter = _syn_map.find(name); + + if (syn_iter != _syn_map.end()) + name = syn_iter->second; + + OptionMap::iterator iter = _map.find(name); + + return iter; +} diff --git a/src/mod/endpoints/mod_khomp/commons/base/config_options.hpp b/src/mod/endpoints/mod_khomp/commons/base/config_options.hpp new file mode 100644 index 0000000000..59e381f893 --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/base/config_options.hpp @@ -0,0 +1,772 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#ifndef _CONFIG_OPTIONS_HPP_ +#define _CONFIG_OPTIONS_HPP_ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace Config +{ + /* exceptions */ + + struct Failure: public std::runtime_error + { + Failure(const std::string & msg) : std::runtime_error(msg) {}; + }; + + struct EmptyValue: public std::runtime_error + { + EmptyValue(): std::runtime_error("accessed option still not loaded from configuration") {}; + }; + + /* types */ + + typedef int SIntType; + typedef unsigned int UIntType; + typedef bool BooleanType; + typedef std::string StringType; + + template < typename Type > + struct Value; + + template < typename Type > + struct InnerOptionBase; + + template < typename Type > + struct InnerOption; + + struct Option; + + /* here we go! */ + + template < typename Type > + struct Range + { + Range(const Type _minimum, const Type _maximum, const Type _step) + : minimum(_minimum), maximum(_maximum), step(_step) {}; + + const Type minimum, maximum, step; + }; + + typedef std::set < std::string > StringSet; + + template < typename Type > + struct Value: COUNTER_SUPER(Value < Type >) + { + friend class COUNTER_CLASS(Value < Type >); + friend class InnerOptionBase< Type >; + friend class InnerOption < Type >; + friend class Option; + + Value() + : _tmpval(0), _stored(0), _loaded(false), _inited(false) + {}; + + Value(const Value & o) + : COUNTER_REFER(o, Value < Type >), + _tmpval(o._tmpval), _stored(o._stored), + _loaded(o._loaded), _inited(o._inited) + {}; + + const Type & operator()(void) const + { + if (!_inited) + throw EmptyValue(); + + if (!_stored) + return *_tmpval; + + return *_stored; + }; + + const Type & get(void) const { return operator()(); }; + bool loaded(void) const { return _loaded; }; + + void store(const Type val) + { + if (_tmpval) + { + delete _tmpval; + _tmpval = 0; + } + + _tmpval = new Type(val); + + _loaded = true; + _inited = true; + } + + protected: + void unreference(void) + { + _inited = false; + _loaded = false; + + if (_tmpval) + { + delete _tmpval; + _tmpval = 0; + } + + if (_stored) + { + delete _stored; + _stored = 0; + } + }; + + protected: + void commit(Type def) + { + if (_tmpval) + { + { + delete _stored; + _stored = 0; + } + + _stored = _tmpval; + _tmpval = 0; + } + else + { + if (!_stored) + _stored = new Type(def); + } + + _loaded = true; + _inited = true; + }; + + void reset(void) + { + _loaded = false; + } + + protected: + const Type * _tmpval; + const Type * _stored; + bool _loaded; + bool _inited; + }; + + struct FunctionValue + { + friend class InnerFunctionType; + friend class Option; + + FunctionValue() + : _loaded(false), _inited(false) {}; + + virtual ~FunctionValue() {}; + + public: + virtual void operator()(const StringType & val) + { + throw Failure("undefined operator() for value"); + } + + const StringType & get(void) const + { + if (!_inited) + throw EmptyValue(); + + return _stored; + }; + + bool loaded(void) const { return _loaded; }; + + protected: + void commit(const StringType def) + { + if (_tmpval.empty()) + { + _stored = def; + } + else + { + _stored = _tmpval; + _tmpval.clear(); + } + + operator()(_stored); + + _loaded = true; + _inited = true; + }; + + void store(const StringType val) + { + _tmpval = val; + _loaded = true; + _inited = true; + } + + void reset(void) + { + _loaded = false; + } + + private: + StringType _tmpval; + StringType _stored; + bool _loaded; + bool _inited; + }; + + /* NOTE: we use a non-templated classe to place this functions inside the .cpp */ + struct Restriction + { + static void checkRange(const std::string & name, const SIntType value, const Range < SIntType > & range); + static void checkRange(const std::string & name, const UIntType value, const Range < UIntType > & range); + static void checkStringSet(const std::string & name, const StringType & value, const StringSet & allowed); + }; + + template < typename Type > + struct InnerOptionBase + { + typedef Variable < Value < Type > > MemberValue; + + InnerOptionBase(const std::string name, MemberValue option, const Type defvalue) + : _name(name), _option(option), _default(defvalue) {}; + + template < typename Object > + void reset(Object * const obj) const + { + _option(obj).reset(); + } + + template < typename Object > + const Type & get(const Object * const obj) const + { + return _option(obj).get(); + } + + template < typename Object > + bool loaded(const Object * const obj) const + { + return _option(obj).loaded(); + } + + protected: + const std::string _name; + MemberValue _option; + const Type _default; + }; + + template < > + struct InnerOption < SIntType >: public InnerOptionBase < SIntType > + { + typedef InnerOptionBase < SIntType > Super; + typedef Super::MemberValue MemberValue; + + InnerOption(const std::string name, MemberValue option, const SIntType defval, + const SIntType min, const SIntType max, const SIntType step) + : Super(name, option, defval), _range(min, max, step) {}; + + template < typename Object > + void commit(Object * const obj) const + { + Restriction::checkRange(_name, _default, _range); + _option(obj).commit(_default); + }; + + template < typename Object > + void store(Object * const obj, const SIntType stored) const + { + Restriction::checkRange(_name, _default, _range); + _option(obj).store(stored); + } + + using Super::reset; + using Super::get; + + const Range< SIntType > _range; + }; + + template < > + struct InnerOption < UIntType >: public InnerOptionBase < UIntType > + { + typedef InnerOptionBase < UIntType > Super; + typedef Super::MemberValue MemberValue; + + InnerOption(const std::string name, MemberValue option, const UIntType defval, + const UIntType min, const UIntType max, const UIntType step) + : Super(name, option, defval), _range(min, max, step) {}; + + template < typename Object > + void commit(Object * const obj) const + { + Restriction::checkRange(_name, _default, _range); + _option(obj).commit(_default); + }; + + template < typename Object > + void store(Object * const obj, const UIntType stored) const + { + Restriction::checkRange(_name, _default, _range); + _option(obj).store(stored); + } + + using Super::reset; + using Super::get; + + const Range< UIntType > _range; + }; + + template < > + struct InnerOption < BooleanType >: public InnerOptionBase < BooleanType > + { + typedef InnerOptionBase < BooleanType > Super; + typedef Super::MemberValue MemberValue; + + InnerOption(std::string name, MemberValue option, BooleanType defval) + : Super(name, option, defval) {}; + + template < typename Object > + void commit(Object * obj) const + { + _option(obj).commit(_default); + }; + + template < typename Object > + void store(Object * obj, BooleanType stored) const + { + _option(obj).store(stored); + } + + using Super::reset; + using Super::get; + }; + + template < > + struct InnerOption < StringType >: public InnerOptionBase < StringType > + { + typedef InnerOptionBase < StringType > Super; + typedef Super::MemberValue MemberValue; + + InnerOption(const std::string name, MemberValue option, const StringType defval, const StringSet & allowed) + : Super(name, option, defval), _allowed(allowed) {}; + + InnerOption(const std::string name, MemberValue option, const StringType defval) + : Super(name, option, defval) {}; + + template < typename Object > + void commit(Object * const obj) const + { + Restriction::checkStringSet(_name, _default, _allowed); + _option(obj).commit(_default); + }; + + template < typename Object > + void store(Object * const obj, const StringType stored) const + { + Restriction::checkStringSet(_name, _default, _allowed); + _option(obj).store(stored); + } + + using Super::reset; + using Super::get; + + const StringSet _allowed; + }; + + struct InnerFunctionType + { + typedef Variable < FunctionValue > MemberValue; + + InnerFunctionType(const std::string name, MemberValue option, const StringType defval, const StringSet & allowed) + : _name(name), _option(option), _default(defval), _allowed(allowed) {}; + + InnerFunctionType(const std::string name, MemberValue option, const StringType defval) + : _name(name), _option(option), _default(defval) {}; + + template < typename Object > + const StringType & get(const Object * const obj) const + { + return _option(obj).get(); + } + + template < typename Object > + bool loaded(const Object * const obj) const + { + return _option(obj).loaded(); + } + + template < typename Object > + void reset(Object * const obj) const + { + _option(obj).reset(); + } + + template < typename Object > + void commit(Object * const obj) const + { + Restriction::checkStringSet(_name, _default, _allowed); + _option(obj).commit(_default); + }; + + template < typename Object > + void store(Object * const obj, const StringType stored) const + { + Restriction::checkStringSet(_name, _default, _allowed); + _option(obj).store(stored); + } + + protected: + const std::string _name; + MemberValue _option; + const StringType _default; + + public: + const StringSet _allowed; + }; + + struct Option + { + typedef InnerOption < SIntType > InnerSIntType; + typedef InnerOption < UIntType > InnerUIntType; + typedef InnerOption < BooleanType > InnerBooleanType; + typedef InnerOption < StringType > InnerStringType; + + typedef Variable < Value < SIntType > > SIntMemberType; + typedef Variable < Value < UIntType > > UIntMemberType; + typedef Variable < Value < BooleanType > > BooleanMemberType; + typedef Variable < Value < StringType > > StringMemberType; + + typedef Variable < FunctionValue > FunctionMemberType; + + typedef Tagged::Union < InnerStringType, + Tagged::Union < InnerBooleanType, + Tagged::Union < InnerSIntType , + Tagged::Union < InnerUIntType, + Tagged::Union < InnerFunctionType > > > > > + InnerType; + + explicit Option(std::string, StringMemberType, const StringType, StringSet & allowed, bool listme = true); + explicit Option(std::string, StringMemberType, const StringType = "", bool listme = true); + explicit Option(std::string, SIntMemberType, const SIntType = 0, SIntType min = INT_MIN, SIntType max = INT_MAX, SIntType step = 1, bool listme = true); + explicit Option(std::string, UIntMemberType, const UIntType = 0, UIntType min = 0, UIntType max = UINT_MAX, UIntType step = 1, bool listme = true); + explicit Option(std::string, BooleanMemberType, const BooleanType = false, bool listme = true); + + explicit Option(std::string, FunctionMemberType, const StringType, StringSet & allowed, bool listme = true); + explicit Option(std::string, FunctionMemberType, const StringType = "", bool listme = true); + + Option(const Option & o); + + ~Option(void); + + template < typename Object > + void set(Object * object, std::string value) + { + try + { + /**/ if (_option.check()) _option.get().store(object, value); + else if (_option.check()) _option.get().store(object, value); + else if (_option.check()) _option.get().store(object, Strings::toboolean(value)); + else if (_option.check()) _option.get().store(object, Strings::tolong(value)); + else if (_option.check()) _option.get().store(object, Strings::toulong(value)); + else + { + throw Failure(STG(FMT("set() not implemented for type used in option '%s'") % _myname)); + } + } + catch (Strings::invalid_value & e) + { + throw Failure(STG(FMT("got invalid value '%s' for option '%s'") % value % _myname)); + } + catch (EmptyVariable & e) + { + throw Failure(STG(FMT("uninitialized variable while setting value '%s' for option '%s'") % value % _myname)); + } + } + + template < typename Object > + std::string get(const Object * const object) const + { + try + { + /**/ if (_option.check()) return _option.get().get(object); + else if (_option.check()) return _option.get().get(object); + else if (_option.check()) return (_option.get().get(object) ? "yes" : "no"); + else if (_option.check()) return STG(FMT("%d") % _option.get().get(object)); + else if (_option.check()) return STG(FMT("%u") % _option.get().get(object)); + else + { + throw Failure(STG(FMT("get() not implemented for type used in option '%s'") % _myname)); + } + } + catch (EmptyVariable & e) + { + throw Failure(STG(FMT("uninitialized variable while getting value for option '%s'") % _myname)); + } + } + + template < typename Object > + bool loaded(const Object * const object) const + { + try + { + /**/ if (_option.check()) return _option.get().loaded(object); + else if (_option.check()) return _option.get().loaded(object); + else if (_option.check()) return _option.get().loaded(object); + else if (_option.check()) return _option.get().loaded(object); + else if (_option.check()) return _option.get().loaded(object); + else + { + throw Failure(STG(FMT("loaded() not implemented for type used in option '%s'") % _myname)); + } + } + catch (EmptyVariable & e) + { + throw Failure(STG(FMT("uninitialized variable while checking load status for option '%s'") % _myname)); + } + } + + template < typename Object > + void reset(Object * const object) + { + try + { + /**/ if (_option.check()) _option.get().reset(object); + else if (_option.check()) _option.get().reset(object); + else if (_option.check()) _option.get().reset(object); + else if (_option.check()) _option.get().reset(object); + else if (_option.check()) _option.get().reset(object); + else + { + throw Failure(STG(FMT("reset() not implemented for type used in option '%s'") % _myname)); + } + } + catch (EmptyVariable & e) + { + throw Failure(STG(FMT("uninitialized variable while reseting status for option '%s'") % _myname)); + } + } + + template < typename Object > + void commit(Object * const object) + { + try + { + /**/ if (_option.check()) _option.get().commit(object); + else if (_option.check()) _option.get().commit(object); + else if (_option.check()) _option.get().commit(object); + else if (_option.check()) _option.get().commit(object); + else if (_option.check()) _option.get().commit(object); + else + { + throw Failure(STG(FMT("commit() not implemented for type used in option '%s'") % _myname)); + } + } + catch (EmptyVariable & e) + { + throw Failure(STG(FMT("uninitialized variable while commiting option '%s'") % _myname)); + } + } + + const std::string & name(void) const { return _myname; } + bool listme(void) const { return _listme; }; + + const char ** values(void); + + template < typename Object > + void copyFrom(const Object * const srcobj, Object * const dstobj, bool force = false) + { + if (loaded(dstobj) && !force) + return; + + if (loaded(srcobj)) + set(dstobj, get(srcobj)); + else + reset(dstobj); + } + + protected: + const std::string _myname; + InnerType _option; + const bool _listme; + const char ** _values; + }; + + struct Options + { + typedef std::vector < std::string > Messages; + + Options(); + ~Options(); + + typedef std::set < std::string > StringSet; + + typedef std::map < std::string, Option > OptionMap; + typedef std::pair < std::string, Option > OptionPair; + + typedef std::map < std::string, std::string > SynOptionMap; + typedef std::pair < std::string, std::string > SynOptionPair; + + bool add(Option option); + + /* only valid in "process" (for backwards compatibility config files) */ + bool synonym(std::string, std::string); + + template < typename Type > + void set(const std::string & name, Type value) + { + OptionMap::iterator iter = find_option(name); + + if (iter == _map.end()) + throw Failure(STG(FMT("unknown option: %s") % name)); + + iter->second.set(value); + } + + template < typename Object > + std::string get(const Object * const object, const std::string & name) + { + OptionMap::iterator iter = find_option(name); + + if (iter == _map.end()) + throw Failure(STG(FMT("unknown option: %s") % name)); + + return iter->second.get(object); + } + + template < typename Object > + void process(Object * const object, const char * name, const char * value) + { + OptionMap::iterator iter = find_option(name); + + if (iter == _map.end()) + throw Failure(STG(FMT("unknown option '%s'") % name)); + + iter->second.set(object, value); + } + + template < typename Object > + Messages commit(Object * const object) + { + Messages msgs; + + for (OptionMap::iterator i = _map.begin(); i != _map.end(); ++i) + { + try + { + i->second.commit(object); + } + catch (Failure & e) + { + msgs.push_back(e.what()); + } + } + + return msgs; + } + + template < typename Object > + void reset(Object * object) + { + for (OptionMap::iterator i = _map.begin(); i != _map.end(); ++i) + i->second.reset(object); + } + + template < typename Object > + bool loaded(Object * object, std::string name) + { + OptionMap::iterator iter = find_option(name); + + if (iter == _map.end()) + return false; + + return iter->second.loaded(object); + } + + bool exists(const std::string & name) + { + OptionMap::iterator iter = find_option(name); + + return (iter != _map.end()); + } + + StringSet options(void); + + const char ** values(const char *); /* option value */ + const char ** values(void); /* values from options */ + + template < typename Object > + void copyFrom(const std::string & name, const Object * const src_obj, Object * const dst_obj, bool force = false) + { + OptionMap::iterator iter = find_option(name); + + if (iter == _map.end()) + throw Failure(STG(FMT("unknown option '%s'") % name)); + + iter->second.copyFrom(src_obj, dst_obj, force); + } + + template < typename Object > + void copyFrom(Object * src_obj, Object * dst_obj, bool force = false) + { + for (OptionMap::iterator iter = _map.begin(); iter != _map.end(); ++iter) + iter->second.copyFrom(src_obj, dst_obj, force); + } + + protected: + OptionMap::iterator find_option(std::string); + + protected: + OptionMap _map; + SynOptionMap _syn_map; + + const char ** _values; + }; +}; + +#endif /* _CONFIG_OPTIONS_HPP_ */ diff --git a/src/mod/endpoints/mod_khomp/commons/base/configurator/configfile.cpp b/src/mod/endpoints/mod_khomp/commons/base/configurator/configfile.cpp new file mode 100644 index 0000000000..8a46587a59 --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/base/configurator/configfile.cpp @@ -0,0 +1,241 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ +#include + +#include + +#if _MSC_VER >= 1400 +#undef close +#endif + +void Configfile::ignore(const std::string & str) +{ + _ignores.insert(str); +}; + +bool Configfile::select(Section **ptr, const std::string & str) +{ + /* default section == this! */ + *ptr = this; + + /* always success by default */ + return true; +}; + +bool Configfile::adjust(Section * section, const std::string & opt, const std::string & val) +{ + return section->load(opt, val); +}; + +bool Configfile::deserialize(std::ifstream & fd) +{ + Section * section = NULL; + + /* default selection! */ + if (!select(§ion)) + { + _errors.push_back("default selection has failed!"); + return false; + } + + size_t count = 0; + + while (fd.good()) + { + std::string str; + + /* read one line! */ + std::getline(fd, str); + + size_t lst = str.size() - 1; + + if (str.size() >= 1 && str[lst] == '\r') //cuida das quebras de linha do tipo \r\n + { + str.erase(lst,1); + --lst; + } + + /* empty line! */ + if (str.size() == 0) + continue; + + /* comment! */ + if (str[0] == '#') + continue; + + ++count; + + if (str[0] == '[' && str[lst] == ']') + { + str.erase(0,1); --lst; + str.erase(lst,1); --lst; + + if (!select(§ion, str)) + { + _errors.push_back(STG(FMT("erroneous section '%s'") % str)); + + /* ignore this section */ + section = NULL; + continue; + } + } + else + { + std::string::size_type pos = str.find('='); + + if (pos == std::string::npos) + { + _errors.push_back(STG(FMT("erroneous separator '%s'") % str)); + continue; + }; + + if (section == NULL) + { + _errors.push_back(STG(FMT("no section for option '%s'") % str)); + continue; + } + + std::string opt(str.substr(0,pos)); + std::string val(str.substr(pos+1)); + + if (_ignores.find(opt) != _ignores.end()) + continue; + + if (val == "@") val = ""; + + if (adjust(section, opt, val)) + continue; + + _errors.push_back(STG(FMT("option '%s' does " + "not exist or '%s' is not a valid value (at section '%s')") + % opt % val % section->name())); + } + } + + // retorna 'true' se arquivo tinha alguma coisa valida. + return (count != 0); +} + +bool Configfile::obtain() +{ + std::ifstream fd(_filename.c_str()); + + if (!fd.is_open()) + { + _errors.push_back(STG(FMT("unable to open file '%s': %s") + % _filename % strerror(errno))); + return false; + }; + + if (!deserialize(fd)) + { + fd.close(); + return false; + } + + fd.close(); + return true; +}; + +void Configfile::recurse(std::ofstream & fd, Section * section) +{ + typedef Section::SectionMap::const_iterator SectionIter; + typedef Section::OptionMap::const_iterator OptionIter; + + for (OptionIter i = section->option_begin(); i != section->option_end(); i++) + { + std::string res; + + if ((*i).second.store(res)) + { + if (res == "") res = "@"; + fd << (*i).first << "=" << res << std::endl; + } + } + + if (!section->recursive()) + return; + + for (SectionIter j = section->section_begin(); j != section->section_end(); j++) + recurse(fd, (*j).second); +} + +bool Configfile::serialize(std::ofstream & fd) +{ + recurse(fd, this); + return true; +} + +bool Configfile::provide() +{ + std::string tmp(_filename); + tmp += ".new"; + + std::ofstream fd(tmp.c_str()); + + if (!fd.good()) + { + _errors.push_back(STG(FMT("unable to open file '%s': %s") + % tmp % strerror(errno))); + return false; + } + + if (!serialize(fd)) + { + fd.close(); + return false; + } + + fd.close(); + + if (rename(tmp.c_str(), _filename.c_str()) != 0) + { + _errors.push_back(STG(FMT("unable to replace config file '%s': %s") + % _filename % strerror(errno))); + return false; + } + + return true; +} + +#if _MSC_VER >= 1400 +#define close _close +#endif diff --git a/src/mod/endpoints/mod_khomp/commons/configurator/configfile.hpp b/src/mod/endpoints/mod_khomp/commons/base/configurator/configfile.hpp similarity index 65% rename from src/mod/endpoints/mod_khomp/commons/configurator/configfile.hpp rename to src/mod/endpoints/mod_khomp/commons/base/configurator/configfile.hpp index 61f42469af..e725c09964 100644 --- a/src/mod/endpoints/mod_khomp/commons/configurator/configfile.hpp +++ b/src/mod/endpoints/mod_khomp/commons/base/configurator/configfile.hpp @@ -1,7 +1,7 @@ -/* +/* KHOMP generic endpoint/channel library. - Copyright (C) 2007-2009 Khomp Ind. & Com. - + Copyright (C) 2007-2009 Khomp Ind. & Com. + The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ @@ -23,20 +23,20 @@ The LGPL header follows below: - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ #include @@ -53,38 +53,38 @@ struct Configfile: public Section { - typedef std::list < std::string > ErrorVector; - typedef std::set < std::string > NameSet; + typedef std::list < std::string > ErrorVector; + typedef std::set < std::string > NameSet; - Configfile(std::string name, std::string desc) - : Section(name, desc), _good(false) {}; + Configfile(const std::string & name, const std::string & desc) + : Section(name, desc), _good(false) {}; - virtual ~Configfile() {}; + virtual ~Configfile() {}; - bool good() { return _good; }; - std::string & filename() { return _filename; }; + bool good() const { return _good; }; + const std::string & filename() const { return _filename; }; - ErrorVector & errors() { return _errors; }; + const ErrorVector & errors() const { return _errors; }; - void ignore(std::string); + void ignore(const std::string &); - virtual bool obtain(); - virtual bool provide(); + virtual bool obtain(); + virtual bool provide(); protected: - virtual bool select(Section **, std::string str = ""); - virtual bool adjust(Section *, std::string & opt, std::string & val); + virtual bool select(Section **, const std::string & str = ""); + virtual bool adjust(Section *, const std::string & opt, const std::string & val); - virtual bool deserialize(std::ifstream &); - virtual bool serialize(std::ofstream &); + virtual bool deserialize(std::ifstream &); + virtual bool serialize(std::ofstream &); - void recurse(std::ofstream &, Section *); + void recurse(std::ofstream &, Section *); protected: - bool _good; - ErrorVector _errors; - NameSet _ignores; - std::string _filename; + bool _good; + ErrorVector _errors; + NameSet _ignores; + std::string _filename; }; #endif /* _CONFIG_CONFIGFILE_HPP_ */ diff --git a/src/mod/endpoints/mod_khomp/commons/base/configurator/option.cpp b/src/mod/endpoints/mod_khomp/commons/base/configurator/option.cpp new file mode 100644 index 0000000000..6de9212bf3 --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/base/configurator/option.cpp @@ -0,0 +1,186 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include + +bool Option::equals(const std::string & value) const +{ + switch (_restriction.numeral()) + { + case Restriction::N_UNIQUE: + { + Restriction::Value my_value; + + if (!_restriction.get(Restriction::F_USER, my_value)) + return false; + + return (my_value == value); + } + case Restriction::N_MULTIPLE: + { + Restriction::Vector my_values; + + if (!_restriction.get(Restriction::F_USER, my_values)) + return false; + + for (Restriction::Vector::iterator i = my_values.begin(); i != my_values.end(); i++) + { + if ((*i) == value) + return true; + } + + return false; + } + } + + return false; +} + +bool Option::load(const std::string & value) +{ + bool ret = _restriction.set( (const Restriction::Format)Restriction::F_FILE, value); + + if (ret) _modified = false; + + return ret; +} + +bool Option::change(const std::string & value) +{ + bool ret = _restriction.set(Restriction::F_FILE, value); + + if (ret) _modified = true; + + return ret; +} + +bool Option::store(std::string & value) const +{ + switch (_restriction.numeral()) + { + case Restriction::N_UNIQUE: + return _restriction.get(Restriction::F_FILE, value); + + case Restriction::N_MULTIPLE: + { + Restriction::Vector values; + + if (!_restriction.get(Restriction::F_FILE, values)) + return false; + + Strings::Merger strs; + + for (Restriction::Vector::iterator i = values.begin(); i != values.end(); i++) + strs.add(*i); + + value = strs.merge(","); + + return true; + } + + default: + return false; + } +} + +/* +Option::Flags Option::set(const char * value) +{ + std::string str_value(value); + return set(str_value); +} +*/ + +Option::Flags Option::set(const Restriction::Value & value) +{ + Restriction::Value last_value, curr_value; + Flags flags; + + bool ret1 = _restriction.get(Restriction::F_USER, last_value); + + if (!_restriction.set(Restriction::F_USER, value)) + return flags; + + flags[F_ADJUSTED] = true; + + bool ret2 = _restriction.get(Restriction::F_USER, curr_value); + + if (!ret1 || (ret2 && (last_value != curr_value))) + { + flags[F_MODIFIED] = true; + _modified = true; + } + + return flags; +} + +Option::Flags Option::set(const Restriction::Vector & values) +{ + Restriction::Vector last_values, curr_values; + Flags flags; + + bool ret1 = _restriction.get(Restriction::F_USER, last_values); + + if (!_restriction.set(Restriction::F_USER, values)) + return flags; + + flags[F_ADJUSTED] = true; + + bool ret2 = _restriction.get(Restriction::F_USER, curr_values); + + if (!ret1 || (ret2 && (last_values != curr_values))) + { + flags[F_MODIFIED] = true; + _modified = true; + } + + return flags; +} + +bool Option::get(Restriction::Value & value) const +{ + return _restriction.get(Restriction::F_USER, value); +} + +bool Option::get(Restriction::Vector & values) const +{ + return _restriction.get(Restriction::F_USER, values); +} diff --git a/src/mod/endpoints/mod_khomp/commons/configurator/option.hpp b/src/mod/endpoints/mod_khomp/commons/base/configurator/option.hpp similarity index 52% rename from src/mod/endpoints/mod_khomp/commons/configurator/option.hpp rename to src/mod/endpoints/mod_khomp/commons/base/configurator/option.hpp index 8aa103a0cc..e46ab75902 100644 --- a/src/mod/endpoints/mod_khomp/commons/configurator/option.hpp +++ b/src/mod/endpoints/mod_khomp/commons/base/configurator/option.hpp @@ -1,7 +1,7 @@ -/* +/* KHOMP generic endpoint/channel library. - Copyright (C) 2007-2009 Khomp Ind. & Com. - + Copyright (C) 2007-2009 Khomp Ind. & Com. + The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ @@ -23,20 +23,20 @@ The LGPL header follows below: - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ #include @@ -45,6 +45,7 @@ #include #include +#include #include #include @@ -56,67 +57,72 @@ struct Option { enum FlagTypes { - F_MODIFIED = 0x0, /* if option was modified */ - F_ADJUSTED = 0x1, /* if option was correctly formated */ + F_MODIFIED = 0x0, /* if option was modified */ + F_ADJUSTED = 0x1, /* if option was correctly formated */ }; - struct Flags: public std::vector - { - Flags(): std::vector(2) {}; - }; + struct Flags: public std::vector + { + Flags(): std::vector(2) {}; + }; - typedef Restriction::Value Value; - typedef Restriction::Vector Vector; + typedef Restriction::Value Value; + typedef Restriction::Vector Vector; /* exception */ - struct InvalidDefaultValue + struct InvalidDefaultValue: public std::runtime_error { - InvalidDefaultValue(std::string name, std::string value) - : _name(name), _value(value) {}; + InvalidDefaultValue(const std::string & name, const std::string & value) + : std::runtime_error(STG(FMT("invalid default value '%s' for option '%s'") % value % name)), + _name(name), _value(value) + {}; - std::string & name() { return _name; }; - std::string & value() { return _value; }; + ~InvalidDefaultValue() throw () + {}; + + const std::string & name() const { return _name; }; + const std::string & value() const { return _value; }; protected: - std::string _name; - std::string _value; + const std::string _name; + const std::string _value; }; - Option(std::string name, std::string desc, std::string defvalue, Restriction restriction) - : _name(name), _desc(desc), _restriction(restriction), _modified(true) - { - std::string value(defvalue); + Option(const std::string & name, const std::string & desc, const std::string & defvalue, const Restriction & restriction) + : _name(name), _description(desc), _restriction(restriction), _modified(true) + { +// std::string value(defvalue); - if (!(set(value)[F_ADJUSTED])) + if (!(set(defvalue)[F_ADJUSTED])) throw InvalidDefaultValue(name, defvalue); - } + } - const std::string & name() { return _name; }; - const std::string & description() { return _desc; }; + const std::string & name() const { return _name; }; + const std::string & description() const { return _description; }; - Restriction & restriction() { return _restriction; }; - bool modified() { return _modified; }; + const Restriction & restriction() const { return _restriction; }; + bool modified() const { return _modified; }; public: - bool load(std::string &); - bool change(std::string &); - bool store(std::string &); + bool load(const std::string &); + bool change(const std::string &); + bool store(std::string &) const; - Flags set(const char *); - Flags set(Value &); - Flags set(Vector &); +// Flags set(const char *); + Flags set(const Value &); + Flags set(const Vector &); - bool get(Value &); - bool get(Vector &); + bool get(Value &) const; + bool get(Vector &) const; - bool equals(std::string &); + bool equals(const std::string &) const; protected: - std::string _name; - std::string _desc; + const std::string _name; + const std::string _description; - Restriction _restriction; - bool _modified; + Restriction _restriction; + bool _modified; }; #endif /* _CONFIG_OPTION_HPP_ */ diff --git a/src/mod/endpoints/mod_khomp/commons/base/configurator/restriction.cpp b/src/mod/endpoints/mod_khomp/commons/base/configurator/restriction.cpp new file mode 100644 index 0000000000..52be1ea881 --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/base/configurator/restriction.cpp @@ -0,0 +1,358 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include +#include + +#include +#include + +#include + +/* internal helper! */ +bool Restriction::equalNumber(const double a, const double b) +{ + char tmp1[64]; + char tmp2[64]; + + snprintf(tmp1, sizeof(tmp1), "%.3f", a); + snprintf(tmp2, sizeof(tmp2), "%.3f", b); + + if (strncmp(tmp1, tmp2, sizeof(tmp1))) + return false; + + return true; +} + +/* process value to our internal representation */ + +bool Restriction::process(Restriction::Format fmt, + const Restriction::Value & value, Restriction::Value & final) const +{ + switch (_bounds) + { + case B_RANGE: + { + if (_kind != K_NUMBER) + return false; + + std::string tmpvalue; + + Restriction::Value::const_iterator itr = value.begin(); + Restriction::Value::const_iterator end = value.end(); + + tmpvalue.reserve(value.size()); + + // f*cking dot/comma notation! + for (; itr != end; ++itr) + tmpvalue += ((*itr) != ',' ? (*itr) : '.'); + + try + { + double newvalue = Strings::todouble(tmpvalue); + + if (newvalue < _init && newvalue > _fini) + return false; + + double res = (newvalue - _init) / _step; + + if (!Restriction::equalNumber(res, rint(res))) + return false; + + final = value; + return true; + } + catch (...) + { + return false; + } + } + + case B_LIST: + for (List::const_iterator i = _list.begin(); i != _list.end(); i++) + { + const Value & tmp = (*i); + + if (tmp == value) + { + final = value; + return true; + } + } + return false; + + case B_MAPS: + switch (fmt) + { + case F_USER: + { + Map::const_iterator i = _map_from_usr.find(value); + + if (i == _map_from_usr.end()) + return false; + + const Value & tmp = (*i).second; + + final = tmp; + return true; + } + + case F_FILE: + { + Map::const_iterator i = _map_from_cfg.find(value); + + if (i == _map_from_cfg.end()) + return false; + + final = value; + return true; + } + + default: + break; + } + return false; + + case B_FREE: + final = value; + return true; + + default: + break; + } + + return false; +} + +/* unprocess the value (outputs the external representation) */ + +bool Restriction::unprocess(Restriction::Format fmt, + const Restriction::Value & value, Restriction::Value & final) const +{ + switch (_bounds) + { + case B_MAPS: + + switch (fmt) + { + case F_USER: + { + Map::const_iterator i = _map_from_cfg.find(value); + + if (i == _map_from_cfg.end()) + return false; + + final = (*i).second; + return true; + } + default: + break; + } + + default: + final = value; + return true; + } +} + +/***************************** *****************************/ + +bool Restriction::get(Restriction::Format fmt, Restriction::Value & value) const +{ + if (_numeral != N_UNIQUE) + return false; + + if (!unprocess(fmt, _value._unique, value)) + return false; + + return true; +} + +bool Restriction::get(Restriction::Format fmt, Restriction::Vector & values) const +{ + if (_numeral != N_MULTIPLE) + return false; + + const List & my_values = _value._multiple; + + for (List::const_iterator i = my_values.begin(); i != my_values.end(); i++) + { + const Value & value = (*i); + + Value final; + + if (!unprocess(fmt, value, final)) + return false; + + values.push_back(final); + }; + + return true; +} + +/***************************** *****************************/ + +bool Restriction::set(Restriction::Format fmt, const Restriction::Value & value) +{ + switch (_numeral) + { + case N_UNIQUE: + { + Value final; + + if (!constThis().process(fmt, value, final)) + return false; + + _value._unique = final; + return true; + } + + case N_MULTIPLE: + { + if (value == "@" || value == "#" || value == "") + { + _value._multiple.clear(); + return true; + } + + Strings::vector_type values; + Strings::tokenize(value, values, ","); + + return set(fmt, values); + } + + default: + return false; + } +} + +bool Restriction::set(Restriction::Format fmt, const Restriction::Vector & values) +{ + if (_numeral != N_MULTIPLE) + return false; + + if (values.empty()) + { + _value._multiple.clear(); + } + else + { + /* list needed to store temporary values */ + List finals; + + for (Vector::const_iterator i = values.begin(); i != values.end(); i++) + { + const Value & value = (*i); + + Value final; + + if (!constThis().process(fmt, value, final)) + return false; + + finals.push_back(final); + } + + List & lst = _value._multiple; + + /* need to clear values set before */ + lst.clear(); + + for (List::iterator i = finals.begin(); i != finals.end(); i++) + { + Value value = (*i); + lst.push_back(value); + } + }; + + return true; +} + +/***************************** *****************************/ + +void Restriction::allowed(Restriction::Vector & vals) const +{ + switch (_bounds) + { + case B_FREE: + return; + + case B_LIST: + for (List::const_iterator i = _list.begin(); i != _list.end(); i++) + vals.push_back(*i); + break; + + case B_MAPS: + for (Map::const_iterator i = _map_from_usr.begin(); i != _map_from_usr.end(); i++) + vals.push_back(i->first); + break; + + case B_RANGE: + { + if (_kind != K_NUMBER) + return; + + // is there any fraction? + bool has_fraction = + (!Restriction::equalNumber(_init, rint(_init))) || + (!Restriction::equalNumber(_fini, rint(_fini))) || + (!Restriction::equalNumber(_step, rint(_step))); + + const char * format = (has_fraction ? "%.2f" : "%02.0f"); + + for (double i = _init; i <= _fini; i += _step) + { + char tmp[32]; + snprintf(tmp, sizeof(tmp), format, i); + vals.push_back(std::string(tmp)); + } + break; + } + + default: + break; + } +} + +void Restriction::init_class() +{ + _value._unique.clear(); + _value._multiple.clear(); +} diff --git a/src/mod/endpoints/mod_khomp/commons/base/configurator/restriction.hpp b/src/mod/endpoints/mod_khomp/commons/base/configurator/restriction.hpp new file mode 100644 index 0000000000..576560dbd4 --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/base/configurator/restriction.hpp @@ -0,0 +1,269 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include + +#include +#include +#include +#include + +#include + +#ifndef _CONFIG_RESTRICTION_HPP_ +#define _CONFIG_RESTRICTION_HPP_ + +struct Restriction: public ConstThis < Restriction > +{ + /* generic types */ + + // TODO: change this type name for something different + // to avoid conflicting with "format.hpp". + enum Format + { + F_USER, + F_FILE + }; + + enum Kind + { + K_STRING, + K_NUMBER // = K_INTEGER // compatibility + }; + + enum Bounds + { + B_FREE, + B_RANGE, + B_LIST, + B_MAPS + }; + + enum Numeral + { + N_UNIQUE, + N_MULTIPLE + }; + + typedef std::string Value; + + /* types used for data input */ + struct Pair + { + const char *pretty; + const char *value; + }; + + typedef std::pair < Value, Value > PairMap; + typedef std::list < PairMap > ListMap; + + /* types used internally */ + typedef std::map < Value, Value > Map; + typedef std::vector < Value > Vector; + + typedef std::list < Value > List; + typedef std::pair < Value, Value > MapPair; + + struct Generic + { + Value _unique; + List _multiple; + }; + + Restriction(Kind kind, Numeral num) + : _kind(kind), _bounds(B_FREE), _numeral(num), _unit(""), + _init(-1), _fini(-1), _step(-1) + { + init_class(); + } + + Restriction(Kind kind, Numeral num, + double init, double fini, double step = 1) + : _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(""), + _init(init), _fini(fini), _step(step) + { + init_class(); + } + + Restriction(Kind kind, Numeral num, + const char *unit, double init, double fini, double step = 1.0) + : _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(unit), + _init(init), _fini(fini), _step(step) + { + init_class(); + } + + Restriction(Kind kind, Numeral num, + std::string unit, double init, double fini, double step = 1.0) + : _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(unit), + _init(init), _fini(fini), _step(step) + { + init_class(); + } + + Restriction(Kind kind, Numeral num, + const char *first, ...) + : _kind(kind), _bounds(B_LIST), _numeral(num), _unit(""), + _init(-1), _fini(-1), _step(-1) + { + _list.push_back(std::string(first)); + + va_list ap; + va_start(ap, first); + + while (true) + { + const char *arg = va_arg(ap, const char *); + + if (arg == NULL) break; + + _list.push_back(std::string(arg)); + } + + init_class(); + } + + Restriction(Kind kind, const char *unit, Numeral num, + const char *first, ...) + : _kind(kind), _bounds(B_LIST), _numeral(num), _unit(unit), + _init(-1), _fini(-1), _step(-1) + { + _list.push_back(std::string(first)); + + va_list ap; + va_start(ap, first); + + while (true) + { + const char *arg = va_arg(ap, const char *); + + if (arg == NULL) break; + + _list.push_back(std::string(arg)); + } + + init_class(); + } + + Restriction(Kind kind, Numeral num, + const struct Pair first, ...) + : _kind(kind), _bounds(B_MAPS), _numeral(num), _unit(""), + _init(-1), _fini(-1), _step(-1) + { + _map_from_usr.insert(MapPair(Value(first.pretty), Value(first.value))); + _map_from_cfg.insert(MapPair(Value(first.value), Value(first.pretty))); + + va_list ap; + va_start(ap, first); + + while (true) + { + Pair arg = va_arg(ap, Pair); + + if (arg.pretty == NULL) break; + + _map_from_usr.insert(MapPair(Value(arg.pretty), Value(arg.value))); + _map_from_cfg.insert(MapPair(Value(arg.value), Value(arg.pretty))); + } + + init_class(); + } + + Restriction(Kind kind, Numeral num, List list) + : _kind(kind), _bounds(B_LIST), _numeral(num), _unit(""), + _init(-1), _fini(-1), _step(-1), _list(list) + { + init_class(); + } + + Restriction(Kind kind, Numeral num, ListMap map) + : _kind(kind), _bounds(B_MAPS), _numeral(num), _unit(""), + _init(-1), _fini(-1), _step(-1) + { + for (ListMap::iterator i = map.begin(); i != map.end(); i++) + { + _map_from_usr.insert(MapPair(Value((*i).first), Value((*i).second))); + _map_from_cfg.insert(MapPair(Value((*i).second), Value((*i).first))); + } + + init_class(); + } + + const Kind kind() const { return _kind; }; + const Bounds bounds() const { return _bounds; }; + const Numeral numeral() const { return _numeral; }; + + const std::string & unit() const { return _unit; }; + + bool set(Format, const Vector &); + bool set(Format, const Value &); + + bool get(Format, Vector &) const; + bool get(Format, Value &) const; + + void allowed(Vector &) const; + + private: + bool process(const Format, const Value &, Value &) const; + bool unprocess(const Format, const Value &, Value &) const; + + void init_class(); + + static bool equalNumber(const double, const double); + + protected: + const Kind _kind; + const Bounds _bounds; + const Numeral _numeral; + + Value _unit; + + const double _init, _fini, _step; + + Map _map_from_usr, + _map_from_cfg; + + List _list; + + Generic _value; +}; + +#endif /* _CONFIG_RESTRICTION_HPP_ */ diff --git a/src/mod/endpoints/mod_khomp/commons/configurator/section.cpp b/src/mod/endpoints/mod_khomp/commons/base/configurator/section.cpp similarity index 59% rename from src/mod/endpoints/mod_khomp/commons/configurator/section.cpp rename to src/mod/endpoints/mod_khomp/commons/base/configurator/section.cpp index 5d26858054..9ed775b044 100644 --- a/src/mod/endpoints/mod_khomp/commons/configurator/section.cpp +++ b/src/mod/endpoints/mod_khomp/commons/base/configurator/section.cpp @@ -1,7 +1,7 @@ -/* +/* KHOMP generic endpoint/channel library. - Copyright (C) 2007-2009 Khomp Ind. & Com. - + Copyright (C) 2007-2009 Khomp Ind. & Com. + The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ @@ -23,108 +23,114 @@ The LGPL header follows below: - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ #include -void Section::options(Section::OptionVector & vec) +void Section::options(Section::OptionVector & vec) const { - for (OptionMap::iterator it = _options.begin(); it != _options.end();) - { - vec.push_back(&((*it).second)); - ++it; - } + for (OptionMap::const_iterator it = _options.begin(); it != _options.end();) + { + vec.push_back(const_cast< Option * >(&(it->second))); + ++it; + } } -void Section::sections(Section::SectionVector & vec) +void Section::sections(Section::SectionVector & vec) const { - for (SectionMap::iterator it = _sections.begin(); it != _sections.end();) - { - vec.push_back((*it).second); - ++it; - } + for (SectionMap::const_iterator it = _sections.begin(); it != _sections.end();) + { + vec.push_back(const_cast< Section * >(it->second)); + ++it; + } } /*********/ -Option * Section::option_find(std::string & str, bool recurse) +Option * Section::option_find(const std::string & str, bool recurse) const { - OptionMap::iterator i = _options.find(str); + OptionMap::const_iterator i = _options.find(str); - if (i == _options.end()) + if (i == _options.end()) { if (!recurse) - throw not_found(); + throw OptionNotFound(str, _name); +// throw not_found(); - for (SectionMap::iterator i = _sections.begin(); i != _sections.end(); i++) + for (SectionMap::const_iterator i = _sections.begin(); i != _sections.end(); i++) { try { return i->second->option_find(str, recurse); } - catch (not_found & e) + catch (NotFound & e) { /* keep looping! */ }; } - throw not_found(); +// throw not_found(); + throw OptionNotFound(str, _name); } - return &((*i).second); + return const_cast< Option * >(&(i->second)); } +/* Option * Section::option_find(const char * str, bool recurse) { - std::string sstr(str); - return option_find(sstr, recurse); + std::string sstr(str); + return option_find(sstr, recurse); } +*/ /*********/ -Section * Section::section_find(std::string & str, bool recurse) +Section * Section::section_find(const std::string & str, bool recurse) const { - SectionMap::iterator i = _sections.find(str); + SectionMap::const_iterator i = _sections.find(str); - if (i == _sections.end()) + if (i == _sections.end()) { if (!recurse) - throw not_found(); + throw SectionNotFound(str, _name); - for (SectionMap::iterator i = _sections.begin(); i != _sections.end(); i++) + for (SectionMap::const_iterator i = _sections.begin(); i != _sections.end(); i++) { try { return i->second->section_find(str, recurse); } - catch (not_found & e) + catch (NotFound & e) { /* keep looping! */ }; } - throw not_found(); + throw SectionNotFound(str, _name); } - return ((*i).second); + return const_cast< Section * >(i->second); } +/* Section * Section::section_find(const char * str, bool recurse) { - std::string sstr(str); - return section_find(sstr, recurse); + std::string sstr(str); + return section_find(sstr, recurse); } +*/ diff --git a/src/mod/endpoints/mod_khomp/commons/base/configurator/section.hpp b/src/mod/endpoints/mod_khomp/commons/base/configurator/section.hpp new file mode 100644 index 0000000000..d5a8c95688 --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/base/configurator/section.hpp @@ -0,0 +1,260 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#ifndef _CONFIG_SECTION_HPP_ +#define _CONFIG_SECTION_HPP_ + +#include +#include +#include +#include +#include + +#include + +#include + +struct Section +{ + typedef std::map < std::string, Option > OptionMap; + typedef std::vector< Option * > OptionVector; + + typedef std::map < std::string, Section * > SectionMap; + typedef std::vector < Section * > SectionVector; + + struct NotFound: public std::runtime_error + { + NotFound(const std::string & type, const std::string & name, const std::string & me) + : std::runtime_error(STG(FMT("%s '%s' not found on section '%s'") % type % name % me)) {}; + }; + + struct OptionNotFound: public NotFound + { + OptionNotFound(const std::string & name, const std::string & me) + : NotFound("option", name, me) {}; + }; + + struct SectionNotFound: public NotFound + { + SectionNotFound(const std::string & name, const std::string & me) + : NotFound("section", name, me) {}; + }; + + typedef NotFound not_found; /* backward compatibility */ + +// protected: + Section(const std::string & name, const std::string & desc, bool recursive = true) + : _name(name), _description(desc), _recursive(recursive) {}; + + void add(const Option & o) + { + _options.insert(std::pair(o.name(), o)); + }; + + void del(const std::string & name) + { + _options.erase(name); + }; + + void add(Section * s) + { + _sections.insert(std::pair< std::string, Section * >(s->name(), s)); + }; + + public: + const std::string & name() const { return _name; }; + const std::string & description() const { return _description; }; + + const bool recursive() const { return _recursive; }; + + OptionMap::const_iterator option_begin() const { return _options.begin(); }; + OptionMap::const_iterator option_end() const { return _options.end(); }; + + SectionMap::const_iterator section_begin() const { return _sections.begin(); }; + SectionMap::const_iterator section_end() const { return _sections.end(); }; + + /**/ + +// Option * option_find(const char *, bool recurse = false) const; +// Section * section_find(const char *, bool recurse = false) const; + + Option * option_find(const std::string &, bool recurse = false) const; + Section * section_find(const std::string &, bool recurse = false) const; + + /**/ + + void options(OptionVector &) const; + void sections(SectionVector &) const; + + /**/ + + template < typename T, typename F > + bool search_and_apply(const std::string & key, T & value, F f) + { + OptionMap::iterator i = _options.find(key); + + if (i != _options.end()) + return f(i->second); + + if (!_recursive) + return false; + + return (find_if(_sections.begin(), _sections.end(), f) != _sections.end()); + } + + private: + struct ConstKeyValue + { + ConstKeyValue(const std::string & k, const std::string &v) + : _k(k), _v(v) {}; + + const std::string & _k; + const std::string & _v; + }; + + struct KeyValue + { + KeyValue(const std::string & k, std::string &v) + : _k(k), _v(v) {}; + + const std::string & _k; + std::string & _v; + }; + + struct load_section: protected ConstKeyValue + { + load_section(const std::string & k, const std::string & v): ConstKeyValue(k,v) {}; + + bool operator()(Option & o) { return o.load(_v); }; + bool operator()(SectionMap::value_type & v) { return v.second->load(_k,_v); }; + }; + + struct change_section: protected ConstKeyValue + { + change_section(const std::string & k, const std::string & v): ConstKeyValue(k,v) {}; + + bool operator()(Option & o) { return o.change(_v); }; + bool operator()(SectionMap::value_type & v) { return v.second->change(_k,_v); }; + }; + + struct store_section: protected KeyValue + { + store_section(const std::string & k, std::string & v): KeyValue(k,v) {}; + + bool operator()(Option & o) { return o.store(_v); }; + bool operator()(SectionMap::value_type & v) { return v.second->store(_k,_v); }; + }; + + struct set_section: protected ConstKeyValue + { + set_section(const std::string & k, const std::string & v): ConstKeyValue(k,v) {}; + + bool operator()(Option & o) { return (o.set(_v))[Option::F_ADJUSTED]; }; + bool operator()(SectionMap::value_type & v) { return v.second->set(_k,_v); }; + }; + + struct get_section: protected KeyValue + { + get_section(const std::string & k, std::string & v): KeyValue(k,v) {}; + + bool operator()(Option & o) { return o.get(_v); }; + bool operator()(SectionMap::value_type & v) { return v.second->get(_k,_v); }; + }; + + struct modified_section + { + bool operator()(const OptionMap::value_type & v) { return v.second.modified(); }; + bool operator()(const SectionMap::value_type & v) { return v.second->modified(); }; + }; + + public: +/* + bool load(const char * key, const std::string value) + { + std::string skey(key); + return search_and_apply(skey, value, load_section(skey, value)); + } +*/ + bool load(const std::string & key, const std::string & value) + { + return search_and_apply(key, value, load_section(key, value)); + } + + bool change(const std::string & key, const std::string & value) + { + return search_and_apply(key, value, change_section(key, value)); + } + + bool store(const std::string & key, std::string & value) + { + return search_and_apply(key, value, store_section(key, value)); + } + + bool set(const std::string & key, const std::string & value) + { + return search_and_apply(key, value, set_section(key, value)); + } + + bool get(const std::string & key, std::string & value) + { + return search_and_apply(key, value, get_section(key, value)); + } + + bool modified() const + { + return ((find_if(_options.begin(), _options.end(), modified_section()) != _options.end()) || + (find_if(_sections.begin(), _sections.end(), modified_section()) != _sections.end())); + } + + private: + Section(): _name(""), _description(""), _recursive(false) {}; + + protected: + const std::string _name; + const std::string _description; + + OptionMap _options; + SectionMap _sections; + + const bool _recursive; +}; + +#endif /* _CONFIG_SECTION_HPP_ */ diff --git a/src/mod/endpoints/mod_khomp/commons/base/const_this.hpp b/src/mod/endpoints/mod_khomp/commons/base/const_this.hpp new file mode 100644 index 0000000000..48e3c1e32f --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/base/const_this.hpp @@ -0,0 +1,15 @@ + +#ifndef _CONST_THIS_H_ +#define _CONST_THIS_H_ + +template < typename T > +struct ConstThis +{ + T const & constThis() const + { + // TODO: will this return the right reference? + return static_cast(*this); + } +}; + +#endif /* _CONST_THIS_H_ */ diff --git a/src/mod/endpoints/mod_khomp/commons/flagger.hpp b/src/mod/endpoints/mod_khomp/commons/base/flagger.hpp similarity index 100% rename from src/mod/endpoints/mod_khomp/commons/flagger.hpp rename to src/mod/endpoints/mod_khomp/commons/base/flagger.hpp diff --git a/src/mod/endpoints/mod_khomp/commons/format.cpp b/src/mod/endpoints/mod_khomp/commons/base/format.cpp similarity index 89% rename from src/mod/endpoints/mod_khomp/commons/format.cpp rename to src/mod/endpoints/mod_khomp/commons/base/format.cpp index 20f79204ec..74223cc406 100644 --- a/src/mod/endpoints/mod_khomp/commons/format.cpp +++ b/src/mod/endpoints/mod_khomp/commons/base/format.cpp @@ -42,27 +42,7 @@ #include "format.hpp" //#include -Format::Format(const char * format_string, bool raise_exception) -: _format(format_string), _valid(true), _raise(raise_exception) -{ - initialize(format_string); -} - -/* -Format::Format(std::string & format_string, bool raise_exception) -: _format(NULL), _valid(true), _raise(raise_exception) -{ - initialize(format_string.c_str()); -} -*/ - -Format::Format(std::string format_string, bool raise_exception) -: _format(format_string), _valid(true), _raise(raise_exception) -{ - initialize(format_string.c_str()); -} - -void Format::initialize(const char * format_string) +void FormatTraits::initialize(const char * format_string) { std::string txt; @@ -82,7 +62,6 @@ void Format::initialize(const char * format_string) if (*ptr2 == '%') { txt += *ptr; - ptr += 2; continue; } @@ -238,36 +217,20 @@ void Format::initialize(const char * format_string) push_argument(txt, T_LITERAL); } -void Format::mark_invalid(std::string & msg) +void FormatTraits::push_argument(std::string & data, FormatTraits::Type type) { - if (_valid) - { - _valid = false; +// std::cerr << "pushing type (" << type << ") with format (" << data << ")" << std::endl; - std::string finalmsg; - - finalmsg += "** INVALID FORMAT: "; - finalmsg += msg; - finalmsg += " **"; - - _result = finalmsg; - } + _args.push(Argument(data, type)); + data.clear(); } -void Format::raise_check(void) +void FormatTraits::pop_argument(void) { - if (!_valid && _raise) - throw InvalidFormat(_result); + _args.pop(); } -bool Format::validity_check(void) -{ - raise_check(); - - return _valid; -} - -const Format::Argument * Format::next_argument(void) +const FormatTraits::Argument * FormatTraits::next_argument(void) { // std::cerr << "size: " << _args.size() << std::endl; @@ -294,38 +257,81 @@ const Format::Argument * Format::next_argument(void) } } -void Format::pop_argument(void) +/******************************************************************/ + +#if 0 +Format::Format(const char * format_string, bool raise_exception) +: _format(format_string), _valid(true), _raise(raise_exception) { - _args.pop(); + FormatTraits::initialize(format_string); } -void Format::push_argument(std::string & data, Format::Type type) +Format::Format(std::string format_string, bool raise_exception) +: _format(format_string), _valid(true), _raise(raise_exception) { -// std::cerr << "pushing type (" << type << ") with format (" << data << ")" << std::endl; + FormatTraits::initialize(format_string.c_str()); +} - _args.push(Argument(data, type)); - data.clear(); +/* +Format::Format(std::string & format_string, bool raise_exception) +: _format(NULL), _valid(true), _raise(raise_exception) +{ + initialize(format_string.c_str()); +} +*/ + +void Format::mark_invalid(std::string & msg) +{ + if (_valid) + { + _valid = false; + + _result = "** INVALID FORMAT: "; + _result += msg; + _result += " **"; + } +} + +void Format::raise(void) const +{ + if (!_valid) + { + // call specialized class + FormatException::raise(_result); + } +} + +bool Format::valid(void) const +{ +// raise(); + return _valid; } std::string Format::str() { - if (!validity_check()) + if (!valid()) return _result; - if (next_argument() == NULL) +// try +// { + if (next_argument() != NULL) + { + std::string msg; + + msg += "too few arguments passed for format '"; + msg += _format; + msg += "' ("; + msg += _format; + msg += ")"; + + mark_invalid(msg); + return _result; - - std::string msg; - - msg += "too few arguments passed for format '"; - msg += _format; - msg += "' ("; - msg += _format; - msg += ")"; - - mark_invalid(msg); - - return _result; + } +// catch (NoArgumentLeft e) +// { +// return _result; +// } } - +#endif diff --git a/src/mod/endpoints/mod_khomp/commons/format.hpp b/src/mod/endpoints/mod_khomp/commons/base/format.hpp similarity index 81% rename from src/mod/endpoints/mod_khomp/commons/format.hpp rename to src/mod/endpoints/mod_khomp/commons/base/format.hpp index b1ebe74396..0469e4fdf9 100644 --- a/src/mod/endpoints/mod_khomp/commons/format.hpp +++ b/src/mod/endpoints/mod_khomp/commons/base/format.hpp @@ -52,37 +52,35 @@ #include #ifdef WIN32 // WINDOWS -#include +# include #endif - -/* macros used for shortening lines and making the code clearer */ -#define STG(x) (x).str() -#define FMT(x) Format(x) - -struct Format +struct InvalidFormat { - static const unsigned int strings_base_length = 64; - static const unsigned int generic_base_length = 64; + InvalidFormat(std::string _msg) : msg(_msg) {} + const std::string msg; +}; - struct InvalidFormat +template < bool E > +struct FormatException +{ + void raise(const std::string & msg) const { - InvalidFormat(std::string msg) : _msg(msg) {} - - std::string _msg; + /* DO NOTHING */ }; +}; - explicit Format(const char * format_string, bool raise_exception = false); - explicit Format(std::string format_string, bool raise_exception = false); - - void initialize(const char *); - - std::string str(void); - - //////////////////////////////////////////////////////////// - - protected: +template < > +struct FormatException < true > +{ + void raise(const std::string & msg) const + { + throw InvalidFormat(msg); + }; +}; +struct FormatTraits +{ enum Type { T_ANYTHING = 1, @@ -113,24 +111,240 @@ struct Format Argument(std::string fmts, Type type) : _fmts(fmts), _type(type) {}; - Type type(void) const { return _type; } + const Type type(void) const { return _type; } const std::string & fmts(void) const { return _fmts; } protected: - std::string _fmts; - Type _type; + const std::string _fmts; + const Type _type; }; typedef std::queue < Argument > ArgumentQueue; - //////////////////////////////////////////////////////////// - - public: + ////////////////////////////////// template < typename V > - Format & operator%( V value ) + bool number_verify_signed_short( V value ) const { - if (!validity_check()) + return + ((typeid(V) == typeid(short int) || + typeid(V) == typeid(short) || + typeid(V) == typeid(const short int) || + typeid(V) == typeid(const short) || + typeid(V) == typeid(volatile short int) || + typeid(V) == typeid(volatile short)) && + sizeof(V) == sizeof(short)); + } + + template < typename V > + bool number_verify_unsigned_short( V value ) const + { + return + ((typeid(V) == typeid(unsigned short int) || + typeid(V) == typeid(unsigned short) || + typeid(V) == typeid(const unsigned short int) || + typeid(V) == typeid(const unsigned short) || + typeid(V) == typeid(volatile unsigned short int) || + typeid(V) == typeid(volatile unsigned short)) && + sizeof(V) == sizeof(unsigned short)); + } + + template < typename V > + bool number_verify_signed_long( V value ) const + { + return + ((typeid(V) == typeid(long int) || + typeid(V) == typeid(long) || + typeid(V) == typeid(const long int) || + typeid(V) == typeid(const long) || + typeid(V) == typeid(volatile long int) || + typeid(V) == typeid(volatile long)) && + sizeof(V) == sizeof(long)); + } + + template < typename V > + bool number_verify_unsigned_long( V value ) const + { + return + ((typeid(V) == typeid(unsigned long int) || + typeid(V) == typeid(unsigned long) || + typeid(V) == typeid(const unsigned long int) || + typeid(V) == typeid(const unsigned long) || + typeid(V) == typeid(volatile unsigned long int) || + typeid(V) == typeid(volatile unsigned long)) && + sizeof(V) == sizeof(long long)); + } + + template < typename V > + bool number_verify_signed_long_long( V value ) const + { + return + ((typeid(V) == typeid(long long int) || + typeid(V) == typeid(long long) || + typeid(V) == typeid(const long long int) || + typeid(V) == typeid(const long long) || + typeid(V) == typeid(volatile long long) || + typeid(V) == typeid(volatile long long int)) && + sizeof(V) == sizeof(long long)); + } + + template < typename V > + bool number_verify_unsigned_long_long( V value ) const + { + return + ((typeid(V) == typeid(unsigned long long int) || + typeid(V) == typeid(unsigned long long) || + typeid(V) == typeid(const unsigned long long int) || + typeid(V) == typeid(const unsigned long long) || + typeid(V) == typeid(volatile unsigned long long) || + typeid(V) == typeid(volatile unsigned long long int)) && + sizeof(V) == sizeof(unsigned long long)); + } + + template < typename V > + bool number_verify_signed_int( V value ) const + { + return + (sizeof(V) <= sizeof(int) || + typeid(V) == typeid(int) || + typeid(V) == typeid(const int) || + typeid(V) == typeid(volatile int)); + } + + template < typename V > + bool number_verify_unsigned_int( V value ) const + { + return + (sizeof(V) <= sizeof(unsigned int) || + typeid(V) == typeid(unsigned int) || + typeid(V) == typeid(const unsigned int) || + typeid(V) == typeid(volatile unsigned int)); + } + + template < typename V > + bool generic_verify( V value, const Type type ) const + { + switch (type) + { + /* EXCEPTION: consider any number an valid input. */ + case T_SIGNED_INT: + case T_UNSIGNED_INT: + return + (number_verify_signed_int(value) || + number_verify_unsigned_int(value) || + number_verify_signed_long(value) || + number_verify_unsigned_long(value) || + number_verify_signed_short(value) || + number_verify_unsigned_short(value)); + + case T_SIGNED_SHORT_SHORT: + return (typeid(V) == typeid(char) || typeid(V) == typeid(const char)); + + case T_SIGNED_SHORT: + return number_verify_signed_short(value); + + case T_SIGNED_LONG: + return number_verify_signed_long(value); + + case T_SIGNED_LONG_LONG: + return number_verify_signed_long_long(value); + + case T_UNSIGNED_SHORT_SHORT: + return (typeid(V) == typeid(unsigned char) || typeid(V) == typeid(unsigned char)); + + case T_UNSIGNED_SHORT: + return number_verify_unsigned_short(value); + + case T_UNSIGNED_LONG: + return number_verify_unsigned_long(value); + + case T_UNSIGNED_LONG_LONG: + return number_verify_unsigned_long_long(value); + + case T_FLOAT: + return (typeid(V) == typeid(float)) || (typeid(V) == typeid(double) || + typeid(V) == typeid(const float)) || (typeid(V) == typeid(const double)); + + case T_CHAR: + return (typeid(V) == typeid(char)) || (typeid(V) == typeid(unsigned char) || + typeid(V) == typeid(const char)) || (typeid(V) == typeid(const unsigned char)); + + case T_POINTER: + case T_STRING: + return false; + + case T_ANYTHING: + return true; + + case T_LITERAL: + return false; + } + + return false; + }; + + const Argument * next_argument(void); + + void push_argument(std::string & data, const Type type); + void pop_argument(void); + + void initialize(const char *); + + protected: + ArgumentQueue _args; + std::string _result; + +}; + +template < bool E = false > +struct FormatBase: protected FormatTraits, protected FormatException < E > +{ + static const unsigned int strings_base_length = 64; + static const unsigned int generic_base_length = 64; + + explicit FormatBase(const char * format_string) + : _format(format_string), _valid(true) + { + FormatTraits::initialize(format_string); + }; + + explicit FormatBase(std::string format_string) + : _format(format_string), _valid(true) + { + FormatTraits::initialize(format_string.c_str()); + }; + + bool valid(void) const + { + return _valid; + } + + const std::string str() + { + if (valid() && (next_argument() != NULL)) + { + std::string msg; + + // TODO: why format appears two times? + msg += "too few arguments passed for format '"; + msg += _format; + msg += "' ("; + msg += _format; + msg += ")"; + + mark_invalid(msg); + } + + raise(); + return _result; + }; + + //////////////////////////////////////////////////////////// + + template < typename V > + FormatBase & operator%( V value ) + { + if (!valid()) return *this; const Argument * top = next_argument(); @@ -149,7 +363,7 @@ struct Format { char temp[generic_base_length]; - if (!generic_verify(value, top->type())) + if (!FormatTraits::generic_verify(value, top->type())) { std::string msg; @@ -171,14 +385,14 @@ struct Format pop_argument(); } - raise_check(); + raise(); return *this; } template < typename V > - Format & operator%( V * value ) + FormatBase & operator%( V * value ) { - if (!validity_check()) + if (!valid()) return *this; const Argument * top = next_argument(); @@ -256,20 +470,13 @@ struct Format pop_argument(); } - raise_check(); + raise(); return *this; } -/* - Format & operator%( std::string value ) + FormatBase & operator%( const std::string value ) { - return operator%(value); - } -*/ - - Format & operator%( const std::string value ) - { - if (!validity_check()) + if (!valid()) return *this; const Argument * top = next_argument(); @@ -313,200 +520,42 @@ struct Format pop_argument(); } - raise_check(); + raise(); return *this; } - protected: - - template < typename V > - bool number_verify_signed_short( V value ) + protected: + void mark_invalid(std::string & msg) { - return - ((typeid(V) == typeid(short int) || - typeid(V) == typeid(short) || - typeid(V) == typeid(const short int) || - typeid(V) == typeid(const short) || - typeid(V) == typeid(volatile short int) || - typeid(V) == typeid(volatile short)) && - sizeof(V) == sizeof(short)); - } - - template < typename V > - bool number_verify_unsigned_short( V value ) - { - return - ((typeid(V) == typeid(unsigned short int) || - typeid(V) == typeid(unsigned short) || - typeid(V) == typeid(const unsigned short int) || - typeid(V) == typeid(const unsigned short) || - typeid(V) == typeid(volatile unsigned short int) || - typeid(V) == typeid(volatile unsigned short)) && - sizeof(V) == sizeof(unsigned short)); - } - - template < typename V > - bool number_verify_signed_long( V value ) - { - return - ((typeid(V) == typeid(long int) || - typeid(V) == typeid(long) || - typeid(V) == typeid(const long int) || - typeid(V) == typeid(const long) || - typeid(V) == typeid(volatile long int) || - typeid(V) == typeid(volatile long)) && - sizeof(V) == sizeof(long)); - } - - template < typename V > - bool number_verify_unsigned_long( V value ) - { - return - ((typeid(V) == typeid(unsigned long int) || - typeid(V) == typeid(unsigned long) || - typeid(V) == typeid(const unsigned long int) || - typeid(V) == typeid(const unsigned long) || - typeid(V) == typeid(volatile unsigned long int) || - typeid(V) == typeid(volatile unsigned long)) && - sizeof(V) == sizeof(long long)); - } - - template < typename V > - bool number_verify_signed_long_long( V value ) - { - return - ((typeid(V) == typeid(long long int) || - typeid(V) == typeid(long long) || - typeid(V) == typeid(const long long int) || - typeid(V) == typeid(const long long) || - typeid(V) == typeid(volatile long long) || - typeid(V) == typeid(volatile long long int)) && - sizeof(V) == sizeof(long long)); - } - - template < typename V > - bool number_verify_unsigned_long_long( V value ) - { - return - ((typeid(V) == typeid(unsigned long long int) || - typeid(V) == typeid(unsigned long long) || - typeid(V) == typeid(const unsigned long long int) || - typeid(V) == typeid(const unsigned long long) || - typeid(V) == typeid(volatile unsigned long long) || - typeid(V) == typeid(volatile unsigned long long int)) && - sizeof(V) == sizeof(unsigned long long)); - } - - template < typename V > - bool number_verify_signed_int( V value ) - { - return - (sizeof(V) <= sizeof(int) || - typeid(V) == typeid(int) || - typeid(V) == typeid(const int) || - typeid(V) == typeid(volatile int)); - } - - template < typename V > - bool number_verify_unsigned_int( V value ) - { - return - (sizeof(V) <= sizeof(unsigned int) || - typeid(V) == typeid(unsigned int) || - typeid(V) == typeid(const unsigned int) || - typeid(V) == typeid(volatile unsigned int)); - } - - template < typename V > - bool generic_verify( V value, Type type ) - { - switch (type) + if (_valid) { - /* EXCEPTION: consider any number an valid input. */ - case T_SIGNED_INT: - case T_UNSIGNED_INT: - return - (number_verify_signed_int(value) || - number_verify_unsigned_int(value) || - number_verify_signed_long(value) || - number_verify_unsigned_long(value) || - number_verify_signed_short(value) || - number_verify_unsigned_short(value)); + _valid = false; - case T_SIGNED_SHORT_SHORT: - return (typeid(V) == typeid(char) || typeid(V) == typeid(const char)); - - case T_SIGNED_SHORT: - return number_verify_signed_short(value); - - case T_SIGNED_LONG: - return number_verify_signed_long(value); - - case T_SIGNED_LONG_LONG: - return number_verify_signed_long_long(value); - - case T_UNSIGNED_SHORT_SHORT: - return (typeid(V) == typeid(unsigned char) || typeid(V) == typeid(unsigned char)); - - case T_UNSIGNED_SHORT: - return number_verify_unsigned_short(value); - - case T_UNSIGNED_LONG: - return number_verify_unsigned_long(value); - - case T_UNSIGNED_LONG_LONG: - return number_verify_unsigned_long_long(value); - - case T_FLOAT: - return (typeid(V) == typeid(float)) || (typeid(V) == typeid(double) || - typeid(V) == typeid(const float)) || (typeid(V) == typeid(const double)); - - case T_CHAR: - return (typeid(V) == typeid(char)) || (typeid(V) == typeid(unsigned char) || - typeid(V) == typeid(const char)) || (typeid(V) == typeid(const unsigned char)); - - case T_POINTER: - case T_STRING: - return false; - - case T_ANYTHING: - return true; - - case T_LITERAL: - return false; + _result = "** INVALID FORMAT: "; + _result += msg; + _result += " **"; } + } - return false; - }; - - void mark_invalid(std::string &); - - bool validity_check(void); - void raise_check(void); - -/* - struct NoArgumentLeft + void raise(void) const { - NoArgumentLeft(): empty(0) {}; - - unsigned int empty; - }; -*/ - - const Argument * next_argument(void); - - void pop_argument(void); - void push_argument(std::string & data, Type type); + if (!_valid) + { + // call specialized class + FormatException< E >::raise(_result); + } + } private: - std::string _format; - - bool _valid; - bool _raise; - - std::string _result; - ArgumentQueue _args; + const std::string _format; + bool _valid; }; -#endif /* _FORMAT_H_ */ +/* useful typedef for general usage (not generating exceptions) */ +typedef FormatBase<> Format; +/* macros used for shortening lines and making the code clearer */ +#define STG(x) (x).str() +#define FMT(x) Format(x) + +#endif /* _FORMAT_H_ */ diff --git a/src/mod/endpoints/mod_khomp/commons/function.hpp b/src/mod/endpoints/mod_khomp/commons/base/function.hpp similarity index 65% rename from src/mod/endpoints/mod_khomp/commons/function.hpp rename to src/mod/endpoints/mod_khomp/commons/base/function.hpp index c448299acd..7470bf245d 100644 --- a/src/mod/endpoints/mod_khomp/commons/function.hpp +++ b/src/mod/endpoints/mod_khomp/commons/base/function.hpp @@ -46,12 +46,13 @@ namespace Function { - struct EmptyFunction {}; + struct EmptyFunction {}; + struct NonMemberFunction {}; /**/ template < typename FunctionTraits > - struct StorageBase: NEW_REFCOUNTER(StorageBase < FunctionTraits >) + struct StorageBase: COUNTER_SUPER(StorageBase < FunctionTraits >) { typedef typename FunctionTraits::BaseType BaseType; @@ -59,27 +60,33 @@ namespace Function typedef typename FunctionTraits::ObjType ObjType; template < typename Functor > - StorageBase(Functor f) - : _object(reinterpret_cast(new Functor(f))), - _function(reinterpret_cast(&(Functor::operator()))), + StorageBase(const Functor f) + : _object(reinterpret_cast< ObjType >(new Functor(f))), + _function(reinterpret_cast< FunType >(&Functor::operator())), _malloced(true) {}; template < typename Functor > StorageBase(Functor & f, bool malloced) - : _object(reinterpret_cast((malloced ? new Functor(f) : &f))), - _function(reinterpret_cast(&(Functor::operator()))), + : _object(reinterpret_cast< ObjType >((malloced ? new Functor(f) : &f))), + _function(reinterpret_cast< FunType >(&Functor::operator())), _malloced(malloced) {}; + StorageBase(FunType const * member) + : _object(reinterpret_cast< ObjType >(0)), + _function(reinterpret_cast< FunType >(member)), + _malloced(false) + {}; + StorageBase() - : _object(reinterpret_cast(0)), - _function(reinterpret_cast(0)), + : _object(reinterpret_cast< ObjType >(0)), + _function(reinterpret_cast< FunType >(0)), _malloced(false) {}; StorageBase(const StorageBase & o) - : INC_REFCOUNTER(o, StorageBase < FunctionTraits >), + : COUNTER_REFER(o, StorageBase < FunctionTraits >), _object(o._object), _function(o._function), _malloced(o._malloced) {}; @@ -95,9 +102,9 @@ namespace Function template < typename Functor > void operator=(Functor f) { - _object = reinterpret_cast(new Functor(f)), - _function = reinterpret_cast(&(Functor::operator())); - _malloced = false; + _object = reinterpret_cast< ObjType >(new Functor(f)), + _function = reinterpret_cast< FunType >(&Functor::operator()); + _malloced = true; } protected: @@ -229,10 +236,15 @@ namespace Function typedef StorageBase < Function0Traits < R > > Storage; template < typename Functor > - Function0(Functor f): Storage(f) {}; + Function0(const Functor f) + : Storage(f) {}; template < typename Functor > - Function0(Functor & f, bool m): Storage(f, m) {}; + Function0(Functor & f, bool m) + : Storage(f, m) {}; + + Function0(const typename Function0Traits < R >::FunType * m) + : Storage(m) {}; Function0() {}; @@ -243,6 +255,18 @@ namespace Function return ((Storage::_object)->*(Storage::_function))(); } + + template < typename Object > + R operator()(Object * object) + { + if (reinterpret_cast(Storage::_function) == 0) + throw EmptyFunction(); + + if (reinterpret_cast(Storage::_object) != 0) + throw NonMemberFunction(); + + return (reinterpret_cast< typename Function0Traits < R >::ObjType *>(object)->*(Storage::_function))(); + } }; template < typename R, typename A0 > @@ -251,10 +275,15 @@ namespace Function typedef StorageBase < Function1Traits < R, A0 > > Storage; template < typename Functor > - Function1(Functor f): Storage(f) {}; + Function1(const Functor f) + : Storage(f) {}; template < typename Functor > - Function1(Functor & f, bool m): Storage(f, m) {}; + Function1(Functor & f, bool m) + : Storage(f, m) {}; + + Function1(const typename Function1Traits < R, A0 >::FunType * m) + : Storage(m) {}; Function1() {}; @@ -265,6 +294,18 @@ namespace Function return ((Storage::_object)->*(Storage::_function))(a0); } + + template < typename Object > + R operator()(Object * object, A0 a0) + { + if (reinterpret_cast(Storage::_function) == 0) + throw EmptyFunction(); + + if (reinterpret_cast(Storage::_object) != 0) + throw NonMemberFunction(); + + return (reinterpret_cast< typename Function1Traits < R, A0 >::ObjType *>(object)->*(Storage::_function))(a0); + } }; template < typename R, typename A0, typename A1 > @@ -273,10 +314,15 @@ namespace Function typedef StorageBase < Function2Traits < R, A0, A1 > > Storage; template < typename Functor > - Function2(Functor f): Storage(f) {}; + Function2(const Functor f) + : Storage(f) {}; template < typename Functor > - Function2(Functor & f, bool m): Storage(f, m) {}; + Function2(Functor & f, bool m) + : Storage(f, m) {}; + + Function2(const typename Function2Traits < R, A0, A1 >::FunType * m) + : Storage(m) {}; Function2() {}; @@ -287,6 +333,18 @@ namespace Function return ((Storage::_object)->*(Storage::_function))(a0, a1); } + + template < typename Object > + R operator()(Object * object, A0 a0, A1 a1) + { + if (reinterpret_cast(Storage::_function) == 0) + throw EmptyFunction(); + + if (reinterpret_cast(Storage::_object) != 0) + throw NonMemberFunction(); + + return (reinterpret_cast< typename Function2Traits < R, A0, A1 >::ObjType *>(object)->*(Storage::_function))(a0, a1); + } }; template < typename R, typename A0, typename A1, typename A2 > @@ -295,20 +353,37 @@ namespace Function typedef StorageBase < Function3Traits < R, A0, A1, A2 > > Storage; template < typename Functor > - Function3(Functor f): Storage(f) {}; + Function3(const Functor f) + : Storage(f) {}; template < typename Functor > - Function3(Functor & f, bool m): Storage(f, m) {}; + Function3(Functor & f, bool m) + : Storage(f, m) {}; + + Function3(const typename Function3Traits < R, A0, A1, A2 >::FunType * m) + : Storage(m) {}; Function3() {}; R operator()(A0 a0, A1 a1, A2 a2) { - if (reinterpret_cast(Storage::_object) == 0) + if (reinterpret_cast(Storage::_object) == 0) throw EmptyFunction(); return ((Storage::_object)->*(Storage::_function))(a0, a1, a2); } + + template < typename Object > + R operator()(Object * object, A0 a0, A1 a1, A2 a2) + { + if (reinterpret_cast(Storage::_function) == 0) + throw EmptyFunction(); + + if (reinterpret_cast(Storage::_object) != 0) + throw NonMemberFunction(); + + return (reinterpret_cast< typename Function3Traits < R, A0, A1, A2 >::ObjType *>(object)->*(Storage::_function))(a0, a1, a2); + } }; template < typename R, typename A0, typename A1, typename A2, typename A3 > @@ -317,10 +392,15 @@ namespace Function typedef StorageBase < Function4Traits < R, A0, A1, A2, A3 > > Storage; template < typename Functor > - Function4(Functor f): Storage(f) {}; + Function4(const Functor f) + : Storage(f) {}; template < typename Functor > - Function4(Functor & f, bool m): Storage(f, m) {}; + Function4(Functor & f, bool m) + : Storage(f, m) {}; + + Function4(const typename Function4Traits < R, A0, A1, A2, A3 >::FunType * m) + : Storage(m) {}; Function4() {}; @@ -331,6 +411,18 @@ namespace Function return ((Storage::_object)->*(Storage::_function))(a0, a1, a2, a3); } + + template < typename Object > + R operator()(Object * object, A0 a0, A1 a1, A2 a2, A3 a3) + { + if (reinterpret_cast(Storage::_function) == 0) + throw EmptyFunction(); + + if (reinterpret_cast(Storage::_object) != 0) + throw NonMemberFunction(); + + return (reinterpret_cast< typename Function4Traits < R, A0, A1, A2, A3 >::ObjType *>(object)->*(Storage::_function))(a0, a1, a2, a3); + } }; }; diff --git a/src/mod/endpoints/mod_khomp/commons/initializer.hpp b/src/mod/endpoints/mod_khomp/commons/base/initializer.hpp similarity index 86% rename from src/mod/endpoints/mod_khomp/commons/initializer.hpp rename to src/mod/endpoints/mod_khomp/commons/base/initializer.hpp index e0e110d49c..16359e8c97 100644 --- a/src/mod/endpoints/mod_khomp/commons/initializer.hpp +++ b/src/mod/endpoints/mod_khomp/commons/base/initializer.hpp @@ -47,32 +47,32 @@ template < typename Type > struct Initializer: public std::vector< Type > { - typedef std::vector< Type > super; + typedef std::vector< Type > Super; - Initializer(Type e) { push_back(e); }; - Initializer(Type & e) { push_back(e); }; + Initializer(Type e) { Super::push_back(e); }; + Initializer(Type & e) { Super::push_back(e); }; - Initializer & operator&(Initializer v) + Initializer & operator&(const Initializer v) { - insert(super::end(), v.begin(), v.end()); + Super::insert(Super::end(), v.begin(), v.end()); return *this; }; Initializer & operator&(Initializer & v) { - insert(super::end(), v.begin(), v.end()); + Super::insert(Super::end(), v.begin(), v.end()); return *this; }; Initializer & operator&(Type v) { - insert(super::end(), v); + Super::insert(Super::end(), v); return *this; }; Initializer & operator&(Type & v) { - insert(super::end(), v); + Super::insert(Super::end(), v); return *this; }; }; diff --git a/src/mod/endpoints/mod_khomp/commons/k3lapi.cpp b/src/mod/endpoints/mod_khomp/commons/base/k3lapi.cpp similarity index 77% rename from src/mod/endpoints/mod_khomp/commons/k3lapi.cpp rename to src/mod/endpoints/mod_khomp/commons/base/k3lapi.cpp index f5afa1348f..09f5c81c0e 100644 --- a/src/mod/endpoints/mod_khomp/commons/k3lapi.cpp +++ b/src/mod/endpoints/mod_khomp/commons/base/k3lapi.cpp @@ -41,18 +41,16 @@ #include -#include -#include +#include -K3LAPI::K3LAPI(bool has_exceptions) -: _has_exceptions(has_exceptions), - _device_count(0), _channel_count(0), _link_count(0), +K3LAPIBase::K3LAPIBase() +: _device_count(0), _channel_count(0), _link_count(0), _device_config(0), _channel_config(0), _link_config(0) {}; /* initialize the whole thing! */ -void K3LAPI::start(void) +void K3LAPIBase::start(void) { /* tie the used k3l to the compiled k3l version */ char *ret = k3lStart(k3lApiMajorVersion, k3lApiMinorVersion, 0); //k3lApiBuildVersion); @@ -64,7 +62,7 @@ void K3LAPI::start(void) init(); } -void K3LAPI::stop(void) +void K3LAPIBase::stop(void) { k3lStop(); fini(); @@ -72,7 +70,7 @@ void K3LAPI::stop(void) /* envio de comandos para placa */ -void K3LAPI::mixer(int32 dev, int32 obj, byte track, KMixerSource src, int32 index) +void K3LAPIBase::mixer(int32 dev, int32 obj, byte track, KMixerSource src, int32 index) const { KMixerCommand mix; @@ -83,7 +81,7 @@ void K3LAPI::mixer(int32 dev, int32 obj, byte track, KMixerSource src, int32 ind command(dev, obj, CM_MIXER, (const char *) &mix); } -void K3LAPI::mixerRecord(int32 dev, int32 obj, byte track, KMixerSource src, int32 index) +void K3LAPIBase::mixerRecord(int32 dev, KDeviceType type, int32 obj, byte track, KMixerSource src, int32 index) const { /* estes buffers *NAO PODEM SER ESTATICOS*! */ char cmd[] = { 0x3f, 0x03, (char)obj, (char)track, 0xff, 0xff }; @@ -131,12 +129,12 @@ void K3LAPI::mixerRecord(int32 dev, int32 obj, byte track, KMixerSource src, int break; } - int32 dsp = get_dsp(dev, DSP_AUDIO); + int32 dsp = get_dsp(type, DSP_AUDIO); raw_command(dev, dsp, cmd, sizeof(cmd)); } -void K3LAPI::mixerCTbus(int32 dev, int32 obj, byte track, KMixerSource src, int32 index) +void K3LAPIBase::mixerCTbus(int32 dev, int32 obj, byte track, KMixerSource src, int32 index) const { KMixerCommand mix; @@ -147,12 +145,12 @@ void K3LAPI::mixerCTbus(int32 dev, int32 obj, byte track, KMixerSource src, int3 command(dev, obj, CM_MIXER_CTBUS, (const char *) &mix); } -void K3LAPI::command(int32 dev, int32 obj, int32 code, std::string & str) +void K3LAPIBase::command(int32 dev, int32 obj, int32 code, std::string & str) const { command(dev, obj, code, str.c_str()); } -void K3LAPI::command (int32 dev, int32 obj, int32 code, const char * parms) +void K3LAPIBase::command (int32 dev, int32 obj, int32 code, const char * parms) const { K3L_COMMAND cmd; @@ -166,12 +164,12 @@ void K3LAPI::command (int32 dev, int32 obj, int32 code, const char * parms) throw failed_command(code, dev, obj, rc); } -void K3LAPI::raw_command(int32 dev, int32 dsp, std::string & str) +void K3LAPIBase::raw_command(int32 dev, int32 dsp, std::string & str) const { raw_command(dev, dsp, str.data(), str.size()); } -void K3LAPI::raw_command(int32 dev, int32 dsp, const char * cmds, int32 size) +void K3LAPIBase::raw_command(int32 dev, int32 dsp, const char * cmds, int32 size) const { std::string str(cmds, size); @@ -181,7 +179,7 @@ void K3LAPI::raw_command(int32 dev, int32 dsp, const char * cmds, int32 size) throw failed_raw_command(dev, dsp, rc); } -KLibraryStatus K3LAPI::get_param(K3L_EVENT *ev, const char *name, std::string &res) +KLibraryStatus K3LAPIBase::get_param(K3L_EVENT *ev, const char *name, std::string &res) const { char tmp_param[256]; memset((void*)tmp_param, 0, sizeof(tmp_param)); @@ -195,7 +193,7 @@ KLibraryStatus K3LAPI::get_param(K3L_EVENT *ev, const char *name, std::string &r return ksSuccess; } -std::string K3LAPI::get_param(K3L_EVENT *ev, const char *name) +std::string K3LAPIBase::get_param(K3L_EVENT *ev, const char *name) const { std::string res; @@ -207,7 +205,7 @@ std::string K3LAPI::get_param(K3L_EVENT *ev, const char *name) return res; } -void K3LAPI::init(void) +void K3LAPIBase::init(void) { if (_device_count != 0) return; @@ -217,20 +215,16 @@ void K3LAPI::init(void) _device_config = new device_conf_type[_device_count]; _channel_config = new channel_ptr_conf_type[_device_count]; _link_config = new link_ptr_conf_type[_device_count]; - _channel_count = new unsigned int[_device_count]; - _link_count = new unsigned int[_device_count]; + _channel_count = new unsigned int[_device_count]; + _link_count = new unsigned int[_device_count]; for (unsigned int dev = 0; dev < _device_count; dev++) { - KLibraryStatus ret = ksSuccess; - _device_type[dev] = (KDeviceType) k3lGetDeviceType(dev); /* caches each device config */ - ret = (KLibraryStatus)k3lGetDeviceConfig(dev, ksoDevice + dev, &(_device_config[dev]), sizeof(_device_config[dev])); - - if (ret != ksSuccess) - throw start_failed(STG(FMT("k3lGetDeviceConfig(dev=%d): %s") % dev % Verbose::status(ret))); + if (k3lGetDeviceConfig(dev, ksoDevice + dev, &(_device_config[dev]), sizeof(_device_config[dev])) != ksSuccess) + throw start_failed("k3lGetDeviceConfig(device)"); /* adjust channel/link count for device */ _channel_count[dev] = _device_config[dev].ChannelCount; @@ -241,10 +235,9 @@ void K3LAPI::init(void) for (unsigned int obj = 0; obj < _channel_count[dev]; obj++) { - ret = (KLibraryStatus)k3lGetDeviceConfig(dev, ksoChannel + obj, &(_channel_config[dev][obj]), sizeof(_channel_config[dev][obj])); - - if (ret != ksSuccess) - throw start_failed(STG(FMT("k3lGetDeviceConfig(dev=%d,chan=%d): %s") % dev % obj % Verbose::status(ret))); + if (k3lGetDeviceConfig(dev, ksoChannel + obj, &(_channel_config[dev][obj]), + sizeof(_channel_config[dev][obj])) != ksSuccess) + throw start_failed("k3lGetDeviceConfig(channel)"); } /* adjust link count for device */ @@ -255,15 +248,14 @@ void K3LAPI::init(void) for (unsigned int obj = 0; obj < _link_count[dev]; obj++) { - ret = (KLibraryStatus)k3lGetDeviceConfig(dev, ksoLink + obj, &(_link_config[dev][obj]), sizeof(_link_config[dev][obj])); - - if (ret != ksSuccess) - throw start_failed(STG(FMT("k3lGetDeviceConfig(dev=%d,link=%d): %s") % dev % obj % Verbose::status(ret))); + if (k3lGetDeviceConfig(dev, ksoLink + obj, &(_link_config[dev][obj]), + sizeof(_link_config[dev][obj])) != ksSuccess) + throw start_failed("k3lGetDeviceConfig(link)"); } } } -void K3LAPI::fini(void) +void K3LAPIBase::fini(void) { for (unsigned int dev = 0; dev < _device_count; dev++) { @@ -290,9 +282,9 @@ void K3LAPI::fini(void) if (_link_count) { delete[] _link_count; _link_count = NULL; } } -int32 K3LAPI::get_dsp(int32 dev, K3LAPI::DspType type) +int32 K3LAPIBase::get_dsp(KDeviceType devtype, K3LAPI::DspType type) const { - switch (device_type(dev)) + switch (devtype) { case kdtFXO: case kdtFXOVoIP: @@ -311,3 +303,7 @@ int32 K3LAPI::get_dsp(int32 dev, K3LAPI::DspType type) } } +int32 K3LAPIBase::get_dsp(const K3LAPIBase::GenericTarget & tgt, K3LAPI::DspType type) const +{ + return get_dsp(_device_type[tgt.device], type); +} diff --git a/src/mod/endpoints/mod_khomp/commons/k3lapi.hpp b/src/mod/endpoints/mod_khomp/commons/base/k3lapi.hpp similarity index 50% rename from src/mod/endpoints/mod_khomp/commons/k3lapi.hpp rename to src/mod/endpoints/mod_khomp/commons/base/k3lapi.hpp index 596548405b..ef12a3f676 100644 --- a/src/mod/endpoints/mod_khomp/commons/k3lapi.hpp +++ b/src/mod/endpoints/mod_khomp/commons/base/k3lapi.hpp @@ -40,6 +40,9 @@ */ #include +#include + +#include #include @@ -59,15 +62,110 @@ #ifndef _K3LAPI_HPP_ #define _K3LAPI_HPP_ -struct K3LAPI +struct K3LAPITraits { + struct invalid_device; + struct invalid_channel; + struct invalid_link; + + struct invalid_target: public std::runtime_error + { + friend class invalid_device; + friend class invalid_channel; + friend class invalid_link; + + const int32 device, object; + + protected: + invalid_target(int32 _device, int32 _object, const std::string & msg) + : std::runtime_error(msg), device(_device), object(_object) {}; + }; + + struct invalid_device: public invalid_target + { + invalid_device(int32 _device) + : invalid_target(_device, -1, STG(FMT("invalid device number '%d'") % _device)) {}; + }; + + struct invalid_channel: public invalid_target + { + invalid_channel(int32 _device, int32 _channel) + : invalid_target(_device, _channel, STG(FMT("invalid channel number '%d' on device '%d'") % _channel % _device)) {}; + }; + + struct invalid_link: public invalid_target + { + invalid_link(int32 _device, int32 _link) + : invalid_target(_device, _link, STG(FMT("invalid link number '%d' on device '%d'") % _link % _device)) {}; + }; +}; + +struct K3LAPIBase +{ + /* High level checked object identifier. */ + + struct GenericTarget + { + typedef enum { DEVICE, CHANNEL, MIXER, LINK } Type; + + GenericTarget(const K3LAPIBase & k3lapi, Type _type, int32 _device, int32 _object) + : type(_type), device((unsigned int)_device), object((unsigned int)_object) + { + switch (_type) + { + case DEVICE: + if (!k3lapi.valid_device(_device)) + throw K3LAPITraits::invalid_device(_device); + break; + + case CHANNEL: + case MIXER: + if (!k3lapi.valid_channel(_device, _object)) + throw K3LAPITraits::invalid_channel(_device, _object); + break; + + case LINK: + if (!k3lapi.valid_link(_device, _object)) + throw K3LAPITraits::invalid_link(_device, _object); + break; + } + }; + + const Type type; + + const unsigned int device; + const unsigned int object; + }; + +/* + struct LinkTarget : public GenericTarget + { + LinkTarget(const K3LAPIBase & k3lapi, int32 _device, int32 _object) + : GenericTarget(k3lapi, GenericTarget::LINK, _device, _object) {}; + }; + + struct ChannelTarget : public GenericTarget + { + ChannelTarget(const K3LAPIBase & k3lapi, int32 _device, int32 _object) + : GenericTarget(k3lapi, GenericTarget::CHANNEL, _device, _object) {}; + }; + +*/ + template < GenericTarget::Type T > + struct Target: public GenericTarget + { + Target(const K3LAPIBase & k3lapi, int32 _device, int32 _object) + : GenericTarget(k3lapi, T, _device, _object) {}; + +// operator const GenericTarget&() const { return static_cast(*this); }; + }; + /* exceptions */ - struct start_failed + struct start_failed: public std::runtime_error { - start_failed(const char * _msg) : msg(_msg) {}; - start_failed(std::string _msg) : msg(_msg) {}; - std::string msg; + start_failed(const char * msg) + : std::runtime_error(msg) {}; }; struct failed_command @@ -91,30 +189,6 @@ struct K3LAPI int32 rc; }; - struct invalid_device - { - invalid_device(int32 _device) - : device(_device) {}; - - int32 device; - }; - - struct invalid_channel - { - invalid_channel(int32 _device, int32 _channel) - : device(_device), channel(_channel) {}; - - int32 device, channel; - }; - - struct invalid_link - { - invalid_link(unsigned int _device, unsigned int _link) - : device(_device), link(_link) {}; - - int32 device, link; - }; - struct get_param_failed { get_param_failed(std::string _name, int32 _rc) @@ -124,6 +198,8 @@ struct K3LAPI KLibraryStatus rc; }; + /* typedefs essenciais */ + typedef K3L_DEVICE_CONFIG device_conf_type; typedef K3L_CHANNEL_CONFIG channel_conf_type; typedef K3L_CHANNEL_CONFIG * channel_ptr_conf_type; @@ -132,8 +208,8 @@ struct K3LAPI /* constructors/destructors */ - K3LAPI(bool has_exceptions = false); - virtual ~K3LAPI() {}; + K3LAPIBase(); + virtual ~K3LAPIBase() {}; /* (init|final)ialize the whole thing! */ @@ -142,239 +218,106 @@ struct K3LAPI /* verificacao de intervalos */ - inline bool valid_device(int32 dev) + inline bool valid_device(int32 dev) const { return (dev >= 0 && dev < ((int32)_device_count)); } - inline bool valid_channel(int32 dev, int32 obj) + inline bool valid_channel(int32 dev, int32 obj) const { return (valid_device(dev) && obj >= 0 && obj < ((int32)_channel_count[dev])); } - inline bool valid_link(int32 dev, int32 obj) + inline bool valid_link(int32 dev, int32 obj) const { return (valid_device(dev) && obj >= 0 && obj < ((int32)_link_count[dev])); } - /*! - \brief High level object identifier - Since Khomp works with an object concept, this is used to map the - object id with its proper type. - */ - struct target - { - /*! The types a target can have */ - typedef enum { DEVICE, CHANNEL, MIXER, LINK } target_type; - - target(K3LAPI & k3lapi, target_type type_init, int32 device_value, int32 object_value) - : type(type_init), - device((unsigned short)device_value), - object((unsigned short)object_value) - { - switch (type_init) - { - case DEVICE: - if (!k3lapi.valid_device(device_value)) - throw invalid_device(device_value); - break; - - case CHANNEL: - case MIXER: - if (!k3lapi.valid_channel(device_value, object_value)) - throw invalid_channel(device_value, object_value); - break; - - case LINK: - if (!k3lapi.valid_link(device_value, object_value)) - throw invalid_link(device_value, object_value); - break; - } - - }; - - const target_type type; - - const unsigned short device; - const unsigned short object; - }; - /* envio de comandos para placa (geral) */ - void raw_command(int32 dev, int32 dsp, std::string & str); - void raw_command(int32 dev, int32 dsp, const char * cmds, int32 size); + void raw_command(int32 dev, int32 dsp, std::string & str) const; + void raw_command(int32 dev, int32 dsp, const char * cmds, int32 size) const; /* obter dados 'cacheados' (geral) */ - inline unsigned int device_count(void) + inline unsigned int device_count(void) const { return _device_count; } /* envio de comandos para placa (sem identificadores) */ - void mixer(int32 dev, int32 obj, byte track, KMixerSource src, int32 index); - void mixerRecord(int32 dev, int32 obj, byte track, KMixerSource src, int32 index); - void mixerCTbus(int32 dev, int32 obj, byte track, KMixerSource src, int32 index); + void mixer(int32 dev, int32 obj, byte track, KMixerSource src, int32 index) const; + void mixerRecord(int32 dev, KDeviceType type, int32 obj, byte track, KMixerSource src, int32 index) const; + void mixerCTbus(int32 dev, int32 obj, byte track, KMixerSource src, int32 index) const; - void command (int32 dev, int32 obj, int32 code, std::string & str); - void command (int32 dev, int32 obj, int32 code, const char * parms = NULL); + void command (int32 dev, int32 obj, int32 code, std::string & str) const; + void command (int32 dev, int32 obj, int32 code, const char * parms = NULL) const; - /* obter dados 'cacheados' (sem identificadores) */ - - inline unsigned int channel_count(int32 dev) - { - if (!valid_device(dev)) - { - if (_has_exceptions) - throw invalid_device(dev); - else - return 0; - } - - return _channel_count[dev]; - } - - inline unsigned int link_count(int32 dev) - { - if (!valid_device(dev)) - { - if (_has_exceptions) - throw invalid_device(dev); - else - return 0; - } - - return _link_count[dev]; - } - - inline uint32 channel_stats(int32 dev, int32 obj, uint32 index) - { - if (!valid_channel(dev, obj)) - { - if (_has_exceptions) - throw invalid_channel(dev, obj); - else - return 0; - } - - uint32 res_value = (uint32)-1; - stt_code stt_res = ksFail; - -#if K3L_AT_LEAST(2,1,0) - stt_res = k3lGetChannelStats(dev, obj, index, &res_value); -#endif - - if(stt_res != ksSuccess) - { - return (uint32)-1; - } - - return res_value; - } - - KDeviceType device_type(int32 dev) - { - if (!valid_device(dev)) - { - if (_has_exceptions) - throw invalid_device(dev); - else - return kdtDevTypeCount; - } - - return _device_type[dev]; - } - - - K3L_DEVICE_CONFIG & device_config(int32 dev) - { - if (!valid_device(dev)) - throw invalid_device(dev); - - return _device_config[dev]; - } - - K3L_CHANNEL_CONFIG & channel_config(int32 dev, int32 obj) - { - if (!valid_channel(dev, obj)) - throw invalid_channel(dev, obj); - - return _channel_config[dev][obj]; - } - - K3L_LINK_CONFIG & link_config(int32 dev, int32 obj) - { - if (!valid_link(dev, obj)) - throw invalid_channel(dev, obj); - - return _link_config[dev][obj]; - } /* envio de comandos para placa (com identificadores) */ - void mixer(target & tgt, byte track, KMixerSource src, int32 index) + void mixer(const GenericTarget & tgt, byte track, KMixerSource src, int32 index) const { - mixer((int32)tgt.device, (int32)tgt.object, track, src, index); + mixer(tgt.device, tgt.object, track, src, index); } - void mixerRecord(target & tgt, byte track, KMixerSource src, int32 index) + void mixerRecord(const GenericTarget & tgt, byte track, KMixerSource src, int32 index) const { - mixerRecord((int32)tgt.device, (int32)tgt.object, track, src, index); + mixerRecord((int32)tgt.device, _device_type[tgt.device], (int32)tgt.object, track, src, index); } - void mixerCTbus(target & tgt, byte track, KMixerSource src, int32 index) + void mixerCTbus(const GenericTarget & tgt, byte track, KMixerSource src, int32 index) const { mixerCTbus((int32)tgt.device, (int32)tgt.object, track, src, index); } - void command (target & tgt, int32 code, std::string & str) + void command(const GenericTarget & tgt, int32 code, std::string & str) const { command((int32)tgt.device, (int32)tgt.object, code, str); }; - void command (target & tgt, int32 code, const char * parms = NULL) + void command(const GenericTarget & tgt, int32 code, const char * parms = NULL) const { command((int32)tgt.device, (int32)tgt.object, code, parms); }; /* obter dados 'cacheados' (com indentificadores) */ - inline unsigned int channel_count(target & tgt) + inline unsigned int channel_count(const GenericTarget & tgt) const { return _channel_count[tgt.device]; } - inline unsigned int link_count(target & tgt) + inline unsigned int link_count(const GenericTarget & tgt) const { return _link_count[tgt.device]; } - KDeviceType device_type(target & tgt) + KDeviceType device_type(const GenericTarget & tgt) const { return _device_type[tgt.device]; } - - K3L_DEVICE_CONFIG & device_config(target & tgt) + const K3L_DEVICE_CONFIG & device_config(const GenericTarget & tgt) const { return _device_config[tgt.device]; } - K3L_CHANNEL_CONFIG & channel_config(target & tgt) + const K3L_CHANNEL_CONFIG & channel_config(const Target & tgt) const { return _channel_config[tgt.device][tgt.object]; } - K3L_LINK_CONFIG & link_config(target & tgt) + const K3L_LINK_CONFIG & link_config(const Target & tgt) const { return _link_config[tgt.device][tgt.object]; } /* pega valores em strings de eventos */ - KLibraryStatus get_param(K3L_EVENT *ev, const char *name, std::string &res); - std::string get_param(K3L_EVENT *ev, const char *name); + KLibraryStatus get_param(K3L_EVENT *ev, const char *name, std::string &res) const; + std::string get_param(K3L_EVENT *ev, const char *name) const; /* inicializa valores em cache */ @@ -389,12 +332,12 @@ struct K3LAPI DSP_SIGNALING, }; - int32 get_dsp(int32, DspType); + int32 get_dsp(KDeviceType, DspType) const; + + int32 get_dsp(const GenericTarget &, DspType) const; protected: - const bool _has_exceptions; - unsigned int _device_count; unsigned int * _channel_count; unsigned int * _link_count; @@ -405,4 +348,145 @@ struct K3LAPI KDeviceType * _device_type; }; +/* exceptions */ +template < bool E = false > +struct K3LAPIException +{ + void invalid_device(const int32 device) const + { + /* NOTHING */ + } + + void invalid_channel(const int32 device, const int32 channel) const + { + /* NOTHING */ + } + + void invalid_link(const int32 device, const int32 link) const + { + /* NOTHING */ + } +}; + +template < > +struct K3LAPIException < true > +{ + void invalid_device(const int32 device) const + { + throw K3LAPITraits::invalid_device(device); + } + + void invalid_channel(const int32 device, const int32 channel) const + { + throw K3LAPITraits::invalid_channel(device, channel); + } + + void invalid_link(const int32 device, const int32 link) const + { + throw K3LAPITraits::invalid_link(device, link); + } +}; + +template < bool E = false > +struct K3LAPITemplate: public K3LAPIBase, protected K3LAPIException < E > +{ + using K3LAPIBase::device_config; + using K3LAPIBase::channel_config; + using K3LAPIBase::link_config; + + using K3LAPIBase::device_type; + using K3LAPIBase::get_dsp; + + using K3LAPIBase::mixerRecord; + + /* obter dados 'cacheados' (sem identificadores) */ + + inline unsigned int channel_count(int32 dev) const + { + if (!valid_device(dev)) + { + K3LAPIException< E >::invalid_device(dev); + return 0; + } + + return _channel_count[dev]; + } + + inline unsigned int link_count(int32 dev) const + { + if (!valid_device(dev)) + { + K3LAPIException< E >::invalid_device(dev); + return 0; + } + + return _link_count[dev]; + } + + inline uint32 channel_stats(int32 dev, int32 obj, uint32 index) const + { + if (!valid_channel(dev, obj)) + { + K3LAPIException< E >::invalid_channel(dev, obj); + return 0u; + } + + uint32 res_value = 0u; + +#if K3L_AT_LEAST(2,1,0) + if (k3lGetChannelStats(dev, obj, index, &res_value) != ksSuccess) + return 0u; + + return res_value; +#endif + } + + KDeviceType device_type(int32 dev) const + { + if (!valid_device(dev)) + { + K3LAPIException< E >::invalid_device(dev); + return kdtDevTypeCount; + } + + return _device_type[dev]; + } + + const K3L_DEVICE_CONFIG & device_config(int32 dev) const + { + if (!valid_device(dev)) + throw K3LAPITraits::invalid_device(dev); + + return _device_config[dev]; + } + + const K3L_CHANNEL_CONFIG & channel_config(int32 dev, int32 obj) const + { + if (!valid_channel(dev, obj)) + throw K3LAPITraits::invalid_channel(dev, obj); + + return _channel_config[dev][obj]; + } + + const K3L_LINK_CONFIG & link_config(int32 dev, int32 obj) const + { + if (!valid_link(dev, obj)) + throw K3LAPITraits::invalid_link(dev, obj); + + return _link_config[dev][obj]; + } + + int32 get_dsp(int32 dev, DspType type) const + { + return get_dsp(device_type(dev), type); + } + + void mixerRecord(int32 dev, int32 obj, byte track, KMixerSource src, int32 index) const + { + mixerRecord(dev, device_type(dev), obj, track, src, index); + } +}; + +typedef K3LAPITemplate<> K3LAPI; + #endif /* _K3LAPI_HPP_ */ diff --git a/src/mod/endpoints/mod_khomp/commons/k3lutil.cpp b/src/mod/endpoints/mod_khomp/commons/base/k3lutil.cpp similarity index 83% rename from src/mod/endpoints/mod_khomp/commons/k3lutil.cpp rename to src/mod/endpoints/mod_khomp/commons/base/k3lutil.cpp index 83ac82efae..3fda813a03 100644 --- a/src/mod/endpoints/mod_khomp/commons/k3lutil.cpp +++ b/src/mod/endpoints/mod_khomp/commons/base/k3lutil.cpp @@ -46,7 +46,8 @@ std::string K3LUtil::channelStatus(int32 dev, int32 channel, { try { - K3L_CHANNEL_CONFIG & config = _k3lapi.channel_config(dev, channel); + const K3L_CHANNEL_CONFIG & config = _k3lapi.channel_config(dev, channel); + K3L_CHANNEL_STATUS status; KLibraryStatus ret = (KLibraryStatus) k3lGetDeviceStatus (dev, @@ -60,7 +61,7 @@ std::string K3LUtil::channelStatus(int32 dev, int32 channel, : "Unknown (fail)"); } } - catch(K3LAPI::invalid_channel & e) + catch(K3LAPITraits::invalid_channel & e) { return (fmt == Verbose::EXACT ? "" : "Unknown (fail)"); } @@ -83,64 +84,35 @@ std::string K3LUtil::callStatus(int32 dev, int32 channel, } std::string K3LUtil::linkStatus(int32 dev, int32 link, - Verbose::Presentation fmt, KSignaling sig) + Verbose::Presentation fmt, KSignaling signaling, bool simpleStatus) { try { - if (sig == ksigInactive) + if (signaling == ksigInactive) { - K3L_LINK_CONFIG & config = _k3lapi.link_config(dev, link); - sig = config.Signaling; + const K3L_LINK_CONFIG & config = _k3lapi.link_config(dev, link); + signaling = config.Signaling; } - K3L_LINK_STATUS status; + K3L_LINK_STATUS status; KLibraryStatus ret = (KLibraryStatus) k3lGetDeviceStatus (dev, link + ksoLink, &status, sizeof(status)); switch (ret) { - case ksSuccess: return Verbose::linkStatus(sig, status.E1, fmt); + case ksSuccess: return Verbose::linkStatus(signaling, status.E1, fmt, simpleStatus); default: return (fmt == Verbose::EXACT ? "" : "Unknown (failure)"); } } - catch(K3LAPI::invalid_channel & e) + catch(K3LAPITraits::invalid_channel & e) { return (fmt == Verbose::EXACT ? "" : "Unknown (failure)"); } } -std::string K3LUtil::getLinkStatus(int32 dev, int32 link, - Verbose::Presentation fmt) -{ - switch (_k3lapi.device_type(dev)) - { -#if K3L_AT_LEAST(1,6,0) - case kdtFXS: - case kdtFXSSpx: - return linkStatus(dev, link, fmt, ksigAnalogTerminal); - -#if K3L_AT_LEAST(2,1,0) - case kdtE1FXSSpx: - if (link == 1) - return linkStatus(dev, link, fmt, ksigAnalogTerminal); -#endif -#endif - default: - break; - } - - K3L_LINK_CONFIG & conf = _k3lapi.link_config(dev, link); - - std::string res = linkStatus(dev, link, fmt); - - if (conf.ReceivingClock & 0x01) - res += (fmt == Verbose::EXACT ? ",sync" : " (sync)"); - - return res; -} unsigned int K3LUtil::physicalLinkCount(int32 dev, bool count_virtual) { @@ -199,7 +171,7 @@ unsigned int K3LUtil::physicalLinkCount(int32 dev, bool count_virtual) break; } } - catch(K3LAPI::invalid_device & e) + catch(K3LAPITraits::invalid_device & e) { return 0; } diff --git a/src/mod/endpoints/mod_khomp/commons/k3lutil.hpp b/src/mod/endpoints/mod_khomp/commons/base/k3lutil.hpp similarity index 95% rename from src/mod/endpoints/mod_khomp/commons/k3lutil.hpp rename to src/mod/endpoints/mod_khomp/commons/base/k3lutil.hpp index e547f3df6e..9d87d8b0f6 100644 --- a/src/mod/endpoints/mod_khomp/commons/k3lutil.hpp +++ b/src/mod/endpoints/mod_khomp/commons/base/k3lutil.hpp @@ -64,10 +64,8 @@ struct K3LUtil std::string linkStatus(int32, int32, Verbose::Presentation fmt = Verbose::HUMAN, - KSignaling sig = ksigInactive); - - std::string getLinkStatus(int32, int32, - Verbose::Presentation fmt = Verbose::HUMAN); + KSignaling sig = ksigInactive, + bool simpleStatus = false); unsigned int physicalLinkCount(int32 dev, bool count_virtual = false); diff --git a/src/mod/endpoints/mod_khomp/commons/logger.hpp b/src/mod/endpoints/mod_khomp/commons/base/logger.hpp similarity index 89% rename from src/mod/endpoints/mod_khomp/commons/logger.hpp rename to src/mod/endpoints/mod_khomp/commons/base/logger.hpp index 6fcf7bffe3..6c333e7b87 100644 --- a/src/mod/endpoints/mod_khomp/commons/logger.hpp +++ b/src/mod/endpoints/mod_khomp/commons/base/logger.hpp @@ -55,6 +55,7 @@ #if defined(COMMONS_LIBRARY_USING_ASTERISK) extern "C" { + #include #include } #elif defined(COMMONS_LIBRARY_USING_CALLWEAVER) @@ -443,35 +444,17 @@ struct Logger localtime_r (&tv, <); #endif - out_msg += STG(FMT("[%04d-%02d-%02d %02d:%02d:%02d] ") - % (lt.tm_year + 1900) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour - % lt.tm_min % lt.tm_sec); - -#elif defined(COMMONS_LIBRARY_USING_CALLWEAVER) +#elif defined(COMMONS_LIBRARY_USING_CALLWEAVER) || defined(COMMONS_LIBRARY_USING_FREESWITCH) time_t tv; struct tm lt; time (&tv); localtime_r (&tv, <); - - out_msg += STG(FMT("[%04d-%02d-%02d %02d:%02d:%02d] ") - % (lt.tm_year + 1900) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour - % lt.tm_min % lt.tm_sec); - -#elif defined(COMMONS_LIBRARY_USING_FREESWITCH) - time_t tv; - struct tm lt; - - time (&tv); - - localtime_r (&tv, <); - - out_msg += STG(FMT("[%04d-%02d-%02d %02d:%02d:%02d] ") - % (lt.tm_year + 1900) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour - % lt.tm_min % lt.tm_sec); - #endif + out_msg += STG(FMT("[%02d-%02d-%02d %02d:%02d:%02d] ") + % (lt.tm_year % 100) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour + % lt.tm_min % lt.tm_sec); } if (opt._flags[Option::DATETIMEMS]) @@ -497,16 +480,16 @@ struct Logger #endif #if ASTERISK_AT_LEAST(1,6,0) - out_msg += STG(FMT("[%04d-%02d-%02d %02d:%02d:%02d:%04d] ") - % (lt.tm_year + 1900) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour % lt.tm_min + out_msg += STG(FMT("[%02d-%02d-%02d %02d:%02d:%02d:%04d] ") + % (lt.tm_year % 100) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour % lt.tm_min % lt.tm_sec % (tv.tv_usec / 1000)); #else - out_msg += STG(FMT("[%04d-%02d-%02d %02d:%02d:%02d:%04d] ") - % (lt.tm_year + 1900) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour % lt.tm_min + out_msg += STG(FMT("[%02d-%02d-%02d %02d:%02d:%02d:%04d] ") + % (lt.tm_year % 100) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour % lt.tm_min % lt.tm_sec % (tv * 1000)); #endif -#elif defined(COMMONS_LIBRARY_USING_CALLWEAVER) +#elif defined(COMMONS_LIBRARY_USING_CALLWEAVER) || defined(COMMONS_LIBRARY_USING_FREESWITCH) time_t tv; struct tm lt; @@ -514,22 +497,9 @@ struct Logger localtime_r (&tv, <); - out_msg += STG(FMT("[%04d-%02d-%02d %02d:%02d:%02d:%04d] ") - % (lt.tm_year + 1900) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour % lt.tm_min + out_msg += STG(FMT("[%02d-%02d-%02d %02d:%02d:%02d:%04d] ") + % (lt.tm_year % 100) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour % lt.tm_min % lt.tm_sec % (tv * 1000)); - -#elif defined(COMMONS_LIBRARY_USING_FREESWITCH) - time_t tv; - struct tm lt; - - time (&tv); - - localtime_r (&tv, <); - - out_msg += STG(FMT("[%04d-%02d-%02d %02d:%02d:%02d:%04d] ") - % (lt.tm_year + 1900) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour % lt.tm_min - % lt.tm_sec % (tv * 1000)); - #endif } @@ -538,7 +508,7 @@ struct Logger if (opt._flags[Option::THREADID]) { #if defined (COMMONS_LIBRARY_USING_ASTERISK) || defined(COMMONS_LIBRARY_USING_CALLWEAVER) || defined(COMMONS_LIBRARY_USING_FREESWITCH) - out_msg += STG(FMT("t=%08p ") % ((void*)pthread_self())); + out_msg += STG(FMT("%08x ") % ((unsigned long)pthread_self())); #endif } diff --git a/src/mod/endpoints/mod_khomp/commons/noncopyable.hpp b/src/mod/endpoints/mod_khomp/commons/base/noncopyable.hpp similarity index 100% rename from src/mod/endpoints/mod_khomp/commons/noncopyable.hpp rename to src/mod/endpoints/mod_khomp/commons/base/noncopyable.hpp diff --git a/src/mod/endpoints/mod_khomp/commons/refcounter.hpp b/src/mod/endpoints/mod_khomp/commons/base/refcounter.hpp similarity index 94% rename from src/mod/endpoints/mod_khomp/commons/refcounter.hpp rename to src/mod/endpoints/mod_khomp/commons/base/refcounter.hpp index 6ba8ae8b2f..d1738185bb 100644 --- a/src/mod/endpoints/mod_khomp/commons/refcounter.hpp +++ b/src/mod/endpoints/mod_khomp/commons/base/refcounter.hpp @@ -45,6 +45,11 @@ #ifndef _REFCOUNTER_HPP_ #define _REFCOUNTER_HPP_ +#define COUNTER_CLASS(...) ReferenceCounter< __VA_ARGS__ > +#define COUNTER_SUPER(...) public COUNTER_CLASS( __VA_ARGS__ ) +#define COUNTER_REFER(o, ...) COUNTER_CLASS( __VA_ARGS__ )(static_cast< const COUNTER_CLASS( __VA_ARGS__ ) & >(o)) + +// DEPRECATED DECLARATIONS /// #define NEW_REFCOUNTER(...) public ReferenceCounter< __VA_ARGS__ > #define INC_REFCOUNTER(o, ...) ReferenceCounter< __VA_ARGS__ >(static_cast< const ReferenceCounter < __VA_ARGS__ > & >(o)) @@ -179,13 +184,13 @@ struct ReferenceCounter }; template < typename T > -struct ReferenceContainer: NEW_REFCOUNTER(ReferenceContainer< T >) +struct ReferenceContainer: COUNTER_SUPER(ReferenceContainer< T >) { /* type */ typedef T Type; /* shorthand */ - typedef ReferenceCounter < ReferenceContainer< Type > > Counter; + typedef COUNTER_CLASS(ReferenceContainer< Type >) Counter; // TODO: make this a generic exception someday struct NotFound {}; @@ -249,7 +254,7 @@ struct ReferenceContainer: NEW_REFCOUNTER(ReferenceContainer< T >) }; // return value (pointer)! - Type * operator()(void) + Type * operator()(void) const { return _reference_value; }; diff --git a/src/mod/endpoints/mod_khomp/commons/regex.cpp b/src/mod/endpoints/mod_khomp/commons/base/regex.cpp similarity index 94% rename from src/mod/endpoints/mod_khomp/commons/regex.cpp rename to src/mod/endpoints/mod_khomp/commons/base/regex.cpp index 61f941c214..d2b8cd0469 100644 --- a/src/mod/endpoints/mod_khomp/commons/regex.cpp +++ b/src/mod/endpoints/mod_khomp/commons/base/regex.cpp @@ -74,7 +74,7 @@ void Regex::Expression::initialize(void) _errorstate = regcomp(&_comp_regex, _expression, _flags); } -std::string Regex::Expression::regerror_as_string(void) +std::string Regex::Expression::regerror_as_string(void) const { unsigned int count = regerror(_errorstate, &_comp_regex, 0, 0) + 1; @@ -95,6 +95,7 @@ void Regex::Match::initialize(void) { _subcounter = (_expression.subcount() + 2); // 0 + N.. + invalid _submatches = new regmatch_t[_subcounter]; + _subcaching = new std::string[_subcounter]; _have_match = (regexec(_expression.repr(), _basestring.c_str(), _subcounter, _submatches, _flags) == 0); } @@ -117,7 +118,7 @@ std::string Regex::Match::replace(Regex::ReplaceMap & map) try { if (_submatches[0].rm_so != 0 && (map.find(0) != map.end())) - return _basestring.replace(_submatches[0].rm_so, _submatches[0].rm_eo - _submatches[0].rm_so, map.find(0)->second); + return buffer.replace(_submatches[0].rm_so, _submatches[0].rm_eo - _submatches[0].rm_so, map.find(0)->second); for (unsigned int n = 1; (_submatches[n].rm_so != -1) && (n < _subcounter); n++) { diff --git a/src/mod/endpoints/mod_khomp/commons/regex.hpp b/src/mod/endpoints/mod_khomp/commons/base/regex.hpp similarity index 78% rename from src/mod/endpoints/mod_khomp/commons/regex.hpp rename to src/mod/endpoints/mod_khomp/commons/base/regex.hpp index daf20147a8..61325238b8 100644 --- a/src/mod/endpoints/mod_khomp/commons/regex.hpp +++ b/src/mod/endpoints/mod_khomp/commons/base/regex.hpp @@ -111,12 +111,12 @@ struct Regex } } - bool valid(void) { return (_errorstate == 0); } + bool valid(void) const { return (_errorstate == 0); } - unsigned int subcount(void) { return _subcounter; } - const regex_t * repr(void) { return &_comp_regex; } + unsigned int subcount(void) const { return _subcounter; } + const regex_t * repr(void) const { return &_comp_regex; } - std::string error(void) + std::string error(void) const { switch (_errorstate) { @@ -127,31 +127,33 @@ struct Regex } private: - void initialize(void); - std::string regerror_as_string(void); + std::string regerror_as_string(void) const; + + private: + void initialize(void); protected: const char * _expression; - bool _alloced; + const bool _alloced; unsigned int _subcounter; int _errorstate; regex_t _comp_regex; - unsigned int _flags; + const unsigned int _flags; }; - struct Match: NEW_REFCOUNTER(Match) + struct Match: COUNTER_SUPER(Match) { - Match(const char * basestring, Expression & expression, unsigned int flags = 0) + Match(const char * basestring, const Expression & expression, unsigned int flags = 0) : _basestring(basestring), _expression(expression), _subcounter(0), _submatches(0), _have_match(false), _flags(flags) { initialize(); } - Match(std::string & basestring, Expression & expression, unsigned int flags = 0) + Match(const std::string & basestring, const Expression & expression, unsigned int flags = 0) : _basestring(basestring), _expression(expression), _subcounter(0), _submatches(0), _have_match(false), _flags(flags) { @@ -159,7 +161,7 @@ struct Regex } Match(const Match & o) - : INC_REFCOUNTER(o, Match), + : COUNTER_REFER(o, Match), _basestring(o._basestring), _expression(o._expression), _subcounter(o._subcounter), _submatches(o._submatches), _have_match(o._have_match), _flags(o._flags) @@ -169,6 +171,10 @@ struct Regex void unreference() { delete[] _submatches; + delete[] _subcaching; + + _submatches = 0; + _subcaching = 0; } bool matched(void) @@ -184,34 +190,23 @@ struct Regex return false; } - std::string submatch(int number) + const std::string & submatch(int number) { if (!matched(number)) - return ""; + return _subcaching[_subcounter - 1 /* invalid, always empty! */ ]; - return _basestring.substr(_submatches[number].rm_so, - _submatches[number].rm_eo - _submatches[number].rm_so); - } - - /** - * \brief gets a map with all matches - * \return std::map with all matches - * \note index 0 in map, is the complete string - * \author Eduardo Nunes Pereira - * - * If fails the empty map is returned - */ - std::map obtain_match_map() - { - int match_counter = 0; - std::map tmp_map; - while(matched(match_counter)) + if (_subcaching[number].empty()) { - tmp_map.insert(std::make_pair(match_counter,submatch(match_counter))); - match_counter++; + _subcaching[number].assign(_basestring, _submatches[number].rm_so, + _submatches[number].rm_eo - _submatches[number].rm_so); } - return tmp_map; + return _subcaching[number]; + } + + const std::string & operator[](int number) + { + return submatch(number); } /** @@ -226,25 +221,21 @@ struct Regex std::string replace(ReplaceMap &); std::string replace(std::string, unsigned int index = REP_BASE); - std::string operator[](int number) - { - return submatch(number); - } - // NOTE: there is already a way to get subcount defined on EXPRESSION class! private: void initialize(void); protected: - std::string _basestring; - Expression & _expression; + const std::string _basestring; + const Expression & _expression; unsigned int _subcounter; regmatch_t * _submatches; - + std::string * _subcaching; bool _have_match; - unsigned int _flags; + + const unsigned int _flags; }; }; diff --git a/src/mod/endpoints/mod_khomp/commons/base/ringbuffer.cpp b/src/mod/endpoints/mod_khomp/commons/base/ringbuffer.cpp new file mode 100644 index 0000000000..42056307e0 --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/base/ringbuffer.cpp @@ -0,0 +1,485 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include + +// #include + + + /* Documentation of the formula used in the buffer arithmetic. + * + * [0|1|2|3|4|5|6|7] => size=8 + * | | + * reader | + * writer + * + * => writer has places [5,6,7,0,1] to write (5 places). + * + * => 8 - (4-2+1) = 8 - (2+1) = 8 - 3 = 5 + * + * > writer goes 1 up, amount goes 1 down. + * > reader goes 1 up, amount goes 1 up. + * > size goes 1 down, amount goes 1 down. + * + */ + +/********** BUFFER FUNCTIONS **********/ + +/* writes everything or nothing */ +bool Ringbuffer_traits::traits_provide(char * buffer, const char * value, unsigned int amount, bool do_not_overwrite) +{ + /* avoid using different values */ + Buffer_table cache = _pointers; + + bool need_overwrite = false; + + if (amount > free_blocks(cache)) + { + if (do_not_overwrite) + return false; + + /* if we are allowed to overwrite, just the buffer size matters for us */ + if (amount >= _size) + return false; + + /* we need to change reader pointer below... */ + need_overwrite = true; + } + + const unsigned int wr = cache.writer.complete; + const unsigned int wp = cache.writer.complete - 1; + + /* should we go around the buffer for writing? */ + if ((wr + amount) > _size) + { +// fprintf(stderr, "%p> first if matched\n", this); + + if (need_overwrite) + { + do + { + Buffer_pointer extra(cache.reader); + extra.complete = ((wr + amount) % _size); // (extra.complete + amount) % _size; +// extra.complete = (extra.complete + amount) % _size; + + if (update(cache.reader, extra)) + break; + } + while (true); + } + + unsigned int wr1 = _size - wr + 1; /* writer is already 1 position after */ + unsigned int wr2 = amount - wr1; + +// fprintf(stderr, "%p> partial write: (%d/%d) %d/%d [%d/%d]\n", this, wr1, wr2, amount, _size, reader, writer); + + /* two partial writes (one at the end, another at the beginning) */ + memcpy((void *) &(buffer[wp]), (const void *) (value), _block * wr1); + memcpy((void *) (buffer), (const void *) &(value[wr1]), _block * wr2); + } + else + { +// fprintf(stderr, "%p> second if matched\n", this); + + if (need_overwrite) + { + do + { + Buffer_pointer extra(cache.reader); + extra.complete = ((wr + amount) % _size); // (extra.complete + amount) % _size; + + if (update(cache.reader, extra)) + break; + } + while (true); + } + +// fprintf(stderr, "%p> full write: a=%d/s=%d [r=%d/w=%d]\n", this, amount, _size, reader, writer); + + /* we are talking about buffers here, man! */ + memcpy((void *) &(buffer[wp]), (const void *) value, _block * amount); + } + + _pointers.writer.complete = ((wp + amount) % _size) + 1; + _pointers.writer.partial = 1; + +// if (need_overwrite) +// fprintf(stdout, "%p> write end: w=%d/r=%d\n", this, _pointers.writer.complete, _pointers.reader.complete); + + return true; +} + +/* returns the number of itens that have been read */ +unsigned int Ringbuffer_traits::traits_consume(const char * buffer, char * value, unsigned int amount, bool atomic_mode) +{ + /* avoid using different values */ + Buffer_table cache = _pointers; + + const unsigned int available = used_blocks(cache); + + if (atomic_mode && amount > available) + return false; + + const unsigned int rd = _pointers.reader.complete; + + unsigned int total = std::min(amount, available); + + /* should we go around the buffer for reading? */ + if ((rd + total) >= _size) + { + unsigned int rd1 = _size - rd; + unsigned int rd2 = total - rd1; + +// fprintf(stderr, "%p> partial read: (%d/%d) %d/%d [%d/%d]\n", this, rd1, rd2, total, _size, reader, writer); + + /* two partial consumes (one at the end, another at the beginning) */ + memcpy((void *) (value), (const void *) &(buffer[rd]), _block * rd1); + memcpy((void *) &(value[rd1]), (const void *) (buffer), _block * rd2); + } + else + { +// fprintf(stderr, "%p> full read: %d/%d [%d/%d]\n", this, total, _size, reader, writer); + + /* we are talking about buffers here, man! */ + memcpy((void *) value, (const void *) &(buffer[rd]), _block * total); + } + + do + { + /* jump the reader forward */ + Buffer_pointer index((cache.reader.complete + total) % _size, 0); + + if (update(cache.reader, index)) + break; + } + while (true); + +// fprintf(stderr, "%p> read end: %d [block=%d]\n", this, reader, _block); + + return total; +} + +/********** TWO-PHASE BUFFER FUNCTIONS ***********/ + +/* returns the number of itens that have been read */ +unsigned int Ringbuffer_traits::traits_consume_begins(const char * buffer, char * value, unsigned int amount, bool atomic_mode) +{ + /* avoid using different values */ + Buffer_table cache = _pointers; + + const unsigned int available = used_blocks(cache); + + if (amount > available) + { + if (atomic_mode) + return false; + } + + const unsigned int rd = _pointers.reader.complete; + + unsigned int total = std::min(amount, available); + + /* should we go around the buffer for reading? */ + if ((rd + total) >= _size) + { + unsigned int rd1 = _size - rd; + unsigned int rd2 = total - rd1; + +// fprintf(stderr, "%p> partial read: (%d/%d) %d/%d [%d/%d]\n", this, rd1, rd2, total, _size, reader, writer); + + /* two partial consumes (one at the end, another at the beginning) */ + memcpy((void *) (value), (const void *) &(buffer[rd]), _block * rd1); + memcpy((void *) &(value[rd1]), (const void *) (buffer), _block * rd2); + } + else + { +// fprintf(stderr, "%p> full read: %d/%d [%d/%d]\n", this, total, _size, reader, writer); + + /* we are talking about buffers here, man! */ + memcpy((void *) value, (const void *) &(buffer[rd]), _block * total); + } + + return total; +} + +bool Ringbuffer_traits::traits_consume_commit(unsigned int amount) +{ + if (amount == 0) + return true; + + /* avoid using different values */ + Buffer_table cache = _pointers; + + const unsigned int available = used_blocks(cache); + + /* cannot commit more than available! */ + if (amount > available) + return false; + + unsigned int total = std::min(amount, available); + + do + { + /* jump the reader forward */ + Buffer_pointer index((cache.reader.complete + total) % _size, 0); + + if (update(cache.reader, index)) + break; + } + while (true); + +// fprintf(stderr, "%p> read end: %d [block=%d]\n", this, reader, _block); + + return true; +} + +/********** PARTIAL BUFFER FUNCTIONS (bytes) ***********/ + +/* writes everything or nothing */ +bool Ringbuffer_traits::traits_provide_partial(char * buffer, const char * value, unsigned int amount) +{ + /* avoid using different values */ + Buffer_table cache = _pointers; + + const unsigned int memsize = (_size * _block); + + if (amount > (free_blocks(cache) * _block)) + return false; + + const unsigned int wr = ((cache.writer.complete - 1) * _block) + cache.writer.partial; + const unsigned int wp = wr - 1; + + /* should we go around the buffer for writing? */ + if ((wr + amount) > memsize) + { +// fprintf(stderr, "%p> first if matched\n", this); + + unsigned int wr1 = memsize - wr + 1; /* writer is already 1 position after */ + unsigned int wr2 = amount - wr1; + +// fprintf(stderr, "%p> partial write: (%d/%d) %d/%d [%d/%d]\n", this, wr1, wr2, amount, _size, reader, writer); + + /* two partial writes (one at the end, another at the beginning) */ + memcpy((void *) &(buffer[wp]), (const void *) (value), wr1); + memcpy((void *) (buffer), (const void *) &(value[wr1]), wr2); + } + else + { +// fprintf(stderr, "%p> second if matched\n", this); + +// fprintf(stderr, "%p> full write: a=%d/s=%d [r=%d/w=%d]\n", this, amount, _size, reader, writer); + + /* we are talking about buffers here, man! */ + memcpy((void *) &(buffer[wp]), (const void *) value, amount); + } + + const unsigned int new_wp = (wp + amount) % memsize; + + _pointers.writer.complete = (unsigned int)(floor((double)new_wp / (double)_block) + 1); + _pointers.writer.partial = (new_wp % _block) + 1; + +// if (need_overwrite) +// fprintf(stdout, "%p> write end: w=%d/r=%d\n", this, _pointers.writer.complete, _pointers.reader.complete); + + return true; +} + +/* returns the number of bytes that have been read */ +unsigned int Ringbuffer_traits::traits_consume_partial(const char * buffer, char * value, unsigned int amount) +{ + /* avoid using different values */ + Buffer_table cache = _pointers; + + const unsigned int available = used_blocks(cache) * _block; + + const unsigned int rd = (_pointers.reader.complete * _block) + _pointers.reader.partial; + + const unsigned int memsize = _size * _block; + + unsigned int total = std::min(amount, available); + + /* should we go around the buffer for reading? */ + if ((rd + total) >= _size) + { + unsigned int rd1 = memsize - rd; + unsigned int rd2 = total - rd1; + +// fprintf(stderr, "%p> partial read: (%d/%d) %d/%d [%d/%d]\n", this, rd1, rd2, total, _size, reader, writer); + + /* two partial consumes (one at the end, another at the beginning) */ + memcpy((void *) (value), (const void *) &(buffer[rd]), rd1); + memcpy((void *) &(value[rd1]), (const void *) (buffer), rd2); + } + else + { +// fprintf(stderr, "%p> full read: %d/%d [%d/%d]\n", this, total, _size, reader, writer); + + /* we are talking about buffers here, man! */ + memcpy((void *) value, (const void *) &(buffer[rd]), total); + } + + do + { + const unsigned int new_rd = (((cache.reader.complete * _block) + cache.reader.partial) + total) % memsize; + + /* jump the reader forward */ + Buffer_pointer index((unsigned int)floor((double)new_rd / (double)_block), (unsigned short)(new_rd % _block)); + + if (update(cache.reader, index)) + break; + } + while (true); + +// fprintf(stderr, "%p> read end: %d [block=%d]\n", this, reader, _block); + + return total; +} + +/********** IO FUNCTIONS **********/ + +/* returns the number of items written to from buffer to stream */ +unsigned int Ringbuffer_traits::traits_put(const char * buffer, std::ostream &fd, unsigned int amount) +{ + /* avoid using different values */ + Buffer_table cache = _pointers; + + const unsigned int available = used_blocks(cache); + + if (amount > available) + return false; + + const unsigned int wr = _pointers.writer.complete; + const unsigned int rd = _pointers.reader.complete; + + unsigned int total = std::min(amount, available); + + /* should we go around the buffer for reading? */ + if ((rd + total) >= _size) + { + unsigned int rd1 = _size - rd; + unsigned int rd2 = total - rd1; + +// fprintf(stderr, "%p> partial read: (%d/%d) %d/%d [%d/%d]\n", this, rd1, rd2, total, _size, reader, writer); + + /* two partial consumes (one at the end, another at the beginning) */ + fd.write((const char *) &(buffer[rd]), _block * rd1); + fd.write((const char *) (buffer), _block * rd2); + } + else + { +// fprintf(stderr, "%p> full read: %d/%d [%d/%d]\n", this, total, _size, reader, writer); + fd.write((const char *) &(buffer[rd]), _block * total); + } + + do + { + /* jump the reader forward */ + Buffer_pointer index((cache.reader.complete + total) % _size, 0); + + if (update(cache.reader, index)) + break; + } + while (true); + +// fprintf(stderr, "%p> read end: %d [block=%d]\n", this, reader, _block); + + return total; +} + +/* returns number of items read from stream to buffer */ +unsigned int Ringbuffer_traits::traits_get(char * buffer, std::istream &fd, unsigned int amount) +{ + /* avoid using different values */ + Buffer_table cache = _pointers; + + if (amount > free_blocks(cache)) + return false; + + const unsigned int wr = cache.writer.complete; + const unsigned int wp = cache.writer.complete - 1; + + unsigned int real_amount = 0; + + /* should we go around the buffer for writing? */ + if ((wr + amount) > _size) + { +// fprintf(stderr, "%p> first if matched\n", this); + + unsigned int wr1 = _size - wr + 1; /* writer is already 1 position after */ + unsigned int wr2 = amount - wr1; + +// fprintf(stderr, "%p> partial write: (%d/%d) %d/%d [%d/%d]\n", this, wr1, wr2, amount, _size, reader, writer); + + /* two partial writes (one at the end, another at the beginning) */ + unsigned int char_amount = 0; + + /* one partial write on the buffer (at the end) */ + fd.read((char *) &(buffer[wp]), _block * wr1); + char_amount += fd.gcount(); + + if (fd.gcount() == (int)(_block * wr1)) + { + /* another partial write on the buffer (at the beginning) */ + fd.read((char *) (buffer), _block * wr2); + char_amount += fd.gcount(); + } + + real_amount = char_amount / _block; + } + else + { +// fprintf(stderr, "%p> second if matched\n", this); + +// fprintf(stderr, "%p> full write: a=%d/s=%d [r=%d/w=%d]\n", this, amount, _size, reader, writer); + + /* we are talking about buffers here, man! */ + fd.read((char *) &(buffer[wp]), _block * amount); + + real_amount = fd.gcount() / _block; + } + + _pointers.writer.complete = ((wp + amount) % _size) + 1; + _pointers.writer.partial = 1; + +// fprintf(stdout, "%p> write end: %d\n", this, _pointers.writer.complete); + + return real_amount; +} diff --git a/src/mod/endpoints/mod_khomp/commons/ringbuffer.hpp b/src/mod/endpoints/mod_khomp/commons/base/ringbuffer.hpp similarity index 88% rename from src/mod/endpoints/mod_khomp/commons/ringbuffer.hpp rename to src/mod/endpoints/mod_khomp/commons/base/ringbuffer.hpp index 39f8ffe8fb..b9ecd7e6bd 100644 --- a/src/mod/endpoints/mod_khomp/commons/ringbuffer.hpp +++ b/src/mod/endpoints/mod_khomp/commons/base/ringbuffer.hpp @@ -46,6 +46,12 @@ Also, it works only for single-reader + single-writer, since it does not depends on external mutex functions. + + NOTE: for single element provide/consume, this abstraction has standard C++ semantics. + + for multiple and partial element provide/consume, memcpy is used - thus complex C++ + objects which need correct copy constructor semantics should not copied this way. + */ #include @@ -61,7 +67,7 @@ struct Buffer_pointer { - Buffer_pointer(unsigned int _complete = 0u, unsigned short _partial = 0u) + Buffer_pointer(unsigned int _complete, unsigned short _partial) : complete(_complete), partial(_partial) {}; @@ -134,6 +140,10 @@ __attribute__((packed)); struct Ringbuffer_traits { + struct BufferFull {}; + struct BufferEmpty {}; + + protected: Ringbuffer_traits(unsigned int block, unsigned int size) : _block(block), _size(size) {}; @@ -155,6 +165,28 @@ struct Ringbuffer_traits return Atomic::doCAS(&(_pointers.reader), &cache, update); } + inline unsigned int free_blocks(const Buffer_table & cache) const + { + const unsigned int r = cache.reader.complete; + const unsigned int w = cache.writer.complete; + + if (r >= w) + return (r - w); + + return _size - (w - r); + } + + inline unsigned int used_blocks(const Buffer_table & cache) const + { + const unsigned int r = cache.reader.complete; + const unsigned int w = cache.writer.complete; + + if (r >= w) + return (_size - (r - w)) - 1; + + return (w - r) - 1; + } + protected: const unsigned int _block; const unsigned int _size; @@ -163,11 +195,8 @@ struct Ringbuffer_traits }; template -struct Ringbuffer: protected Ringbuffer_traits, public NonCopyable +struct Ringbuffer: public Ringbuffer_traits, public NonCopyable { - struct BufferFull {}; - struct BufferEmpty {}; - Ringbuffer(unsigned int size) : Ringbuffer_traits(sizeof(T), size) { @@ -189,15 +218,17 @@ struct Ringbuffer: protected Ringbuffer_traits, public NonCopyable } /***** GENERIC RANGE/INDEX CALCULATION FUNCTIONS *****/ - bool may_write(Buffer_table & cache) + + protected: + inline bool may_write(const Buffer_table & cache) const { const unsigned int r = cache.reader.complete; const unsigned int w = cache.writer.complete; - return (((r - w) != 1) && (!(r == 0 && w == _size))); + return (((r - w) != 0) && (!(r == 0 && w == _size))); } - bool may_read(Buffer_table & cache) + inline bool may_read(const Buffer_table & cache) const { if ((cache.writer.complete - cache.reader.complete) == 1) return false; @@ -205,7 +236,7 @@ struct Ringbuffer: protected Ringbuffer_traits, public NonCopyable return true; } - unsigned int writer_next(Buffer_pointer & cache, Buffer_pointer & index) + inline unsigned int writer_next(const Buffer_pointer & cache, Buffer_pointer & index) const { unsigned int dest = cache.complete - 1, temp = cache.complete + 1; @@ -218,7 +249,7 @@ struct Ringbuffer: protected Ringbuffer_traits, public NonCopyable return dest; }; - void reader_next(Buffer_pointer & cache, Buffer_pointer & index) + inline void reader_next(const Buffer_pointer & cache, Buffer_pointer & index) const { unsigned int temp = cache.complete + 1; @@ -230,6 +261,7 @@ struct Ringbuffer: protected Ringbuffer_traits, public NonCopyable /***** BUFFER FUNCTIONS *****/ + public: bool provide(const T & value) { Buffer_table cache = _pointers; @@ -280,9 +312,9 @@ struct Ringbuffer: protected Ringbuffer_traits, public NonCopyable } /* writes everything or nothing */ - inline bool provide(const T * value, unsigned int amount, bool skip_overwrite = true) + inline bool provide(const T * value, unsigned int amount, bool do_not_overwrite = true) { - return traits_provide((char *)_buffer, (const char *) value, amount, skip_overwrite); + return traits_provide((char *)_buffer, (const char *) value, amount, do_not_overwrite); } /* returns the number of items that have been read (atomic_mode == true means 'all or nothing') */ @@ -337,7 +369,7 @@ struct Ringbuffer: protected Ringbuffer_traits, public NonCopyable // fprintf(stderr, "%p> write: %d/%d [%d/%d]\n", this, _pointers.reader, _pointers.writer, _pointers.reader_partial, _pointers.writer_partial); } - T & consumer_start(void) + const T & consumer_start(void) { Buffer_table cache = _pointers; @@ -391,13 +423,13 @@ struct Ringbuffer: protected Ringbuffer_traits, public NonCopyable /* returns the number of items written to from buffer to stream */ inline unsigned int put(std::ostream &fd, unsigned int amount) { - return traits_put((char *)_buffer, fd, amount); + return traits_put((const char *)_buffer, fd, amount); } /* returns number of items read from stream to buffer */ inline unsigned int get(std::istream &fd, unsigned int amount) { - return traits_get((const char *)_buffer, fd, amount); + return traits_get((char *)_buffer, fd, amount); } void clear() diff --git a/src/mod/endpoints/mod_khomp/commons/saved_condition.cpp b/src/mod/endpoints/mod_khomp/commons/base/saved_condition.cpp similarity index 100% rename from src/mod/endpoints/mod_khomp/commons/saved_condition.cpp rename to src/mod/endpoints/mod_khomp/commons/base/saved_condition.cpp diff --git a/src/mod/endpoints/mod_khomp/commons/saved_condition.hpp b/src/mod/endpoints/mod_khomp/commons/base/saved_condition.hpp similarity index 100% rename from src/mod/endpoints/mod_khomp/commons/saved_condition.hpp rename to src/mod/endpoints/mod_khomp/commons/base/saved_condition.hpp diff --git a/src/mod/endpoints/mod_khomp/commons/scoped_lock.hpp b/src/mod/endpoints/mod_khomp/commons/base/scoped_lock.hpp similarity index 100% rename from src/mod/endpoints/mod_khomp/commons/scoped_lock.hpp rename to src/mod/endpoints/mod_khomp/commons/base/scoped_lock.hpp diff --git a/src/mod/endpoints/mod_khomp/commons/simple_lock.hpp b/src/mod/endpoints/mod_khomp/commons/base/simple_lock.hpp similarity index 96% rename from src/mod/endpoints/mod_khomp/commons/simple_lock.hpp rename to src/mod/endpoints/mod_khomp/commons/base/simple_lock.hpp index 4f6619f456..8f22fe6bdb 100644 --- a/src/mod/endpoints/mod_khomp/commons/simple_lock.hpp +++ b/src/mod/endpoints/mod_khomp/commons/base/simple_lock.hpp @@ -55,7 +55,7 @@ * implement the "unreference()" method for releasing resources. */ template < typename Implementor > -struct SimpleLockCommon: NEW_REFCOUNTER( SimpleLockCommon < Implementor > ) +struct SimpleLockCommon: COUNTER_SUPER( SimpleLockCommon < Implementor > ) { friend class ReferenceCounter < SimpleLockCommon < Implementor > >; @@ -71,7 +71,7 @@ struct SimpleLockCommon: NEW_REFCOUNTER( SimpleLockCommon < Implementor > ) {}; SimpleLockCommon(const SimpleLockCommon & o) - : INC_REFCOUNTER(o, SimpleLockCommon) + : COUNTER_REFER(o, SimpleLockCommon) {}; virtual ~SimpleLockCommon() diff --git a/src/mod/endpoints/mod_khomp/commons/strings.cpp b/src/mod/endpoints/mod_khomp/commons/base/strings.cpp similarity index 87% rename from src/mod/endpoints/mod_khomp/commons/strings.cpp rename to src/mod/endpoints/mod_khomp/commons/base/strings.cpp index 5e1cbc7004..b7b84025a8 100644 --- a/src/mod/endpoints/mod_khomp/commons/strings.cpp +++ b/src/mod/endpoints/mod_khomp/commons/base/strings.cpp @@ -141,6 +141,38 @@ unsigned int Strings::tokenize(const std::string & str, Strings::vector_type & t return (cur_token - 1); } +long Strings::tolong(const std::string & str, int base) +{ + return tolong(str.c_str(), base); +} + +unsigned long Strings::toulong(const std::string & str, int base) +{ + return toulong(str.c_str(), base); +} + +unsigned long long Strings::toulonglong(const std::string & str, int base) +{ + return toulonglong(str.c_str(), base); +} + +double Strings::todouble(const std::string & str) +{ + return todouble(str.c_str()); +} + +long Strings::tolong(const char * str, int base) +{ + char *str_end = 0; + + unsigned long value = strtol(str, &str_end, base); + + if (str_end && *str_end == 0) + return value; + + throw invalid_value(str); +} + bool Strings::toboolean(std::string str) { std::string tmp(str); @@ -153,11 +185,11 @@ bool Strings::toboolean(std::string str) throw invalid_value(str); } -long Strings::tolong(std::string str, int base) +unsigned long Strings::toulong(const char * str, int base) { char *str_end = 0; - unsigned long value = strtol(str.c_str(), &str_end, base); + unsigned long value = strtoul(str, &str_end, base); if (str_end && *str_end == 0) return value; @@ -165,26 +197,14 @@ long Strings::tolong(std::string str, int base) throw invalid_value(str); } -unsigned long Strings::toulong(std::string str, int base) -{ - char *str_end = 0; - - unsigned long value = strtoul(str.c_str(), &str_end, base); - - if (str_end && *str_end == 0) - return value; - - throw invalid_value(str); -} - -unsigned long long Strings::toulonglong(std::string str, int base) +unsigned long long Strings::toulonglong(const char * str, int base) { #if defined(_WINDOWS) || defined(_Windows) || defined(_WIN32) || defined(WIN32) throw not_implemented(); #else char *str_end = 0; - unsigned long long value = strtoull(str.c_str(), &str_end, base); + unsigned long long value = strtoull(str, &str_end, base); if (str_end && *str_end == 0) return value; @@ -193,11 +213,11 @@ unsigned long long Strings::toulonglong(std::string str, int base) #endif } -double Strings::todouble(std::string str) +double Strings::todouble(const char * str) { char *str_end = 0; - double value = strtod(str.c_str(), &str_end); + double value = strtod(str, &str_end); if (str_end && *str_end == 0) return value; diff --git a/src/mod/endpoints/mod_khomp/commons/strings.hpp b/src/mod/endpoints/mod_khomp/commons/base/strings.hpp similarity index 81% rename from src/mod/endpoints/mod_khomp/commons/strings.hpp rename to src/mod/endpoints/mod_khomp/commons/base/strings.hpp index 056b9335c6..947da384d9 100644 --- a/src/mod/endpoints/mod_khomp/commons/strings.hpp +++ b/src/mod/endpoints/mod_khomp/commons/base/strings.hpp @@ -68,6 +68,8 @@ struct Strings bool empty() { return _list.empty(); }; + const list_type & list() { return _list; }; + protected: list_type _list; }; @@ -75,8 +77,8 @@ struct Strings public: struct invalid_value { - invalid_value(const char * value): _value(value) {}; - invalid_value(std::string value): _value(value) {}; + invalid_value(const char * value): _value(value) {}; + invalid_value(const std::string & value): _value(value) {}; std::string & value() { return _value; } @@ -92,10 +94,15 @@ struct Strings static bool toboolean(std::string); static std::string fromboolean(bool); - static long tolong(std::string, int base = 10); - static unsigned long toulong(std::string, int base = 10); - static unsigned long long toulonglong(std::string, int base = 10); - static double todouble(std::string); + static long tolong(const std::string &, int base = 10); + static unsigned long toulong(const std::string &, int base = 10); + static unsigned long long toulonglong(const std::string &, int base = 10); + static double todouble(const std::string &); + + static long tolong(const char *, int base = 10); + static unsigned long toulong(const char *, int base = 10); + static unsigned long long toulonglong(const char *, int base = 10); + static double todouble(const char *); static std::string lower(std::string); static std::string hexadecimal(std::string); diff --git a/src/mod/endpoints/mod_khomp/commons/freeswitch/saved_condition.cpp b/src/mod/endpoints/mod_khomp/commons/base/system/freeswitch/saved_condition.cpp similarity index 83% rename from src/mod/endpoints/mod_khomp/commons/freeswitch/saved_condition.cpp rename to src/mod/endpoints/mod_khomp/commons/base/system/freeswitch/saved_condition.cpp index 29169f3d54..d4d9861f5c 100644 --- a/src/mod/endpoints/mod_khomp/commons/freeswitch/saved_condition.cpp +++ b/src/mod/endpoints/mod_khomp/commons/base/system/freeswitch/saved_condition.cpp @@ -1,7 +1,7 @@ -/* +/* KHOMP generic endpoint/channel library. - Copyright (C) 2007-2009 Khomp Ind. & Com. - + Copyright (C) 2007-2009 Khomp Ind. & Com. + The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ @@ -23,40 +23,40 @@ The LGPL header follows below: - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ #include "saved_condition.hpp" bool SavedCondition::wait(unsigned int msec) { - bool ret = true; + bool ret = true; switch_mutex_lock(_mutex); if (!_signaled) - { + { /* msec * 1000 = The amount of time in microseconds to wait. */ - if (switch_thread_cond_timedwait(_condition, _mutex, (switch_interval_time_t)msec * 1000) != 0) - ret = false; - } - + if (switch_thread_cond_timedwait(_condition, _mutex, (switch_interval_time_t)msec * 1000) != 0) + ret = false; + } + _signaled = false; - switch_mutex_unlock(_mutex); + switch_mutex_unlock(_mutex); - return ret; + return ret; } diff --git a/src/mod/endpoints/mod_khomp/commons/freeswitch/saved_condition.hpp b/src/mod/endpoints/mod_khomp/commons/base/system/freeswitch/saved_condition.hpp similarity index 94% rename from src/mod/endpoints/mod_khomp/commons/freeswitch/saved_condition.hpp rename to src/mod/endpoints/mod_khomp/commons/base/system/freeswitch/saved_condition.hpp index 8acf0f3e0b..b34e40b0c0 100644 --- a/src/mod/endpoints/mod_khomp/commons/freeswitch/saved_condition.hpp +++ b/src/mod/endpoints/mod_khomp/commons/base/system/freeswitch/saved_condition.hpp @@ -1,7 +1,7 @@ -/* +/* KHOMP generic endpoint/channel library. - Copyright (C) 2007-2009 Khomp Ind. & Com. - + Copyright (C) 2007-2009 Khomp Ind. & Com. + The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ @@ -23,20 +23,20 @@ The LGPL header follows below: - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ #ifndef _SAVED_CONDITION_ @@ -104,7 +104,7 @@ struct SavedCondition : public SavedConditionCommon// : public RefCounter < Save if (!_signaled) switch_thread_cond_wait(_condition, _mutex); - + _signaled = false; switch_mutex_unlock(_mutex); diff --git a/src/mod/endpoints/mod_khomp/commons/freeswitch/simple_lock.hpp b/src/mod/endpoints/mod_khomp/commons/base/system/freeswitch/simple_lock.hpp similarity index 96% rename from src/mod/endpoints/mod_khomp/commons/freeswitch/simple_lock.hpp rename to src/mod/endpoints/mod_khomp/commons/base/system/freeswitch/simple_lock.hpp index 530d912ee1..acae57648d 100644 --- a/src/mod/endpoints/mod_khomp/commons/freeswitch/simple_lock.hpp +++ b/src/mod/endpoints/mod_khomp/commons/base/system/freeswitch/simple_lock.hpp @@ -1,7 +1,7 @@ -/* +/* KHOMP generic endpoint/channel library. - Copyright (C) 2007-2009 Khomp Ind. & Com. - + Copyright (C) 2007-2009 Khomp Ind. & Com. + The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ @@ -23,20 +23,20 @@ The LGPL header follows below: - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ #ifndef _SIMPLE_LOCK_HPP_ @@ -72,7 +72,7 @@ struct SimpleLockBasic: public SimpleLockCommon < Implementor > { /* do nothing */ }; - + void unreference() { switch_mutex_destroy(_mutex); diff --git a/src/mod/endpoints/mod_khomp/commons/freeswitch/thread.hpp b/src/mod/endpoints/mod_khomp/commons/base/system/freeswitch/thread.hpp similarity index 94% rename from src/mod/endpoints/mod_khomp/commons/freeswitch/thread.hpp rename to src/mod/endpoints/mod_khomp/commons/base/system/freeswitch/thread.hpp index af50240307..9e5abc4372 100644 --- a/src/mod/endpoints/mod_khomp/commons/freeswitch/thread.hpp +++ b/src/mod/endpoints/mod_khomp/commons/base/system/freeswitch/thread.hpp @@ -1,7 +1,7 @@ -/* +/* KHOMP generic endpoint/channel library. - Copyright (C) 2007-2009 Khomp Ind. & Com. - + Copyright (C) 2007-2009 Khomp Ind. & Com. + The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ @@ -23,20 +23,20 @@ The LGPL header follows below: - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ #ifndef _THREAD_HPP_ @@ -66,7 +66,7 @@ struct Thread : ThreadCommon T _data; A _arg; }; - + template struct ThreadData < T, R, void > : ThreadDataCommon { @@ -79,7 +79,7 @@ struct Thread : ThreadCommon T _data; }; - + template struct ThreadData < T, void, A > : ThreadDataCommon { @@ -111,7 +111,7 @@ struct Thread : ThreadCommon }; template - Thread(T obj, switch_memory_pool_t *pool=NULL) : + Thread(T obj, switch_memory_pool_t *pool=NULL) : _thread_info(new ThreadData::Return, void>(obj)), _pool(pool), _can_delete_pool(false) @@ -134,7 +134,7 @@ struct Thread : ThreadCommon } switch_threadattr_stacksize_set( - (switch_threadattr_t *)_thread_info->_attribute, + (switch_threadattr_t *)_thread_info->_attribute, SWITCH_THREAD_STACKSIZE); if(!priority()) @@ -143,9 +143,9 @@ struct Thread : ThreadCommon } } - + template - Thread(T obj, A arg, switch_memory_pool_t *pool=NULL) : + Thread(T obj, A arg, switch_memory_pool_t *pool=NULL) : _thread_info(new ThreadData::Return, A>(obj, arg)), _pool(pool), _can_delete_pool(false) @@ -168,7 +168,7 @@ struct Thread : ThreadCommon } switch_threadattr_stacksize_set( - (switch_threadattr_t *)_thread_info->_attribute, + (switch_threadattr_t *)_thread_info->_attribute, SWITCH_THREAD_STACKSIZE); if(!priority()) @@ -178,11 +178,11 @@ struct Thread : ThreadCommon } - ~Thread() + ~Thread() { if(_thread_info) delete _thread_info; - + if (_can_delete_pool) switch_core_destroy_memory_pool(&_pool); } @@ -202,10 +202,10 @@ struct Thread : ThreadCommon if(!_pool || !_thread_info->_attribute) return false; - switch_thread_create((switch_thread_t**)&_thread_info->_self, - (switch_threadattr_t *)_thread_info->_attribute, - run, - _thread_info, + switch_thread_create((switch_thread_t**)&_thread_info->_self, + (switch_threadattr_t *)_thread_info->_attribute, + run, + _thread_info, _pool); if(!_thread_info->_self) @@ -223,13 +223,13 @@ struct Thread : ThreadCommon * * SWITCH_DECLARE(switch_status_t) switch_thread_join(switch_status_t *retval, switch_thread_t *thd); */ - + if(!_thread_info->_self) return -2; int retval = 0; - if(switch_thread_join((switch_status_t*)&retval, + if(switch_thread_join((switch_status_t*)&retval, (switch_thread_t *)_thread_info->_self) != 0) return -1; @@ -267,7 +267,7 @@ private: { #ifndef WIN32 struct sched_param param; - + struct apr_threadattr_t *myattr = (struct apr_threadattr_t *)_thread_info->_attribute; if (pthread_attr_setschedpolicy( @@ -307,13 +307,13 @@ protected: static void *SWITCH_THREAD_FUNC run(BaseThreadType *thread, void * obj) { - //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, + //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, // "Starting new Thread\n"); ThreadDataCommon * data = (ThreadDataCommon *)obj; int retval = data->run(); - //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, + //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, // "Stopping new Thread = %d\n", retval); ((Thread *)(data->_thread))->exit(retval); diff --git a/src/mod/endpoints/mod_khomp/commons/tagged_union.hpp b/src/mod/endpoints/mod_khomp/commons/base/tagged_union.hpp similarity index 84% rename from src/mod/endpoints/mod_khomp/commons/tagged_union.hpp rename to src/mod/endpoints/mod_khomp/commons/base/tagged_union.hpp index 1616268c5f..f46aab0b75 100644 --- a/src/mod/endpoints/mod_khomp/commons/tagged_union.hpp +++ b/src/mod/endpoints/mod_khomp/commons/base/tagged_union.hpp @@ -42,11 +42,14 @@ #ifndef _TAGGED_UNION_HPP_ #define _TAGGED_UNION_HPP_ -#include - -#include #include +#include +#include +#include + +#include + namespace Tagged { struct EmptyUnion @@ -69,7 +72,7 @@ namespace Tagged ~EmptyUnion() { _adjusted = false; }; - bool operator==(const EmptyUnion & o) + bool operator==(const EmptyUnion & o) const { return true; }; @@ -80,24 +83,24 @@ namespace Tagged void setup(void) { _adjusted = true; }; protected: - bool value_set(void) { return false; }; - bool value_get(void) { return false; }; + bool value_set(void) const { return false; }; + bool value_get(void) const { return false; }; - bool value_check(void) { return false; }; + bool value_check(void) const { return false; }; template < typename S > - bool value_visit(S & visitor, typename S::ReturnType & ret) + bool value_visit(S & visitor, typename S::ReturnType & ret) const { return false; }; template < typename S > - bool value_visit_void(S & visitor) + bool value_visit_void(S & visitor) const { return false; }; - bool adjusted() { return _adjusted; }; + bool adjusted() const { return _adjusted; }; private: bool _adjusted; @@ -114,7 +117,7 @@ namespace Tagged // constructor with initializer template < typename U > - Union( U value ) + Union(U value) : _value(0) { set(value); @@ -123,7 +126,7 @@ namespace Tagged // copy constructor Union(const Union & o) : E(static_cast(o)), - _value( (o._value ? new const V(*(o._value)) : 0) ) + _value( (o._value ? new V(*(o._value)) : 0) ) {}; // copy assignment operator @@ -137,7 +140,7 @@ namespace Tagged if (o._value) { - _value = new const V(*(o._value)); + _value = new V(*(o._value)); } E::operator=(static_cast(o)); @@ -163,18 +166,21 @@ namespace Tagged } template < typename U > - bool check(void) + bool check(void) const { - return value_check(static_cast(0)); + return value_check(static_cast< const U * const>(0)); }; template < typename U > - const U & get(void) + U & get(void) const { - const U * res = 0; + U * res = 0; + + if (!E::adjusted()) + throw std::runtime_error("tagged union empty!"); if (!value_get(&res) || !res) - throw std::runtime_error("type mismatch"); + throw std::runtime_error(STG(FMT("type mismatch when asked for '%s'") % typeid(U).name())); return *res; }; @@ -190,7 +196,7 @@ namespace Tagged }; template < typename S > - typename S::ReturnType visit(S visitor) + typename S::ReturnType visit(S visitor) const { typename S::ReturnType ret; @@ -201,7 +207,7 @@ namespace Tagged }; template < typename S > - void visit_void(S visitor) + void visit_void(S visitor) const { if (!value_visit_void(visitor)) throw std::runtime_error("unable to visit empty value"); @@ -219,7 +225,7 @@ namespace Tagged }; // compare (equal) operator - bool operator==(const Union & o) + bool operator==(const Union & o) const { bool are_equal = false; @@ -236,7 +242,7 @@ namespace Tagged }; // compare types - bool sameType(const Union & o) + bool sameType(const Union & o) const { if ((!(_value) && !(o._value)) || (_value && o._value)) return E::operator==(static_cast(o)); @@ -254,13 +260,13 @@ namespace Tagged bool value_set(V val) { - _value = new const V(val); + _value = new V(val); E::setup(); return true; }; - bool value_get(const V ** val) + bool value_get(V ** val) const { if (!_value) return false; @@ -269,14 +275,14 @@ namespace Tagged return true; } - bool value_check(const V * const junk) + bool value_check(const V * const junk) const { (void)junk; return (_value != 0); }; template < typename S > - bool value_visit(S & visitor, typename S::ReturnType & ret) + bool value_visit(S & visitor, typename S::ReturnType & ret) const { if (_value) { @@ -288,7 +294,7 @@ namespace Tagged }; template < typename S > - bool value_visit_void(S & visitor) + bool value_visit_void(S & visitor) const { if (_value) { @@ -300,7 +306,7 @@ namespace Tagged }; private: - const V * _value; + V * _value; }; }; diff --git a/src/mod/endpoints/mod_khomp/commons/thread.hpp b/src/mod/endpoints/mod_khomp/commons/base/thread.hpp similarity index 100% rename from src/mod/endpoints/mod_khomp/commons/thread.hpp rename to src/mod/endpoints/mod_khomp/commons/base/thread.hpp diff --git a/src/mod/endpoints/mod_khomp/commons/timer.cpp b/src/mod/endpoints/mod_khomp/commons/base/timer.cpp similarity index 96% rename from src/mod/endpoints/mod_khomp/commons/timer.cpp rename to src/mod/endpoints/mod_khomp/commons/base/timer.cpp index 36e32f521a..0cb0ac4340 100644 --- a/src/mod/endpoints/mod_khomp/commons/timer.cpp +++ b/src/mod/endpoints/mod_khomp/commons/base/timer.cpp @@ -276,6 +276,20 @@ bool TimerTraits::traits_restart (TimerTraits::Index & idx, bool force) return ret; } +void TimerTraits::traits_setup(TimerTraits::Index * idx, unsigned int msecs, const void * func, void * data, unsigned int value) +{ + _mutex.lock(); + + if (idx->valid) + { + (void)traits_del_unlocked(*idx); + } + + *idx = traits_add_unlocked(msecs, func, data, value); + + _mutex.unlock(); +} + bool TimerTraits::traits_del_unlocked (TimerTraits::Index & idx) { bool ret = false; diff --git a/src/mod/endpoints/mod_khomp/commons/timer.hpp b/src/mod/endpoints/mod_khomp/commons/base/timer.hpp similarity index 93% rename from src/mod/endpoints/mod_khomp/commons/timer.hpp rename to src/mod/endpoints/mod_khomp/commons/base/timer.hpp index 382efa1645..24d115d991 100644 --- a/src/mod/endpoints/mod_khomp/commons/timer.hpp +++ b/src/mod/endpoints/mod_khomp/commons/base/timer.hpp @@ -125,6 +125,8 @@ struct TimerTraits bool traits_del (Index & idx); bool traits_del (const void * func, const void * data = 0, unsigned int value = 0); + void traits_setup(Index * idx, unsigned int msecs, const void * func, void * data = 0, unsigned int value = 0); + /* timer start/stop functions */ bool start(void); bool stop(void); @@ -169,7 +171,7 @@ struct TimerTraits }; template < typename F, typename D > -struct TimerTemplate: NEW_REFCOUNTER(TimerTemplate< F, D >) +struct TimerTemplate: COUNTER_SUPER(TimerTemplate< F, D >) { typedef TimerTraits::Index Index; typedef TimerTraits::Control Control; @@ -179,7 +181,7 @@ struct TimerTemplate: NEW_REFCOUNTER(TimerTemplate< F, D >) {}; TimerTemplate(const TimerTemplate< F, D > & o) - : INC_REFCOUNTER(o, TimerTemplate< F, D >), + : COUNTER_REFER(o, TimerTemplate< F, D >), _timer(o._timer) {}; @@ -192,6 +194,11 @@ struct TimerTemplate: NEW_REFCOUNTER(TimerTemplate< F, D >) bool start() { return _timer->start(); } bool stop() { return _timer->stop(); } + inline void setup(Index * idx, unsigned int msecs, F * func, D data = 0, unsigned int value = 0) + { + _timer->traits_setup(idx, msecs, (const void *)func, (void *)(data), value); + } + inline Index add(unsigned int msecs, F * func, D data = 0, unsigned int value = 0) { return _timer->traits_add(msecs, (const void *)func, (void *)(data), value); diff --git a/src/mod/endpoints/mod_khomp/commons/types.hpp b/src/mod/endpoints/mod_khomp/commons/base/types.hpp similarity index 88% rename from src/mod/endpoints/mod_khomp/commons/types.hpp rename to src/mod/endpoints/mod_khomp/commons/base/types.hpp index adbd8abe36..5ab6d292c6 100644 --- a/src/mod/endpoints/mod_khomp/commons/types.hpp +++ b/src/mod/endpoints/mod_khomp/commons/base/types.hpp @@ -55,15 +55,33 @@ /*** Used for checking information on classes and stuff.. ***/ template< typename T > -class IsClass +struct IsClass { protected: - template< typename X > static char ( &A( void(X::*)() ) )[1]; - template< typename X > static char ( &A( X ) )[2]; + template < typename X > static char ( &A( void(X::*)() ) )[1]; + template < typename X > static char ( &A( X ) )[2]; public: static bool const Result = sizeof( A< T >(0) ) == 1; }; +template < typename T > +struct IsConst +{ + static bool const Result = false; +}; + +template < typename T > +struct IsConst< const T > +{ + static bool const Result = true; +}; + +template < typename T > +struct IsConst< T const * > +{ + static bool const Result = true; +}; + /*** Used for template metaprogramming ***/ template < bool Value, typename Then, typename Else > diff --git a/src/mod/endpoints/mod_khomp/commons/variant.hpp b/src/mod/endpoints/mod_khomp/commons/base/variable.hpp similarity index 53% rename from src/mod/endpoints/mod_khomp/commons/variant.hpp rename to src/mod/endpoints/mod_khomp/commons/base/variable.hpp index 410a770a6e..efeb0f53b7 100644 --- a/src/mod/endpoints/mod_khomp/commons/variant.hpp +++ b/src/mod/endpoints/mod_khomp/commons/base/variable.hpp @@ -11,7 +11,7 @@ the specific language governing rights and limitations under the License. Alternatively, the contents of this file may be used under the terms of the - "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + "GNU Lesser General Public License 2.1" license (the "LGPL" License), in which case the provisions of "LGPL License" are applicable instead of those above. If you wish to allow use of your version of this file only under the terms of @@ -41,87 +41,84 @@ #include -#include +#ifndef _VARIABLE_HPP_ +#define _VARIABLE_HPP_ -#ifndef _VARIANT_H_ -#define _VARIANT_H_ - -/* this is internal, should not be used by the user */ -struct NoArgumentDefined {}; - -template < typename UserReturnType, typename UserArgumentType = NoArgumentDefined > -struct VariantBaseType +template < typename R > +struct VariableBaseTable { - typedef UserReturnType ReturnType; - typedef UserArgumentType ArgumentType; - - virtual ~VariantBaseType() {}; - - virtual int which() = 0; - - virtual ReturnType visit(void) { return ReturnType(); }; - virtual ReturnType visit(ArgumentType) { return ReturnType(); }; + R value; }; -template < typename BaseType = VariantBaseType < void > > -struct Variant: NEW_REFCOUNTER(Variant < BaseType >) +struct EmptyVariable {}; + +template < typename R > +struct Variable { - typedef typename BaseType::ReturnType ReturnType; - typedef typename BaseType::ArgumentType ArgumentType; + protected: + typedef VariableBaseTable< R > BaseType; - struct InvalidType {}; + typedef const BaseType * ConstObjType; + typedef BaseType * ObjType; + typedef R BaseType::* VarType; - Variant(BaseType * value, bool is_owner = false) - : _value(value), _is_owner(is_owner) {}; + public: + template < typename ConstructorObjType > + Variable(R ConstructorObjType::* v) + : _adjusted(true), + _variable(reinterpret_cast(v)) + {}; - Variant(const Variant & v) - : INC_REFCOUNTER(v, Variant < BaseType >), - _value(v._value), _is_owner(v._is_owner) {}; + Variable() + : _adjusted(false) + {}; - virtual ~Variant() {}; - - void unreference() + template < typename MemberType > + void operator=(const MemberType v) { - if (_is_owner && _value) - { - delete _value; - _value = 0; - } - }; - - template < typename ValueType > - ValueType & get(void) - { - try - { - ValueType & ret = dynamic_cast < ValueType & > (*_value); - return ret; - } - catch (std::bad_cast & e) - { - throw InvalidType(); - } - }; - - int which() - { - return _value->which(); + _adjusted = true; + _variable = reinterpret_cast(v); } - ReturnType visit(void) + template < typename Type > + R & operator()(Type * obj) const { - return _value->visit(); + if (!_adjusted) + throw EmptyVariable(); + + return (reinterpret_cast< ObjType >(obj))->*(_variable); } - ReturnType visit(ArgumentType arg) + template < typename Type > + R & operator()(Type & obj) const { - return _value->visit(arg); + if (!_adjusted) + throw EmptyVariable(); + + return (reinterpret_cast< ObjType >(&obj))->*(_variable); } - protected: - BaseType * _value; - bool _is_owner; + template < typename Type > + const R & operator()(const Type * obj) const + { + if (!_adjusted) + throw EmptyVariable(); + + return (reinterpret_cast< ConstObjType >(obj))->*(_variable); + } + + template < typename Type > + const R & operator()(const Type & obj) const + { + if (!_adjusted) + throw EmptyVariable(); + + return (reinterpret_cast< ConstObjType >(&obj))->*(_variable); + } + + protected: + bool _adjusted; + VarType _variable; }; -#endif /* _VARIANT_H_ */ - +#endif /* _VARIABLE_HPP_ */ diff --git a/src/mod/endpoints/mod_khomp/commons/verbose.cpp b/src/mod/endpoints/mod_khomp/commons/base/verbose.cpp similarity index 82% rename from src/mod/endpoints/mod_khomp/commons/verbose.cpp rename to src/mod/endpoints/mod_khomp/commons/base/verbose.cpp index 182d159ca1..bdc412e231 100644 --- a/src/mod/endpoints/mod_khomp/commons/verbose.cpp +++ b/src/mod/endpoints/mod_khomp/commons/base/verbose.cpp @@ -54,11 +54,11 @@ /********************************************/ -std::string Verbose::channelStatus(int32 dev, int32 obj, int32 cs, Verbose::Presentation fmt) +std::string Verbose::channelStatus(const int32 dev, const int32 obj, const int32 cs, const Verbose::Presentation fmt) const { try { - K3L_CHANNEL_CONFIG & config = _api.channel_config(dev, obj); + const K3L_CHANNEL_CONFIG & config = _api.channel_config(dev, obj); return Verbose::channelStatus(config.Signaling, cs, fmt); } catch (...) @@ -68,14 +68,14 @@ std::string Verbose::channelStatus(int32 dev, int32 obj, int32 cs, Verbose::Pres } #if K3L_AT_LEAST(2,0,0) -std::string Verbose::event(int32 obj, K3L_EVENT *ev, R2CountryType r2_country, Verbose::Presentation fmt) +std::string Verbose::event(const int32 obj, const K3L_EVENT * const ev, const R2CountryType r2_country, const Verbose::Presentation fmt) const #else -std::string Verbose::event(int32 obj, K3L_EVENT *ev, Verbose::Presentation fmt) +std::string Verbose::event(const int32 obj, const K3L_EVENT * const ev, const Verbose::Presentation fmt) const #endif { try { - K3L_CHANNEL_CONFIG & config = _api.channel_config(ev->DeviceId, obj); + const K3L_CHANNEL_CONFIG & config = _api.channel_config(ev->DeviceId, obj); #if K3L_AT_LEAST(2,0,0) return Verbose::event(config.Signaling, obj, ev, r2_country, fmt); #else @@ -94,7 +94,7 @@ std::string Verbose::event(int32 obj, K3L_EVENT *ev, Verbose::Presentation fmt) /********************************************/ -std::string Verbose::echoLocation(KEchoLocation ec, Verbose::Presentation fmt) +std::string Verbose::echoLocation(const KEchoLocation ec, const Verbose::Presentation fmt) { switch (ec) { @@ -109,7 +109,7 @@ std::string Verbose::echoLocation(KEchoLocation ec, Verbose::Presentation fmt) return presentation(fmt, "", "Unknown"); }; -std::string Verbose::echoCancellerConfig(KEchoCancellerConfig ec, Verbose::Presentation fmt) +std::string Verbose::echoCancellerConfig(KEchoCancellerConfig ec, const Verbose::Presentation fmt) { switch (ec) { @@ -124,21 +124,24 @@ std::string Verbose::echoCancellerConfig(KEchoCancellerConfig ec, Verbose::Prese return presentation(fmt, "", "Unknown"); }; -// TODO: internal_deviceType / internal_deviceModel +std::string Verbose::deviceName(const KDeviceType dt, const int32 model, const Verbose::Presentation fmt) +{ + return deviceName(dt, model, 0, fmt); +} -std::string Verbose::deviceName(KDeviceType dt, int32 model, Verbose::Presentation fmt) +std::string Verbose::deviceName(const KDeviceType dt, const int32 model, const int32 count, const Verbose::Presentation fmt) { try { std::string value; - value += internal_deviceType(dt); + value += internal_deviceType(dt, count); value += "-"; - value += internal_deviceModel(dt, model); + value += internal_deviceModel(dt, model, count); return value; } - catch (internal_not_found & e) + catch (internal_not_found e) { PRESENTATION_CHECK_RETURN(fmt, STG(FMT("[type/model='%d/%d']") % (int)dt % (int)model), @@ -146,13 +149,18 @@ std::string Verbose::deviceName(KDeviceType dt, int32 model, Verbose::Presentati } } -std::string Verbose::deviceType(KDeviceType dt, Verbose::Presentation fmt) +std::string Verbose::deviceType(const KDeviceType dt, const Verbose::Presentation fmt) +{ + return deviceType(dt, 0, fmt); +} + +std::string Verbose::deviceType(const KDeviceType dt, const int32 count, const Verbose::Presentation fmt) { try { - return internal_deviceType(dt); + return internal_deviceType(dt, count); } - catch (internal_not_found & e) + catch (internal_not_found e) { PRESENTATION_CHECK_RETURN(fmt, STG(FMT("[type='%d']") % (int)dt), @@ -160,11 +168,11 @@ std::string Verbose::deviceType(KDeviceType dt, Verbose::Presentation fmt) } } -std::string Verbose::internal_deviceType(KDeviceType dt) +std::string Verbose::internal_deviceType(const KDeviceType dt, const int32 count) { switch (dt) { - case kdtE1: return "K2E1"; + case kdtE1: return (count > 34 || count == 0 ? "K2E1" : "K1E1"); #if K3L_AT_LEAST(1,6,0) case kdtFXO: return "KFXO"; @@ -183,10 +191,10 @@ std::string Verbose::internal_deviceType(KDeviceType dt) #endif #if K3L_AT_LEAST(1,5,0) - case kdtE1IP: return "K2E1"; + case kdtE1IP: return (count > 90 || count == 0 ? "K2E1" : "K1E1"); #endif #if K3L_AT_LEAST(1,5,1) - case kdtE1Spx: return "K2E1"; + case kdtE1Spx: return (count > 30 || count == 0 ? "K2E1" : "K1E1"); case kdtGWIP: return "KGWIP"; #endif @@ -202,7 +210,6 @@ std::string Verbose::internal_deviceType(KDeviceType dt) case kdtGSMUSBSpx: return "KGSMUSB"; case kdtE1FXSSpx: return "KE1FXS"; - case kdtDevTypeCount: return "DevTypeCount"; #endif #if K3L_EXACT(2,1,0) @@ -212,18 +219,24 @@ std::string Verbose::internal_deviceType(KDeviceType dt) #if K3L_AT_LEAST(2,2,0) case kdtE1AdHoc: return "KE1AdHoc"; #endif + case kdtDevTypeCount: break; } throw internal_not_found(); } -std::string Verbose::deviceModel(KDeviceType dt, int32 model, Verbose::Presentation fmt) +std::string Verbose::deviceModel(const KDeviceType dt, const int32 model, const Verbose::Presentation fmt) +{ + return deviceModel(dt, model, 0, fmt); +}; + +std::string Verbose::deviceModel(const KDeviceType dt, const int32 model, const int32 count, const Verbose::Presentation fmt) { try { - return internal_deviceModel(dt, model); + return internal_deviceModel(dt, model, count); } - catch (internal_not_found & e) + catch (internal_not_found e) { PRESENTATION_CHECK_RETURN(fmt, STG(FMT("[model='%d']") % (int)model), @@ -231,17 +244,17 @@ std::string Verbose::deviceModel(KDeviceType dt, int32 model, Verbose::Presentat } } -std::string Verbose::internal_deviceModel(KDeviceType dt, int32 model) +std::string Verbose::internal_deviceModel(const KDeviceType dt, const int32 model, const int32 count) { switch (dt) { case kdtE1: switch ((KE1DeviceModel)model) { - case kdmE1600: return "600"; - case kdmE1600E: return "600E"; + case kdmE1600: return (count > 34 || count == 0 ? "600" : "300"); + case kdmE1600E: return (count > 34 || count == 0 ? "600" : "300"); #if K3L_AT_LEAST(2,0,0) - case kdmE1600EX: return "600EX"; + case kdmE1600EX: return (count > 34 || count == 0 ? "600" : "300"); #endif } throw internal_not_found(); @@ -255,14 +268,38 @@ std::string Verbose::internal_deviceModel(KDeviceType dt, int32 model) #endif { #if K3L_AT_LEAST(1,6,0) - case kdmFXO80: return "80"; - case kdmFXOHI: return "HI"; + case kdmFXO80: + switch (count) + { + case 0: /* default */ + case 8: return "80"; + case 4: return "40"; + } + break; + + case kdmFXOHI: + switch (count) + { + case 0: /* default */ + case 8: return "80-HI"; + case 4: return "40-HI"; + } + break; + case kdmFXO160HI: return "160HI"; #if K3L_AT_LEAST(2,1,0) - case kdmFXO240HI: return "240HI"; + case kdmFXO240HI: return "240HI"; #endif #else - case kdmFXO80: return "80"; + case kdmFXO80: + switch (count) + { + case 0: /* default */ + case 8: return "80"; + case 4: return "40"; + } + break; + #endif } @@ -300,13 +337,13 @@ std::string Verbose::internal_deviceModel(KDeviceType dt, int32 model) switch ((KE1GWDeviceModel)model) { #if K3L_AT_LEAST(1,6,0) - case kdmE1GW640: return "640"; + case kdmE1GW640: return "640"; #if K3L_AT_LEAST(2,0,0) case kdmE1GW640EX: return "640EX"; #endif #else - case kdmE1600V: return "600V"; - case kdmE1600EV: return "600EV"; + case kdmE1600V: return (count > 34 || count == 0 ? "600V" : "300V" ); + case kdmE1600EV: return (count > 34 || count == 0 ? "600EV" : "600EV"); #endif } @@ -337,12 +374,12 @@ std::string Verbose::internal_deviceModel(KDeviceType dt, int32 model) switch ((KE1IPDeviceModel)model) { #if K3L_AT_LEAST(1,6,0) - case kdmE1IP: return "E1IP"; + case kdmE1IP: return "E1IP"; #if K3L_AT_LEAST(2,0,0) case kdmE1IPEX: return "E1IPEX"; #endif #else - case kdmE1600EG: return "600EG"; + case kdmE1600EG: return (count > 90 || count == 0 ? "600EG" : "300EG"); #endif } @@ -353,8 +390,8 @@ std::string Verbose::internal_deviceModel(KDeviceType dt, int32 model) case kdtE1Spx: switch ((KE1SpxDeviceModel)model) { - case kdmE1Spx: return "SPX"; - case kdm2E1Based: return "SPX-2E1"; + case kdmE1Spx: return "SPX"; + case kdm2E1Based: return "SPX-2E1"; #if K3L_AT_LEAST(2,0,0) case kdmE1SpxEX: return "SPXEX"; #endif @@ -367,7 +404,7 @@ std::string Verbose::internal_deviceModel(KDeviceType dt, int32 model) #if K3L_AT_LEAST(1,6,0) case kdmGWIP: return "GWIP"; #if K3L_AT_LEAST(2,0,0) - case kdmGWIPEX: return "GWIPEX"; + case kdmGWIPEX: return "GWIPEX"; #endif #else case kdmGW600G: return "600G"; @@ -382,9 +419,9 @@ std::string Verbose::internal_deviceModel(KDeviceType dt, int32 model) case kdtFXS: switch ((KFXSDeviceModel)model) { - case kdmFXS300: return "300"; + case kdmFXS300: return (count > 30 || count == 0 ? "300" : "150"); #if K3L_AT_LEAST(2,0,0) - case kdmFXS300EX: return "300EX"; + case kdmFXS300EX: return (count > 30 || count == 0 ? "300EX" : "150EX"); #endif } @@ -393,10 +430,10 @@ std::string Verbose::internal_deviceModel(KDeviceType dt, int32 model) case kdtFXSSpx: switch ((KFXSSpxDeviceModel)model) { - case kdmFXSSpx300: return "SPX"; - case kdmFXSSpx2E1Based: return "SPX-2E1"; + case kdmFXSSpx300: return (count > 30 || count == 0 ? "300-SPX" : "150-SPX"); + case kdmFXSSpx2E1Based: return "SPX-2E1"; #if K3L_AT_LEAST(2,0,0) - case kdmFXSSpx300EX: return "SPXEX"; + case kdmFXSSpx300EX: return (count > 30 || count == 0 ? "300-SPXEX" : "150-SPXEX"); #endif } @@ -405,9 +442,27 @@ std::string Verbose::internal_deviceModel(KDeviceType dt, int32 model) case kdtGSM: switch ((KGSMDeviceModel)model) { - case kdmGSM: return "40"; + case kdmGSM: + switch (count) + { + case 0: /* default */ + case 4: return "40"; + case 3: return "30"; + case 2: return "20"; + case 1: return "10"; + } + break; #if K3L_AT_LEAST(2,0,0) - case kdmGSMEX: return "40EX"; + case kdmGSMEX: + switch (count) + { + case 0: /* default */ + case 4: return "40EX"; + case 3: return "80EX"; + case 2: return "20EX"; + case 1: return "10EX"; + } + break; #endif } @@ -416,9 +471,27 @@ std::string Verbose::internal_deviceModel(KDeviceType dt, int32 model) case kdtGSMSpx: switch ((KGSMSpxDeviceModel)model) { - case kdmGSMSpx: return "SPX"; + case kdmGSMSpx: + switch (count) + { + case 0: /* default */ + case 4: return "40"; + case 3: return "30"; + case 2: return "20"; + case 1: return "10"; + } + break; #if K3L_AT_LEAST(2,0,0) - case kdmGSMSpxEX: return "SPXEX"; + case kdmGSMSpxEX: + switch (count) + { + case 0: /* default */ + case 4: return "40-SPXEX"; + case 3: return "80-SPXEX"; + case 2: return "20-SPXEX"; + case 1: return "10-SPXEX"; + } + break; #endif } @@ -444,8 +517,8 @@ std::string Verbose::internal_deviceModel(KDeviceType dt, int32 model) case kdtE1FXSSpx: switch ((KGSMSpxDeviceModel)model) { - case kdmE1FXSSpx: return "SPX"; - case kdmE1FXSSpxEX: return "SPXEX"; + case kdmE1FXSSpx: return "450-SPX"; + case kdmE1FXSSpxEX: return "450-SPXEX"; } throw internal_not_found(); @@ -476,7 +549,7 @@ std::string Verbose::internal_deviceModel(KDeviceType dt, int32 model) throw internal_not_found(); } -std::string Verbose::signaling(KSignaling sig, Verbose::Presentation fmt) +std::string Verbose::signaling(const KSignaling sig, const Verbose::Presentation fmt) { switch (sig) { @@ -523,7 +596,7 @@ std::string Verbose::signaling(KSignaling sig, Verbose::Presentation fmt) STG(FMT("Unknown signaling (%d)") % (int)sig)); } -std::string Verbose::systemObject(KSystemObject so, Verbose::Presentation fmt) +std::string Verbose::systemObject(const KSystemObject so, const Verbose::Presentation fmt) { switch (so) { @@ -544,7 +617,7 @@ std::string Verbose::systemObject(KSystemObject so, Verbose::Presentation fmt) STG(FMT("Unknown object (%d)") % (int)so)); } -std::string Verbose::mixerTone(KMixerTone mt, Verbose::Presentation fmt) +std::string Verbose::mixerTone(const KMixerTone mt, const Verbose::Presentation fmt) { switch (mt) { @@ -567,7 +640,7 @@ std::string Verbose::mixerTone(KMixerTone mt, Verbose::Presentation fmt) STG(FMT("Unknonwn tone (%d)") % (int)mt)); } -std::string Verbose::mixerSource(KMixerSource ms, Verbose::Presentation fmt) +std::string Verbose::mixerSource(const KMixerSource ms, const Verbose::Presentation fmt) { switch (ms) { @@ -588,7 +661,7 @@ std::string Verbose::mixerSource(KMixerSource ms, Verbose::Presentation fmt) STG(FMT("Unknonwn source (%d)") % (int)ms)); } -std::string Verbose::channelFeatures(int32 flags, Verbose::Presentation fmt) +std::string Verbose::channelFeatures(const int32 flags, const Verbose::Presentation fmt) { if (0x00 != flags) { @@ -603,9 +676,7 @@ std::string Verbose::channelFeatures(int32 flags, Verbose::Presentation fmt) if (kcfHighImpEvents & flags) strs.add(presentation(fmt, "HighImpEvents", "High Impedance Events")); #if K3L_AT_LEAST(1,6,0) if (kcfCallAnswerInfo & flags) strs.add(presentation(fmt, "CallAnswerInfo", "Call Answer Info")); -#if !K3L_AT_LEAST(2,2,0) if (kcfOutputVolume & flags) strs.add(presentation(fmt, "OutputVolume", "Output Volume")); -#endif if (kcfPlayerAGC & flags) strs.add(presentation(fmt, "PlayerAGC", "Player AGC")); #endif @@ -617,7 +688,7 @@ std::string Verbose::channelFeatures(int32 flags, Verbose::Presentation fmt) PRESENTATION_CHECK_RETURN(fmt, "", "No features"); } -std::string Verbose::seizeFail(KSeizeFail sf, Verbose::Presentation fmt) +std::string Verbose::seizeFail(const KSeizeFail sf, const Verbose::Presentation fmt) { switch (sf) { @@ -635,7 +706,7 @@ std::string Verbose::seizeFail(KSeizeFail sf, Verbose::Presentation fmt) } #if K3L_AT_LEAST(1,5,0) -std::string Verbose::internal_sipFailures(KSIP_Failures code, Verbose::Presentation fmt) +std::string Verbose::internal_sipFailures(const KSIP_Failures code, const Verbose::Presentation fmt) { switch (code) { @@ -691,13 +762,13 @@ std::string Verbose::internal_sipFailures(KSIP_Failures code, Verbose::Presentat throw internal_not_found(); } -std::string Verbose::sipFailures(KSIP_Failures code, Verbose::Presentation fmt) +std::string Verbose::sipFailures(const KSIP_Failures code, const Verbose::Presentation fmt) { try { return internal_sipFailures(code, fmt); } - catch (internal_not_found & e) + catch (internal_not_found e) { PRESENTATION_CHECK_RETURN(fmt, STG(FMT("[KSIP_Failures='%d']") % (int)code), @@ -708,7 +779,7 @@ std::string Verbose::sipFailures(KSIP_Failures code, Verbose::Presentation fmt) #endif #if K3L_AT_LEAST(1,5,1) -std::string Verbose::internal_isdnCause(KQ931Cause code, Verbose::Presentation fmt) +std::string Verbose::internal_isdnCause(const KQ931Cause code, const Verbose::Presentation fmt) { switch (code) { @@ -810,13 +881,13 @@ std::string Verbose::internal_isdnCause(KQ931Cause code, Verbose::Presentation f throw internal_not_found(); } -std::string Verbose::isdnCause(KQ931Cause code, Verbose::Presentation fmt) +std::string Verbose::isdnCause(const KQ931Cause code, const Verbose::Presentation fmt) { try { return internal_isdnCause(code); } - catch (internal_not_found & e) + catch (internal_not_found e) { return STG(FMT("[KQ931Cause='%d']") % (int)code); } @@ -824,7 +895,7 @@ std::string Verbose::isdnCause(KQ931Cause code, Verbose::Presentation fmt) #endif #if K3L_AT_LEAST(1,5,2) -std::string Verbose::isdnDebug(int32 flags, Verbose::Presentation fmt) +std::string Verbose::isdnDebug(const int32 flags, const Verbose::Presentation fmt) { if (0x00 != flags) { @@ -844,9 +915,9 @@ std::string Verbose::isdnDebug(int32 flags, Verbose::Presentation fmt) #endif #if K3L_AT_LEAST(2,0,0) -std::string Verbose::internal_signGroupB(KSignGroupB group, R2CountryType country, Verbose::Presentation fmt) +std::string Verbose::internal_signGroupB(const KSignGroupB group, const R2CountryType country, const Verbose::Presentation fmt) #else -std::string Verbose::internal_signGroupB(KSignGroupB group, Verbose::Presentation fmt) +std::string Verbose::internal_signGroupB(const KSignGroupB group, const Verbose::Presentation fmt) #endif { #if K3L_AT_LEAST(2,0,0) @@ -955,9 +1026,9 @@ std::string Verbose::internal_signGroupB(KSignGroupB group, Verbose::Presentatio } #if K3L_AT_LEAST(2,0,0) -std::string Verbose::signGroupB(KSignGroupB group, R2CountryType r2_country, Verbose::Presentation fmt) +std::string Verbose::signGroupB(const KSignGroupB group, const R2CountryType r2_country, const Verbose::Presentation fmt) #else -std::string Verbose::signGroupB(KSignGroupB group, Verbose::Presentation fmt) +std::string Verbose::signGroupB(const KSignGroupB group, const Verbose::Presentation fmt) #endif { try @@ -968,7 +1039,7 @@ std::string Verbose::signGroupB(KSignGroupB group, Verbose::Presentation fmt) return internal_signGroupB(group, fmt); #endif } - catch (internal_not_found & e) + catch (internal_not_found e) { PRESENTATION_CHECK_RETURN(fmt, STG(FMT("[KSignGroupB='%d']") % (int)group), @@ -977,9 +1048,9 @@ std::string Verbose::signGroupB(KSignGroupB group, Verbose::Presentation fmt) } #if K3L_AT_LEAST(2,0,0) -std::string Verbose::internal_signGroupII(KSignGroupII group, R2CountryType country, Verbose::Presentation fmt) +std::string Verbose::internal_signGroupII(const KSignGroupII group, const R2CountryType country, const Verbose::Presentation fmt) #else -std::string Verbose::internal_signGroupII(KSignGroupII group, Verbose::Presentation fmt) +std::string Verbose::internal_signGroupII(const KSignGroupII group, const Verbose::Presentation fmt) #endif { #if K3L_AT_LEAST(2,0,0) @@ -1085,9 +1156,9 @@ std::string Verbose::internal_signGroupII(KSignGroupII group, Verbose::Presentat } #if K3L_AT_LEAST(2,0,0) -std::string Verbose::signGroupII(KSignGroupII group, R2CountryType r2_country, Verbose::Presentation fmt) +std::string Verbose::signGroupII(const KSignGroupII group, const R2CountryType r2_country, const Verbose::Presentation fmt) #else -std::string Verbose::signGroupII(KSignGroupII group, Verbose::Presentation fmt) +std::string Verbose::signGroupII(const KSignGroupII group, const Verbose::Presentation fmt) #endif { try @@ -1098,7 +1169,7 @@ std::string Verbose::signGroupII(KSignGroupII group, Verbose::Presentation fmt) return internal_signGroupII(group); #endif } - catch (internal_not_found & e) + catch (internal_not_found e) { PRESENTATION_CHECK_RETURN(fmt, STG(FMT("[KSignGroupII='%d']") % (int)group), @@ -1107,9 +1178,9 @@ std::string Verbose::signGroupII(KSignGroupII group, Verbose::Presentation fmt) } #if K3L_AT_LEAST(2,0,0) -std::string Verbose::callFail(KSignaling sig, R2CountryType country, int32 info, Verbose::Presentation fmt) +std::string Verbose::callFail(const KSignaling sig, const R2CountryType country, const int32 info, const Verbose::Presentation fmt) #else -std::string Verbose::callFail(KSignaling sig, int32 info, Verbose::Presentation fmt) +std::string Verbose::callFail(const KSignaling sig, const int32 info, const Verbose::Presentation fmt) #endif { try @@ -1130,8 +1201,10 @@ std::string Verbose::callFail(KSignaling sig, int32 info, Verbose::Presentation #endif #if K3L_EXACT(2,1,0) case ksigISUP: +#if !K3L_AT_LEAST(2,2,0) case ksigFax: #endif +#endif #if K3L_AT_LEAST(1,6,0) case ksigCAS_EL7: case ksigE1LC: @@ -1181,7 +1254,7 @@ std::string Verbose::callFail(KSignaling sig, int32 info, Verbose::Presentation #endif } } - catch (internal_not_found & e) + catch (internal_not_found e) { /* this exception is used for breaking the control flow */ } @@ -1191,7 +1264,7 @@ std::string Verbose::callFail(KSignaling sig, int32 info, Verbose::Presentation STG(FMT("Unknown call fail code for '%s' (%d)") % signaling(sig, fmt) % (int)info)); } -std::string Verbose::channelFail(KSignaling sig, int32 code, Verbose::Presentation fmt) +std::string Verbose::channelFail(const KSignaling sig, const int32 code, const Verbose::Presentation fmt) { try { @@ -1202,7 +1275,9 @@ std::string Verbose::channelFail(KSignaling sig, int32 code, Verbose::Presentati case ksigSIP: #if K3L_EXACT(2,1,0) case ksigISUP: +#if !K3L_AT_LEAST(2,2,0) case ksigFax: +#endif #endif throw internal_not_found(); @@ -1248,7 +1323,7 @@ std::string Verbose::channelFail(KSignaling sig, int32 code, Verbose::Presentati #endif } } - catch (internal_not_found & e) + catch (internal_not_found e) { /* this exception is used for breaking the control flow */ } @@ -1258,7 +1333,7 @@ std::string Verbose::channelFail(KSignaling sig, int32 code, Verbose::Presentati STG(FMT("Unknown channel fail code for '%s' (%d)") % signaling(sig, fmt) % (int)code)); } -std::string Verbose::internalFail(KInternalFail inf, Verbose::Presentation fmt) +std::string Verbose::internalFail(const KInternalFail inf, const Verbose::Presentation fmt) { switch (inf) { @@ -1277,7 +1352,7 @@ std::string Verbose::internalFail(KInternalFail inf, Verbose::Presentation fmt) STG(FMT("Unknown internal failure (%d)") % (int)inf)); } -std::string Verbose::linkErrorCounter(KLinkErrorCounter ec, Verbose::Presentation fmt) +std::string Verbose::linkErrorCounter(const KLinkErrorCounter ec, const Verbose::Presentation fmt) { switch (ec) { @@ -1304,7 +1379,7 @@ std::string Verbose::linkErrorCounter(KLinkErrorCounter ec, Verbose::Presentatio STG(FMT("Unknown link error counter (%d)") % (int)ec)); } -std::string Verbose::callStatus(KCallStatus code, Verbose::Presentation fmt) +std::string Verbose::callStatus(const KCallStatus code, const Verbose::Presentation fmt) { switch (code) { @@ -1319,7 +1394,7 @@ std::string Verbose::callStatus(KCallStatus code, Verbose::Presentation fmt) STG(FMT("Unknown call status (%d)") % (int)code)); } -std::string Verbose::linkStatus(KSignaling sig, int32 code, Verbose::Presentation fmt) +std::string Verbose::linkStatus(const KSignaling sig, const int32 code, const Verbose::Presentation fmt, const bool simpleStatus) { switch (sig) { @@ -1340,7 +1415,9 @@ std::string Verbose::linkStatus(KSignaling sig, int32 code, Verbose::Presentatio #endif #if K3L_EXACT(2,1,0) - case ksigFax: +#if !K3L_AT_LEAST(2,2,0) + case ksigFax: +#endif return presentation(fmt, "[ksigFax]", "FAX"); #endif case ksigContinuousEM: @@ -1386,9 +1463,18 @@ std::string Verbose::linkStatus(KSignaling sig, int32 code, Verbose::Presentatio if (kesUnknownAlarm & code) strs.add(presentation(fmt, "UnknownAlarm", "Slip alarm")); if (kesE1Error & code) strs.add(presentation(fmt, "E1Error", "E1 error")); - PRESENTATION_CHECK_RETURN(fmt, - STG(FMT("kes{%s}") % strs.merge(",")), - strs.merge(", ")); + if (simpleStatus) + { + PRESENTATION_CHECK_RETURN(fmt, + STG(FMT("kes{%s}") % *(strs.list().begin())), + *(strs.list().begin())); + } + else + { + PRESENTATION_CHECK_RETURN(fmt, + STG(FMT("kes{%s}") % strs.merge(",")), + strs.merge(", ")); + } } } @@ -1397,7 +1483,7 @@ std::string Verbose::linkStatus(KSignaling sig, int32 code, Verbose::Presentatio STG(FMT("Unknown link status for '%s' (%d)") % signaling(sig) % (int)code)); } -std::string Verbose::channelStatus(KSignaling sig, int32 flags, Verbose::Presentation fmt) +std::string Verbose::channelStatus(const KSignaling sig, const int32 flags, const Verbose::Presentation fmt) { try { @@ -1413,8 +1499,10 @@ std::string Verbose::channelStatus(KSignaling sig, int32 flags, Verbose::Present #if K3L_EXACT(2,1,0) case ksigISUP: return presentation(fmt, "[ksigISUP]", "ISUP trunk"); +#if !K3L_AT_LEAST(2,2,0) case ksigFax: return presentation(fmt, "[ksigFax]", "FAX"); +#endif #endif case ksigAnalog: @@ -1532,7 +1620,7 @@ std::string Verbose::channelStatus(KSignaling sig, int32 flags, Verbose::Present } } } - catch (internal_not_found & e) + catch (internal_not_found e) { /* we use this exception to break the control flow */ } @@ -1542,7 +1630,7 @@ std::string Verbose::channelStatus(KSignaling sig, int32 flags, Verbose::Present STG(FMT("Unknown channel status for '%s' (%d)") % signaling(sig) % flags)); } -std::string Verbose::status(KLibraryStatus code, Verbose::Presentation fmt) +std::string Verbose::status(const KLibraryStatus code, const Verbose::Presentation fmt) { switch (code) { @@ -1569,7 +1657,7 @@ std::string Verbose::status(KLibraryStatus code, Verbose::Presentation fmt) STG(FMT("Unknown library status (%d)") % (int)code)); } -std::string Verbose::h100configIndex(KH100ConfigIndex code, Verbose::Presentation fmt) +std::string Verbose::h100configIndex(const KH100ConfigIndex code, const Verbose::Presentation fmt) { switch (code) { @@ -1584,7 +1672,7 @@ std::string Verbose::h100configIndex(KH100ConfigIndex code, Verbose::Presentatio case khciCTbusFreq07_04: return presentation(fmt, "khciCTbusFreq07_04", "CTBus Frequency 07 04"); // TODO: find better name case khciCTbusFreq11_08: return presentation(fmt, "khciCTbusFreq11_08", "CTBus Frequency 11 08"); // TODO: find better name case khciCTbusFreq15_12: return presentation(fmt, "khciCTbusFreq15_12", "CTBus Frequency 15 12"); // TODO: find better name - case khciMax: return presentation(fmt, "khciMax", "Max"); // TODO: find better name + case khciMax: return presentation(fmt, "khciMax", "Max"); // TODO: find better name case khciMasterDevId: return presentation(fmt, "khciMasterDevId", "Master Device Number"); case khciSecMasterDevId: return presentation(fmt, "khciSecMasterDevId", "Secondary Master Device Number"); case khciCtNetrefDevId: return presentation(fmt, "khciCtNetrefDevId", "CTBus Network Reference Device Number"); @@ -1599,7 +1687,7 @@ std::string Verbose::h100configIndex(KH100ConfigIndex code, Verbose::Presentatio } #if K3L_AT_LEAST(1,6,0) -std::string Verbose::callStartInfo(KCallStartInfo code, Verbose::Presentation fmt) +std::string Verbose::callStartInfo(const KCallStartInfo code, const Verbose::Presentation fmt) { switch (code) { @@ -1615,13 +1703,13 @@ std::string Verbose::callStartInfo(KCallStartInfo code, Verbose::Presentation fm STG(FMT("Unknown call answer info (%d)") % (int)code)); } -std::string Verbose::gsmCallCause(KGsmCallCause code, Verbose::Presentation fmt) +std::string Verbose::gsmCallCause(const KGsmCallCause code, const Verbose::Presentation fmt) { try { return internal_gsmCallCause(code, fmt); } - catch (internal_not_found & e) + catch (internal_not_found e) { PRESENTATION_CHECK_RETURN(fmt, STG(FMT("[KGsmCallCause='%d']") % (int)code), @@ -1629,7 +1717,7 @@ std::string Verbose::gsmCallCause(KGsmCallCause code, Verbose::Presentation fmt) } } -std::string Verbose::internal_gsmCallCause(KGsmCallCause code, Verbose::Presentation fmt) +std::string Verbose::internal_gsmCallCause(const KGsmCallCause code, const Verbose::Presentation fmt) { switch (code) { @@ -1686,13 +1774,13 @@ std::string Verbose::internal_gsmCallCause(KGsmCallCause code, Verbose::Presenta throw internal_not_found(); } -std::string Verbose::gsmMobileCause(KGsmMobileCause code, Verbose::Presentation fmt) +std::string Verbose::gsmMobileCause(const KGsmMobileCause code, const Verbose::Presentation fmt) { try { return internal_gsmMobileCause(code, fmt); } - catch (internal_not_found & e) + catch (internal_not_found e) { PRESENTATION_CHECK_RETURN(fmt, STG(FMT("[KGsmMobileCause='%d']") % (int)code), @@ -1700,7 +1788,7 @@ std::string Verbose::gsmMobileCause(KGsmMobileCause code, Verbose::Presentation } } -std::string Verbose::internal_gsmMobileCause(KGsmMobileCause code, Verbose::Presentation fmt) +std::string Verbose::internal_gsmMobileCause(const KGsmMobileCause code, const Verbose::Presentation fmt) { switch (code) { @@ -1792,13 +1880,13 @@ std::string Verbose::internal_gsmMobileCause(KGsmMobileCause code, Verbose::Pres throw internal_not_found(); } -std::string Verbose::gsmSmsCause(KGsmSmsCause code, Verbose::Presentation fmt) +std::string Verbose::gsmSmsCause(const KGsmSmsCause code, const Verbose::Presentation fmt) { try { return internal_gsmSmsCause(code, fmt); } - catch (internal_not_found & e) + catch (internal_not_found e) { PRESENTATION_CHECK_RETURN(fmt, STG(FMT("[KGsmSmsCause='%d']") % (int)code), @@ -1806,7 +1894,7 @@ std::string Verbose::gsmSmsCause(KGsmSmsCause code, Verbose::Presentation fmt) } } -std::string Verbose::internal_gsmSmsCause(KGsmSmsCause code, Verbose::Presentation fmt) +std::string Verbose::internal_gsmSmsCause(const KGsmSmsCause code, const Verbose::Presentation fmt) { switch (code) { @@ -1890,13 +1978,13 @@ std::string Verbose::internal_gsmSmsCause(KGsmSmsCause code, Verbose::Presentati throw internal_not_found(); } -std::string Verbose::q931ProgressIndication(KQ931ProgressIndication code, Verbose::Presentation fmt) +std::string Verbose::q931ProgressIndication(const KQ931ProgressIndication code, const Verbose::Presentation fmt) { try { return internal_q931ProgressIndication(code); } - catch (internal_not_found & e) + catch (internal_not_found e) { PRESENTATION_CHECK_RETURN(fmt, STG(FMT("[KQ931ProgressIndication='%d']") % (int)code), @@ -1904,7 +1992,7 @@ std::string Verbose::q931ProgressIndication(KQ931ProgressIndication code, Verbos } } -std::string Verbose::internal_q931ProgressIndication(KQ931ProgressIndication code, Verbose::Presentation fmt) +std::string Verbose::internal_q931ProgressIndication(const KQ931ProgressIndication code, const Verbose::Presentation fmt) { switch (code) { @@ -1924,7 +2012,7 @@ std::string Verbose::internal_q931ProgressIndication(KQ931ProgressIndication cod #if K3L_AT_LEAST(2,1,0) -std::string Verbose::faxResult(KFaxResult code, Verbose::Presentation fmt) +std::string Verbose::faxResult(const KFaxResult code, const Verbose::Presentation fmt) { switch (code) { @@ -1945,7 +2033,7 @@ std::string Verbose::faxResult(KFaxResult code, Verbose::Presentation fmt) STG(FMT("Unknown fax result (%d)") % (int)code)); } -std::string Verbose::faxFileErrorCause(KFaxFileErrorCause code, Verbose::Presentation fmt) +std::string Verbose::faxFileErrorCause(const KFaxFileErrorCause code, const Verbose::Presentation fmt) { switch (code) { @@ -1969,307 +2057,12 @@ std::string Verbose::faxFileErrorCause(KFaxFileErrorCause code, Verbose::Present #endif - /********/ -std::string Verbose::commandName(int32 code) -{ - switch ((kcommand)code) - { - case K_CM_SEIZE: return "CM_SEIZE"; - case K_CM_SYNC_SEIZE: return "CM_SYNC_SEIZE"; - case K_CM_DIAL_DTMF: return "CM_DIAL_DTMF"; -#if K3L_AT_LEAST(1,6,0) - case K_CM_SIP_REGISTER: return "CM_SIP_REGISTER"; -#endif - case K_CM_DISCONNECT: return "CM_DISCONNECT"; - case K_CM_CONNECT: return "CM_CONNECT"; - case K_CM_PRE_CONNECT: return "CM_PRE_CONNECT"; - case K_CM_CAS_CHANGE_LINE_STT: return "CM_CAS_CHANGE_LINE_STT"; - case K_CM_CAS_SEND_MFC: return "CM_CAS_SEND_MFC"; - case K_CM_SET_FORWARD_CHANNEL: return "CM_SET_FORWARD_CHANNEL"; - case K_CM_CAS_SET_MFC_DETECT_MODE: return "CM_CAS_SET_MFC_DETECT_MODE"; - case K_CM_DROP_COLLECT_CALL: return "CM_DROP_COLLECT_CALL"; - -#if K3L_AT_LEAST(1,5,0) - case K_CM_MAKE_CALL: return "CM_MAKE_CALL"; -#endif - -#if K3L_AT_LEAST(1,4,0) - case K_CM_RINGBACK: return "CM_RINGBACK"; -#endif - -#if K3L_AT_LEAST(1,5,1) - case K_CM_USER_INFORMATION: return "CM_USER_INFORMATION"; -#endif - -#if K3L_AT_LEAST(1,4,0) && !K3L_AT_LEAST(2,2,0) - case K_CM_VOIP_SEIZE: return "CM_VOIP_SEIZE"; - -#if !K3L_AT_LEAST(2,0,0) - /* internal commands */ - case K_CM_VOIP_START_DEBUG: return "CM_VOIP_START_DEBUG"; - case K_CM_VOIP_STOP_DEBUG: return "CM_VOIP_STOP_DEBUG"; - case K_CM_VOIP_DUMP_STAT: return "CM_VOIP_DUMP_STAT"; -#endif -#endif - -#if K3L_AT_LEAST(1,5,2) && !K3L_AT_LEAST(2,0,0) - /* internal command */ - case K_CM_ISDN_DEBUG: return "CM_ISDN_DEBUG"; -#endif - - case K_CM_LOCK_INCOMING: return "CM_LOCK_INCOMING"; - case K_CM_UNLOCK_INCOMING: return "CM_UNLOCK_INCOMING"; - case K_CM_LOCK_OUTGOING: return "CM_LOCK_OUTGOING"; - case K_CM_UNLOCK_OUTGOING: return "CM_UNLOCK_OUTGOING"; - - case K_CM_START_SEND_FAIL: return "CM_START_SEND_FAIL"; - case K_CM_STOP_SEND_FAIL: return "CM_STOP_SEND_FAIL"; - -#if K3L_AT_LEAST(1,5,3) - case K_CM_END_OF_NUMBER: return "CM_END_OF_NUMBER"; -#endif - -#if K3L_AT_LEAST(1,6,0) - case K_CM_SS_TRANSFER: return "CM_SS_TRANSFER"; - case K_CM_GET_SMS: return "CM_GET_SMS"; - case K_CM_PREPARE_SMS: return "CM_PREPARE_SMS"; - case K_CM_SEND_SMS: return "CM_SEND_SMS"; -#endif -#if K3L_HAS_MPTY_SUPPORT - case K_CM_HOLD_SWITCH: return "CM_HOLD_SWITCH"; - case K_CM_MPTY_CONF: return "CM_MPTY_CONF"; - case K_CM_MPTY_SPLIT: return "CM_MPTY_SPLIT"; -#endif - - case K_CM_ENABLE_DTMF_SUPPRESSION: return "CM_ENABLE_DTMF_SUPPRESSION"; - case K_CM_DISABLE_DTMF_SUPPRESSION: return "CM_DISABLE_DTMF_SUPPRESSION"; - case K_CM_ENABLE_AUDIO_EVENTS: return "CM_ENABLE_AUDIO_EVENTS"; - case K_CM_DISABLE_AUDIO_EVENTS: return "CM_DISABLE_AUDIO_EVENTS"; - case K_CM_ENABLE_CALL_PROGRESS: return "CM_ENABLE_CALL_PROGRESS"; - case K_CM_DISABLE_CALL_PROGRESS: return "CM_DISABLE_CALL_PROGRESS"; - case K_CM_FLASH: return "CM_FLASH"; - case K_CM_ENABLE_PULSE_DETECTION: return "CM_ENABLE_PULSE_DETECTION"; - case K_CM_DISABLE_PULSE_DETECTION: return "CM_DISABLE_PULSE_DETECTION"; - case K_CM_ENABLE_ECHO_CANCELLER: return "CM_ENABLE_ECHO_CANCELLER"; - case K_CM_DISABLE_ECHO_CANCELLER: return "CM_DISABLE_ECHO_CANCELLER"; - case K_CM_ENABLE_AGC: return "CM_ENABLE_AGC"; - case K_CM_DISABLE_AGC: return "CM_DISABLE_AGC"; - case K_CM_ENABLE_HIGH_IMP_EVENTS: return "CM_ENABLE_HIGH_IMP_EVENTS"; - case K_CM_DISABLE_HIGH_IMP_EVENTS: return "CM_DISABLE_HIGH_IMP_EVENTS"; - -#if K3L_AT_LEAST(1,6,0) - case K_CM_ENABLE_CALL_ANSWER_INFO: return "CM_ENABLE_CALL_ANSWER_INFO"; - case K_CM_DISABLE_CALL_ANSWER_INFO: return "CM_DISABLE_CALL_ANSWER_INFO"; -#endif - - case K_CM_RESET_LINK: return "CM_RESET_LINK"; - -#if K3L_AT_LEAST(1,6,0) - case K_CM_CLEAR_LINK_ERROR_COUNTER: return "CM_CLEAR_LINK_ERROR_COUNTER"; -#endif - - case K_CM_SEND_DTMF: return "CM_SEND_DTMF"; - case K_CM_STOP_AUDIO: return "CM_STOP_AUDIO"; - case K_CM_HARD_RESET: return "CM_HARD_RESET"; - - case K_CM_SEND_TO_CTBUS: return "CM_SEND_TO_CTBUS"; - case K_CM_RECV_FROM_CTBUS: return "CM_RECV_FROM_CTBUS"; - case K_CM_SETUP_H100: return "CM_SETUP_H100"; - - case K_CM_MIXER: return "CM_MIXER"; - case K_CM_CLEAR_MIXER: return "CM_CLEAR_MIXER"; - case K_CM_PLAY_FROM_FILE: return "CM_PLAY_FROM_FILE"; - case K_CM_RECORD_TO_FILE: return "CM_RECORD_TO_FILE"; - case K_CM_PLAY_FROM_STREAM: return "CM_PLAY_FROM_STREAM"; - case K_CM_STOP_PLAY: return "CM_STOP_PLAY"; - case K_CM_STOP_RECORD: return "CM_STOP_RECORD"; - case K_CM_PAUSE_PLAY: return "CM_PAUSE_PLAY"; - case K_CM_PAUSE_RECORD: return "CM_PAUSE_RECORD"; - case K_CM_INCREASE_VOLUME: return "CM_INCREASE_VOLUME"; - case K_CM_DECREASE_VOLUME: return "CM_DECREASE_VOLUME"; - case K_CM_LISTEN: return "CM_LISTEN"; - case K_CM_STOP_LISTEN: return "CM_STOP_LISTEN"; - case K_CM_PREPARE_FOR_LISTEN: return "CM_PREPARE_FOR_LISTEN"; - - case K_CM_PLAY_SOUND_CARD: return "CM_PLAY_SOUND_CARD"; - case K_CM_STOP_SOUND_CARD: return "CM_STOP_SOUND_CARD"; - - case K_CM_MIXER_CTBUS: return "CM_MIXER_CTBUS"; - case K_CM_PLAY_FROM_STREAM_EX: return "CM_PLAY_FROM_STREAM_EX"; - case K_CM_ENABLE_PLAYER_AGC: return "CM_ENABLE_PLAYER_AGC"; - case K_CM_DISABLE_PLAYER_AGC: return "CM_DISABLE_PLAYER_AGC"; - case K_CM_START_STREAM_BUFFER: return "CM_START_STREAM_BUFFER"; - case K_CM_ADD_STREAM_BUFFER: return "CM_ADD_STREAM_BUFFER"; - case K_CM_STOP_STREAM_BUFFER: return "CM_STOP_STREAM_BUFFER"; - case K_CM_SEND_BEEP: return "CM_SEND_BEEP"; - case K_CM_SEND_BEEP_CONF: return "CM_SEND_BEEP_CONF"; - case K_CM_ADD_TO_CONF: return "CM_ADD_TO_CONF"; - case K_CM_REMOVE_FROM_CONF: return "CM_REMOVE_FROM_CONF"; - case K_CM_RECORD_TO_FILE_EX: return "CM_RECORD_TO_FILE_EX"; - -#if K3L_AT_LEAST(1,5,4) - case K_CM_SET_VOLUME: return "CM_SET_VOLUME"; -#endif - case K_CM_SET_LINE_CONDITION: return "CM_SET_LINE_CONDITION"; - case K_CM_SEND_LINE_CONDITION: return "CM_SEND_LINE_CONDITION"; - case K_CM_SET_CALLER_CATEGORY: return "CM_SET_CALLER_CATEGORY"; - case K_CM_DIAL_MFC: return "CM_DIAL_MFC"; - - case K_CM_INTERNAL_PLAY: return "CM_INTERNAL_PLAY"; - case K_CM_RESUME_PLAY: return "CM_RESUME_PLAY"; - case K_CM_RESUME_RECORD: return "CM_RESUME_RECORD"; - case K_CM_INTERNAL_PLAY_EX: return "CM_INTERNAL_PLAY_EX"; -#if !K3L_AT_LEAST(2,0,0) - case K_CM_PING: return "CM_PING"; -#if K3L_AT_LEAST(1,6,0) - case K_CM_LOG_REQUEST: return "CM_LOG_REQUEST"; - case K_CM_LOG_CREATE_DISPATCHER: return "CM_LOG_CREATE_DISPATCHER"; - case K_CM_LOG_DESTROY_DISPATCHER: return "CM_LOG_DESTROY_DISPATCHER"; -#endif -#endif - -#if K3L_AT_LEAST(1,6,0) - case K_CM_START_CADENCE: return "CM_START_CADENCE"; - case K_CM_STOP_CADENCE: return "CM_STOP_CADENCE"; - case K_CM_CHECK_NEW_SMS: return "CM_CHECK_NEW_SMS"; - case K_CM_SEND_TO_MODEM: return "CM_SEND_TO_MODEM"; -#endif -#if K3L_AT_LEAST(2,1,0) - case K_CM_START_FAX_TX: return "CM_START_FAX_TX"; - case K_CM_STOP_FAX_TX: return "CM_STOP_FAX_TX"; - case K_CM_ADD_FAX_FILE: return "CM_ADD_FAX_FILE"; - case K_CM_ADD_FAX_PAGE_BREAK: return "CM_ADD_FAX_PAGE_BREAK"; - case K_CM_START_FAX_RX: return "CM_START_FAX_RX"; - case K_CM_STOP_FAX_RX: return "CM_STOP_FAX_RX"; - case K_CM_SIM_CARD_SELECT: return "CM_SIM_CARD_SELECT"; -#endif - -#if K3L_AT_LEAST(2,1,0) - case K_CM_NOTIFY_WATCHDOG: return "CM_NOTIFY_WATCHDOG"; - case K_CM_STOP_WATCHDOG: return "CM_STOP_WATCHDOG"; - case K_CM_WATCHDOG_COUNT: return "CM_WATCHDOG_COUNT"; - case K_CM_START_WATCHDOG: return "CM_START_WATCHDOG"; -#endif - - } - - return STG(FMT("[command='%d']") % code); -} - -std::string Verbose::eventName(int32 code) -{ - switch ((kevent)code) - { - case K_EV_CHANNEL_FREE: return "EV_CHANNEL_FREE"; - case K_EV_CONNECT: return "EV_CONNECT"; - case K_EV_DISCONNECT: return "EV_DISCONNECT"; - case K_EV_CALL_SUCCESS: return "EV_CALL_SUCCESS"; - case K_EV_CALL_FAIL: return "EV_CALL_FAIL"; - case K_EV_NO_ANSWER: return "EV_NO_ANSWER"; - case K_EV_BILLING_PULSE: return "EV_BILLING_PULSE"; - case K_EV_SEIZE_SUCCESS: return "EV_SEIZE_SUCCESS"; - case K_EV_SEIZE_FAIL: return "EV_SEIZE_FAIL"; - case K_EV_SEIZURE_START: return "EV_SEIZURE_START"; - case K_EV_CAS_LINE_STT_CHANGED: return "EV_CAS_LINE_STT_CHANGED"; - case K_EV_CAS_MFC_RECV: return "EV_CAS_MFC_RECV"; - -#if K3L_AT_LEAST(1,5,0) - case K_EV_NEW_CALL: return "EV_NEW_CALL"; -#endif - -#if K3L_AT_LEAST(1,5,1) - case K_EV_USER_INFORMATION: return "EV_USER_INFORMATION"; -#endif - -#if K3L_AT_LEAST(1,5,3) - case K_EV_DIALED_DIGIT: return "EV_DIALED_DIGIT"; -#endif - -#if K3L_AT_LEAST(1,6,0) - case K_EV_SIP_REGISTER_INFO: return "EV_SIP_REGISTER_INFO"; -#endif - -#if K3L_AT_LEAST(1,4,0) - case K_EV_CALL_HOLD_START: return "EV_CALL_HOLD_START"; - case K_EV_CALL_HOLD_STOP: return "EV_CALL_HOLD_STOP"; -#endif - -#if K3L_AT_LEAST(1,6,0) - case K_EV_SS_TRANSFER_FAIL: return "EV_SS_TRANSFER_FAIL"; - case K_EV_FLASH: return "EV_FLASH"; -#endif - - case K_EV_DTMF_DETECTED: return "EV_DTMF_DETECTED"; - case K_EV_DTMF_SEND_FINISH: return "EV_DTMF_SEND_FINISH"; - case K_EV_AUDIO_STATUS: return "EV_AUDIO_STATUS"; - case K_EV_CADENCE_RECOGNIZED: return "EV_CADENCE_RECOGNIZED"; - - case K_EV_END_OF_STREAM: return "EV_END_OF_STREAM"; - case K_EV_PULSE_DETECTED: return "EV_PULSE_DETECTED"; - -#if K3L_AT_LEAST(1,5,1) - case K_EV_POLARITY_REVERSAL: return "EV_POLARITY_REVERSAL"; -#endif - -#if K3L_AT_LEAST(1,6,0) - case K_EV_ISDN_PROGRESS_INDICATOR: return "EV_ISDN_PROGRESS_INDICATOR"; - case K_EV_CALL_ANSWER_INFO: return "EV_CALL_ANSWER_INFO"; - case K_EV_COLLECT_CALL: return "EV_COLLECT_CALL"; - case K_EV_SIP_DTMF_DETECTED: return "EV_SIP_DTMF_DETECTED"; - - case K_EV_RECV_FROM_MODEM: return "EV_RECV_FROM_MODEM"; - case K_EV_NEW_SMS: return "EV_NEW_SMS"; - case K_EV_SMS_INFO: return "EV_SMS_INFO"; - case K_EV_SMS_DATA: return "EV_SMS_DATA"; - case K_EV_SMS_SEND_RESULT: return "EV_SMS_SEND_RESULT"; - case K_EV_RING_DETECTED: return "EV_RING_DETECTED"; - case K_EV_PHYSICAL_LINK_DOWN: return "EV_PHYSICAL_LINK_DOWN"; - case K_EV_PHYSICAL_LINK_UP: return "EV_PHYSICAL_LINK_UP"; -#endif -#if K3L_HAS_MPTY_SUPPORT - case K_EV_CALL_MPTY_START: return "EV_CALL_MPTY_START"; - case K_EV_CALL_MPTY_STOP: return "EV_CALL_MPTY_STOP"; - case K_EV_GSM_COMMAND_STATUS: return "EV_GSM_COMMAND_STATUS"; -#endif -#if !K3L_AT_LEAST(2,0,0) - case K_EV_PONG: return "EV_PONG"; -#endif - case K_EV_CHANNEL_FAIL: return "EV_CHANNEL_FAIL"; - case K_EV_REFERENCE_FAIL: return "EV_REFERENCE_FAIL"; - case K_EV_INTERNAL_FAIL: return "EV_INTERNAL_FAIL"; - case K_EV_HARDWARE_FAIL: return "EV_HARDWARE_FAIL"; - case K_EV_LINK_STATUS: return "EV_LINK_STATUS"; - -#if K3L_AT_LEAST(1,4,0) - case K_EV_CLIENT_RECONNECT: return "EV_CLIENT_RECONNECT"; - case K_EV_VOIP_SEIZURE: return "EV_VOIP_SEIZURE"; -#endif - case K_EV_SEIZURE: return "EV_SEIZURE"; -#if K3L_AT_LEAST(2,1,0) - case K_EV_FAX_CHANNEL_FREE: return "EV_FAX_CHANNEL_FREE"; - case K_EV_FAX_FILE_SENT: return "EV_FAX_FILE_SENT"; - case K_EV_FAX_FILE_FAIL: return "EV_FAX_FILE_FAIL"; - /*case K_EV_FAX_MESSAGE_CONFIRMATION:return "EV_FAX_MESSAGE_CONFIRMATION";*/ - case K_EV_FAX_TX_TIMEOUT: return "EV_FAX_TX_TIMEOUT"; - case K_EV_FAX_PAGE_CONFIRMATION:return "EV_FAX_PAGE_CONFIRMATION"; - case K_EV_FAX_REMOTE_INFO: return "EV_FAX_REMOTE_INFO"; -#endif - -#if K3L_AT_LEAST(2,1,0) - case K_EV_WATCHDOG_COUNT: return "EV_WATCHDOG_COUNT"; -#endif - } - - return STG(FMT("[event='%d']") % code); -} - - #if K3L_AT_LEAST(2,0,0) -std::string Verbose::command(int32 dev, K3L_COMMAND *k3lcmd, R2CountryType r2_country, Verbose::Presentation fmt) +std::string Verbose::command(const int32 dev, const K3L_COMMAND * const k3lcmd, const R2CountryType r2_country, const Verbose::Presentation fmt) #else -std::string Verbose::command(int32 dev, K3L_COMMAND *k3lcmd, Verbose::Presentation fmt) +std::string Verbose::command(const int32 dev, const K3L_COMMAND * const k3lcmd, const Verbose::Presentation fmt) #endif { #if K3L_AT_LEAST(2,0,0) @@ -2280,106 +2073,107 @@ std::string Verbose::command(int32 dev, K3L_COMMAND *k3lcmd, Verbose::Presentati } #if K3L_AT_LEAST(2,0,0) -std::string Verbose::command(int32 cmd_code, int32 dev_idx, int32 obj_idx, const char * params, R2CountryType r2_country, Verbose::Presentation fmt) +std::string Verbose::command(const int32 cmd_code, const int32 dev_idx, const int32 obj_idx, const char * const params, const R2CountryType r2_country, const Verbose::Presentation fmt) #else -std::string Verbose::command(int32 cmd_code, int32 dev_idx, int32 obj_idx, const char * params, Verbose::Presentation fmt) +std::string Verbose::command(const int32 cmd_code, const int32 dev_idx, const int32 obj_idx, const char * const params, const Verbose::Presentation fmt) #endif { unsigned short int dev = (unsigned short int) dev_idx; unsigned short int obj = (unsigned short int) obj_idx; - kcommand code = (kcommand) cmd_code; + VerboseTraits::Command code = (VerboseTraits::Command) cmd_code; std::string buf, extra; switch (code) { - case K_CM_SEIZE: - case K_CM_SYNC_SEIZE: - //case K_CM_VOIP_SEIZE://deprecated - case K_CM_DIAL_MFC: - case K_CM_DIAL_DTMF: + case VerboseTraits::K_CM_SEIZE: + case VerboseTraits::K_CM_SYNC_SEIZE: + case VerboseTraits::K_CM_VOIP_SEIZE: + case VerboseTraits::K_CM_DIAL_MFC: + case VerboseTraits::K_CM_DIAL_DTMF: - case K_CM_CONNECT: - case K_CM_PRE_CONNECT: - case K_CM_DISCONNECT: - case K_CM_DROP_COLLECT_CALL: + case VerboseTraits::K_CM_CONNECT: + case VerboseTraits::K_CM_PRE_CONNECT: + case VerboseTraits::K_CM_DISCONNECT: + case VerboseTraits::K_CM_DROP_COLLECT_CALL: - case K_CM_START_SEND_FAIL: - case K_CM_STOP_SEND_FAIL: + case VerboseTraits::K_CM_START_SEND_FAIL: + case VerboseTraits::K_CM_STOP_SEND_FAIL: - case K_CM_ENABLE_DTMF_SUPPRESSION: - case K_CM_DISABLE_DTMF_SUPPRESSION: - case K_CM_ENABLE_AUDIO_EVENTS: - case K_CM_DISABLE_AUDIO_EVENTS: - case K_CM_ENABLE_CALL_PROGRESS: - case K_CM_DISABLE_CALL_PROGRESS: - case K_CM_ENABLE_PULSE_DETECTION: - case K_CM_DISABLE_PULSE_DETECTION: - case K_CM_ENABLE_ECHO_CANCELLER: - case K_CM_DISABLE_ECHO_CANCELLER: - case K_CM_ENABLE_AGC: - case K_CM_DISABLE_AGC: - case K_CM_ENABLE_HIGH_IMP_EVENTS: - case K_CM_DISABLE_HIGH_IMP_EVENTS: + case VerboseTraits::K_CM_ENABLE_DTMF_SUPPRESSION: + case VerboseTraits::K_CM_DISABLE_DTMF_SUPPRESSION: + case VerboseTraits::K_CM_ENABLE_AUDIO_EVENTS: + case VerboseTraits::K_CM_DISABLE_AUDIO_EVENTS: + case VerboseTraits::K_CM_ENABLE_CALL_PROGRESS: + case VerboseTraits::K_CM_DISABLE_CALL_PROGRESS: + case VerboseTraits::K_CM_ENABLE_PULSE_DETECTION: + case VerboseTraits::K_CM_DISABLE_PULSE_DETECTION: + case VerboseTraits::K_CM_ENABLE_ECHO_CANCELLER: + case VerboseTraits::K_CM_DISABLE_ECHO_CANCELLER: + case VerboseTraits::K_CM_ENABLE_AGC: + case VerboseTraits::K_CM_DISABLE_AGC: + case VerboseTraits::K_CM_ENABLE_HIGH_IMP_EVENTS: + case VerboseTraits::K_CM_DISABLE_HIGH_IMP_EVENTS: - case K_CM_FLASH: - case K_CM_RESET_LINK: - case K_CM_CLEAR_MIXER: + case VerboseTraits::K_CM_FLASH: + case VerboseTraits::K_CM_RESET_LINK: + case VerboseTraits::K_CM_CLEAR_MIXER: - case K_CM_LOCK_INCOMING: - case K_CM_UNLOCK_INCOMING: - case K_CM_LOCK_OUTGOING: - case K_CM_UNLOCK_OUTGOING: + case VerboseTraits::K_CM_LOCK_INCOMING: + case VerboseTraits::K_CM_UNLOCK_INCOMING: + case VerboseTraits::K_CM_LOCK_OUTGOING: + case VerboseTraits::K_CM_UNLOCK_OUTGOING: - case K_CM_INCREASE_VOLUME: - case K_CM_DECREASE_VOLUME: + case VerboseTraits::K_CM_INCREASE_VOLUME: + case VerboseTraits::K_CM_DECREASE_VOLUME: - case K_CM_STOP_RECORD: - case K_CM_PAUSE_RECORD: - case K_CM_RESUME_RECORD: + case VerboseTraits::K_CM_STOP_RECORD: + case VerboseTraits::K_CM_PAUSE_RECORD: + case VerboseTraits::K_CM_RESUME_RECORD: - case K_CM_STOP_LISTEN: + case VerboseTraits::K_CM_STOP_LISTEN: - case K_CM_PLAY_SOUND_CARD: - case K_CM_STOP_SOUND_CARD: - case K_CM_RINGBACK: + case VerboseTraits::K_CM_PLAY_SOUND_CARD: + case VerboseTraits::K_CM_STOP_SOUND_CARD: + case VerboseTraits::K_CM_RINGBACK: #if K3L_AT_LEAST(1,4,0) && !K3L_AT_LEAST(2,0,0) - case K_CM_VOIP_START_DEBUG: - case K_CM_VOIP_STOP_DEBUG: - case K_CM_VOIP_DUMP_STAT: + case VerboseTraits::K_CM_VOIP_START_DEBUG: + case VerboseTraits::K_CM_VOIP_STOP_DEBUG: + case VerboseTraits::K_CM_VOIP_DUMP_STAT: #endif #if K3L_AT_LEAST(1,5,3) - case K_CM_END_OF_NUMBER: + case VerboseTraits::K_CM_END_OF_NUMBER: #endif #if K3L_AT_LEAST(1,5,4) - case K_CM_SET_VOLUME: + case VerboseTraits::K_CM_SET_VOLUME: #endif #if K3L_AT_LEAST(1,6,0) - case K_CM_ENABLE_CALL_ANSWER_INFO: - case K_CM_DISABLE_CALL_ANSWER_INFO: + case VerboseTraits::K_CM_ENABLE_CALL_ANSWER_INFO: + case VerboseTraits::K_CM_DISABLE_CALL_ANSWER_INFO: - case K_CM_SS_TRANSFER: + case VerboseTraits::K_CM_SS_TRANSFER: - case K_CM_CHECK_NEW_SMS: - case K_CM_GET_SMS: - case K_CM_PREPARE_SMS: - case K_CM_SEND_SMS: + case VerboseTraits::K_CM_CHECK_NEW_SMS: + case VerboseTraits::K_CM_GET_SMS: + case VerboseTraits::K_CM_PREPARE_SMS: + case VerboseTraits::K_CM_SEND_SMS: - case K_CM_START_CADENCE: - case K_CM_STOP_CADENCE: - case K_CM_SEND_TO_MODEM: + case VerboseTraits::K_CM_START_CADENCE: + case VerboseTraits::K_CM_STOP_CADENCE: + case VerboseTraits::K_CM_SEND_TO_MODEM: #endif #if K3L_HAS_MPTY_SUPPORT - case K_CM_HOLD_SWITCH: - case K_CM_MPTY_CONF: - case K_CM_MPTY_SPLIT: + case VerboseTraits::K_CM_HOLD_SWITCH: + case VerboseTraits::K_CM_MPTY_CONF: + case VerboseTraits::K_CM_MPTY_SPLIT: #endif #if K3L_AT_LEAST(2,1,0) - case K_CM_SIM_CARD_SELECT: + case VerboseTraits::K_CM_SIM_CARD_SELECT: + case VerboseTraits::K_CM_CT_TRANSFER: #endif if (params != NULL) { @@ -2394,12 +2188,12 @@ std::string Verbose::command(int32 cmd_code, int32 dev_idx, int32 obj_idx, const return show(buf, commandName(code), Target(CHANNEL, dev, obj)); } - case K_CM_SEND_DTMF: /* ?? */ + case VerboseTraits::K_CM_SEND_DTMF: /* ?? */ return show(buf, commandName(code), Target(CHANNEL, dev, obj)); /****/ - case K_CM_STOP_AUDIO: + case VerboseTraits::K_CM_STOP_AUDIO: extra = "stop='"; switch ((params ? (int)(*params) : -1)) { @@ -2415,7 +2209,7 @@ std::string Verbose::command(int32 cmd_code, int32 dev_idx, int32 obj_idx, const /****/ #if K3L_AT_LEAST(1,5,2) && !K3L_AT_LEAST(2,0,0) - case K_CM_ISDN_DEBUG: + case VerboseTraits::K_CM_ISDN_DEBUG: extra = "flags='"; extra += isdnDebug((unsigned long)params); extra += "'"; @@ -2426,7 +2220,7 @@ std::string Verbose::command(int32 cmd_code, int32 dev_idx, int32 obj_idx, const /****/ #if K3L_AT_LEAST(1,5,1) - case K_CM_USER_INFORMATION: + case VerboseTraits::K_CM_USER_INFORMATION: #endif if (params != NULL) { @@ -2448,7 +2242,7 @@ std::string Verbose::command(int32 cmd_code, int32 dev_idx, int32 obj_idx, const - case K_CM_CAS_CHANGE_LINE_STT: + case VerboseTraits::K_CM_CAS_CHANGE_LINE_STT: { const char status = (params ? *params : 0x00); @@ -2462,7 +2256,7 @@ std::string Verbose::command(int32 cmd_code, int32 dev_idx, int32 obj_idx, const return show(buf, commandName(code), Target(CHANNEL, dev, obj), extra); } - case K_CM_CAS_SEND_MFC: + case VerboseTraits::K_CM_CAS_SEND_MFC: { char mfc = (params ? *params : 0xff); @@ -2471,7 +2265,7 @@ std::string Verbose::command(int32 cmd_code, int32 dev_idx, int32 obj_idx, const return show(buf, commandName(code), Target(CHANNEL, dev, obj), extra); } - case K_CM_CAS_SET_MFC_DETECT_MODE: + case VerboseTraits::K_CM_CAS_SET_MFC_DETECT_MODE: { int mode = (params ? *((int *)params) : -1); @@ -2480,7 +2274,7 @@ std::string Verbose::command(int32 cmd_code, int32 dev_idx, int32 obj_idx, const return show(buf, commandName(code), Target(CHANNEL, dev, obj), extra); } - case K_CM_SET_FORWARD_CHANNEL: + case VerboseTraits::K_CM_SET_FORWARD_CHANNEL: { int channel = (params ? *((int*) params) : -1); @@ -2490,7 +2284,7 @@ std::string Verbose::command(int32 cmd_code, int32 dev_idx, int32 obj_idx, const } #if K3L_AT_LEAST(1,5,0) - case K_CM_MAKE_CALL: + case VerboseTraits::K_CM_MAKE_CALL: extra = "options='"; extra += (params ? params : ""); extra += "'"; @@ -2498,8 +2292,8 @@ std::string Verbose::command(int32 cmd_code, int32 dev_idx, int32 obj_idx, const return show(buf, commandName(code), Target(CHANNEL, dev, obj), extra); #endif - case K_CM_MIXER: - case K_CM_MIXER_CTBUS: + case VerboseTraits::K_CM_MIXER: + case VerboseTraits::K_CM_MIXER_CTBUS: { if (params) { @@ -2537,29 +2331,29 @@ std::string Verbose::command(int32 cmd_code, int32 dev_idx, int32 obj_idx, const return show(buf, commandName(code), Target(MIXER, dev, obj), extra); }; - case K_CM_PLAY_FROM_FILE: + case VerboseTraits::K_CM_PLAY_FROM_FILE: extra = "file='"; extra += (params ? params : ""); extra += "'"; return show(buf, commandName(code), Target(PLAYER, dev, obj), extra); - case K_CM_RECORD_TO_FILE: + case VerboseTraits::K_CM_RECORD_TO_FILE: extra = "file='"; extra += (params ? params : ""); extra += "'"; return show(buf, commandName(code), Target(PLAYER, dev, obj), extra); - case K_CM_RECORD_TO_FILE_EX: + case VerboseTraits::K_CM_RECORD_TO_FILE_EX: extra = "params='"; extra += (params ? params : ""); extra += "'"; return show(buf, commandName(code), Target(PLAYER, dev, obj), extra); - case K_CM_PLAY_FROM_STREAM: - case K_CM_ADD_STREAM_BUFFER: + case VerboseTraits::K_CM_PLAY_FROM_STREAM: + case VerboseTraits::K_CM_ADD_STREAM_BUFFER: { struct buffer_param { @@ -2576,7 +2370,7 @@ std::string Verbose::command(int32 cmd_code, int32 dev_idx, int32 obj_idx, const return show(buf, commandName(code), Target(PLAYER, dev, obj), extra); } - case K_CM_PLAY_FROM_STREAM_EX: + case VerboseTraits::K_CM_PLAY_FROM_STREAM_EX: { struct buffer_param { @@ -2604,24 +2398,24 @@ std::string Verbose::command(int32 cmd_code, int32 dev_idx, int32 obj_idx, const return show(buf, commandName(code), Target(PLAYER, dev, obj), extra); } - case K_CM_STOP_PLAY: - case K_CM_PAUSE_PLAY: - case K_CM_RESUME_PLAY: + case VerboseTraits::K_CM_STOP_PLAY: + case VerboseTraits::K_CM_PAUSE_PLAY: + case VerboseTraits::K_CM_RESUME_PLAY: - case K_CM_START_STREAM_BUFFER: - case K_CM_STOP_STREAM_BUFFER: + case VerboseTraits::K_CM_START_STREAM_BUFFER: + case VerboseTraits::K_CM_STOP_STREAM_BUFFER: - case K_CM_ENABLE_PLAYER_AGC: - case K_CM_DISABLE_PLAYER_AGC: + case VerboseTraits::K_CM_ENABLE_PLAYER_AGC: + case VerboseTraits::K_CM_DISABLE_PLAYER_AGC: - case K_CM_SEND_BEEP: - case K_CM_SEND_BEEP_CONF: + case VerboseTraits::K_CM_SEND_BEEP: + case VerboseTraits::K_CM_SEND_BEEP_CONF: - case K_CM_INTERNAL_PLAY: - case K_CM_INTERNAL_PLAY_EX: + case VerboseTraits::K_CM_INTERNAL_PLAY: + case VerboseTraits::K_CM_INTERNAL_PLAY_EX: return show(buf, commandName(code), Target(PLAYER, dev, obj)); - case K_CM_ADD_TO_CONF: + case VerboseTraits::K_CM_ADD_TO_CONF: extra += "conference='"; extra += (params ? (int) (*params) : -1); extra += "'"; @@ -2631,8 +2425,8 @@ std::string Verbose::command(int32 cmd_code, int32 dev_idx, int32 obj_idx, const case CM_REMOVE_FROM_CONF: return show(buf, commandName(code), Target(MIXER, dev, obj)); - case K_CM_LISTEN: - case K_CM_PREPARE_FOR_LISTEN: + case VerboseTraits::K_CM_LISTEN: + case VerboseTraits::K_CM_PREPARE_FOR_LISTEN: { int msecs = (params ? *((int*)params) : -1); @@ -2641,8 +2435,8 @@ std::string Verbose::command(int32 cmd_code, int32 dev_idx, int32 obj_idx, const return show(buf, commandName(code), Target(PLAYER, dev, obj), extra); } - case K_CM_SEND_TO_CTBUS: - case K_CM_RECV_FROM_CTBUS: + case VerboseTraits::K_CM_SEND_TO_CTBUS: + case VerboseTraits::K_CM_RECV_FROM_CTBUS: { KCtbusCommand *p = (KCtbusCommand*)(params); @@ -2652,8 +2446,8 @@ std::string Verbose::command(int32 cmd_code, int32 dev_idx, int32 obj_idx, const return show(buf, commandName(code), Target(CHANNEL, dev, obj), extra); } - case K_CM_SET_LINE_CONDITION: - case K_CM_SEND_LINE_CONDITION: + case VerboseTraits::K_CM_SET_LINE_CONDITION: + case VerboseTraits::K_CM_SEND_LINE_CONDITION: extra = "condition='"; #if K3L_AT_LEAST(2,0,0) extra += signGroupB((KSignGroupB) *((int *) params), r2_country); @@ -2664,7 +2458,7 @@ std::string Verbose::command(int32 cmd_code, int32 dev_idx, int32 obj_idx, const return show(buf, commandName(code), Target(CHANNEL, dev, obj), extra); - case K_CM_SET_CALLER_CATEGORY: + case VerboseTraits::K_CM_SET_CALLER_CATEGORY: extra = "category='"; #if K3L_AT_LEAST(2,0,0) extra += signGroupII((KSignGroupII) *((int *) params), r2_country); @@ -2676,10 +2470,10 @@ std::string Verbose::command(int32 cmd_code, int32 dev_idx, int32 obj_idx, const return show(buf, commandName(code), Target(CHANNEL, dev, obj), extra); #if K3L_AT_LEAST(1,6,0) - case K_CM_CLEAR_LINK_ERROR_COUNTER: + case VerboseTraits::K_CM_CLEAR_LINK_ERROR_COUNTER: return show(buf, commandName(code), Target(LINK, dev, obj)); - case K_CM_SIP_REGISTER: + case VerboseTraits::K_CM_SIP_REGISTER: if (params != NULL) { extra += "param='"; @@ -2694,7 +2488,7 @@ std::string Verbose::command(int32 cmd_code, int32 dev_idx, int32 obj_idx, const } #endif - case K_CM_SETUP_H100: + case VerboseTraits::K_CM_SETUP_H100: extra += "option='"; extra += h100configIndex((KH100ConfigIndex)obj_idx); extra += "'value='"; @@ -2703,38 +2497,38 @@ std::string Verbose::command(int32 cmd_code, int32 dev_idx, int32 obj_idx, const return show(buf, commandName(code), Target(DEVICE, dev), extra); - case K_CM_HARD_RESET: + case VerboseTraits::K_CM_HARD_RESET: return show(buf, commandName(code), Target(LINK, dev, obj)); #if !K3L_AT_LEAST(2,0,0) /* como funciona? */ - case K_CM_LOG_REQUEST: - case K_CM_LOG_CREATE_DISPATCHER: - case K_CM_LOG_DESTROY_DISPATCHER: + case VerboseTraits::K_CM_LOG_REQUEST: + case VerboseTraits::K_CM_LOG_CREATE_DISPATCHER: + case VerboseTraits::K_CM_LOG_DESTROY_DISPATCHER: - case K_CM_PING: + case VerboseTraits::K_CM_PING: #endif return show(buf, commandName(code), Target(NONE)); #if K3L_AT_LEAST(2,1,0) - case K_CM_START_FAX_TX: - case K_CM_START_FAX_RX: - case K_CM_ADD_FAX_FILE: + case VerboseTraits::K_CM_START_FAX_TX: + case VerboseTraits::K_CM_START_FAX_RX: + case VerboseTraits::K_CM_ADD_FAX_FILE: extra = "params='"; extra += (params ? params : ""); extra += "'"; return show(buf, commandName(code), Target(CHANNEL, dev, obj), extra); - case K_CM_STOP_FAX_TX: - case K_CM_STOP_FAX_RX: - case K_CM_ADD_FAX_PAGE_BREAK: + case VerboseTraits::K_CM_STOP_FAX_TX: + case VerboseTraits::K_CM_STOP_FAX_RX: + case VerboseTraits::K_CM_ADD_FAX_PAGE_BREAK: return show(buf, commandName(code), Target(CHANNEL, dev, obj)); #endif #if K3L_AT_LEAST(2,1,0) - case K_CM_NOTIFY_WATCHDOG: - case K_CM_STOP_WATCHDOG: - case K_CM_START_WATCHDOG: + case VerboseTraits::K_CM_NOTIFY_WATCHDOG: + case VerboseTraits::K_CM_STOP_WATCHDOG: + case VerboseTraits::K_CM_START_WATCHDOG: return show(buf, commandName(code) , Target(DEVICE, obj)); - case K_CM_WATCHDOG_COUNT: + case VerboseTraits::K_CM_WATCHDOG_COUNT: return show(buf, commandName(code) , Target(NONE)); #endif @@ -2745,65 +2539,66 @@ std::string Verbose::command(int32 cmd_code, int32 dev_idx, int32 obj_idx, const } #if K3L_AT_LEAST(2,0,0) -std::string Verbose::event(KSignaling sig, int32 obj_idx, K3L_EVENT *ev, R2CountryType r2_country, Verbose::Presentation fmt) +std::string Verbose::event(const KSignaling sig, const int32 obj_idx, const K3L_EVENT * const ev, const R2CountryType r2_country, const Verbose::Presentation fmt) #else -std::string Verbose::event(KSignaling sig, int32 obj_idx, K3L_EVENT *ev, Verbose::Presentation fmt) +std::string Verbose::event(const KSignaling sig, const int32 obj_idx, const K3L_EVENT * const ev, const Verbose::Presentation fmt) #endif { unsigned short int dev = (unsigned short int) ev->DeviceId; unsigned short int obj = (unsigned short int) obj_idx; - kevent code = (kevent) ev->Code; + VerboseTraits::Event code = (VerboseTraits::Event) ev->Code; - std::string buf, extra; + std::string buf; + std::string extra; switch (code) { - case K_EV_CHANNEL_FREE: - case K_EV_SEIZE_SUCCESS: - case K_EV_CALL_SUCCESS: - case K_EV_NO_ANSWER: - case K_EV_CONNECT: - case K_EV_DTMF_SEND_FINISH: - case K_EV_SEIZURE_START: - case K_EV_BILLING_PULSE: - case K_EV_REFERENCE_FAIL: + case VerboseTraits::VerboseTraits::K_EV_CHANNEL_FREE: + case VerboseTraits::VerboseTraits::K_EV_SEIZE_SUCCESS: + case VerboseTraits::VerboseTraits::K_EV_CALL_SUCCESS: + case VerboseTraits::VerboseTraits::K_EV_NO_ANSWER: + case VerboseTraits::VerboseTraits::K_EV_CONNECT: + case VerboseTraits::VerboseTraits::K_EV_DTMF_SEND_FINISH: + case VerboseTraits::VerboseTraits::K_EV_SEIZURE_START: + case VerboseTraits::VerboseTraits::K_EV_BILLING_PULSE: + case VerboseTraits::VerboseTraits::K_EV_REFERENCE_FAIL: #if K3L_AT_LEAST(1,4,0) - case K_EV_CALL_HOLD_START: - case K_EV_CALL_HOLD_STOP: + case VerboseTraits::VerboseTraits::K_EV_CALL_HOLD_START: + case VerboseTraits::VerboseTraits::K_EV_CALL_HOLD_STOP: #endif #if K3L_AT_LEAST(1,5,0) - case K_EV_NEW_CALL: + case VerboseTraits::VerboseTraits::K_EV_NEW_CALL: #endif #if K3L_AT_LEAST(1,6,0) - case K_EV_FLASH: - case K_EV_POLARITY_REVERSAL: - case K_EV_COLLECT_CALL: - case K_EV_SS_TRANSFER_FAIL: - case K_EV_RING_DETECTED: + case VerboseTraits::VerboseTraits::K_EV_FLASH: + case VerboseTraits::VerboseTraits::K_EV_POLARITY_REVERSAL: + case VerboseTraits::VerboseTraits::K_EV_COLLECT_CALL: + case VerboseTraits::VerboseTraits::K_EV_RING_DETECTED: + case VerboseTraits::VerboseTraits::K_EV_SS_TRANSFER_FAIL: #endif #if K3L_HAS_MPTY_SUPPORT - case K_EV_CALL_MPTY_START: - case K_EV_CALL_MPTY_STOP: + case VerboseTraits::VerboseTraits::K_EV_CALL_MPTY_START: + case VerboseTraits::VerboseTraits::K_EV_CALL_MPTY_STOP: #endif break; #if K3L_AT_LEAST(1,6,0) - case K_EV_RECV_FROM_MODEM: - case K_EV_SMS_INFO: - case K_EV_SMS_DATA: + case VerboseTraits::VerboseTraits::K_EV_RECV_FROM_MODEM: + case VerboseTraits::VerboseTraits::K_EV_SMS_INFO: + case VerboseTraits::VerboseTraits::K_EV_SMS_DATA: +#endif extra = "data='"; extra += (ev->Params ? (const char *)(ev->Params) : ""); extra += "'"; return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); -#endif #if K3L_AT_LEAST(1,6,0) - case K_EV_SMS_SEND_RESULT: + case VerboseTraits::VerboseTraits::K_EV_SMS_SEND_RESULT: extra = "result='"; #if K3L_AT_LEAST(2,0,0) extra += gsmSmsCause((KGsmSmsCause)ev->AddInfo); @@ -2814,20 +2609,20 @@ std::string Verbose::event(KSignaling sig, int32 obj_idx, K3L_EVENT *ev, Verbose return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); #if K3L_HAS_MPTY_SUPPORT - case K_EV_GSM_COMMAND_STATUS: + case VerboseTraits::VerboseTraits::K_EV_GSM_COMMAND_STATUS: extra = "result='"; extra += gsmMobileCause((KGsmMobileCause)ev->AddInfo); extra += "'"; return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); #endif - case K_EV_CALL_ANSWER_INFO: + case VerboseTraits::VerboseTraits::K_EV_CALL_ANSWER_INFO: extra = "info='"; extra += callStartInfo((KCallStartInfo)ev->AddInfo); extra += "'"; return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); - case K_EV_NEW_SMS: + case VerboseTraits::VerboseTraits::K_EV_NEW_SMS: if (ev->AddInfo != 0) { extra = "messages='"; @@ -2840,7 +2635,7 @@ std::string Verbose::event(KSignaling sig, int32 obj_idx, K3L_EVENT *ev, Verbose return show(buf, eventName(code), Target(CHANNEL, dev, obj)); } - case K_EV_ISDN_PROGRESS_INDICATOR: + case VerboseTraits::VerboseTraits::K_EV_ISDN_PROGRESS_INDICATOR: if (ev->AddInfo != 0) { extra = "indication='"; @@ -2854,19 +2649,19 @@ std::string Verbose::event(KSignaling sig, int32 obj_idx, K3L_EVENT *ev, Verbose } #endif - case K_EV_CAS_LINE_STT_CHANGED: + case VerboseTraits::VerboseTraits::K_EV_CAS_LINE_STT_CHANGED: extra = STG(FMT("[a=%d,b=%d,c=%d,d=%d]") % ((ev->AddInfo & 0x8) >> 3) % ((ev->AddInfo & 0x4) >> 2) % ((ev->AddInfo & 0x2) >> 1) % (ev->AddInfo & 0x1)); return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); - case K_EV_CAS_MFC_RECV: + case VerboseTraits::VerboseTraits::K_EV_CAS_MFC_RECV: extra = STG(FMT("digit='%d'") % ev->AddInfo); return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); - case K_EV_CALL_FAIL: + case VerboseTraits::VerboseTraits::K_EV_CALL_FAIL: extra = "cause='"; #if K3L_AT_LEAST(2,0,0) extra += callFail(sig, r2_country, ev->AddInfo); @@ -2887,7 +2682,7 @@ std::string Verbose::event(KSignaling sig, int32 obj_idx, K3L_EVENT *ev, Verbose return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); - case K_EV_DISCONNECT: + case VerboseTraits::VerboseTraits::K_EV_DISCONNECT: switch (sig) { #if K3L_AT_LEAST(1,5,1) @@ -2921,16 +2716,16 @@ std::string Verbose::event(KSignaling sig, int32 obj_idx, K3L_EVENT *ev, Verbose break; #if K3L_AT_LEAST(1,6,0) - case K_EV_SIP_DTMF_DETECTED: + case VerboseTraits::VerboseTraits::K_EV_SIP_DTMF_DETECTED: #endif - case K_EV_DTMF_DETECTED: - case K_EV_PULSE_DETECTED: - case K_EV_DIALED_DIGIT: + case VerboseTraits::VerboseTraits::K_EV_DTMF_DETECTED: + case VerboseTraits::VerboseTraits::K_EV_PULSE_DETECTED: + case VerboseTraits::VerboseTraits::K_EV_DIALED_DIGIT: extra = STG(FMT("digit='%c'") % (char)ev->AddInfo); return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); - case K_EV_SEIZURE: + case VerboseTraits::VerboseTraits::K_EV_SEIZURE: { KIncomingSeizeParams *n = (KIncomingSeizeParams *) ( ((char*)ev) + sizeof(K3L_EVENT) ); @@ -2945,7 +2740,7 @@ std::string Verbose::event(KSignaling sig, int32 obj_idx, K3L_EVENT *ev, Verbose } #if K3L_AT_LEAST(1,4,0) - case K_EV_VOIP_SEIZURE: + case VerboseTraits::VerboseTraits::K_EV_VOIP_SEIZURE: { char *numB = ((char*)ev) + sizeof(K3L_EVENT); char *numA = numB + 61; @@ -2961,43 +2756,43 @@ std::string Verbose::event(KSignaling sig, int32 obj_idx, K3L_EVENT *ev, Verbose #endif - case K_EV_END_OF_STREAM: + case VerboseTraits::VerboseTraits::K_EV_END_OF_STREAM: return show(buf, eventName(code), Target(PLAYER, dev, obj)); - case K_EV_AUDIO_STATUS: + case VerboseTraits::VerboseTraits::K_EV_AUDIO_STATUS: extra = "tone='"; extra += mixerTone((KMixerTone)ev->AddInfo); extra += "'"; return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); - case K_EV_CADENCE_RECOGNIZED: + case VerboseTraits::VerboseTraits::K_EV_CADENCE_RECOGNIZED: extra = STG(FMT("cadence='%c'") % (char)(ev->AddInfo)); return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); - case K_EV_CHANNEL_FAIL: + case VerboseTraits::VerboseTraits::K_EV_CHANNEL_FAIL: extra = "reason='"; extra += channelFail(sig, ev->AddInfo); extra += "'"; return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); - case K_EV_SEIZE_FAIL: + case VerboseTraits::VerboseTraits::K_EV_SEIZE_FAIL: extra = "reason='"; extra += seizeFail((KSeizeFail) ev->AddInfo); extra += "'"; return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); - case K_EV_INTERNAL_FAIL: + case VerboseTraits::VerboseTraits::K_EV_INTERNAL_FAIL: extra = "reason='"; extra += internalFail((KInternalFail) ev->AddInfo); extra += "'"; return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); - case K_EV_HARDWARE_FAIL: + case VerboseTraits::VerboseTraits::K_EV_HARDWARE_FAIL: extra = "component='"; extra += systemObject((KSystemObject) ev->AddInfo); extra += "'"; @@ -3018,18 +2813,18 @@ std::string Verbose::event(KSignaling sig, int32 obj_idx, K3L_EVENT *ev, Verbose } - case K_EV_LINK_STATUS: + case VerboseTraits::VerboseTraits::K_EV_LINK_STATUS: // EV_LINK_STATUS has always zero in ObjectInfo (and AddInfo!) /* fall throught... */ #if K3L_AT_LEAST(1,6,0) - case K_EV_PHYSICAL_LINK_UP: - case K_EV_PHYSICAL_LINK_DOWN: + case VerboseTraits::VerboseTraits::K_EV_PHYSICAL_LINK_UP: + case VerboseTraits::VerboseTraits::K_EV_PHYSICAL_LINK_DOWN: return show(buf, eventName(code), Target(LINK, dev, obj)); #endif #if K3L_AT_LEAST(1,5,1) - case K_EV_USER_INFORMATION: + case VerboseTraits::VerboseTraits::K_EV_USER_INFORMATION: { KUserInformation *info = (KUserInformation *)(ev->Params); @@ -3044,7 +2839,7 @@ std::string Verbose::event(KSignaling sig, int32 obj_idx, K3L_EVENT *ev, Verbose #endif #if K3L_AT_LEAST(1,6,0) - case K_EV_SIP_REGISTER_INFO: + case VerboseTraits::VerboseTraits::K_EV_SIP_REGISTER_INFO: extra = "params='"; extra += (ev->Params ? (const char *) (ev->Params) : ""); extra += "',status='"; @@ -3055,28 +2850,28 @@ std::string Verbose::event(KSignaling sig, int32 obj_idx, K3L_EVENT *ev, Verbose #endif #if !K3L_AT_LEAST(2,0,0) - case K_EV_PONG: + case VerboseTraits::VerboseTraits::K_EV_PONG: #endif #if K3L_AT_LEAST(1,4,0) - case K_EV_CLIENT_RECONNECT: + case VerboseTraits::VerboseTraits::K_EV_CLIENT_RECONNECT: #endif return show(buf, eventName(code), Target(NONE)); #if K3L_AT_LEAST(2,1,0) - case K_EV_FAX_CHANNEL_FREE: + case VerboseTraits::VerboseTraits::K_EV_FAX_CHANNEL_FREE: extra = "status='"; extra += faxResult((KFaxResult)ev->AddInfo); extra += "'"; return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); - case K_EV_FAX_FILE_SENT: + case VerboseTraits::VerboseTraits::K_EV_FAX_FILE_SENT: extra = "filename='"; extra += (ev->Params ? (const char *) (ev->Params) : ""); extra += "'"; return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); - case K_EV_FAX_FILE_FAIL: + case VerboseTraits::VerboseTraits::K_EV_FAX_FILE_FAIL: extra = "cause='"; extra += faxFileErrorCause((KFaxFileErrorCause)ev->AddInfo); extra += "',filename='"; @@ -3084,22 +2879,29 @@ std::string Verbose::event(KSignaling sig, int32 obj_idx, K3L_EVENT *ev, Verbose extra += "'"; return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); - case K_EV_FAX_REMOTE_INFO: + case VerboseTraits::VerboseTraits::K_EV_FAX_REMOTE_INFO: extra = ((ev->Params && ev->ParamSize != 0) ? (const char *) ev->Params : ""); return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); - /*case K_EV_FAX_MESSAGE_CONFIRMATION:*/ - case K_EV_FAX_PAGE_CONFIRMATION: - case K_EV_FAX_TX_TIMEOUT: + case VerboseTraits::VerboseTraits::K_EV_FAX_PAGE_CONFIRMATION: + case VerboseTraits::VerboseTraits::K_EV_FAX_TX_TIMEOUT: return show(buf, eventName(code), Target(CHANNEL, dev, obj)); #endif #if K3L_AT_LEAST(2,1,0) - case K_EV_WATCHDOG_COUNT: + case VerboseTraits::VerboseTraits::K_EV_WATCHDOG_COUNT: extra = STG(FMT("count='%d'") % (char)ev->AddInfo); return show(buf , eventName(code), Target(NONE), extra); #endif +#if K3L_AT_LEAST(2,1,0) + case VerboseTraits::VerboseTraits::K_EV_CT_TRANSFER_FAIL: + extra = "cause='"; + extra += isdnCause((KQ931Cause)ev->AddInfo); + extra += "'"; + + return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); +#endif } // default handler... @@ -3117,7 +2919,7 @@ std::string Verbose::event(KSignaling sig, int32 obj_idx, K3L_EVENT *ev, Verbose /********************************************/ -std::string Verbose::show(std::string & buf, std::string name, Target tgt, std::string & extra) +std::string Verbose::show(std::string & buf, const std::string & name, const Target tgt, const std::string & extra) { if (tgt.type == NONE) { @@ -3134,7 +2936,7 @@ std::string Verbose::show(std::string & buf, std::string name, Target tgt, std:: return buf; } -std::string Verbose::show(std::string & buf, std::string name, Target tgt) +std::string Verbose::show(std::string & buf, const std::string & name, const Target tgt) { std::string tmp(""); @@ -3142,7 +2944,7 @@ std::string Verbose::show(std::string & buf, std::string name, Target tgt) return buf; } -void Verbose::generate(std::string &buf, std::string &name, Target tgt, std::string &extra) +void Verbose::generate(std::string & buf, const std::string & name, const Target tgt, const std::string & extra) { switch (tgt.type) { diff --git a/src/mod/endpoints/mod_khomp/commons/base/verbose.hpp b/src/mod/endpoints/mod_khomp/commons/base/verbose.hpp new file mode 100644 index 0000000000..a0ea290b7e --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/base/verbose.hpp @@ -0,0 +1,303 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#ifndef _VERBOSE_HPP_ +#define _VERBOSE_HPP_ + +#include +#include +#include + +#include + +// k3lApiMajorVersion +#ifndef CM_PING +# include +# include +#endif + +#include +#include +#include + +#include + +struct Verbose +{ + typedef enum + { + R2_COUNTRY_BRA = 1, + R2_COUNTRY_ARG = 2, + R2_COUNTRY_CHI = 3, + R2_COUNTRY_MEX = 4, + R2_COUNTRY_URY = 5, + R2_COUNTRY_VEN = 6 + } + R2CountryType; + + typedef enum + { + HUMAN, + EXACT + } + Presentation; + + /* dynamic (object) stuff */ + + Verbose(const K3LAPI & api) + : _api(api) {}; + +#if K3L_AT_LEAST(2,0,0) + std::string event(const int32, const K3L_EVENT * const, + const R2CountryType r2_country = R2_COUNTRY_BRA, + const Presentation fmt = HUMAN) const; +#else + std::string event(const int32, const K3L_EVENT * const, + const Presentation fmt = HUMAN) const; +#endif + + std::string channelStatus(const int32, const int32, const int32, + const Presentation fmt = HUMAN) const; + + /* end of dynamic (object) stuff */ + + protected: + const K3LAPI & _api; + + /* used internally */ + struct internal_not_found {}; + + public: + + /* static (class) stuff */ + + static std::string echoLocation(const KEchoLocation, const Presentation fmt = HUMAN); + static std::string echoCancellerConfig(const KEchoCancellerConfig, const Presentation fmt = HUMAN); + +#if K3L_AT_LEAST(2,0,0) + static std::string event(const KSignaling, const int32, const K3L_EVENT * const, + const R2CountryType = R2_COUNTRY_BRA, Presentation fmt = HUMAN); +#else + static std::string event(const KSignaling, const int32, const K3L_EVENT * const, + const Presentation fmt = HUMAN); +#endif + +#if K3L_AT_LEAST(2,0,0) + static std::string command(const int32, const K3L_COMMAND * const, + const R2CountryType = R2_COUNTRY_BRA, + const Presentation fmt = HUMAN); + + static std::string command(const int32, const int32, const int32, const char * const, + const R2CountryType = R2_COUNTRY_BRA, + const Presentation fmt = HUMAN); +#else + static std::string command(const int32, const K3L_COMMAND * const, + const Presentation fmt = HUMAN); + + static std::string command(const int32, const int32, const int32, const char * const, + const Presentation fmt = HUMAN); +#endif + + static std::string deviceName(const KDeviceType, const int32, const int32 count = 0, const Presentation fmt = HUMAN); + static std::string deviceName(const KDeviceType, const int32, const Presentation fmt); + + static std::string deviceType(const KDeviceType, const int32 count = 0, const Presentation fmt = HUMAN); + static std::string deviceType(const KDeviceType, const Presentation fmt); + + static std::string deviceModel(const KDeviceType, const int32, const int32 count = 0, const Presentation fmt = HUMAN); + static std::string deviceModel(const KDeviceType, const int32, const Presentation fmt); + + static std::string channelFeatures(const int32, const Presentation fmt = HUMAN); + static std::string signaling(const KSignaling, const Presentation fmt = HUMAN); + static std::string systemObject(const KSystemObject, const Presentation fmt = HUMAN); + static std::string mixerTone(const KMixerTone, const Presentation fmt = HUMAN); + static std::string mixerSource(const KMixerSource, const Presentation fmt = HUMAN); + + static std::string seizeFail(const KSeizeFail, const Presentation fmt = HUMAN); + +#if K3L_AT_LEAST(2,0,0) + static std::string callFail(const KSignaling, const R2CountryType, const int32, const Presentation fmt = HUMAN); +#else + static std::string callFail(const KSignaling, const int32, const Presentation fmt = HUMAN); +#endif + + static std::string channelFail(const KSignaling, const int32, const Presentation fmt = HUMAN); + static std::string internalFail(const KInternalFail, const Presentation fmt = HUMAN); + + static std::string linkErrorCounter(const KLinkErrorCounter, const Presentation fmt = HUMAN); + + static std::string linkStatus(const KSignaling, const int32, const Presentation fmt = HUMAN, const bool simpleStatus = false); + static std::string channelStatus(const KSignaling, const int32, const Presentation fmt = HUMAN); + static std::string callStatus(const KCallStatus, const Presentation fmt = HUMAN); + static std::string status(const KLibraryStatus, const Presentation fmt = HUMAN); + +#if K3L_AT_LEAST(2,0,0) + static std::string signGroupB(const KSignGroupB, const R2CountryType contry = R2_COUNTRY_BRA, + Presentation fmt = HUMAN); +#else + static std::string signGroupB(const KSignGroupB, const Presentation fmt = HUMAN); +#endif + +#if K3L_AT_LEAST(2,0,0) + static std::string signGroupII(const KSignGroupII, const R2CountryType contry = R2_COUNTRY_BRA, + Presentation fmt = HUMAN); +#else + static std::string signGroupII(const KSignGroupII, const Presentation fmt = HUMAN); +#endif + + static std::string h100configIndex(const KH100ConfigIndex, const Presentation fmt = HUMAN); + + static std::string eventName(const int32 value) + { + return VerboseTraits::eventName((VerboseTraits::Event)value); + }; + + static std::string commandName(const int32 value) + { + return VerboseTraits::commandName((VerboseTraits::Command)value); + }; + +#if K3L_AT_LEAST(1,5,0) + static std::string sipFailures(const KSIP_Failures, const Presentation fmt = HUMAN); +#endif + +#if K3L_AT_LEAST(1,5,1) + static std::string isdnCause(const KQ931Cause, const Presentation fmt = HUMAN); +#endif + +#if K3L_AT_LEAST(1,5,2) + static std::string isdnDebug(const int32, const Presentation fmt = HUMAN); +#endif + +#if K3L_AT_LEAST(1,6,0) + static std::string callStartInfo(const KCallStartInfo, const Presentation fmt = HUMAN); + + static std::string gsmCallCause(const KGsmCallCause, const Presentation fmt = HUMAN); + static std::string gsmMobileCause(const KGsmMobileCause, const Presentation fmt = HUMAN); + static std::string gsmSmsCause(const KGsmSmsCause, const Presentation fmt = HUMAN); + + static std::string q931ProgressIndication(const KQ931ProgressIndication, + Presentation fmt = HUMAN); +#endif + +#if K3L_AT_LEAST(2,1,0) + static std::string faxResult(const KFaxResult code, const Presentation fmt = HUMAN); + static std::string faxFileErrorCause(const KFaxFileErrorCause code, const Presentation fmt = HUMAN); +#endif + + /* end of static (class) stuff */ + + private: + static std::string internal_deviceType(const KDeviceType, const int32); + static std::string internal_deviceModel(const KDeviceType, const int32, const int32); + +#if K3L_AT_LEAST(1,5,0) + static std::string internal_sipFailures(const KSIP_Failures, const Presentation fmt = HUMAN); +#endif +#if K3L_AT_LEAST(1,5,1) + static std::string internal_isdnCause(const KQ931Cause, const Presentation fmt = HUMAN); +#endif + +#if K3L_AT_LEAST(2,0,0) + static std::string internal_signGroupB(const KSignGroupB, const R2CountryType contry, const Presentation fmt = HUMAN); + static std::string internal_signGroupII(const KSignGroupII, const R2CountryType contry, const Presentation fmt = HUMAN); +#else + static std::string internal_signGroupB(const KSignGroupB, const Presentation fmt = HUMAN); + static std::string internal_signGroupII(const KSignGroupII, const Presentation fmt = HUMAN); +#endif + +#if K3L_AT_LEAST(1,6,0) + static std::string internal_gsmCallCause(const KGsmCallCause, const Presentation fmt = HUMAN); + static std::string internal_gsmMobileCause(const KGsmMobileCause, const Presentation fmt = HUMAN); + static std::string internal_gsmSmsCause(const KGsmSmsCause, const Presentation fmt = HUMAN); + + static std::string internal_q931ProgressIndication(const KQ931ProgressIndication, const Presentation fmt = HUMAN); +#endif + + private: + enum Type + { + DEVICE, + CHANNEL, + PLAYER, + MIXER, + LINK, + NONE + }; + + struct Target + { + Target(Type _type) + : type(_type), device(-1), object(-1) + {}; + + Target(Type _type, int32 _device) + : type(_type), device(_device), object(-1) + {}; + + Target(Type _type, int32 _device, int32 _object) + : type(_type), device(_device), object(_object) + {}; + + const Type type; + const int32 device; + const int32 object; + }; + + static void generate(std::string &, const std::string &, const Target, const std::string &); + + static std::string show(std::string &, const std::string &, const Target, const std::string &); + static std::string show(std::string &, const std::string &, const Target); + + template < typename ReturnType > + static ReturnType presentation(const Presentation fmt, ReturnType str_exact, ReturnType str_human) + { + switch (fmt) + { + case HUMAN: return str_human; + case EXACT: return str_exact; + }; + + return str_exact; + } +}; + +#endif /* _VERBOSE_HPP_ */ diff --git a/src/mod/endpoints/mod_khomp/commons/config_options.cpp b/src/mod/endpoints/mod_khomp/commons/config_options.cpp deleted file mode 100644 index 5383855f65..0000000000 --- a/src/mod/endpoints/mod_khomp/commons/config_options.cpp +++ /dev/null @@ -1,710 +0,0 @@ -/* - KHOMP generic endpoint/channel library. - Copyright (C) 2007-2009 Khomp Ind. & Com. - - The contents of this file are subject to the Mozilla Public License Version 1.1 - (the "License"); you may not use this file except in compliance with the - License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ - - Software distributed under the License is distributed on an "AS IS" basis, - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for - the specific language governing rights and limitations under the License. - - Alternatively, the contents of this file may be used under the terms of the - "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which - case the provisions of "LGPL License" are applicable instead of those above. - - If you wish to allow use of your version of this file only under the terms of - the LGPL License and not to allow others to use your version of this file under - the MPL, indicate your decision by deleting the provisions above and replace them - with the notice and other provisions required by the LGPL License. If you do not - delete the provisions above, a recipient may use your version of this file under - either the MPL or the LGPL License. - - The LGPL header follows below: - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this library; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -*/ - -#include - -ConfigOption::ConfigOption(std::string name, const ConfigOption::StringType & value, const ConfigOption::StringType defvalue, string_allowed_type allowed, bool list_me) -: _my_name(name), _value_data(new StringData(const_cast(value), defvalue, allowed), true), - _list_me(list_me), _values(NULL), _loaded(false) -{}; - -ConfigOption::ConfigOption(std::string name, const ConfigOption::StringType & value, const ConfigOption::StringType defvalue, bool list_me) -: _my_name(name), _value_data(new StringData(const_cast(value), defvalue, string_allowed_type()), true), - _list_me(list_me), _values(NULL), _loaded(false) -{}; - -ConfigOption::ConfigOption(std::string name, const ConfigOption::SignedIntType & value, const ConfigOption::SignedIntType defvalue, - ConfigOption::SignedIntType min, ConfigOption::SignedIntType max, ConfigOption::SignedIntType step, bool list_me) -: _my_name(name), _value_data(new SignedIntData(const_cast(value), defvalue, Range(min, max, step)), true), - _list_me(list_me), _values(NULL), _loaded(false) -{}; - -ConfigOption::ConfigOption(std::string name, const ConfigOption::UnsignedIntType & value, const ConfigOption::UnsignedIntType defvalue, - ConfigOption::UnsignedIntType min, ConfigOption::UnsignedIntType max, ConfigOption::UnsignedIntType step, bool list_me) -: _my_name(name), _value_data(new UnsignedIntData(const_cast(value), defvalue, Range(min, max, step)), true), - _list_me(list_me), _values(NULL), _loaded(false) -{}; - -ConfigOption::ConfigOption(std::string name, const ConfigOption::BooleanType & value, const ConfigOption::BooleanType defvalue, bool list_me) -: _my_name(name), _value_data(new BooleanData(const_cast(value), defvalue), true), - _list_me(list_me), _values(NULL), _loaded(false) -{}; - -ConfigOption::ConfigOption(std::string name, ConfigOption::FunctionType fun, std::string defvalue, string_allowed_type allowed, bool list_me) -: _my_name(name), _value_data(new FunctionData(fun, defvalue, allowed), true), - _list_me(list_me), _values(NULL), _loaded(false) -{}; - -ConfigOption::ConfigOption(std::string name, ConfigOption::FunctionType fun, std::string defvalue, bool list_me) -: _my_name(name), _value_data(new FunctionData(fun, defvalue, string_allowed_type()), true), - _list_me(list_me), _values(NULL), _loaded(false) -{}; - -ConfigOption::ConfigOption(const ConfigOption & o) -: _my_name(o._my_name), _value_data(o._value_data), - _list_me(o._list_me), _values(o._values), _loaded(o._loaded) -{}; - -ConfigOption::~ConfigOption(void) -{ - if (_values) - { - for (unsigned int i = 0; _values[i] != NULL; i++) - delete _values[i]; - - delete[] _values; - _values = NULL; - } -}; - -void ConfigOption::set(ConfigOption::StringType value) -{ - switch (_value_data.which()) - { - case ID_STRING: - { - try - { - StringData & tmp = _value_data.get(); - - if (tmp.string_allowed.empty()) - { - tmp.string_val = value; - _loaded = true; - } - else - { - if (tmp.string_allowed.find(value) != tmp.string_allowed.end()) - { - tmp.string_val = value; - _loaded = true; - return; - } - - std::string allowed_string; - - for (string_allowed_type::iterator i = tmp.string_allowed.begin(); i != tmp.string_allowed.end(); i++) - { - allowed_string += " '"; - allowed_string += (*i); - allowed_string += "'"; - } - - throw ConfigProcessFailure(STG(FMT("value '%s' not allowed for option '%s' (allowed values:%s)") - % value % _my_name % allowed_string)); - } - break; - } - catch(ValueType::InvalidType & e) - { - throw; - } - } - - case ID_FUN: - { - try - { - FunctionData & tmp = _value_data.get(); - tmp.fun_val(value); - _loaded = true; - break; - } - catch(ValueType::InvalidType & e) - { - throw; - } - - } - - default: - { - throw ConfigProcessFailure(STG(FMT("option '%s' is not of type string, nor function defined") % _my_name)); - } - } -} - -void ConfigOption::set(ConfigOption::SignedIntType value) -{ - try - { - SignedIntData & tmp = _value_data.get(); - - if (value < tmp.sint_Range.minimum) - throw ConfigProcessFailure(STG(FMT("value '%d' out-of-Range for option '%s' (too low)") % value % _my_name)); - - if (value > tmp.sint_Range.maximum) - throw ConfigProcessFailure(STG(FMT("value '%d' out-of-Range for option '%s' (too high)") % value % _my_name)); - - if (((value - tmp.sint_Range.minimum) % tmp.sint_Range.step) != 0) - throw ConfigProcessFailure(STG(FMT("value '%d' out-of-Range for option '%s' (outside allowed step)") % value % _my_name)); - - tmp.sint_val = value; - _loaded = true; - } - catch(ValueType::InvalidType & e) - { - throw; - } -} - -void ConfigOption::set(ConfigOption::UnsignedIntType value) -{ - try - { - UnsignedIntData & tmp = _value_data.get(); - - if (value < tmp.uint_Range.minimum) - throw ConfigProcessFailure(STG(FMT("value '%d' out-of-Range for option '%s' (too low)") % value % _my_name)); - - if (value > tmp.uint_Range.maximum) - throw ConfigProcessFailure(STG(FMT("value '%d' out-of-Range for option '%s' (too high)") % value % _my_name)); - - if (((value - tmp.uint_Range.minimum) % tmp.uint_Range.step) != 0) - throw ConfigProcessFailure(STG(FMT("value '%d' out-of-Range for option '%s' (outside allowed step)") % value % _my_name)); - - tmp.uint_val = value; - _loaded = true; - } - catch(ValueType::InvalidType & e) - { - throw; - } -} - -void ConfigOption::set(ConfigOption::BooleanType value) -{ - try - { - BooleanData & tmp = _value_data.get(); - tmp.bool_val = value; - _loaded = true; - } - catch(ValueType::InvalidType & e) - { - throw; - } -} - -std::string & ConfigOption::name(void) { return _my_name; }; - -ConfigOption::value_id_type ConfigOption::type(void) -{ - return (value_id_type) _value_data.which(); -}; - -const char ** ConfigOption::values(void) -{ - if (_values != NULL) - return _values; - - switch ((value_id_type) _value_data.which()) - { - case ConfigOption::ID_BOOL: - { - _values = new const char*[3]; - - _values[0] = strdup("yes"); - _values[1] = strdup("no"); - _values[2] = NULL; - - return _values; - } - - case ConfigOption::ID_SINT: - { - try - { - SignedIntData & tmp = _value_data.get(); - - - unsigned int count = ((tmp.sint_Range.maximum - tmp.sint_Range.minimum) / tmp.sint_Range.step) + 1; - unsigned int index = 0; - - _values = new const char*[count + 1]; - - for (SignedIntType i = tmp.sint_Range.minimum; i <= tmp.sint_Range.maximum; i += tmp.sint_Range.step, index++) - _values[index] = strdup(STG(FMT("%d") % i).c_str()); - - _values[index] = NULL; - - return _values; - } - catch(ValueType::InvalidType & e) - { - throw; - } - } - - case ConfigOption::ID_UINT: - { - try - { - UnsignedIntData & tmp = _value_data.get(); - - unsigned int count = ((tmp.uint_Range.maximum - tmp.uint_Range.minimum) / tmp.uint_Range.step) + 1; - unsigned int index = 0; - - _values = new const char*[count + 1]; - - for (UnsignedIntType i = tmp.uint_Range.minimum; i <= tmp.uint_Range.maximum; i += tmp.uint_Range.step, index++) - _values[index] = strdup(STG(FMT("%d") % i).c_str()); - - _values[index] = NULL; - - return _values; - } - catch(ValueType::InvalidType & e) - { - throw; - } - } - - case ConfigOption::ID_STRING: - { - try - { - StringData & tmp = _value_data.get(); - - _values = new const char*[ tmp.string_allowed.size() + 1 ]; - - unsigned int index = 0; - - for (string_allowed_type::iterator i = tmp.string_allowed.begin(); i != tmp.string_allowed.end(); i++, index++) - _values[index] = strdup((*i).c_str()); - - _values[index] = NULL; - - return _values; - } - catch(ValueType::InvalidType & e) - { - throw; - } - } - - case ConfigOption::ID_FUN: - { - try - { - FunctionData & tmp = _value_data.get(); - - _values = new const char*[ tmp.fun_allowed.size() + 1 ]; - - unsigned int index = 0; - - for (string_allowed_type::iterator i = tmp.fun_allowed.begin(); i != tmp.fun_allowed.end(); i++, index++) - _values[index] = strdup((*i).c_str()); - - _values[index] = NULL; - return _values; - } - catch(ValueType::InvalidType & e) - { - throw; - } - - } - - default: - throw ConfigProcessFailure(STG(FMT("unknown type identifier '%d'") % _value_data.which())); - } -}; - -void ConfigOption::reset(void) -{ - _loaded = false; -}; - -void ConfigOption::commit(void) -{ - if (_loaded) - return; - - switch ((value_id_type) _value_data.which()) - { - case ConfigOption::ID_BOOL: - { - try - { - BooleanData & tmp = _value_data.get(); - tmp.bool_val = tmp.bool_default; - } - catch(ValueType::InvalidType & e) - { - throw; - } - - break; - } - - case ConfigOption::ID_SINT: - { - try - { - SignedIntData & tmp = _value_data.get(); - tmp.sint_val = tmp.sint_default; - } - catch(ValueType::InvalidType & e) - { - throw; - } - break; - } - - case ConfigOption::ID_UINT: - { - try - { - UnsignedIntData & tmp = _value_data.get(); - tmp.uint_val = tmp.uint_default; - } - catch(ValueType::InvalidType & e) - { - throw; - } - break; - } - - case ConfigOption::ID_STRING: - { - try - { - StringData & tmp = _value_data.get(); - tmp.string_val = tmp.string_default; - } - catch(ValueType::InvalidType & e) - { - throw; - } - break; - } - - case ConfigOption::ID_FUN: - { - try - { - FunctionData & tmp = _value_data.get(); - tmp.fun_val(tmp.fun_default); - } - catch(ValueType::InvalidType & e) - { - throw; - } - break; - } - - default: - throw ConfigProcessFailure(STG(FMT("unknown type identifier '%d'") % _value_data.which())); - } - - _loaded = true; -}; - -void ConfigOption::copy_from(ConfigOption & src) -{ - if (src._value_data.which() != _value_data.which()) - throw ConfigProcessFailure(STG(FMT("unable to copy options, source type differs from destination."))); - - if (!src._loaded) - return; - - switch ((value_id_type) _value_data.which()) - { - case ConfigOption::ID_BOOL: - { - try - { - BooleanData & stmp = src._value_data.get(); - BooleanData & dtmp = _value_data.get(); - /* do not copy references, but values.. */ - bool tmpval = stmp.bool_val; - dtmp.bool_val = tmpval; - } - catch(ValueType::InvalidType & e) - { - throw; - } - - break; - } - - case ConfigOption::ID_SINT: - { - try - { - SignedIntData & stmp = src._value_data.get(); - SignedIntData & dtmp = _value_data.get(); - /* do not copy references, but values.. */ - int tmpval = stmp.sint_val; - dtmp.sint_val = tmpval; - } - catch(ValueType::InvalidType & e) - { - throw; - } - - break; - } - - case ConfigOption::ID_UINT: - { - try - { - UnsignedIntData & stmp = src._value_data.get(); - UnsignedIntData & dtmp = _value_data.get(); - /* do not copy references, but values.. */ - unsigned int tmpval = stmp.uint_val; - dtmp.uint_val = tmpval; - } - catch(ValueType::InvalidType & e) - { - throw; - } - - - break; - } - - case ConfigOption::ID_STRING: - { - try - { - StringData & stmp = src._value_data.get(); - StringData & dtmp = _value_data.get(); - /* do not copy references, but values.. */ - std::string tmpval = stmp.string_val; - dtmp.string_val = tmpval; - } - catch(ValueType::InvalidType & e) - { - throw; - } - - break; - } - - case ConfigOption::ID_FUN: - { - /* TO IMPLEMENT (NEEDS ANOTHER METHOD ON FUNCTION FOR GETTING VALUE) */ - -// FunctionData & tmp = boost::get(_value_data); -// -// if (!tmp.loaded) -// { -// tmp.fun_val(tmp.fun_default); -// tmp.loaded = true; -// } - break; - } - - default: - throw ConfigProcessFailure(STG(FMT("unknown type identifier '%d'") % _value_data.which())); - } - - _loaded = true; -}; - -/*********************************/ - -bool ConfigOptions::add(ConfigOption option) -{ - //option_map_type::iterator iter2 = _map.begin(); - - //boost::tie(iter2, ok2) - std::pair ret = _map.insert(option_pair_type(option.name(), option)); - - return ret.second; -} - -bool ConfigOptions::synonym(std::string equiv_opt, std::string main_opt) -{ - //syn_option_map_type::iterator iter = _syn_map.begin(); - - //boost::tie(iter, ok) - std::pair ret = _syn_map.insert(syn_option_pair_type(equiv_opt, main_opt)); - - return ret.second; -} - -ConfigOptions::string_set ConfigOptions::options(void) -{ - string_set res; - - for (option_map_type::iterator i = _map.begin(); i != _map.end(); i++) - res.insert((*i).first); - - return res; -} - -void ConfigOptions::process(const char * name, const char * value) -{ - option_map_type::iterator iter = find_option(name); - - if (iter == _map.end()) - throw ConfigProcessFailure(STG(FMT("unknown option '%s'") % name)); - - try - { - switch ((*iter).second.type()) - { - case ConfigOption::ID_SINT: - set((*iter).first, Strings::toulong(value)); - return; - case ConfigOption::ID_UINT: - set((*iter).first, Strings::tolong(value)); - return; - case ConfigOption::ID_BOOL: - set((*iter).first, Strings::toboolean(value)); - return; - case ConfigOption::ID_STRING: - case ConfigOption::ID_FUN: - set((*iter).first, std::string(value)); - return; - default: - throw ConfigProcessFailure(STG(FMT("unknown type identifier '%d'") % (*iter).second.type())); - } - } - catch (Strings::invalid_value & e) - { - throw ConfigProcessFailure(STG(FMT("invalid value '%s' for option '%s'") % value % name)); - } -} - -const char ** ConfigOptions::values(const char * name) -{ - option_map_type::iterator iter = find_option(name); - - if (iter == _map.end()) - throw ConfigProcessFailure(STG(FMT("unknown option '%s'") % name)); - - return (*iter).second.values(); -} - -const char ** ConfigOptions::values(void) -{ - if (_values != NULL) - return _values; - - unsigned int count = 0; - - for (option_map_type::iterator i = _map.begin(); i != _map.end(); i++) - if ((*i).second.list_me()) - ++count; - - _values = new const char*[ count + 1 ]; - - unsigned int index = 0; - - for (option_map_type::iterator i = _map.begin(); i != _map.end(); i++) - { - if ((*i).second.list_me()) - { - _values[index] = strdup((*i).first.c_str()); - ++index; - } - } - - _values[index] = NULL; - - return _values; -} - -void ConfigOptions::reset(void) -{ - for (option_map_type::iterator i = _map.begin(); i != _map.end(); i++) - (*i).second.reset(); -} - -ConfigOptions::messages_type ConfigOptions::commit(void) -{ - messages_type msgs; - - for (option_map_type::iterator i = _map.begin(); i != _map.end(); i++) - { - try - { - (*i).second.commit(); - } - catch (ConfigProcessFailure & e) - { - msgs.push_back(e.msg); - } - } - - return msgs; -} - -bool ConfigOptions::loaded(std::string name) -{ - option_map_type::iterator iter = find_option(name); - - if (iter == _map.end()) - return false; - - return iter->second.loaded(); -} - -void ConfigOptions::copy_from(ConfigOptions & source, std::string name) -{ - option_map_type::iterator iter_src = source.find_option(name); - option_map_type::iterator iter_dst = find_option(name); - - if (iter_src == source._map.end()) - throw ConfigProcessFailure(STG(FMT("unknown option '%s' on source") % name)); - - if (iter_dst == _map.end()) - throw ConfigProcessFailure(STG(FMT("unknown option '%s' on destination") % name)); - - iter_dst->second.copy_from(iter_src->second); -} - -ConfigOptions::option_map_type::iterator ConfigOptions::find_option(std::string name) -{ - syn_option_map_type::iterator syn_iter = _syn_map.find(name); - - if (syn_iter != _syn_map.end()) - name = syn_iter->second; - - option_map_type::iterator iter = _map.find(name); - - return iter; -} diff --git a/src/mod/endpoints/mod_khomp/commons/config_options.hpp b/src/mod/endpoints/mod_khomp/commons/config_options.hpp deleted file mode 100644 index 3cfe2e1c78..0000000000 --- a/src/mod/endpoints/mod_khomp/commons/config_options.hpp +++ /dev/null @@ -1,286 +0,0 @@ -/* - KHOMP generic endpoint/channel library. - Copyright (C) 2007-2009 Khomp Ind. & Com. - - The contents of this file are subject to the Mozilla Public License Version 1.1 - (the "License"); you may not use this file except in compliance with the - License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ - - Software distributed under the License is distributed on an "AS IS" basis, - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for - the specific language governing rights and limitations under the License. - - Alternatively, the contents of this file may be used under the terms of the - "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which - case the provisions of "LGPL License" are applicable instead of those above. - - If you wish to allow use of your version of this file only under the terms of - the LGPL License and not to allow others to use your version of this file under - the MPL, indicate your decision by deleting the provisions above and replace them - with the notice and other provisions required by the LGPL License. If you do not - delete the provisions above, a recipient may use your version of this file under - either the MPL or the LGPL License. - - The LGPL header follows below: - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this library; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -*/ - -#include -#include -#include - -#include - -#include -#include -#include - -#ifndef _CONFIG_OPTIONS_HPP_ -#define _CONFIG_OPTIONS_HPP_ - -struct ConfigProcessFailure -{ - ConfigProcessFailure(std::string _msg): msg(_msg) {}; - std::string msg; -}; - -struct ConfigOption -{ - typedef int SignedIntType; - typedef unsigned int UnsignedIntType; - typedef bool BooleanType; - typedef std::string StringType; - - typedef Function::Function1 < void, std::string > FunctionType; - - typedef std::set < StringType > string_allowed_type; - - /* this should reflect 'variant.which()'! */ - typedef enum - { - ID_SINT = 0, - ID_UINT = 1, - ID_BOOL = 2, - ID_STRING = 3, - ID_FUN = 4, - } - value_id_type; - - template < typename number_type > - struct Range - { - Range(number_type _minimum, number_type _maximum, number_type _step) - : minimum(_minimum), maximum(_maximum), step(_step) {}; - - number_type minimum, maximum, step; - }; - - struct SignedIntData : public VariantBaseType < void > - { - SignedIntData(SignedIntType & _sint_val, SignedIntType _sint_default, Range< SignedIntType > _sint_Range) - : sint_val(_sint_val), sint_default(_sint_default), sint_Range(_sint_Range) {}; - - int which() - { - return ID_SINT; - } - - SignedIntType & sint_val; - SignedIntType sint_default; - Range sint_Range; - }; - - struct UnsignedIntData : public VariantBaseType < void > - { - UnsignedIntData(UnsignedIntType & _uint_val, UnsignedIntType _uint_default, Range< UnsignedIntType > _uint_Range) - : uint_val(_uint_val), uint_default(_uint_default), uint_Range(_uint_Range) {}; - - int which() - { - return ID_UINT; - } - - UnsignedIntType & uint_val; - UnsignedIntType uint_default; - Range uint_Range; - }; - - struct BooleanData : public VariantBaseType < void > - { - BooleanData(BooleanType & _bool_val, BooleanType _bool_default) - : bool_val(_bool_val), bool_default(_bool_default) {}; - - int which() - { - return ID_BOOL; - } - - BooleanType & bool_val; - BooleanType bool_default; - }; - - struct StringData : public VariantBaseType < void > - { - StringData(std::string & _string_val, std::string _string_default, string_allowed_type _string_allowed) - : string_val(_string_val), string_default(_string_default), string_allowed(_string_allowed) {}; - - int which() - { - return ID_STRING; - } - - std::string & string_val; - std::string string_default; - string_allowed_type string_allowed; - }; - - struct FunctionData : public VariantBaseType < void > - { - FunctionData(FunctionType _fun_val, std::string _fun_default, string_allowed_type _fun_allowed) - : fun_val(_fun_val), fun_default(_fun_default), fun_allowed(_fun_allowed) {}; - - int which() - { - return ID_FUN; - } - - FunctionType fun_val; - std::string fun_default; - string_allowed_type fun_allowed; - }; - - - typedef Variant < VariantBaseType < void > > ValueType; - - ConfigOption(std::string, const StringType &, const StringType, string_allowed_type allowed, bool list_me = true); - ConfigOption(std::string, const StringType &, const StringType = "", bool list_me = true); - ConfigOption(std::string, const SignedIntType &, const SignedIntType = 0, SignedIntType min = -INT_MAX, SignedIntType max = INT_MAX, SignedIntType step = 1, bool list_me = true); - ConfigOption(std::string, const UnsignedIntType &, const UnsignedIntType = 0, UnsignedIntType min = 0, UnsignedIntType max = UINT_MAX, UnsignedIntType step = 1, bool list_me = true); - ConfigOption(std::string, const BooleanType &, const BooleanType = false, bool list_me = true); - ConfigOption(std::string, FunctionType, std::string defvalue, string_allowed_type allowed, bool list_me = true); - ConfigOption(std::string, FunctionType, std::string defvalue = "", bool list_me = true); - - ConfigOption(const ConfigOption & o); - - ~ConfigOption(void); - - void set(StringType value); - - void set(SignedIntType value); - void set(UnsignedIntType value); - void set(BooleanType value); - - BooleanType get_bool(){ return _value_data.get().bool_val; } - std::string get_str(){ return _value_data.get().string_val; } - SignedIntType get_sint(){ return _value_data.get().sint_val; } - UnsignedIntType get_uint(){ return _value_data.get().uint_val; } - - std::string & name(void); - value_id_type type(void); - - const char ** values(void); - - void reset(void); - void commit(void); - - bool list_me(void) { return _list_me; }; - bool loaded(void) { return _loaded; }; - - void copy_from(ConfigOption &); - - protected: - std::string _my_name; - ValueType _value_data; - - bool _list_me; - const char ** _values; - bool _loaded; -}; - -struct ConfigOptions -{ - typedef std::vector < std::string > messages_type; - - ConfigOptions(void): _values(NULL) {}; - - typedef std::set < std::string > string_set; - - typedef std::map < std::string, ConfigOption > option_map_type; - typedef std::pair < std::string, ConfigOption > option_pair_type; - - typedef std::map < std::string, std::string > syn_option_map_type; - typedef std::pair < std::string, std::string > syn_option_pair_type; - - bool add(ConfigOption option); - - /* only valid in "process" (for backwards compatibility config files) */ - bool synonym(std::string, std::string); - - template - void set(std::string name, ValueType value) - { - option_map_type::iterator iter = _map.find(name); - - if (iter == _map.end()) - throw ConfigProcessFailure(STG(FMT("unknown option: %s") % name)); - - (*iter).second.set(value); - } - - std::string get(std::string name) - { - option_map_type::iterator iter = _map.find(name); - - if (iter == _map.end()) - throw ConfigProcessFailure(STG(FMT("unknown option: %s") % name)); - - switch((*iter).second.type()) - { - case ConfigOption::ID_BOOL: return (*iter).second.get_bool() ? "yes" : "no"; - case ConfigOption::ID_STRING: return (*iter).second.get_str(); - case ConfigOption::ID_UINT: return STG(FMT("%d") % (*iter).second.get_uint()); - case ConfigOption::ID_SINT: return STG(FMT("%d") % (*iter).second.get_sint()); - case ConfigOption::ID_FUN: return ""; - } - } - - string_set options(void); - - void process(const char *, const char *); /* process option from file */ - - void reset(void); /* reset loaded opts */ - messages_type commit(void); /* set defaults */ - - const char ** values(const char *); /* option value */ - const char ** values(void); /* values from options */ - - bool loaded(std::string); /* return if config was loaded */ - - void copy_from(ConfigOptions &, std::string); - - protected: - option_map_type::iterator find_option(std::string); - - protected: - option_map_type _map; - syn_option_map_type _syn_map; - - const char ** _values; -}; - -#endif /* _CONFIG_OPTIONS_HPP_ */ - diff --git a/src/mod/endpoints/mod_khomp/commons/configurator/configfile.cpp b/src/mod/endpoints/mod_khomp/commons/configurator/configfile.cpp deleted file mode 100644 index 6aa2e59201..0000000000 --- a/src/mod/endpoints/mod_khomp/commons/configurator/configfile.cpp +++ /dev/null @@ -1,241 +0,0 @@ -/* - KHOMP generic endpoint/channel library. - Copyright (C) 2007-2009 Khomp Ind. & Com. - - The contents of this file are subject to the Mozilla Public License Version 1.1 - (the "License"); you may not use this file except in compliance with the - License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ - - Software distributed under the License is distributed on an "AS IS" basis, - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for - the specific language governing rights and limitations under the License. - - Alternatively, the contents of this file may be used under the terms of the - "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which - case the provisions of "LGPL License" are applicable instead of those above. - - If you wish to allow use of your version of this file only under the terms of - the LGPL License and not to allow others to use your version of this file under - the MPL, indicate your decision by deleting the provisions above and replace them - with the notice and other provisions required by the LGPL License. If you do not - delete the provisions above, a recipient may use your version of this file under - either the MPL or the LGPL License. - - The LGPL header follows below: - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this library; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -*/ -#include - -#include - -#if _MSC_VER >= 1400 -#undef close -#endif - -void Configfile::ignore(std::string str) -{ - _ignores.insert(str); -}; - -bool Configfile::select(Section **ptr, std::string str) -{ - /* default section == this! */ - *ptr = this; - - /* always success by default */ - return true; -}; - -bool Configfile::adjust(Section * section, std::string & opt, std::string & val) -{ - return section->load(opt, val); -}; - -bool Configfile::deserialize(std::ifstream& fd) -{ - Section * section = NULL; - - /* default selection! */ - if (!select(§ion)) - { - _errors.push_back("default selection has failed!"); - return false; - } - - size_t count = 0; - - while (fd.good()) - { - std::string str; - - /* read one line! */ - std::getline(fd, str); - - size_t lst = str.size() - 1; - - if (str.size() >= 1 && str[lst] == '\r') //cuida das quebras de linha do tipo \r\n - { - str.erase(lst,1); - --lst; - } - - /* empty line! */ - if (str.size() == 0) - continue; - - /* comment! */ - if (str[0] == '#') - continue; - - ++count; - - if (str[0] == '[' && str[lst] == ']') - { - str.erase(0,1); --lst; - str.erase(lst,1); --lst; - - if (!select(§ion, str)) - { - _errors.push_back(STG(FMT("erroneous section '%s'") % str)); - - /* ignore this section */ - section = NULL; - continue; - } - } - else - { - std::string::size_type pos = str.find('='); - - if (pos == std::string::npos) - { - _errors.push_back(STG(FMT("erroneous separator '%s'") % str)); - continue; - }; - - if (section == NULL) - { - _errors.push_back(STG(FMT("no section for option '%s'") % str)); - continue; - } - - std::string opt(str.substr(0,pos)); - std::string val(str.substr(pos+1)); - - if (_ignores.find(opt) != _ignores.end()) - continue; - - if (val == "@") val = ""; - - if (adjust(section, opt, val)) - continue; - - _errors.push_back(STG(FMT("option '%s' does " - "not exist or '%s' is not a valid value (at section '%s')") - % opt % val % section->name())); - } - } - - // retorna 'true' se arquivo tinha alguma coisa valida. - return (count != 0); -} - -bool Configfile::obtain() -{ - std::ifstream fd(_filename.c_str()); - - if (!fd.is_open()) - { - _errors.push_back(STG(FMT("unable to open file '%s': %s") - % _filename % strerror(errno))); - return false; - }; - - if (!deserialize(fd)) - { - fd.close(); - return false; - } - - fd.close(); - return true; -}; - -void Configfile::recurse(std::ofstream& fd, Section * section) -{ - typedef Section::SectionMap::iterator section_iter; - typedef Section::OptionMap::iterator option_iter; - - for (option_iter i = section->option_begin(); i != section->option_end(); i++) - { - std::string res; - - if ((*i).second.store(res)) - { - if (res == "") res = "@"; - fd << (*i).first << "=" << res << std::endl; - } - } - - if (!section->recursive()) - return; - - for (section_iter j = section->section_begin(); j != section->section_end(); j++) - recurse(fd, (*j).second); -} - -bool Configfile::serialize(std::ofstream& fd) -{ - recurse(fd, this); - return true; -} - -bool Configfile::provide() -{ - std::string tmp(_filename); - tmp += ".new"; - - std::ofstream fd(tmp.c_str()); - - if (!fd.good()) - { - _errors.push_back(STG(FMT("unable to open file '%s': %s") - % tmp % strerror(errno))); - return false; - } - - if (!serialize(fd)) - { - fd.close(); - return false; - } - - fd.close(); - - if (rename(tmp.c_str(), _filename.c_str()) != 0) - { - _errors.push_back(STG(FMT("unable to replace config file '%s': %s") - % _filename % strerror(errno))); - return false; - } - - return true; -} - -#if _MSC_VER >= 1400 -#define close _close -#endif \ No newline at end of file diff --git a/src/mod/endpoints/mod_khomp/commons/configurator/option.cpp b/src/mod/endpoints/mod_khomp/commons/configurator/option.cpp deleted file mode 100644 index 083883e63f..0000000000 --- a/src/mod/endpoints/mod_khomp/commons/configurator/option.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/* - KHOMP generic endpoint/channel library. - Copyright (C) 2007-2009 Khomp Ind. & Com. - - The contents of this file are subject to the Mozilla Public License Version 1.1 - (the "License"); you may not use this file except in compliance with the - License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ - - Software distributed under the License is distributed on an "AS IS" basis, - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for - the specific language governing rights and limitations under the License. - - Alternatively, the contents of this file may be used under the terms of the - "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which - case the provisions of "LGPL License" are applicable instead of those above. - - If you wish to allow use of your version of this file only under the terms of - the LGPL License and not to allow others to use your version of this file under - the MPL, indicate your decision by deleting the provisions above and replace them - with the notice and other provisions required by the LGPL License. If you do not - delete the provisions above, a recipient may use your version of this file under - either the MPL or the LGPL License. - - The LGPL header follows below: - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this library; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -*/ - -#include - -bool Option::equals(std::string & value) -{ - switch (_restriction.numeral()) - { - case Restriction::N_UNIQUE: - { - Restriction::Value my_value; - - if (!_restriction.get(Restriction::F_USER, my_value)) - return false; - - return (my_value == value); - } - case Restriction::N_MULTIPLE: - { - Restriction::Vector my_values; - - if (!_restriction.get(Restriction::F_USER, my_values)) - return false; - - for (Restriction::Vector::iterator i = my_values.begin(); i != my_values.end(); i++) - { - if ((*i) == value) - return true; - } - - return false; - } - } - - return false; -} - -bool Option::load(std::string & value) -{ - bool ret = _restriction.set(Restriction::F_FILE, value); - - if (ret) _modified = false; - - return ret; -} - -bool Option::change(std::string & value) -{ - bool ret = _restriction.set(Restriction::F_FILE, value); - - if (ret) _modified = true; - - return ret; -} - -bool Option::store(std::string & value) -{ - switch (_restriction.numeral()) - { - case Restriction::N_UNIQUE: - return _restriction.get(Restriction::F_FILE, value); - - case Restriction::N_MULTIPLE: - { - Restriction::Vector values; - - if (!_restriction.get(Restriction::F_FILE, values)) - return false; - - Strings::Merger strs; - - for (Restriction::Vector::iterator i = values.begin(); i != values.end(); i++) - strs.add(*i); - - value = strs.merge(","); - - return true; - } - - default: - return false; - } -} - -Option::Flags Option::set(const char * value) -{ - std::string str_value(value); - return set(str_value); -} - - -Option::Flags Option::set(Restriction::Value & value) -{ - Restriction::Value last_value, curr_value; - Flags flags; - - bool ret1 = _restriction.get(Restriction::F_USER, last_value); - - if (!_restriction.set(Restriction::F_USER, value)) - return flags; - - flags[F_ADJUSTED] = true; - - bool ret2 = _restriction.get(Restriction::F_USER, curr_value); - - if (!ret1 || (ret2 && (last_value != curr_value))) - { - flags[F_MODIFIED] = true; - _modified = true; - } - - return flags; -} - -Option::Flags Option::set(Restriction::Vector & values) -{ - Restriction::Vector last_values, curr_values; - Flags flags; - - bool ret1 = _restriction.get(Restriction::F_USER, last_values); - - if (!_restriction.set(Restriction::F_USER, values)) - return flags; - - flags[F_ADJUSTED] = true; - - bool ret2 = _restriction.get(Restriction::F_USER, curr_values); - - if (!ret1 || (ret2 && (last_values != curr_values))) - { - flags[F_MODIFIED] = true; - _modified = true; - } - - return flags; -} - -bool Option::get(Restriction::Value & value) -{ - return _restriction.get(Restriction::F_USER, value); -} - -bool Option::get(Restriction::Vector & values) -{ - return _restriction.get(Restriction::F_USER, values); -} diff --git a/src/mod/endpoints/mod_khomp/commons/configurator/restriction.cpp b/src/mod/endpoints/mod_khomp/commons/configurator/restriction.cpp deleted file mode 100644 index 9653a7c608..0000000000 --- a/src/mod/endpoints/mod_khomp/commons/configurator/restriction.cpp +++ /dev/null @@ -1,353 +0,0 @@ -/* - KHOMP generic endpoint/channel library. - Copyright (C) 2007-2009 Khomp Ind. & Com. - - The contents of this file are subject to the Mozilla Public License Version 1.1 - (the "License"); you may not use this file except in compliance with the - License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ - - Software distributed under the License is distributed on an "AS IS" basis, - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for - the specific language governing rights and limitations under the License. - - Alternatively, the contents of this file may be used under the terms of the - "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which - case the provisions of "LGPL License" are applicable instead of those above. - - If you wish to allow use of your version of this file only under the terms of - the LGPL License and not to allow others to use your version of this file under - the MPL, indicate your decision by deleting the provisions above and replace them - with the notice and other provisions required by the LGPL License. If you do not - delete the provisions above, a recipient may use your version of this file under - either the MPL or the LGPL License. - - The LGPL header follows below: - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this library; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -*/ - -#include -#include - -#include -#include - -#include - -/* internal helper! */ -bool Restriction::equalNumber(const double a, const double b) -{ - char tmp1[64]; - char tmp2[64]; - - snprintf(tmp1, sizeof(tmp1), "%.3f", a); - snprintf(tmp2, sizeof(tmp2), "%.3f", b); - - if (strncmp(tmp1, tmp2, sizeof(tmp1))) - return false; - - return true; -} - -/* process value to our internal representation */ - -bool Restriction::process(Restriction::Format fmt, - const Restriction::Value & value, Restriction::Value & final) -{ - switch (_bounds) - { - case B_RANGE: - { - if (_kind != K_NUMBER) - return false; - - std::string tmpvalue; - - Restriction::Value::const_iterator itr = value.begin(); - Restriction::Value::const_iterator end = value.end(); - - tmpvalue.reserve(value.size()); - - // f*cking dot/comma notation! - for (; itr != end; ++itr) - tmpvalue += ((*itr) != ',' ? (*itr) : '.'); - - try - { - double newvalue = Strings::todouble(tmpvalue); - - if (newvalue < _init && newvalue > _fini) - return false; - - double res = (newvalue - _init) / _step; - - if (!equalNumber(res, rint(res))) - return false; - - final = value; - return true; - } - catch (...) - { - return false; - } - } - - case B_LIST: - for (List::iterator i = _list.begin(); i != _list.end(); i++) - { - Value & tmp = (*i); - - if (tmp == value) - { - final = value; - return true; - } - } - return false; - - case B_MAPS: - switch (fmt) - { - case F_USER: - { - Map::iterator i = _map_from_usr.find(std::string(value)); - - if (i == _map_from_usr.end()) - return false; - - Value & tmp = (*i).second; - - final = tmp; - return true; - } - - case F_FILE: - { - Map::iterator i = _map_from_cfg.find(std::string(value)); - - if (i == _map_from_cfg.end()) - return false; - - final = value; - return true; - } - - default: - break; - } - return false; - - case B_FREE: - final = value; - return true; - - default: - break; - } - - return false; -} - -/* unprocess the value (outputs the external representation) */ - -bool Restriction::unprocess(Restriction::Format fmt, - const Restriction::Value & value, Restriction::Value & final) -{ - switch (_bounds) - { - case B_MAPS: - - switch (fmt) - { - case F_USER: - { - Map::iterator i = _map_from_cfg.find(std::string(value)); - - if (i == _map_from_cfg.end()) - return false; - - final = (*i).second; - return true; - } - default: - break; - } - - default: - final = value; - return true; - } -} - -/***************************** *****************************/ - -bool Restriction::get(Restriction::Format fmt, Restriction::Value & value) -{ - if (_numeral != N_UNIQUE) - return false; - - if (!unprocess(fmt, _value._unique, value)) - return false; - - return true; -} - -bool Restriction::get(Restriction::Format fmt, Restriction::Vector & values) -{ - if (_numeral != N_MULTIPLE) - return false; - - List & my_values = _value._multiple; - - for (List::iterator i = my_values.begin(); i != my_values.end(); i++) - { - Value & value = (*i); - Value final; - - if (!unprocess(fmt, value, final)) - return false; - - values.push_back(final); - }; - - return true; -} - -/***************************** *****************************/ - -bool Restriction::set(Restriction::Format fmt, Restriction::Value &value) -{ - switch (_numeral) - { - case N_UNIQUE: - { - Value final; - - if (!process(fmt, value, final)) - return false; - - _value._unique = final; - return true; - } - - case N_MULTIPLE: - { - if (value == "@" || value == "#" || value == "") - { - _value._multiple.clear(); - return true; - } - - Strings::vector_type values; - Strings::tokenize(value, values, ","); - - return set(fmt, values); - } - - default: - return false; - } -} - -bool Restriction::set(Restriction::Format fmt, Restriction::Vector & values) -{ - if (_numeral != N_MULTIPLE) - return false; - - if (values.empty()) - { - _value._multiple.clear(); - } - else - { - /* list needed to store temporary values */ - List finals; - - for (Vector::iterator i = values.begin(); i != values.end(); i++) - { - Value & value = (*i); - Value final; - - if (!process(fmt, value, final)) - return false; - - finals.push_back(final); - } - - List & lst = _value._multiple; - - /* need to clear values set before */ - lst.clear(); - - for (List::iterator i = finals.begin(); i != finals.end(); i++) - { - Value value = (*i); - lst.push_back(value); - } - }; - - return true; -} - -/***************************** *****************************/ - -void Restriction::allowed(Restriction::Vector &vals) -{ - switch (_bounds) - { - case B_FREE: - return; - - case B_LIST: - for (List::iterator i = _list.begin(); i != _list.end(); i++) - vals.push_back((*i)); - break; - - case B_MAPS: - for (Map::iterator i = _map_from_usr.begin(); i != _map_from_usr.end(); i++) - vals.push_back((*i).first); - break; - - case B_RANGE: - { - if (_kind != K_NUMBER) - return; - - // is there any fraction? - bool has_fraction = (!equalNumber(_init, rint(_init))) || (!equalNumber(_fini, rint(_fini))) || (!equalNumber(_step, rint(_step))); - - const char * format = (has_fraction ? "%.2f" : "%02.0f"); - - for (double i = _init; i <= _fini; i += _step) - { - char tmp[32]; - snprintf(tmp, sizeof(tmp), format, i); - vals.push_back(std::string(tmp)); - } - break; - } - - default: - break; - } -} - -void Restriction::init_class() -{ - _value._unique.clear(); - _value._multiple.clear(); -} diff --git a/src/mod/endpoints/mod_khomp/commons/configurator/restriction.hpp b/src/mod/endpoints/mod_khomp/commons/configurator/restriction.hpp deleted file mode 100644 index 0815ede3db..0000000000 --- a/src/mod/endpoints/mod_khomp/commons/configurator/restriction.hpp +++ /dev/null @@ -1,321 +0,0 @@ -/* - KHOMP generic endpoint/channel library. - Copyright (C) 2007-2009 Khomp Ind. & Com. - - The contents of this file are subject to the Mozilla Public License Version 1.1 - (the "License"); you may not use this file except in compliance with the - License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ - - Software distributed under the License is distributed on an "AS IS" basis, - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for - the specific language governing rights and limitations under the License. - - Alternatively, the contents of this file may be used under the terms of the - "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which - case the provisions of "LGPL License" are applicable instead of those above. - - If you wish to allow use of your version of this file only under the terms of - the LGPL License and not to allow others to use your version of this file under - the MPL, indicate your decision by deleting the provisions above and replace them - with the notice and other provisions required by the LGPL License. If you do not - delete the provisions above, a recipient may use your version of this file under - either the MPL or the LGPL License. - - The LGPL header follows below: - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this library; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -*/ - -#include - -#include -#include -#include -#include - -#ifndef _CONFIG_RESTRICTION_HPP_ -#define _CONFIG_RESTRICTION_HPP_ - -struct Restriction -{ - /* generic types */ - enum Format - { - F_USER, - F_FILE - }; - - enum Kind - { -// K_INTEGER, -// K_FLOAT, - K_STRING, - K_NUMBER // = K_INTEGER // compatibility - }; - - enum Bounds - { - B_FREE, - B_RANGE, - B_LIST, - B_MAPS - }; - - enum Numeral - { - N_UNIQUE, - N_MULTIPLE - }; - - typedef std::string Value; - - /* types used for data input */ - struct Pair - { - const char *pretty; - const char *value; - }; - - typedef std::pair < Value, Value > PairMap; - typedef std::list < PairMap > ListMap; - - /* types used internally */ - typedef std::map < Value, Value > Map; - typedef std::vector < Value > Vector; - - typedef std::list < Value > List; - typedef std::pair < Value, Value > MapPair; - - struct Generic - { - Value _unique; - List _multiple; - }; - - Restriction(Kind kind, Numeral num) - : _kind(kind), _bounds(B_FREE), _numeral(num), _unit(""), - _init(-1), _fini(-1), _step(-1) - { - init_class(); - } - -/* - Restriction(Kind kind, Numeral num, - int init, int fini, int step = 1) - : _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(unit), - _iinit(init), _ifini(fini), _istep(step), - _finit(-1), _ffini(-1), _fstep(-1) - { - init_class(); - } - - Restriction(Kind kind, Numeral num, - const char *unit, int init, int fini, int step = 1) - : _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(unit), - _iinit(init), _ifini(fini), _istep(step), - _finit(-1), _ffini(-1), _fstep(-1) - { - init_class(); - } - - Restriction(Kind kind, Numeral num, - std::string unit, int init, int fini, int step = 1) - : _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(unit), - _iinit(init), _ifini(fini), _istep(step), - _finit(-1), _ffini(-1), _fstep(-1) - { - init_class(); - } - - Restriction(Kind kind, Numeral num, - float init, float fini, float step = 1) - : _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(unit), - _iinit(-1), _ifini(-1), _istep(-1) - _finit(init), _ffini(fini), _fstep(step), - { - init_class(); - } - - Restriction(Kind kind, Numeral num, - const char *unit, float init, float fini, float step = 1.0) - : _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(unit), - _iinit(-1), _ifini(-1), _istep(-1) - _finit(init), _ffini(fini), _fstep(step), - { - init_class(); - } - - Restriction(Kind kind, Numeral num, - std::string unit, float init, float fini, float step = 1.0) - : _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(unit), - _iinit(-1), _ifini(-1), _istep(-1) - _finit(init), _ffini(fini), _fstep(step), - { - init_class(); - } -*/ - - Restriction(Kind kind, Numeral num, - double init, double fini, double step = 1) - : _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(""), - _init(init), _fini(fini), _step(step) - { - init_class(); - } - - Restriction(Kind kind, Numeral num, - const char *unit, double init, double fini, double step = 1.0) - : _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(unit), - _init(init), _fini(fini), _step(step) - { - init_class(); - } - - Restriction(Kind kind, Numeral num, - std::string unit, double init, double fini, double step = 1.0) - : _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(unit), - _init(init), _fini(fini), _step(step) - { - init_class(); - } - - Restriction(Kind kind, Numeral num, - const char *first, ...) - : _kind(kind), _bounds(B_LIST), _numeral(num), _unit(""), - _init(-1), _fini(-1), _step(-1) - { - _list.push_back(std::string(first)); - - va_list ap; - va_start(ap, first); - - while (true) - { - const char *arg = va_arg(ap, const char *); - - if (arg == NULL) break; - - _list.push_back(std::string(arg)); - } - - init_class(); - } - - Restriction(Kind kind, const char *unit, Numeral num, - const char *first, ...) - : _kind(kind), _bounds(B_LIST), _numeral(num), _unit(unit), - _init(-1), _fini(-1), _step(-1) - { - _list.push_back(std::string(first)); - - va_list ap; - va_start(ap, first); - - while (true) - { - const char *arg = va_arg(ap, const char *); - - if (arg == NULL) break; - - _list.push_back(std::string(arg)); - } - - init_class(); - } - - Restriction(Kind kind, Numeral num, - const struct Pair first, ...) - : _kind(kind), _bounds(B_MAPS), _numeral(num), _unit(""), - _init(-1), _fini(-1), _step(-1) - { - _map_from_usr.insert(MapPair(Value(first.pretty), Value(first.value))); - _map_from_cfg.insert(MapPair(Value(first.value), Value(first.pretty))); - - va_list ap; - va_start(ap, first); - - while (true) - { - Pair arg = va_arg(ap, Pair); - - if (arg.pretty == NULL) break; - - _map_from_usr.insert(MapPair(Value(arg.pretty), Value(arg.value))); - _map_from_cfg.insert(MapPair(Value(arg.value), Value(arg.pretty))); - } - - init_class(); - } - - Restriction(Kind kind, Numeral num, List list) - : _kind(kind), _bounds(B_LIST), _numeral(num), _unit(""), - _init(-1), _fini(-1), _step(-1), _list(list) - { - init_class(); - } - - Restriction(Kind kind, Numeral num, ListMap map) - : _kind(kind), _bounds(B_MAPS), _numeral(num), _unit(""), - _init(-1), _fini(-1), _step(-1) - { - for (ListMap::iterator i = map.begin(); i != map.end(); i++) - { - _map_from_usr.insert(MapPair(Value((*i).first), Value((*i).second))); - _map_from_cfg.insert(MapPair(Value((*i).second), Value((*i).first))); - } - - init_class(); - } - - Kind kind() { return _kind; }; - Bounds bounds() { return _bounds; }; - Numeral numeral() { return _numeral; }; - - Value unit() { return _unit; }; - - bool set(Format, Vector &); - bool set(Format, Value &); - - bool get(Format, Vector &); - bool get(Format, Value &); - - void allowed(Vector &); - - private: - bool process(Format, const Value &, Value &); - bool unprocess(Format, const Value &, Value &); - void init_class(); - - bool equalNumber(const double, const double); - - protected: - Kind _kind; - Bounds _bounds; - Numeral _numeral; - - Value _unit; - - double _init, _fini, _step; - - Map _map_from_usr, - _map_from_cfg; - - List _list; - - Generic _value; -}; - -#endif /* _CONFIG_RESTRICTION_HPP_ */ diff --git a/src/mod/endpoints/mod_khomp/commons/configurator/section.hpp b/src/mod/endpoints/mod_khomp/commons/configurator/section.hpp deleted file mode 100644 index fdb782308a..0000000000 --- a/src/mod/endpoints/mod_khomp/commons/configurator/section.hpp +++ /dev/null @@ -1,226 +0,0 @@ -/* - KHOMP generic endpoint/channel library. - Copyright (C) 2007-2009 Khomp Ind. & Com. - - The contents of this file are subject to the Mozilla Public License Version 1.1 - (the "License"); you may not use this file except in compliance with the - License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ - - Software distributed under the License is distributed on an "AS IS" basis, - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for - the specific language governing rights and limitations under the License. - - Alternatively, the contents of this file may be used under the terms of the - "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which - case the provisions of "LGPL License" are applicable instead of those above. - - If you wish to allow use of your version of this file only under the terms of - the LGPL License and not to allow others to use your version of this file under - the MPL, indicate your decision by deleting the provisions above and replace them - with the notice and other provisions required by the LGPL License. If you do not - delete the provisions above, a recipient may use your version of this file under - either the MPL or the LGPL License. - - The LGPL header follows below: - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this library; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -*/ - -#include -#include -#include -#include -#include - -#include - -#ifndef _CONFIG_SECTION_HPP_ -#define _CONFIG_SECTION_HPP_ - -struct Section -{ - typedef std::map < std::string, Option > OptionMap; - typedef std::vector< Option * > OptionVector; - - typedef std::map < std::string, Section * > SectionMap; - typedef std::vector < Section * > SectionVector; - - struct not_found {}; /* exception */ - -// protected: - Section(std::string name, std::string desc, bool recursive = true) - : _name(name), _description(desc), _recursive(recursive) {}; - - void add(Option o) - { - _options.insert(std::pair(o.name(), o)); - }; - - void del(std::string name) - { - _options.erase(name); - }; - - void add(Section *s) - { - _sections.insert(std::pair(s->name(), s)); - }; - - public: - const std::string & name() { return _name; }; - const std::string & description() { return _description; }; - const bool & recursive() { return _recursive; }; - - OptionMap::iterator option_begin() { return _options.begin(); }; - OptionMap::iterator option_end() { return _options.end(); }; - - SectionMap::iterator section_begin() { return _sections.begin(); }; - SectionMap::iterator section_end() { return _sections.end(); }; - - /**/ - - Option * option_find(const char *, bool recurse = false); - Section * section_find(const char *, bool recurse = false); - - Option * option_find(std::string &, bool recurse = false); - Section * section_find(std::string &, bool recurse = false); - - /**/ - - void options(OptionVector &); - void sections(SectionVector &); - - /**/ - - template - bool search_and_apply(std::string &key, std::string &value, F f) - { - OptionMap::iterator i = _options.find(key); - - if (i != _options.end()) - return f((*i).second); - - if (!_recursive) - return false; - - return (find_if(_sections.begin(), _sections.end(), f) != _sections.end()); - } - - private: - struct key_value - { - key_value(std::string &k, std::string &v): _k(k), _v(v) {}; - std::string & _k, & _v; - }; - - struct load_section: protected key_value - { - load_section(std::string &k, std::string &v): key_value(k,v) {}; - - bool operator()(Option &o) { return o.load(_v); }; - bool operator()(SectionMap::value_type &v) { return v.second->load(_k,_v); }; - }; - - struct change_section: protected key_value - { - change_section(std::string &k, std::string &v): key_value(k,v) {}; - - bool operator()(Option &o) { return o.change(_v); }; - bool operator()(SectionMap::value_type &v) { return v.second->change(_k,_v); }; - }; - - struct store_section: protected key_value - { - store_section(std::string &k, std::string &v): key_value(k,v) {}; - - bool operator()(Option &o) { return o.store(_v); }; - bool operator()(SectionMap::value_type &v) { return v.second->store(_k,_v); }; - }; - - struct set_section: protected key_value - { - set_section(std::string &k, std::string &v): key_value(k,v) {}; - - bool operator()(Option &o) { return (o.set(_v))[Option::F_ADJUSTED]; }; - bool operator()(SectionMap::value_type &v) { return v.second->set(_k,_v); }; - }; - - struct get_section: protected key_value - { - get_section(std::string &k, std::string &v): key_value(k,v) {}; - - bool operator()(Option &o) { return o.get(_v); }; - bool operator()(SectionMap::value_type &v) { return v.second->get(_k,_v); }; - }; - - struct modified_section - { - bool operator()(OptionMap::value_type &v) { return v.second.modified(); }; - bool operator()(SectionMap::value_type &v) { return v.second->modified(); }; - }; - - public: - bool load(const char * key, std::string value) - { - std::string skey(key); - return search_and_apply(skey, value, load_section(skey, value)); - } - - bool load(std::string &key, std::string &value) - { - return search_and_apply(key, value, load_section(key, value)); - } - - bool change(std::string &key, std::string &value) - { - return search_and_apply(key, value, change_section(key, value)); - } - - bool store(std::string &key, std::string &value) - { - return search_and_apply(key, value, store_section(key, value)); - } - - bool set(std::string &key, std::string &value) - { - return search_and_apply(key, value, set_section(key, value)); - } - - bool get(std::string &key, std::string &value) - { - return search_and_apply(key, value, get_section(key, value)); - } - - bool modified() - { - return ((find_if(_options.begin(), _options.end(), modified_section()) != _options.end()) || - (find_if(_sections.begin(), _sections.end(), modified_section()) != _sections.end())); - } - - private: - Section() {}; - - protected: - std::string _name; - std::string _description; - - OptionMap _options; - SectionMap _sections; - - bool _recursive; -}; - -#endif /* _CONFIG_SECTION_HPP_ */ diff --git a/src/mod/endpoints/mod_khomp/commons/ringbuffer.cpp b/src/mod/endpoints/mod_khomp/commons/ringbuffer.cpp deleted file mode 100644 index 428bd29221..0000000000 --- a/src/mod/endpoints/mod_khomp/commons/ringbuffer.cpp +++ /dev/null @@ -1,575 +0,0 @@ -/* - KHOMP generic endpoint/channel library. - Copyright (C) 2007-2009 Khomp Ind. & Com. - - The contents of this file are subject to the Mozilla Public License Version 1.1 - (the "License"); you may not use this file except in compliance with the - License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ - - Software distributed under the License is distributed on an "AS IS" basis, - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for - the specific language governing rights and limitations under the License. - - Alternatively, the contents of this file may be used under the terms of the - "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which - case the provisions of "LGPL License" are applicable instead of those above. - - If you wish to allow use of your version of this file only under the terms of - the LGPL License and not to allow others to use your version of this file under - the MPL, indicate your decision by deleting the provisions above and replace them - with the notice and other provisions required by the LGPL License. If you do not - delete the provisions above, a recipient may use your version of this file under - either the MPL or the LGPL License. - - The LGPL header follows below: - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this library; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -*/ - -#include - -/********** BUFFER FUNCTIONS **********/ - -/* writes everything or nothing */ -bool Ringbuffer_traits::traits_provide(char * buffer, const char * value, unsigned int amount, bool skip_overwrite) -{ - /* avoid using different values */ - Buffer_table cache = _pointers; - - const unsigned int reader = cache.reader.complete; - const unsigned int writer = cache.writer.complete; - - const unsigned int dest = cache.writer.complete - 1; - - const bool reader_less = cache.reader.complete < cache.writer.complete; - - if (amount >= _size) - return false; - - bool ret = true; - - /* should we go around the buffer for writing? */ - if (((writer + amount) > _size) && (reader_less || !skip_overwrite)) - { - /* Documentation of the formula used in the 'if' below. - * - * [0|1|2|3|4|5|6|7] => size=8 - * | | - * reader | - * writer - * - * => writer has places [5,6,7,0,1] to write (5 places). - * - * => 8 - (4-2+1) = 8 - (2+1) = 8 - 3 = 5 - * - * > writer goes 1 up, amount goes 1 down. - * > reader goes 1 up, amount goes 1 up. - * > size goes 1 down, amount goes 1 down. - * - */ - - if ((_size - (writer - reader + 1)) <= amount) - { - if (skip_overwrite) - return false; - - do - { - Buffer_pointer extra(cache.reader); - extra.complete = (extra.complete + amount) % _size; - - if (update(cache.reader, extra)) - break; - } - while (true); - - ret = false; - } - - unsigned int wr1 = _size - writer + 1; /* writer is already 1 position after */ - unsigned int wr2 = amount - wr1; - -// fprintf(stderr, "%p> partial write: (%d/%d) %d/%d [%d/%d]\n", this, wr1, wr2, amount, _size, reader, writer); - - /* two partial writes (one at the end, another at the beginning) */ - memcpy((void *) &(buffer[dest]), (const void *) (value), _block * wr1); - memcpy((void *) (buffer), (const void *) &(value[wr1]), _block * wr2); - } - else - { - if (!reader_less && ((reader - writer) <= amount)) - { - if (skip_overwrite) - return false; - - do - { - Buffer_pointer extra(cache.reader); - extra.complete = (extra.complete + amount) % _size; - - if (update(cache.reader, extra)) - break; - } - while (true); - - ret = false; - } - -// fprintf(stderr, "%p> full write: a=%d/s=%d [r=%d/w=%d]\n", this, amount, _size, reader, writer); - - /* we are talking about buffers here, man! */ - memcpy((void *) &(buffer[dest]), (const void *) value, _block * amount); - } - - _pointers.writer.complete = ((dest + amount) % _size) + 1; - _pointers.writer.partial = 1; - -// fprintf(stderr, "%p> write end: %d [block=%d]\n", this, writer, _block); - - return ret; -} - -/* returns the number of itens that have been read */ -unsigned int Ringbuffer_traits::traits_consume(const char * buffer, char * value, unsigned int amount, bool atomic_mode) -{ - /* avoid using different values */ - Buffer_table cache = _pointers; - - const unsigned int writer = _pointers.writer.complete; - const unsigned int reader = _pointers.reader.complete; - - const bool writer_less = writer < reader; - - unsigned int total = 0; - - /* should we go around the buffer for reading? */ - if (writer_less && (reader + amount >= _size)) - { - total = std::min(_size - (reader - writer + 1), amount); - - if ((total == 0) || (atomic_mode && (total < amount))) - return 0; - - unsigned int rd1 = _size - reader; - unsigned int rd2 = total - rd1; - -// fprintf(stderr, "%p> partial read: (%d/%d) %d/%d [%d/%d]\n", this, rd1, rd2, total, _size, reader, writer); - - /* two partial consumes (one at the end, another at the beginning) */ - memcpy((void *) (value), (const void *) &(buffer[reader]), _block * rd1); - memcpy((void *) &(value[rd1]), (const void *) (buffer), _block * rd2); - } - else - { - total = std::min((!writer_less ? writer - (reader + 1) : amount), amount); - - if ((total == 0) || (atomic_mode && (total < amount))) - return 0; - -// fprintf(stderr, "%p> full read: %d/%d [%d/%d]\n", this, total, _size, reader, writer); - - /* we are talking about buffers here, man! */ - memcpy((void *) value, (const void *) &(buffer[reader]), _block * total); - } - - do - { - /* jump the reader forward */ - Buffer_pointer index((cache.reader.complete + total) % _size); - - if (update(cache.reader, index)) - break; - } - while (true); - -// fprintf(stderr, "%p> read end: %d [block=%d]\n", this, reader, _block); - - return total; -} - -/********** TWO-PHASE BUFFER FUNCTIONS ***********/ - -/* returns the number of itens that have been read */ -unsigned int Ringbuffer_traits::traits_consume_begins(const char * buffer, char * value, unsigned int amount, bool atomic_mode) -{ - Buffer_table cache = _pointers; - - /* avoid using different values */ - const unsigned int reader = cache.reader.complete; - const unsigned int writer = cache.writer.complete; - - const bool writer_less = writer < reader; - - unsigned int total = 0; - - /* should we go around the buffer for reading? */ - if (writer_less && (reader + amount >= _size)) - { - total = std::min(_size - (reader - writer + 1), amount); - - if ((total == 0) || (atomic_mode && (total < amount))) - return 0; - - unsigned int rd1 = _size - reader; - unsigned int rd2 = total - rd1; - -// fprintf(stderr, "%p> partial read: (%d/%d) %d/%d [%d/%d]\n", this, rd1, rd2, total, _size, reader, writer); - - /* two partial consumes (one at the end, another at the beginning) */ - memcpy((void *) (value), (const void *) &(buffer[reader]), _block * rd1); - memcpy((void *) &(value[rd1]), (const void *) (buffer), _block * rd2); - } - else - { - total = std::min((!writer_less ? writer - (reader + 1) : amount), amount); - - if ((total == 0) || (atomic_mode && (total < amount))) - return 0; - -// fprintf(stderr, "%p> full read: %d/%d [%d/%d]\n", this, total, _size, reader, writer); - - /* we are talking about buffers here, man! */ - memcpy((void *) value, (const void *) &(buffer[reader]), _block * total); - } - -// fprintf(stderr, "%p> read end: %d [%d]\n", this, _reader, _reader_partial); - - return total; -} - -bool Ringbuffer_traits::traits_consume_commit(unsigned int amount) -{ - /* avoid using different values */ - Buffer_table cache = _pointers; - - const unsigned int writer = cache.writer.complete; - const unsigned int reader = cache.reader.complete; - - const bool writer_less = writer < reader; - - unsigned int total = 0; - - /* should we go around the buffer for reading? */ - if (writer_less && (reader + amount >= _size)) - { - total = std::min(_size - (reader - writer + 1), amount); - - if (total < amount) - return false; - -// fprintf(stderr, "%p> partial read: (%d/%d) %d/%d [%d/%d]\n", this, rd1, rd2, total, _size, reader, writer); - } - else - { - total = std::min((!writer_less ? writer - (reader + 1) : amount), amount); - - if (total < amount) - return false; - -// fprintf(stderr, "%p> full read: %d/%d [%d/%d]\n", this, total, _size, reader, writer); - } - - do - { - /* jump the reader forward */ - Buffer_pointer index(cache.reader); - index.complete = (index.complete + total) % _size; - - if (update(cache.reader, index)) - break; - } - while (true); - -// fprintf(stderr, "%p> read end: %d [%d]\n", this, _reader, _reader_partial); - - return true; -} - -/********** PARTIAL BUFFER FUNCTIONS (bytes) ***********/ - -/* writes everything or nothing */ -bool Ringbuffer_traits::traits_provide_partial(char * buffer, const char * value, unsigned int amount) -{ - /* avoid using different values */ - Buffer_table cache = _pointers; - - const unsigned int reader = (cache.reader.complete * _block) + cache.reader.partial; - const unsigned int writer = ((cache.writer.complete - 1) * _block) + cache.writer.partial; - - const unsigned int size = _size * _block; - const unsigned int dest = writer - 1; - -// fprintf(stderr, "%p> provide partial: %d/%d [%d/%d]\n", this, reader, writer, amount, size); - - const bool reader_less = reader < writer; - - /* should we go around the buffer for writing? */ - if (reader_less && ((writer + amount) > size)) - { - /* Documentation of the formula used in the 'if' below. - * - * [0|1|2|3|4|5|6|7] => size=8 - * | | - * reader | - * writer - * - * => writer has places [5,6,7,0,1] to write (5 places). - * - * => 8 - (4-2+1) = 8 - (2+1) = 8 - 3 = 5 - * - * > writer goes 1 up, amount goes 1 down. - * > reader goes 1 up, amount goes 1 up. - * > size goes 1 down, amount goes 1 down. - * - */ - - if ((size - (writer - reader + 1)) <= amount) - return false; - - unsigned int wr1 = size - writer + 1; /* writer is already 1 position after */ - unsigned int wr2 = amount - wr1; - -// fprintf(stderr, "%p> p partial write: (%d/%d) %d/%d [%d/%d]\n", this, wr1, wr2, amount, size, reader, writer); - - /* two partial writes (one at the end, another at the beginning) */ - memcpy((void *) &(buffer[dest]), (const void *) (value), wr1); - memcpy((void *) (buffer), (const void *) &(value[wr1]), wr2); - } - else - { - if (!reader_less && ((reader - writer) <= amount)) - return false; - -// fprintf(stderr, "%p> p full write: %d/%d [r=%d/w=%d]\n", this, amount, size, reader, writer); - - /* we are talking about buffers here, man! */ - memcpy((void *) &(buffer[dest]), (const void *) value, amount); - } - - unsigned int new_writer = ((dest + amount) % size) + 1; - - /* update "full length position" */ - _pointers.writer.complete = (unsigned int)floor((double) new_writer / (double)_block)+1; - _pointers.writer.partial = (unsigned short)(new_writer % _block); - -// fprintf(stderr, "%p> p write end: %d [block=%d]\n", this, new_writer, _block); - - return true; -} - -/* returns the number of bytes that have been read */ -unsigned int Ringbuffer_traits::traits_consume_partial(const char * buffer, char * value, unsigned int amount) -{ - /* avoid using different values */ - Buffer_table cache = _pointers; - - const unsigned int writer = ((cache.writer.complete - 1) * _block) + cache.writer.partial; - const unsigned int reader = (cache.reader.complete * _block) + cache.reader.partial; - - const unsigned int size = _size * _block; - -// fprintf(stderr, "%p> consume partial: %d/%d [%d/%d]\n", this, reader, writer, amount, size); - - const bool writer_less = writer < reader; - - unsigned int total = 0; - - /* should we go around the buffer for reading? */ - if (writer_less && (reader + amount >= size)) - { - total = std::min(size - (reader - writer + 1), amount); - - if (total == 0) - return 0; - - unsigned int rd1 = size - reader; - unsigned int rd2 = total - rd1; - -// fprintf(stderr, "%p> p partial read: (%d/%d) %d/%d [%d/%d]\n", this, rd1, rd2, total, size, reader, writer); - - /* two partial consumes (one at the end, another at the beginning) */ - memcpy((void *) (value), (const void *) &(buffer[reader]), rd1); - memcpy((void *) &(value[rd1]), (const void *) (buffer), rd2); - } - else - { - total = std::min((writer_less ? amount : writer - (reader + 1)), amount); - - if (total == 0) - return 0; - -// fprintf(stderr, "%p> p full read: %d/%d [r=%d/w=%d]\n", this, total, size, reader, writer); - - /* we are talking about buffers here, man! */ - memcpy((void *) value, (const void *) &(buffer[reader]), total); - } - - do - { - unsigned int new_reader = (((cache.reader.complete * _block) + cache.reader.partial) + total) % size; - - /* jump the reader forward */ - Buffer_pointer index((unsigned int)floor((double)new_reader / (double)_block), - (unsigned short)(new_reader % _block)); - - if (update(cache.reader, index)) - { -// fprintf(stderr, "%p> p read end: %d [block=%d]\n", this, new_reader, _block); - break; - } - } - while (true); - - return total; -} - - - -/********** IO FUNCTIONS **********/ - -/* returns the number of items written to from buffer to stream */ -unsigned int Ringbuffer_traits::traits_put(const char * buffer, std::ostream &fd, unsigned int amount) -{ - /* avoid using different values */ - Buffer_table cache = _pointers; - - const unsigned int reader = cache.reader.complete; - const unsigned int writer = cache.writer.complete; - - const bool writer_less = writer < reader; - - unsigned int total = 0; - - /* should we go around the buffer for reading? */ - if (writer_less && (reader + amount >= _size)) - { - total = std::min(_size - (reader - writer + 1), amount); - - if (total == 0) - return 0; - - unsigned int rd1 = _size - reader; - unsigned int rd2 = total - rd1; - -// fprintf(stderr, "%p> partial read: (%d/%d) %d/%d [%d/%d]\n", this, rd1, rd2, total, _size, reader, writer); - - /* two partial consumes (one at the end, another at the beginning) */ - fd.write((const char *) &(buffer[reader]), _block * rd1); - fd.write((const char *) (buffer), _block * rd2); - } - else - { - total = std::min((!writer_less ? writer - (reader + 1) : amount), amount); - - if (total == 0) - return 0; - -// fprintf(stderr, "%p> full read: %d/%d [%d/%d]\n", this, total, _size, reader, writer); - - /* we are talking about buffers here, man! */ - fd.write((const char *) &(buffer[reader]), _block * total); - } - - do - { - /* jump the reader forward */ - Buffer_pointer index(cache.reader); - index.complete = (index.complete + total) % _size; - - if (update(cache.reader, index)) - break; - } - while (true); - - return total; -} - -/* returns number of items read from stream to buffer */ -unsigned int Ringbuffer_traits::traits_get(char * buffer, std::istream &fd, unsigned int amount) -{ - /* avoid using different values */ - Buffer_table cache = _pointers; - - const unsigned int reader = cache.reader.complete; - const unsigned int writer = cache.writer.complete; - - const unsigned int dest = writer - 1; - - const bool reader_less = reader < writer; - - unsigned int real_amount = 0; - - /* should we go around the buffer for writing? */ - if (reader_less && ((writer + amount) > _size)) - { - /* Documentation of the formula used in the 'if' below. - * - * [0|1|2|3|4|5|6|7] => size=8 - * | | - * reader | - * writer - * - * => writer has places [5,6,7,0,1] to write (5 places). - * - * => 8 - (4-2+1) = 8 - (2+1) = 8 - 3 = 5 - * - * > writer goes 1 up, amount goes 1 down. - * > reader goes 1 up, amount goes 1 up. - * > size goes 1 down, amount goes 1 down. - * - */ - - if ((_size - (writer - reader + 1)) <= amount) - return false; - - unsigned int wr1 = _size - writer + 1; /* writer is already 1 position after */ - unsigned int wr2 = amount - wr1; - -// fprintf(stderr, "%p> partial write: (%d/%d) %d/%d [%d/%d]\n", this, wr1, wr2, amount, _size, reader, writer); - - unsigned int char_amount = 0; - - /* one partial write on the buffer (at the end) */ - fd.read((char *) &(buffer[dest]), _block * wr1); - char_amount += fd.gcount(); - - if (fd.gcount() == (int)(_block * wr1)) - { - /* another partial write on the buffer (at the beginning) */ - fd.read((char *) (buffer), _block * wr2); - char_amount += fd.gcount(); - } - - real_amount = char_amount / _block; - } - else - { - if (!reader_less && ((reader - writer) <= amount)) - return false; - -// fprintf(stderr, "%p> full write: %d/%d [%d/%d]\n", this, amount, _size, reader, writer); - - /* we are talking about buffers here, man! */ - fd.read((char *) &(buffer[dest]), _block * amount); - - real_amount = fd.gcount() / _block; - } - - _pointers.writer.complete = ((dest + real_amount) % _size) + 1; - _pointers.writer.partial = 1; - - return real_amount; -} diff --git a/src/mod/endpoints/mod_khomp/commons/tools/generate-verbose-headers.sh b/src/mod/endpoints/mod_khomp/commons/tools/generate-verbose-headers.sh new file mode 100755 index 0000000000..7b9012baea --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/tools/generate-verbose-headers.sh @@ -0,0 +1,183 @@ +#!/bin/sh + +cut_defines () +{ + cut -b9- | cut -f1 | cut -d' ' -f1 +} + +list_commands () +{ + egrep -h 'define.+CM_' "$@" | cut_defines +} + +list_events () +{ + # list and remove deprecations + egrep -h 'define.+EV_' "$@" | cut_defines | \ + grep -v 'EV_CALL_PROGRESS\|EV_FAX_MESSAGE_CONFIRMATION' +} + +make_enumeration_one_by_one () +{ + while read line + do + local size=$[50 - $(expr length "${line}")] + + echo -n " K_${line}" + + for ((i=0;i" + echo + echo "#include " + echo + echo "#include " + echo + echo "struct VerboseTraits" + echo "{" + make_enumeration "Command" list_commands "$@" || return 1 + echo + make_enumeration "Event" list_events "$@" || return 1 + echo + echo " static std::string eventName(const Event);" + echo " static std::string commandName(const Command);" + echo "};" + echo + echo "#endif /* _VERBOSE_TRAITS_H_ */" +} + +make_source () +{ + make_license + + echo "#include " + echo + + make_switch_case "Event" "event" list_events "$@" || return 1 + echo + make_switch_case "Command" "command" list_commands "$@" || return 1 +} + +make_run () +{ + local destdir="$1"; shift + + if [ ! -d "${destdir}" ] + then + echo "ERROR: First argument is not a directory!" + return 1 + fi + + make_header "$@" > "${destdir}/verbose_traits.hpp" + make_source "$@" > "${destdir}/verbose_traits.cpp" +} + +make_run "$@" diff --git a/src/mod/endpoints/mod_khomp/commons/verbose.hpp b/src/mod/endpoints/mod_khomp/commons/verbose.hpp deleted file mode 100644 index 4668ea6a9f..0000000000 --- a/src/mod/endpoints/mod_khomp/commons/verbose.hpp +++ /dev/null @@ -1,505 +0,0 @@ -/* - KHOMP generic endpoint/channel library. - Copyright (C) 2007-2009 Khomp Ind. & Com. - - The contents of this file are subject to the Mozilla Public License Version 1.1 - (the "License"); you may not use this file except in compliance with the - License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ - - Software distributed under the License is distributed on an "AS IS" basis, - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for - the specific language governing rights and limitations under the License. - - Alternatively, the contents of this file may be used under the terms of the - "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which - case the provisions of "LGPL License" are applicable instead of those above. - - If you wish to allow use of your version of this file only under the terms of - the LGPL License and not to allow others to use your version of this file under - the MPL, indicate your decision by deleting the provisions above and replace them - with the notice and other provisions required by the LGPL License. If you do not - delete the provisions above, a recipient may use your version of this file under - either the MPL or the LGPL License. - - The LGPL header follows below: - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this library; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -*/ - -#include -#include -#include - -#include - -// k3lApiMajorVersion -#ifndef CM_PING -# include -# include -#endif - -#include -#include -#include - -#ifndef _VERBOSE_HPP_ -#define _VERBOSE_HPP_ - -struct Verbose -{ - typedef enum - { - K_CM_SEIZE = CM_SEIZE, - K_CM_SYNC_SEIZE = CM_SYNC_SEIZE, -#if K3L_AT_LEAST(1,6,0) - K_CM_SIP_REGISTER = CM_SIP_REGISTER, -#endif - K_CM_DIAL_DTMF = CM_DIAL_DTMF, - K_CM_DISCONNECT = CM_DISCONNECT, - K_CM_CONNECT = CM_CONNECT, - K_CM_PRE_CONNECT = CM_PRE_CONNECT, - K_CM_CAS_CHANGE_LINE_STT = CM_CAS_CHANGE_LINE_STT, - K_CM_CAS_SEND_MFC = CM_CAS_SEND_MFC, - K_CM_SET_FORWARD_CHANNEL = CM_SET_FORWARD_CHANNEL, - K_CM_CAS_SET_MFC_DETECT_MODE = CM_CAS_SET_MFC_DETECT_MODE, - K_CM_DROP_COLLECT_CALL = CM_DROP_COLLECT_CALL, - K_CM_MAKE_CALL = CM_MAKE_CALL, - K_CM_RINGBACK = CM_RINGBACK, - K_CM_USER_INFORMATION = CM_USER_INFORMATION, -#if !K3L_AT_LEAST(2,2,0) - K_CM_VOIP_SEIZE = CM_VOIP_SEIZE, //deprecated -#endif - K_CM_LOCK_INCOMING = CM_LOCK_INCOMING, - K_CM_UNLOCK_INCOMING = CM_UNLOCK_INCOMING, - K_CM_LOCK_OUTGOING = CM_LOCK_OUTGOING, - K_CM_UNLOCK_OUTGOING = CM_UNLOCK_OUTGOING, - K_CM_START_SEND_FAIL = CM_START_SEND_FAIL, - K_CM_STOP_SEND_FAIL = CM_STOP_SEND_FAIL, - K_CM_END_OF_NUMBER = CM_END_OF_NUMBER, -#if K3L_AT_LEAST(1,6,0) - K_CM_SS_TRANSFER = CM_SS_TRANSFER, - K_CM_GET_SMS = CM_GET_SMS, - K_CM_PREPARE_SMS = CM_PREPARE_SMS, - K_CM_SEND_SMS = CM_SEND_SMS, -#endif -#if K3L_HAS_MPTY_SUPPORT - K_CM_HOLD_SWITCH = CM_HOLD_SWITCH, - K_CM_MPTY_CONF = CM_MPTY_CONF, - K_CM_MPTY_SPLIT = CM_MPTY_SPLIT, -#endif - K_CM_ENABLE_DTMF_SUPPRESSION = CM_ENABLE_DTMF_SUPPRESSION, - K_CM_DISABLE_DTMF_SUPPRESSION = CM_DISABLE_DTMF_SUPPRESSION, - K_CM_ENABLE_AUDIO_EVENTS = CM_ENABLE_AUDIO_EVENTS, - K_CM_DISABLE_AUDIO_EVENTS = CM_DISABLE_AUDIO_EVENTS, - K_CM_ENABLE_CALL_PROGRESS = CM_ENABLE_CALL_PROGRESS, - K_CM_DISABLE_CALL_PROGRESS = CM_DISABLE_CALL_PROGRESS, - K_CM_FLASH = CM_FLASH, - K_CM_ENABLE_PULSE_DETECTION = CM_ENABLE_PULSE_DETECTION, - K_CM_DISABLE_PULSE_DETECTION = CM_DISABLE_PULSE_DETECTION, - K_CM_ENABLE_ECHO_CANCELLER = CM_ENABLE_ECHO_CANCELLER, - K_CM_DISABLE_ECHO_CANCELLER = CM_DISABLE_ECHO_CANCELLER, - K_CM_ENABLE_AGC = CM_ENABLE_AGC, - K_CM_DISABLE_AGC = CM_DISABLE_AGC, - K_CM_ENABLE_HIGH_IMP_EVENTS = CM_ENABLE_HIGH_IMP_EVENTS, - K_CM_DISABLE_HIGH_IMP_EVENTS = CM_DISABLE_HIGH_IMP_EVENTS, -#if K3L_AT_LEAST(1,6,0) - K_CM_ENABLE_CALL_ANSWER_INFO = CM_ENABLE_CALL_ANSWER_INFO, - K_CM_DISABLE_CALL_ANSWER_INFO = CM_DISABLE_CALL_ANSWER_INFO, -#endif - K_CM_RESET_LINK = CM_RESET_LINK, -#if K3L_AT_LEAST(1,6,0) - K_CM_CLEAR_LINK_ERROR_COUNTER = CM_CLEAR_LINK_ERROR_COUNTER, -#endif - K_CM_SEND_DTMF = CM_SEND_DTMF, - K_CM_STOP_AUDIO = CM_STOP_AUDIO, - K_CM_HARD_RESET = CM_HARD_RESET, - K_CM_SEND_TO_CTBUS = CM_SEND_TO_CTBUS, - K_CM_RECV_FROM_CTBUS = CM_RECV_FROM_CTBUS, - K_CM_SETUP_H100 = CM_SETUP_H100, - K_CM_MIXER = CM_MIXER, - K_CM_CLEAR_MIXER = CM_CLEAR_MIXER, - K_CM_PLAY_FROM_FILE = CM_PLAY_FROM_FILE, - K_CM_RECORD_TO_FILE = CM_RECORD_TO_FILE, - K_CM_PLAY_FROM_STREAM = CM_PLAY_FROM_STREAM, - K_CM_INTERNAL_PLAY = CM_INTERNAL_PLAY, - K_CM_STOP_PLAY = CM_STOP_PLAY, - K_CM_STOP_RECORD = CM_STOP_RECORD, - K_CM_PAUSE_PLAY = CM_PAUSE_PLAY, - K_CM_PAUSE_RECORD = CM_PAUSE_RECORD, - K_CM_RESUME_PLAY = CM_RESUME_PLAY, - K_CM_RESUME_RECORD = CM_RESUME_RECORD, - K_CM_INCREASE_VOLUME = CM_INCREASE_VOLUME, - K_CM_DECREASE_VOLUME = CM_DECREASE_VOLUME, - K_CM_LISTEN = CM_LISTEN, - K_CM_STOP_LISTEN = CM_STOP_LISTEN, - K_CM_PREPARE_FOR_LISTEN = CM_PREPARE_FOR_LISTEN, - K_CM_PLAY_SOUND_CARD = CM_PLAY_SOUND_CARD, - K_CM_STOP_SOUND_CARD = CM_STOP_SOUND_CARD, - K_CM_MIXER_CTBUS = CM_MIXER_CTBUS, - K_CM_PLAY_FROM_STREAM_EX = CM_PLAY_FROM_STREAM_EX, - K_CM_INTERNAL_PLAY_EX = CM_INTERNAL_PLAY_EX, - K_CM_ENABLE_PLAYER_AGC = CM_ENABLE_PLAYER_AGC, - K_CM_DISABLE_PLAYER_AGC = CM_DISABLE_PLAYER_AGC, - K_CM_START_STREAM_BUFFER = CM_START_STREAM_BUFFER, - K_CM_ADD_STREAM_BUFFER = CM_ADD_STREAM_BUFFER, - K_CM_STOP_STREAM_BUFFER = CM_STOP_STREAM_BUFFER, - K_CM_SEND_BEEP = CM_SEND_BEEP, - K_CM_SEND_BEEP_CONF = CM_SEND_BEEP_CONF, - K_CM_ADD_TO_CONF = CM_ADD_TO_CONF, - K_CM_REMOVE_FROM_CONF = CM_REMOVE_FROM_CONF, - K_CM_RECORD_TO_FILE_EX = CM_RECORD_TO_FILE_EX, - K_CM_SET_VOLUME = CM_SET_VOLUME, - K_CM_SET_LINE_CONDITION = CM_SET_LINE_CONDITION, - K_CM_SEND_LINE_CONDITION = CM_SEND_LINE_CONDITION, - K_CM_SET_CALLER_CATEGORY = CM_SET_CALLER_CATEGORY, - K_CM_DIAL_MFC = CM_DIAL_MFC, -#if !K3L_AT_LEAST(2,0,0) - K_CM_VOIP_START_DEBUG = CM_VOIP_START_DEBUG, - K_CM_VOIP_STOP_DEBUG = CM_VOIP_STOP_DEBUG, - K_CM_VOIP_DUMP_STAT = CM_VOIP_DUMP_STAT, - K_CM_ISDN_DEBUG = CM_ISDN_DEBUG, - K_CM_PING = CM_PING, - K_CM_LOG_REQUEST = CM_LOG_REQUEST, - K_CM_LOG_CREATE_DISPATCHER = CM_LOG_CREATE_DISPATCHER, - K_CM_LOG_DESTROY_DISPATCHER = CM_LOG_DESTROY_DISPATCHER, -#endif -#if K3L_AT_LEAST(1,6,0) - K_CM_START_CADENCE = CM_START_CADENCE, - K_CM_STOP_CADENCE = CM_STOP_CADENCE, - K_CM_CHECK_NEW_SMS = CM_CHECK_NEW_SMS, - K_CM_SEND_TO_MODEM = CM_SEND_TO_MODEM, -#endif -#if K3L_AT_LEAST(2,1,0) - K_CM_START_FAX_TX = CM_START_FAX_TX, - K_CM_STOP_FAX_TX = CM_STOP_FAX_TX, - K_CM_ADD_FAX_FILE = CM_ADD_FAX_FILE, - K_CM_ADD_FAX_PAGE_BREAK = CM_ADD_FAX_PAGE_BREAK, - K_CM_START_FAX_RX = CM_START_FAX_RX, - K_CM_STOP_FAX_RX = CM_STOP_FAX_RX, - K_CM_SIM_CARD_SELECT = CM_SIM_CARD_SELECT, -#endif - -#if K3L_AT_LEAST(2,1,0) - K_CM_NOTIFY_WATCHDOG = CM_NOTIFY_WATCHDOG, - K_CM_STOP_WATCHDOG = CM_STOP_WATCHDOG, - K_CM_WATCHDOG_COUNT = CM_WATCHDOG_COUNT, - K_CM_START_WATCHDOG = CM_START_WATCHDOG, -#endif - - } - kcommand; - - typedef enum - { - K_EV_CHANNEL_FREE = EV_CHANNEL_FREE, - K_EV_CONNECT = EV_CONNECT, - K_EV_DISCONNECT = EV_DISCONNECT, - K_EV_CALL_SUCCESS = EV_CALL_SUCCESS, - K_EV_CALL_FAIL = EV_CALL_FAIL, - K_EV_NO_ANSWER = EV_NO_ANSWER, - K_EV_BILLING_PULSE = EV_BILLING_PULSE, - K_EV_SEIZE_SUCCESS = EV_SEIZE_SUCCESS, - K_EV_SEIZE_FAIL = EV_SEIZE_FAIL, - K_EV_SEIZURE_START = EV_SEIZURE_START, - K_EV_CAS_LINE_STT_CHANGED = EV_CAS_LINE_STT_CHANGED, - K_EV_CAS_MFC_RECV = EV_CAS_MFC_RECV, - K_EV_NEW_CALL = EV_NEW_CALL, - K_EV_USER_INFORMATION = EV_USER_INFORMATION, - K_EV_DIALED_DIGIT = EV_DIALED_DIGIT, -#if K3L_AT_LEAST(1,6,0) - K_EV_SIP_REGISTER_INFO = EV_SIP_REGISTER_INFO, - K_EV_RING_DETECTED = EV_RING_DETECTED, -#endif - K_EV_CALL_HOLD_START = EV_CALL_HOLD_START, - K_EV_CALL_HOLD_STOP = EV_CALL_HOLD_STOP, -#if K3L_AT_LEAST(1,6,0) - K_EV_SS_TRANSFER_FAIL = EV_SS_TRANSFER_FAIL, - K_EV_FLASH = EV_FLASH, -#endif - K_EV_DTMF_DETECTED = EV_DTMF_DETECTED, - K_EV_DTMF_SEND_FINISH = EV_DTMF_SEND_FINISH, - K_EV_AUDIO_STATUS = EV_AUDIO_STATUS, - K_EV_CADENCE_RECOGNIZED = EV_CADENCE_RECOGNIZED, - K_EV_END_OF_STREAM = EV_END_OF_STREAM, - K_EV_PULSE_DETECTED = EV_PULSE_DETECTED, - K_EV_POLARITY_REVERSAL = EV_POLARITY_REVERSAL, -#if K3L_AT_LEAST(1,6,0) - K_EV_ISDN_PROGRESS_INDICATOR = EV_ISDN_PROGRESS_INDICATOR, - K_EV_CALL_ANSWER_INFO = EV_CALL_ANSWER_INFO, - K_EV_COLLECT_CALL = EV_COLLECT_CALL, - K_EV_SIP_DTMF_DETECTED = EV_SIP_DTMF_DETECTED, - K_EV_RECV_FROM_MODEM = EV_RECV_FROM_MODEM, - K_EV_NEW_SMS = EV_NEW_SMS, - K_EV_SMS_INFO = EV_SMS_INFO, - K_EV_SMS_DATA = EV_SMS_DATA, - K_EV_SMS_SEND_RESULT = EV_SMS_SEND_RESULT, -#endif -#if K3L_HAS_MPTY_SUPPORT - K_EV_CALL_MPTY_START = EV_CALL_MPTY_START, - K_EV_CALL_MPTY_STOP = EV_CALL_MPTY_STOP, - K_EV_GSM_COMMAND_STATUS = EV_GSM_COMMAND_STATUS, -#endif - K_EV_CHANNEL_FAIL = EV_CHANNEL_FAIL, - K_EV_REFERENCE_FAIL = EV_REFERENCE_FAIL, - K_EV_INTERNAL_FAIL = EV_INTERNAL_FAIL, - K_EV_HARDWARE_FAIL = EV_HARDWARE_FAIL, - K_EV_LINK_STATUS = EV_LINK_STATUS, -#if K3L_AT_LEAST(1,6,0) - K_EV_PHYSICAL_LINK_UP = EV_PHYSICAL_LINK_UP, - K_EV_PHYSICAL_LINK_DOWN = EV_PHYSICAL_LINK_DOWN, -#endif - K_EV_CLIENT_RECONNECT = EV_CLIENT_RECONNECT, - K_EV_VOIP_SEIZURE = EV_VOIP_SEIZURE, - K_EV_SEIZURE = EV_SEIZURE, - -#if K3L_AT_LEAST(2,1,0) - K_EV_FAX_CHANNEL_FREE = EV_FAX_CHANNEL_FREE, - K_EV_FAX_FILE_SENT = EV_FAX_FILE_SENT, - K_EV_FAX_FILE_FAIL = EV_FAX_FILE_FAIL, - K_EV_FAX_MESSAGE_CONFIRMATION = EV_FAX_MESSAGE_CONFIRMATION, - K_EV_FAX_TX_TIMEOUT = EV_FAX_TX_TIMEOUT, - K_EV_FAX_PAGE_CONFIRMATION = EV_FAX_PAGE_CONFIRMATION, - K_EV_FAX_REMOTE_INFO = EV_FAX_REMOTE_INFO, -#endif - -#if K3L_AT_LEAST(2,1,0) - K_EV_WATCHDOG_COUNT = EV_WATCHDOG_COUNT, -#endif - -#if !K3L_AT_LEAST(2,0,0) - K_EV_PONG = EV_PONG, -#endif - } - kevent; - - typedef enum - { - R2_COUNTRY_ARG = 1, - R2_COUNTRY_BRA = 2, - R2_COUNTRY_CHI = 3, - R2_COUNTRY_MEX = 4, - R2_COUNTRY_URY = 5, - R2_COUNTRY_VEN = 6 - } - R2CountryType; - - typedef enum - { - HUMAN, - EXACT - } - Presentation; - - /* dynamic (object) stuff */ - - Verbose(K3LAPI & api): _api(api) {}; - -#if K3L_AT_LEAST(2,0,0) - std::string event(int32, K3L_EVENT*, R2CountryType r2_country = R2_COUNTRY_BRA, - Presentation fmt = HUMAN); -#else - std::string event(int32, K3L_EVENT*, Presentation fmt = HUMAN); -#endif - - std::string channelStatus(int32, int32, int32, Presentation fmt = HUMAN); - - /* end of dynamic (object) stuff */ - - protected: - K3LAPI & _api; - - /* used internally */ - struct internal_not_found {}; - - public: - - /* static (class) stuff */ - - static std::string echoLocation(KEchoLocation, Presentation fmt = HUMAN); - static std::string echoCancellerConfig(KEchoCancellerConfig, Presentation fmt = HUMAN); - -#if K3L_AT_LEAST(2,0,0) - static std::string event(KSignaling, int32, K3L_EVENT*, R2CountryType = R2_COUNTRY_BRA, - Presentation fmt = HUMAN); -#else - static std::string event(KSignaling, int32, K3L_EVENT*, Presentation fmt = HUMAN); -#endif - -#if K3L_AT_LEAST(2,0,0) - static std::string command(int32, K3L_COMMAND*, R2CountryType = R2_COUNTRY_BRA, - Presentation fmt = HUMAN); - static std::string command(int32, int32, int32, const char *, R2CountryType = R2_COUNTRY_BRA, - Presentation fmt = HUMAN); -#else - static std::string command(int32, K3L_COMMAND*, Presentation fmt = HUMAN); - static std::string command(int32, int32, int32, const char *, Presentation fmt = HUMAN); -#endif - - - static std::string deviceName(KDeviceType, int32, Presentation fmt = HUMAN); - - static std::string deviceType(KDeviceType, Presentation fmt = HUMAN); - static std::string deviceModel(KDeviceType, int32, Presentation fmt = HUMAN); - - static std::string channelFeatures(int32, Presentation fmt = HUMAN); - static std::string signaling(KSignaling, Presentation fmt = HUMAN); - static std::string systemObject(KSystemObject, Presentation fmt = HUMAN); - static std::string mixerTone(KMixerTone, Presentation fmt = HUMAN); - static std::string mixerSource(KMixerSource, Presentation fmt = HUMAN); - - static std::string seizeFail(KSeizeFail, Presentation fmt = HUMAN); - -#if K3L_AT_LEAST(2,0,0) - static std::string callFail(KSignaling, R2CountryType, int32, Presentation fmt = HUMAN); -#else - static std::string callFail(KSignaling, int32, Presentation fmt = HUMAN); -#endif - - static std::string channelFail(KSignaling, int32, Presentation fmt = HUMAN); - static std::string internalFail(KInternalFail, Presentation fmt = HUMAN); - - static std::string linkErrorCounter(KLinkErrorCounter, Presentation fmt = HUMAN); - - static std::string linkStatus(KSignaling, int32, Presentation fmt = HUMAN); - static std::string channelStatus(KSignaling, int32, Presentation fmt = HUMAN); - static std::string callStatus(KCallStatus, Presentation fmt = HUMAN); - static std::string status(KLibraryStatus, Presentation fmt = HUMAN); - -#if K3L_AT_LEAST(2,0,0) - static std::string signGroupB(KSignGroupB, R2CountryType contry = R2_COUNTRY_BRA, - Presentation fmt = HUMAN); -#else - static std::string signGroupB(KSignGroupB, Presentation fmt = HUMAN); -#endif - -#if K3L_AT_LEAST(2,0,0) - static std::string signGroupII(KSignGroupII, R2CountryType contry = R2_COUNTRY_BRA, - Presentation fmt = HUMAN); -#else - static std::string signGroupII(KSignGroupII, Presentation fmt = HUMAN); -#endif - - static std::string h100configIndex(KH100ConfigIndex, Presentation fmt = HUMAN); - - static std::string eventName(int32); - static std::string commandName(int32); - -#if K3L_AT_LEAST(1,5,0) - static std::string sipFailures(KSIP_Failures, Presentation fmt = HUMAN); -#endif - -#if K3L_AT_LEAST(1,5,1) - static std::string isdnCause(KQ931Cause, Presentation fmt = HUMAN); -#endif - -#if K3L_AT_LEAST(1,5,2) - static std::string isdnDebug(int32, Presentation fmt = HUMAN); -#endif - -#if K3L_AT_LEAST(1,6,0) - static std::string callStartInfo(KCallStartInfo, Presentation fmt = HUMAN); - - static std::string gsmCallCause(KGsmCallCause, Presentation fmt = HUMAN); - static std::string gsmMobileCause(KGsmMobileCause, Presentation fmt = HUMAN); - static std::string gsmSmsCause(KGsmSmsCause, Presentation fmt = HUMAN); - - static std::string q931ProgressIndication(KQ931ProgressIndication, - Presentation fmt = HUMAN); -#endif - -#if K3L_AT_LEAST(2,1,0) - static std::string faxResult(KFaxResult code, Presentation fmt = HUMAN); - static std::string faxFileErrorCause(KFaxFileErrorCause code, Presentation fmt = HUMAN); -#endif - - /* end of static (class) stuff */ - - private: - static std::string internal_deviceType(KDeviceType); - static std::string internal_deviceModel(KDeviceType, int32); - -#if K3L_AT_LEAST(1,5,0) - static std::string internal_sipFailures(KSIP_Failures, Presentation fmt = HUMAN); -#endif -#if K3L_AT_LEAST(1,5,1) - static std::string internal_isdnCause(KQ931Cause, Presentation fmt = HUMAN); -#endif - -#if K3L_AT_LEAST(2,0,0) - static std::string internal_signGroupB(KSignGroupB, R2CountryType contry, Presentation fmt = HUMAN); - static std::string internal_signGroupII(KSignGroupII, R2CountryType contry, Presentation fmt = HUMAN); -#else - static std::string internal_signGroupB(KSignGroupB, Presentation fmt = HUMAN); - static std::string internal_signGroupII(KSignGroupII, Presentation fmt = HUMAN); -#endif - -#if K3L_AT_LEAST(1,6,0) - static std::string internal_gsmCallCause(KGsmCallCause, Presentation fmt = HUMAN); - static std::string internal_gsmMobileCause(KGsmMobileCause, Presentation fmt = HUMAN); - static std::string internal_gsmSmsCause(KGsmSmsCause, Presentation fmt = HUMAN); - - static std::string internal_q931ProgressIndication(KQ931ProgressIndication, Presentation fmt = HUMAN); -#endif - - private: - enum Type - { - DEVICE, - CHANNEL, - PLAYER, - MIXER, - LINK, - NONE - }; - - struct Target - { - Target(Type _type) - : type(_type), device(-1), object(-1) - {}; - - Target(Type _type, int32 _device) - : type(_type), device(_device), object(-1) - {}; - - Target(Type _type, int32 _device, int32 _object) - : type(_type), device(_device), object(_object) - {}; - - Type type; - int32 device; - int32 object; - }; - - static void generate(std::string &, std::string &, Target, std::string &); - - static std::string show(std::string &, std::string, Target, std::string &); - static std::string show(std::string &, std::string, Target); - - template < typename ReturnType > - static ReturnType presentation(Presentation fmt, ReturnType str_exact, ReturnType str_human) - { - switch (fmt) - { - case HUMAN: return str_human; - case EXACT: return str_exact; - }; - - return str_exact; - } -}; - -#endif /* _VERBOSE_HPP_ */ diff --git a/src/mod/endpoints/mod_khomp/docs/Manual.html b/src/mod/endpoints/mod_khomp/docs/Manual.html index 863ef76847..c4745700b1 100644 --- a/src/mod/endpoints/mod_khomp/docs/Manual.html +++ b/src/mod/endpoints/mod_khomp/docs/Manual.html @@ -37,17 +37,22 @@
  • context-fxs: Contexto de entrada para placas FXS (o padrão é "khomp-DD-CC", onde "DD" será substituído, no momento da ligação, pelo número do dispositivo, "CC" pelo número do canal, e "SSSS" pelo número serial do dispositivo);
  • context-gsm-call (ou "context-gsm"): Contexto de entrada para ligações GSM (o padrão é "khomp-DD-CC", onde "DD" será substituído no momento da ligação pelo número do dispositivo, "CC" pelo número do canal, e "SSSS" pelo número serial do dispositivo);
  • context-gsm-sms: Contexto de entrada para SMSs (o padrão é "khomp-sms-DD-CC", onde "DD" será substituído pelo número de dispositivo, "CC" pelo número do canal, e "SSSS" pelo número serial do dispositivo); -
  • context-pr: Contexto de entrada para ligações em placas KPR (o padrão é "khomp-DD-CC", onde "DD" será substituído, no momento da ligação, pelo número do dispositivo, "CC" pelo número do canal); +
  • context-pr: Contexto de entrada para ligações em placas KPR (o padrão é "khomp-DD-CC", onde "DD" será substituído, no momento da ligação, pelo número do dispositivo, "CC" pelo número do canal); +
  • delay-ringback-co: Define o tempo de delay para ativar a geração de tom de controle de chamada (ringback) pelo Endpoint da Khomp quando há uma indicação de ringback, e não há áudio sendo enviado por quem indicou a situação de controle da chamada; +
  • delay-ringback-pbx: Define o tempo de delay para ativar a geração de controle de chamada (ringback) pelo Endpoint da Khomp quando há uma indicação de ringback, e o áudio de controle enviado não possui nenhum tom (ou seja, está em silêncio);
  • disconnect-delay: Define o tempo em milissegundos para realizar o processamento de um evento de desconexão, para ignorar situações onde outros equipamentos realizam o duplo atendimento para derrubar chamadas a cobrar; +
  • drop-collect-call: Ativa ("yes") ou desativa ("no") o derrubamento de chamadas à cobrar. Caso ativo, todas as chamadas à cobrar serão derrubadas não importando o que foi ajustado na variável KDropCollectCall (o valor padrão é "no");
  • echo-canceller: Ativa ("yes") ou desativa ("no") o cancelamento de eco automático pelo Endpoint; +
  • flash-to-digits: Define os dígitos para serem enviados quando o FLASH é detectado na FXS;
  • fxo-send-pre-audio: Quando ativada ("yes") libera canal de áudio sainte antes da conexão da chamada em placas KFXO (o valor padrão é "yes"); +
  • fxs-digit-timeout: Define o timeout, em segundos, entre dígitos na FXS;
  • fxs-global-orig: Número inicial para numeração seqüencial de ramais das placas KFXS que não estiverem listadas na seção <fxs-branches> (a numeração segue ordem crescente por número da placa e número do canal físico) (o padrão é "0");
  • fxs-co-dialtone: Seqüências de números, separados por vírgula, que disparam um tom contínuo (de central pública) em ramais FXS (ex: "0,99" faz com que, ao discar "0" ou "99", o usuário receba o tom de linha contínuo) (o padrão é vazio);
  • fxs-bina: Quando ativada ("yes"), ligações para ramais FXS enviarão os dígitos correspondentes ao telefone de origem em sinalização BINA DTMF (o valor padrão é "no"); +
  • ignore-letter-dtmfs: Define se o canal deve ignorar DTMFs incomuns detectados pela placa (A, B, C e D). Entretanto, se você necessita passar esses dígitos pela placa, você deve ajustar esta opção para "no" (o valor padrão é "yes");
  • input-volume: Define o volume de entrada das ligações, varia de -10 a +10 ;
  • kommuter-activation: Define se a ativação de dispositivos kommuter encontrados no sistema será feita de forma automática ("auto"), ou de forma manual ("manual") pelo usuário, através do comando "khomp kommuter on/off";
  • kommuter-timeout: Define o timeout (em segundos) com que os kommuters serão inicializados. Se chegarem a este timeout sem receberem notificação do channel, os dispositivos irão comutar para o estado "desligado". O valor mínimo é "0" , onde os links permanecerão sempre comutados no estado "ligado", e o valor máximo é "255"; -
  • language: Define idioma para ligações nas placas Khomp;
  • log-to-console: Define mensagens de log que devem ser impressas na console;
  • log-to-disk: Define mensagens de log que devem ser salvar em disco;
  • out-of-band-dtmfs: Ativa ("yes") ou desativa ("no") a supressão DTMF e o envio destes out-of-band; @@ -55,12 +60,9 @@
  • pulse-forwarding: Ativa ("yes") ou desativa ("no") a detecção de pulsos e a conversão dos mesmos em DTMFs;
  • r2-preconnect-wait: Define o tempo de espera do envio da sinalização de ringback, no protocolo R2/MFC, para iniciar o envio de áudio de silêncio. Apenas utilizado quando "r2-strict-behaviour" estiver ajustado para "no";
  • r2-strict-behaviour: Ativa ("yes") ou desativa ("no") o comportamento da sinalização R2/MFC conforme a norma define. O padrão é "no", e pode ser alterado para "yes" caso seja necessário receber/enviar dados precisos da sinalização do protocolo (condição de B, por exemplo); -
  • ringback-delay-co: Define o tempo de delay para ativar a geração de tom de controle de chamada (ringback) pelo Endpoint da Khomp quando há uma indicação de ringback, e não há áudio sendo enviado por quem indicou a situação de controle da chamada; -
  • ringback-delay-pbx: Define o tempo de delay para ativar a geração de controle de chamada (ringback) pelo Endpoint da Khomp quando há uma indicação de ringback, e o áudio de controle enviado não possui nenhum tom (ou seja, está em silêncio);
  • suppression-delay: Ativa ("yes") ou desativa ("no") o delay necessário para supressão DTMF. Se desativado ("no"), também desativa supressão de DTMFs;
  • trace: Define opções de depuração. Não deve ser utilizado em produção a não ser que estritamente necessário;
  • user-transfer-digits: Define uma seqüência de dígitos DTMF para iniciar a transferencia entre o FreeSWITCH® e um outro PABX (utilizando sinalização de usuário, como QSig ou FXO FLASH); -
  • flash-to-digits: Define os dígitos para serem enviados quando o FLASH é detectado na FXS;

  • @@ -117,15 +119,13 @@
    • context;
    • input-volume;
    • output-volume; -
    • accountcode;
    • calleridnum;
    • calleridname; -
    • mailbox;
    • flash-to-digits.

    Cada opção é separada uma da outra por um pipe "|" ou uma barra "/" e definidas após dois pontos ":", exemplo:

    -
     <param name="200" value="language:en|context:master-branch" />
    +
     <param name="200" value="input-volume:1|context:master-branch" />
     

    Para maiores informações sobre a sintaxe e exemplos, favor consultar o arquivo de configuração.


    diff --git a/src/mod/endpoints/mod_khomp/docs/Manual.pdf b/src/mod/endpoints/mod_khomp/docs/Manual.pdf index 935b299dbc821be862d801ecf934e5131acf1044..260ba542a5a1476b0bb0ecc9bc4b1ef9c313628a 100644 GIT binary patch delta 33248 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 KX(bho_te$ZUHv^Z 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 diff --git a/src/mod/endpoints/mod_khomp/docs/README.pdf b/src/mod/endpoints/mod_khomp/docs/README.pdf index 2b95cfaad4d41964e1155d28a906699c0227b1a1..13a5f5469a80ec0d20f7c85e60e193622eaee77a 100644 GIT binary patch delta 1303 zcmbQRPNILE#DsQEBLhPqFgG@CoX|Rfv2_Ad>jdW32`pPDuvYyQwlp*{urx6>)-^OV zwKO&`G&i!`F7uD|7&D{E_Q#BDUW_6uuV{L1a&)zJouE}3Y$F!myI|+9?M}>W8jSS@ zmI@GHXIETOl$w~!Rl!&r;+uclfM@UT@DDQ>HzuF#voE`SZHYu%QpRjX>o13Hc`Z9+ z7JE{!>))@ye<$YTNi^M1(46$%HmL3!OUobO30@sS8d>^0PT%IpmtUWE;*dh)+B3}p zSre4_o}`2pyw}a`J7scW`o-3>7efl_dpAxx-Mc9#&~n;G*OJWZ0`4ze?=L-jF-Lky z_o?#}Iuoo5CP$x3cAD^{aDrvm?Dd5l;Vj$lJwIH%?-|SNT0Wze!xJx0R(UkX*;3=s zzNFH-*)6-eAP{dan#PVJCmssC~1a~aQ`4K*FxHYNVmmH+FXn&A6SvCLgH-H7@7n+;E|Ppmll zY;EzyrmPKrU8Z+NulBcLeWI&;Vb8M1lXA~{e_MRH?=wSL&(h~N)@fG0pZ%`(+@93M z|M$!^eo|=_Kc^sKZdKTs3&}^zSym_{|5){5LT>y<0~YfeUmh=bR+laJJZ9zf%M&VQ z5d4{ks=w^L=F&&9Rr6baUCx+c%`Oj{p8B_^xdJy1cT!Mtk{BmkTUZ zodth6{aRR%D4Fgk_u2ipsDzCYf3wa^n-AaBQ_4T&?Y)0t%XF{pPV8(m*|gO!>O2ck z{e1dmQJ?jW`lHG;Bs9YdcLdp>ChvAjW1Cmu8u0l5CP} zXp)+oVqun)oMe$`VrrRYW@(vbl#-U1WM@NAMXa42S8+*VQAtHnY8scZrMZcj1(&L- ItG^o;0F6%t-v9sr delta 1245 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 delta 2426 zcmajhc{~%09|v$s!!*j3BRN8BvD=pW$Pv~YO(B&z8fwlx&RU3wnB^#Pl_TT`b9S(D zmSb|?giWp}%2A%@c|HIA`s4Tc=lgoSU!Olde|}3JiIhDOq21$$!%(m@XcP(=PK%;( zN6`*M(GD_bJo(ikSS%I;*T5px;1~o3gTTTy;I(E9p522~ttyeO<()=3+WN`oq8#Cx zT$;*BzeYP~ynYc#lP`yVLK@k+=}@HT$%+(fj>uJ+sE)jYqqpH zh)Y`#+X!eXCe?RxD@1|`2QhQ$RMJFkTkcYir9@=PRv=2CrL4doQ#P1N%H-`SN4Q@- ztd?hmyfl#56Bhz#%o2+jXV_lo^Dm?;9!jD`3wyX74?(`Ui|TJsO>Kcz8NC#!wQb-z z!A(WLxNrtT>E; zEBXDS5vjQHR29f%H}2jVUzg%HTRe5`p}`x#fQbj)W^V5%MS4D%&ICg^BTO*9=2LF? z6f4a|U`*TocD+ams-q{$ertpp4Y}$Jp%e6b?9R2)D%4Z^GtEw~ZX6~b);>G+!NO#V zEAAGzJ(xgF8(YHOAy~x;)5%Sd!uCjifB2-2ySqpds8rJYQvT#eqfVS>sowvOB>XIbLsvr}<_d zcu^)cWCZ2oAWB3y?Bct7lFLQERb&Fatc1Nj$uIK+3GX1%n<|g#_qp=!>ggHLDyGkA zmNv;7MB0kK)Iu(+X)f4{bqW zZ|-|K_jmU3HcOY(*K#2`4pRD|QaLZOc-f9meP;?4EHt-}(LYYwK&XnFr`%Tc+>=r) z2aguFWdWKABF8-fB8i|){e+%iNl}~r3^}V$3-J%HWFDJl!8>47uVD(o`@7kOzt(mB zUYa5%)RVLsZxc!RCZHtvSetpWly7_^p{EBD2Y%u1(WNgl&XU0A7>pC&Wkm!9R%isy=R-^IY-Nv_z52~=auE{N`1E{W9`#@{f z&}6q8?i{`4x|UG3NBVTM1ubg^^|UW2wZ%4#9iVHzXv0dI^p1O%w?aQpEx(>D=wUtk zHAtKJ*m%Zy=E~%LLDXfsz3+~H{+H-7SC)!=SI2Dj#`qL8oY zeg;uTUkLASCQlAAJzb@GHBW|~Gd!kFX>Gzo~5I^oIIY{6V^tdtnGk8pB zfNJV{gejBOd4xJ&kG|tNRcHMG+HZRLu6v>wc-c@$)!Zapy3BvjS3yzYnwX@ue+b9a zhOsc?>T@TmjvSPbUeblXX0GUSDBK*9zeE>5l&D|$`B80BV;%zrp*nnPTP*-2s`m*# zkC5DIMZ zv!^;JcUK0)I^S79uz0`8`feh9<#T+pcHrqRWwjmEUSw2kA^!vS^pKAwLPO#{bHFom_R5( z|J0pk5kUFbyf=)}DXm!P5R1*CyRXnYN#(blRBtMlY(t$|W%mfAXA=X7r`T1$4j4Fn z@p6=VJ69eJmOrzYQc2(rT|}QQBy{ESadL$5d#5Bk#Fq`I1&qwOzzJz4MAP+s)q;T$ zf4zfwU1E+Y-ne_zP^kSzI(|b&ZS2^&(TK_|{n5}Cu$Pp8B!#$!jV=!7nlCS!1{8xD z-s>dBT*~?e5ZpB1ST|hpFE@FWSAVQBujIXK@Wr!lX154MCW(WB6WpTag zO=RpnSnBbl26ArA;X_tnLC+1vXN^U_9-oH*N-j*xWT9$Ox+D5zWADzUfzsAI)*)clm_MiOi%uu!{zV+0jL&NM zAq;wW+;a?1k{R(JDYe*~vN7?~j=q9d$A`jLgcVBWte)-Jm0UMq>hk6pB6_sO|>J#ch zX*t_wz^U4s+IsJ_K9XEu%?7JFsyiLJeAvrl&m9>T{3K-Oj|_@x-?QRG!rF#xhR2-S>Y}c;8<5Alf^G8qP4D3Hk%lyEDFu=OFpThis step is carried out in a semi-automated way using the khompwizard program, a wizard that configures the basic parameters of the system boards. This wizard initializes the configuration files using information from the user when they are needed, initializing the standard settings to default values.

    Typically, this program runs automatically after installation of the system. However, you may need to run it manually if an update is being performed, or if new cards were added to the system after installing new drivers.


    -If you need to set advanced parameters of the board and/or signaling, the program k3lconfig allows you to access all the available settings for each installed card. For more information about this program, check the
    k3lconfig User's Guide. For solving synchronization issues, check the Troubleshooting section for manual configuration of the boards. +If you need to set advanced parameters of the board and/or signaling, the program k3lconfig allows you to access all the available settings for each installed card. For more information about this program, check the k3lconfig User's Guide. For solving synchronization issues, check the Troubleshooting section for manual configuration of the boards.

    Endpoint Configuration

    @@ -39,16 +39,21 @@ If you need to set advanced parameters of the board and/or signaling, the progra
  • context-gsm-call (or context-gsm): Context of entry for GSM boards (the default is "khomp-CC-DD", where "DD" will be replaced at the time of connection by the device number, "CC" by channel number, and "SSSS" by the device serial number);
  • context-gsm-sms: Context for incoming SMSs (the default is "khomp-sms-CC-DD", where "DD" will be replaced by the number of device, "CC" by channel number and "SSSS" by the device's serial number);
  • context-pr: Context for incoming connections on boards KPR (default is "khomp-CC-DD", where "DD" will be replaced at the time of connection by the device number, "CC "by channel number); +
  • delay-ringback-co: Sets the delay to enable the generation of call control tone (ringback) by the Endpoint Khomp when there is an ringback indication from signaling and there is no audio being sent by the channel which indicated the situation (local option); +
  • delay-ringback-pbx: Sets the delay to enable the generation of call control tone (ringback) by the Endpoint Khomp when there is an ringback indication, and the audio has no tone (silence) (local option);
  • disconnect-delay: Sets the time in milliseconds to perform processing a disconnect event, to ignore situations where other equipment performing the double service to overthrow collect calls (local option); +
  • drop-collect-call: Enables/Disables the action of dropping collect calls. If enabled, all collect calls will be dropped no matter what KDropCollectCall is set to (the default value is "no");
  • echo-canceller (former 'echocanceller): Active ("yes") or disables ("no") echo cancellation automatic Endpoint (local option); +
  • flash-to-digits: Defines the digits to be sent when the FLASH is detected on FXS channels;
  • fxo-send-pre-audio: When enabled ("yes") releases audio channel before the outgoing call connection boards KFXO (the default value is "yes"); +
  • fxs-digit-timeout: Defines the timeout, in seconds, between digits of a FXS board's extension;
  • fxs-global-orig: Start number for sequencial branch numbering in FXS cards that are not listed in the [fxs-branches] section (the numbering follows ascending order from board number and physical channel number) (default is "0");
  • fxs-co-dialtone: Sequences of numbers, separated by commas, which fires a continuous tone (of central office) in FXS branches (eg: "0,99" means that, when you dial "0" or "99", the user will hear a continuous dial tone) (default is empty);
  • fxs-bina: When enabled ("yes"), calls to FXS lines will send digits corresponding to the source phone identification using BINA DTMF signaling (the default value is "no") (local option); +
  • ignore-letter-dtmfs: Defines if the channel should ignore some uncommon DTMF digits detected by the board (A, B, C and D). However, if you need to pass those digits througth the board, you may need to set this option to 'no' (the default value is "yes");
  • input-volume: Sets the volume gain for incoming audio (entering the board), from -10 to +10 (local option);
  • kommuter-activation: Sets whether to activate devices kommuter found in the system will be done automatically ("auto") by the channel, or manually ("manual") by the user through the command "khomp kommuter on/off"
  • kommuter-timeout: Sets the timeout (in seconds) for initializing the kommuter devices. If this timeout is reached without receiving notification of the channel, the devices will switch back to "off" condition. The minimum value is "0", where the links will always remain switched "on", and the maximum is "255"; -
  • language: Set language to Khomp channel calls (local option);
  • log-to-console: Set log messages to be printed on the console;
  • log-to-disk (old "log"): Set log messages to be saved to disk;
  • out-of-band-DTMF (former dtmfsuppression): Activate ("yes") or disables ("no") the removal and DTMF sending these out-of-band (local option); @@ -56,12 +61,9 @@ If you need to set advanced parameters of the board and/or signaling, the progra
  • pulse-forwarding (former 'pulsedetection): Active ("yes") or disables ("no") for the detection of pulses and converting them into DTMF (local option);
  • r2-preconnect-wait (former 'r2preconnectwait): Sets the timeout sending the ringback signaling, protocol R2/MFC to start sending audio silence. Only used when "r2-strict-Behavior" is set to "no" (local option);
  • r2-strict-Behaviour: Enable ("yes") or disables ("no") the behavior of signaling R2/MFC as the standard sets. The default is "no", and can be changed to "yes" if needed to receive / send data precise signaling protocol (condition B, for example) (local option); -
  • ringback-delay-co: Sets the delay to enable the generation of call control tone (ringback) by the Endpoint Khomp when there is an ringback indication from signaling and there is no audio being sent by the channel which indicated the situation (local option); -
  • ringback-delay-pbx: Sets the delay to enable the generation of call control tone (ringback) by the Endpoint Khomp when there is an ringback indication, and the audio has no tone (silence) (local option);
  • suppression-delay (former suppressiondelay): Activate ("yes") or disables ("no") the delay necessary to suppress DTMF. If disabled ("no"), also disables suppression of DTMF (local option);
  • trace: Set debugging options. Should not be used in production unless absolutely necessary; -
  • user-transfer-digits: Defines a sequence of DTMF digits to initiate the transfer between FreeSWITCH® and another PBX (using user signaling, like QSig or FXO FLASH). -
  • flash-to-digits: Defines the digits to be sent when the FLASH is detected on FXS channels.. +
  • user-transfer-digits: Defines a sequence of DTMF digits to initiate the transfer between FreeSWITCH® and another PBX (using user signaling, like QSig or FXO FLASH);

  • @@ -121,15 +123,13 @@ For details, please refer to the configuration file for examples.
    • context;
    • input-volume;
    • output-volume; -
    • accountcode;
    • calleridnum;
    • calleridname; -
    • mailbox;
    • flash-to-digits.

    Each option is separated from each other by a pipe "|" or a slash "/" and defined after the colon ":". Example:

    -
    <param name="200" value="language:en|context:master-branch" />
    +
    <param name="200" value="input-volume:1|context:master-branch" />
     

    For more information on the syntax and examples, please refer to the configuration file.

    For more information visit the configuration file 'khomp.conf.xml'. diff --git a/src/mod/endpoints/mod_khomp/docs/User_Guide.pdf b/src/mod/endpoints/mod_khomp/docs/User_Guide.pdf index 832596bdb255ccbd3bc03c675d3afe7a590008b7..e0c33e1c74e1c6f9588831d2b52013482fd13437 100644 GIT binary patch delta 36916 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

    WkXLuEr$VImcWjue|Mhk`fO|V~kNo!_IfS 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 + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/mod/endpoints/mod_khomp/examples/transfer.xml b/src/mod/endpoints/mod_khomp/examples/transfer.xml new file mode 100644 index 0000000000..5c66633574 --- /dev/null +++ b/src/mod/endpoints/mod_khomp/examples/transfer.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/mod/endpoints/mod_khomp/include/applications.h b/src/mod/endpoints/mod_khomp/include/applications.h index 75f55ec5ca..21b66b2b0a 100644 --- a/src/mod/endpoints/mod_khomp/include/applications.h +++ b/src/mod/endpoints/mod_khomp/include/applications.h @@ -268,7 +268,7 @@ struct Transfer if (!(_call->_flags.check(Kflags::XFER_DIALING))) { _call->_flags.set(Kflags::XFER_DIALING); - _idx_xfer_dial = Board::board(_pvt->target().device)->_timers.add(Opt::_transferdigittimeout, &userXferTimer, _pvt, TM_VAL_CALL); + _idx_xfer_dial = Board::board(_pvt->target().device)->_timers.add(Opt::_options._transferdigittimeout(), &userXferTimer, _pvt, TM_VAL_CALL); } else { @@ -280,7 +280,7 @@ struct Transfer } } - catch (K3LAPI::invalid_device & err) + catch (K3LAPITraits::invalid_device & err) { LOG(ERROR, PVT_FMT(_pvt->target(), "Unable to get device: %d!") % err.device); } @@ -506,7 +506,7 @@ struct Transfer if (!(_call->_flags.check(Kflags::XFER_DIALING) || _call->_flags.check(Kflags::XFER_QSIG_DIALING))) { _call->_flags.set(Kflags::XFER_DIALING); - _idx_xfer_dial = Board::board(_pvt->target().device)->_timers.add(Opt::_transferdigittimeout, &userXferTimer, _pvt, TM_VAL_CALL); + _idx_xfer_dial = Board::board(_pvt->target().device)->_timers.add(Opt::_options._transferdigittimeout(), &userXferTimer, _pvt, TM_VAL_CALL); } else { @@ -530,7 +530,7 @@ struct Transfer } } - catch (K3LAPI::invalid_device & err) + catch (K3LAPITraits::invalid_device & err) { LOG(ERROR, PVT_FMT(_pvt->target(), "Unable to get device: %d!") % err.device); } @@ -735,6 +735,9 @@ struct Transfer }; /*************************** SMS **********************************************/ +#define ESL_SMS_RECEIVED "khomp::sms_received" +#define ESL_SMS_SENT "khomp::sms_sent" + struct SMS : public Application { typedef std::list< switch_core_session_t *> OwnersList; @@ -889,6 +892,78 @@ struct SMS : public Application bool _conf; }; + static struct _SMSEvent : public ESL + { + + _SMSEvent() : ESL("khomp::sms") + { + if(_events) + { + _events->push_back(ESL_SMS_RECEIVED); + _events->push_back(ESL_SMS_SENT); + } + } + + ~_SMSEvent() + { + if(_events) + { + //Remove two from vector + _events->pop_back(); + _events->pop_back(); + } + } + + bool operator()(Board::KhompPvt * pvt, ReceiveData & data) + { + switch_event_t *event = create(ESL_SMS_RECEIVED); + + if(!event) + { + LOG(ERROR, "Cannot create SMS ESL"); + return false; + } + + add(event, pvt->target()); + add(event, "Type", data._type); + add(event, "From", data._from); + add(event, "Date", data._date); + add(event, "Size", data._size); + add(event, "Coding", data._coding); + add(event, "Serial", data._serial); + add(event, "Id", data._id); + add(event, "Page", data._page); + add(event, "Pages", data._pages); + add(event, "Sc_date", data._sc_date); + add(event, "Status", data._status); + add(event, "Body", data._body); + + return fire(&event); + } + + bool operator()(Board::KhompPvt * pvt, SendData & data) + { + switch_event_t *event = create(ESL_SMS_SENT); + + if(!event) + { + LOG(ERROR, "Cannot create SMS ESL"); + return false; + } + + add(event, pvt->target()); + add(event, "Dest", data._dest); + add(event, "Body", data._body); + add(event, "Confirmation?", (data._conf ? "Yes" : "No")); + + + return fire(&event); + } + + + + } SMSEvent; + struct Request { /* "empty" constructor */ diff --git a/src/mod/endpoints/mod_khomp/include/cli.h b/src/mod/endpoints/mod_khomp/include/cli.h index 214e2aa2d5..bb251bb16b 100644 --- a/src/mod/endpoints/mod_khomp/include/cli.h +++ b/src/mod/endpoints/mod_khomp/include/cli.h @@ -99,12 +99,52 @@ struct Command std::string usage; /* usage of the command, a help */ }; +struct CommandXMLOutput : public Command +{ + void createRoot(const char *name) + { + root = switch_xml_new(name); + } + + void insertXML(switch_xml_t xml) + { + switch_xml_insert(xml,root,0); + } + + void clearRoot() + { + if(root) + { + switch_xml_free(root); + root = NULL; + } + } + + void printXMLOutput(switch_stream_handle_t *stream) + { + K::Logger::Logg2(C_CLI,stream,switch_xml_toxml(root,SWITCH_FALSE)); + } + + CommandXMLOutput() : root(NULL) {}; + + switch_xml_t root; /* for commands that ouput as xml */ +}; + struct Cli { /* Useful definitions --------------------------------------------------- */ typedef switch_status_t (APIFunc)(const char*, switch_core_session_t*, switch_stream_handle_t*); typedef std::vector Commands; + /* Define the output types form commands */ + typedef enum + { + VERBOSE = 1, + CONCISE, + DETAILED, + XML + } OutputType; + /* register our commands, but you must create the command function */ static void registerCommands(APIFunc func,switch_loadable_module_interface_t **mod_int); @@ -145,27 +185,31 @@ struct Cli /* The Commands --------------------------------------------------------- */ /* khomp summary */ - static struct _KhompSummary : public Command + static struct _KhompSummary : public CommandXMLOutput { _KhompSummary(bool on_cli_term = true): - _on_cli_term(on_cli_term) + CommandXMLOutput(), + _on_cli_term(on_cli_term), + xdevs(NULL) { complete_name = "summary"; options.push_back("verbose"); options.push_back("concise"); + options.push_back("xml"); brief = "Print system info."; usage = \ "Prints detailed info about the system like API version and \n" \ "boards characteristics like DSPs version.\n\n" \ -"Usage: khomp summary [concise]"; +"Usage: khomp summary [concise|verbose|xml]"; _commands.push_back(this); }; bool execute(int argc, char *argv[]); - bool _on_cli_term; /* indicates if message is sent to fs_cli */ + bool _on_cli_term; /* indicates if message is sent to fs_cli */ + switch_xml_t xdevs; /* support xml needed to help the interation */ } KhompSummary; /* khomp show calls */ @@ -239,21 +283,22 @@ struct Cli } KhompChannelsUnblock; /* khomp show statistics */ - static struct _KhompShowStatistics : public Command + static struct _KhompShowStatistics : public CommandXMLOutput { - _KhompShowStatistics() + _KhompShowStatistics() : CommandXMLOutput(), xdevs(NULL) { complete_name = "show statistics"; options.push_back("verbose"); options.push_back("detailed"); + options.push_back("xml"); brief = "Shows statistics of the channels."; usage = \ "Shows statistics of the channels, like number of calls incoming \n" \ "and outgoing, status, status time.\n\n" \ -"Usage: khomp show statistics [{verbose [ []]} | \n" \ +"Usage: khomp show statistics [{{verbose|xml} [ []]} | \n" \ " {detailed }]\n" \ "\tboard -- Number of the board (start from 0).\n" \ "\tchannel -- Number of the channel (start from 0).\n" \ @@ -274,20 +319,22 @@ struct Cli bool execute(int argc, char *argv[]); /* support functions */ - void cliStatistics(unsigned int device); - void cliDetailedStatistics(unsigned int device, unsigned int channel); + void cliStatistics(unsigned int device, OutputType output_type); + void cliDetailedStatistics(unsigned int device, unsigned int channel, OutputType output_type); + switch_xml_t xdevs; /* support xml needed to help the interation */ } KhompShowStatistics; /* khomp show channels */ - static struct _KhompShowChannels: public Command + static struct _KhompShowChannels: public CommandXMLOutput { - _KhompShowChannels() + _KhompShowChannels() : CommandXMLOutput(), xdev(NULL) { complete_name = "show channels"; options.push_back("verbose"); options.push_back("concise"); + options.push_back("xml"); brief = "Show all channels status."; usage = \ @@ -295,34 +342,40 @@ struct Cli "khomp API point of view.\n\n" \ "Usage: \n" \ "khomp show channels [{ []} | \n" \ - "{{concise|verbose} [ []]}]\n" \ + "{{concise|verbose|xml} [ []]}]\n" \ "\tboard -- Number of the board (start from 0).\n" \ "e.g. khomp show channels - List status of all channels of all boards.\n" \ "e.g. khomp show channels concise 0 - List status of all channels of \n" \ -" board 0 in a concise way."; +" board 0 in a concise way.\n" \ +"e.g. khomp show channels xml 0 - List status of all channels of \n" \ +" board 0 in a xml structure."; _commands.push_back(this); }; /* support function for _KhompShowChannels */ - void showChannel(unsigned int device, bool concise, unsigned int channel); - void showChannels(unsigned int device, bool concise); + void showChannel(unsigned int device, unsigned int channel, OutputType output_type = Cli::VERBOSE); + void showChannels(unsigned int device, OutputType output_type = Cli::VERBOSE); bool execute(int argc, char *argv[]); + switch_xml_t xdev; /* support xml needed to help the interation */ + } KhompShowChannels; /* khomp show links */ - static struct _KhompShowLinks: public Command + static struct _KhompShowLinks: public CommandXMLOutput { - _KhompShowLinks() + _KhompShowLinks() : CommandXMLOutput(), xdev(NULL) { complete_name = "show links"; options.push_back("verbose"); options.push_back("concise"); + options.push_back("xml"); options.push_back("errors"); options.push_back("errors verbose"); options.push_back("errors concise"); + options.push_back("errors xml"); brief = "Show E1 link(s) status/errors counters in a concise \n" \ "way or not."; @@ -332,8 +385,9 @@ struct Cli "status/the error counters of each link on the board. It prints in \n" \ "a concise way for parsing facilities.\n\n" \ "Usage: \n" \ -"khomp show links [[errors] [{} | {{concise|verbose} []}]]\n" \ +"khomp show links [[errors] [{} | {{concise|verbose|xml} []}]]\n"\ "e.g. khomp show links - Show all links of all boards.\n" \ +"e.g. khomp show links xml - Show all links of all boards in xml.\n" \ "e.g. khomp show links errors - Show error counters of all links of \n" \ " all boards.\n" \ "e.g. khomp show links errors 0 - Show error counters of all links of \n" \ @@ -343,10 +397,12 @@ struct Cli }; /* support function for _KhompShowLinks */ - void showLinks(unsigned int device, bool concise); - void showErrors(unsigned int device, bool concise); + void showLinks(unsigned int device, OutputType output_type = Cli::VERBOSE); + void showErrors(unsigned int device, OutputType output_type = Cli::VERBOSE); + std::string getLinkStatus(int dev, int obj, Verbose::Presentation fmt); bool execute(int argc, char *argv[]); + switch_xml_t xdev; /* support xml needed to help the interation */ } KhompShowLinks; /* khomp clear links */ @@ -653,24 +709,41 @@ struct Cli { complete_name = "get"; + options.push_back("dialplan"); options.push_back("echo-canceller"); + options.push_back("auto-gain-control"); options.push_back("out-of-band-dtmfs"); + options.push_back("suppression-delay"); options.push_back("auto-fax-adjustment"); + options.push_back("fax-adjustment-timeout"); options.push_back("pulse-forwarding"); options.push_back("r2-strict-behaviour"); options.push_back("r2-preconnect-wait"); - options.push_back("native-bridge"); - options.push_back("suppression-delay"); - options.push_back("context-fxo"); - options.push_back("context-fxo-alt"); - options.push_back("context-fxs"); - options.push_back("context-fxs-alt"); - options.push_back("context-gsm-call"); - options.push_back("context-gsm-call-alt"); - options.push_back("context-gsm-sms"); options.push_back("context-digital"); + options.push_back("context-fxs"); + options.push_back("context-fxo"); + options.push_back("context-gsm-call"); + options.push_back("context-gsm-sms"); + options.push_back("context-pr"); + options.push_back("log-to-console"); + options.push_back("log-to-disk"); + options.push_back("trace"); options.push_back("output-volume"); options.push_back("input-volume"); + options.push_back("fxs-global-orig"); + options.push_back("fxs-co-dialtone"); + options.push_back("fxs-bina"); + options.push_back("disconnect-delay"); + options.push_back("delay-ringback-co"); + options.push_back("delay-ringback-pbx"); + options.push_back("ignore-letter-dtmfs"); + options.push_back("fxo-send-pre-audio"); + options.push_back("fxs-digit-timeout"); + options.push_back("drop-collect-call"); + options.push_back("kommuter-activation"); + options.push_back("kommuter-timeout"); + options.push_back("user-transfer-digits"); + options.push_back("flash-to-digits"); brief = "Get configuration options in the Khomp channel."; @@ -678,36 +751,37 @@ struct Cli "Usage: khomp get