diff --git a/build/modules.conf.in b/build/modules.conf.in
index 67e1fe62ae..37244a188a 100644
--- a/build/modules.conf.in
+++ b/build/modules.conf.in
@@ -105,5 +105,5 @@ say/mod_say_ru
#say/mod_say_th
## Experimental Modules (don't cry if they're broken)
-#../../contrib/mod/endpoints/mod_khomp
+#endpoints/mod_khomp
#../../contrib/mod/xml_int/mod_xml_odbc
diff --git a/conf/autoload_configs/switch.conf.xml b/conf/autoload_configs/switch.conf.xml
index e861b1b61a..896dd0e712 100644
--- a/conf/autoload_configs/switch.conf.xml
+++ b/conf/autoload_configs/switch.conf.xml
@@ -86,6 +86,7 @@
+
diff --git a/docs/phrase/phrase_en.xml b/docs/phrase/phrase_en.xml
index 65c70171fb..a028a2aae0 100644
--- a/docs/phrase/phrase_en.xml
+++ b/docs/phrase/phrase_en.xml
@@ -426,6 +426,7 @@
+
@@ -437,7 +438,7 @@
-
+
diff --git a/libs/freetdm/configure.ac b/libs/freetdm/configure.ac
index a8ed67f228..18f83d8f1d 100644
--- a/libs/freetdm/configure.ac
+++ b/libs/freetdm/configure.ac
@@ -205,6 +205,18 @@ if test "${have_sng_isdn}" = "yes"; then
fi
fi
+if test "${have_sng_ss7}" = "yes"; then
+ if test "${build}" == "${host}"
+ then
+ case "${host}" in
+ x86_64-*)
+ # X86_64 machines need additional flags when compiling against libsng_isdn
+ CFLAGS="$CFLAGS -DBIT_64 -DALIGN_64BIT"
+ ;;
+ esac
+ fi
+fi
+
COMP_VENDOR_CFLAGS="$COMP_VENDOR_CFLAGS"
AC_SUBST(COMP_VENDOR_CFLAGS)
AC_CONFIG_FILES([Makefile
diff --git a/libs/freetdm/src/ftdm_sched.c b/libs/freetdm/src/ftdm_sched.c
index a7736ce8a2..00a303aae6 100644
--- a/libs/freetdm/src/ftdm_sched.c
+++ b/libs/freetdm/src/ftdm_sched.c
@@ -55,7 +55,7 @@ struct ftdm_sched {
struct ftdm_timer {
char name[80];
ftdm_timer_id_t id;
-#ifdef __linux__
+#if defined(__linux__) || defined(__FreeBSD__)
struct timeval time;
#endif
void *usrdata;
@@ -234,7 +234,7 @@ failed:
FT_DECLARE(ftdm_status_t) ftdm_sched_run(ftdm_sched_t *sched)
{
ftdm_status_t status = FTDM_FAIL;
-#ifdef __linux__
+#if defined(__linux__) || defined(__FreeBSD__)
ftdm_timer_t *runtimer;
ftdm_timer_t *timer;
ftdm_sched_callback_t callback;
@@ -315,7 +315,7 @@ FT_DECLARE(ftdm_status_t) ftdm_sched_timer(ftdm_sched_t *sched, const char *name
int ms, ftdm_sched_callback_t callback, void *data, ftdm_timer_id_t *timerid)
{
ftdm_status_t status = FTDM_FAIL;
-#ifdef __linux__
+#if defined(__linux__) || defined(__FreeBSD__)
struct timeval now;
int rc = 0;
ftdm_timer_t *newtimer;
@@ -396,7 +396,7 @@ done:
FT_DECLARE(ftdm_status_t) ftdm_sched_get_time_to_next_timer(const ftdm_sched_t *sched, int32_t *timeto)
{
ftdm_status_t status = FTDM_FAIL;
-#ifdef __linux__
+#if defined(__linux__) || defined(__FreeBSD__)
int res = -1;
int ms = 0;
struct timeval currtime;
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 827647f1f6..41833c54d3 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
@@ -79,6 +79,7 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
sngisdn_info->suInstId = get_unique_suInstId(suId);
sngisdn_info->spInstId = spInstId;
+
if (conEvnt->cdPtyNmb.eh.pres && signal_data->num_local_numbers) {
uint8_t local_number_matched = 0;
@@ -128,14 +129,12 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
#if 0
/* Export ftdmchan variables here if we need to */
ftdm_channel_add_var(ftdmchan, "isdn_specific_var", "1");
- ftdm_channel_add_var(ftdmchan, "isdn_crap", "morecrap");
- ftdm_channel_add_var(ftdmchan, "isdn_stuff", "s");
- ftdm_channel_add_var(ftdmchan, "isdn_d", "asdsadasdasdsad");
#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);
+ 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) {
ftdmchan->caller_data.bearer_layer1 = sngisdn_get_infoTranCap_from_stack(conEvnt->bearCap[0].usrInfoLyr1Prot.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 80a85ceec8..3284d54165 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
@@ -143,6 +143,7 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
signal_data->signalling == SNGISDN_SIGNALING_NET) {
sngisdn_info->ces = CES_MNGMNT;
}
+ 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);
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c
index 92284edba3..38d3723061 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c
@@ -616,8 +616,8 @@ static ftdm_status_t handle_print_usuage(ftdm_stream_handle_t *stream)
stream->write_function(stream, "Sangoma SS7 CLI usuage:\n\n");
stream->write_function(stream, "Ftmod_sangoma_ss7 general control:\n");
- stream->write_function(stream, "ftdm ss7 set ftace X Y\n");
- stream->write_function(stream, "ftdm ss7 set mtace X Y\n");
+ stream->write_function(stream, "ftdm ss7 set ftrace X Y\n");
+ stream->write_function(stream, "ftdm ss7 set mtrace X Y\n");
stream->write_function(stream, "\n");
stream->write_function(stream, "Ftmod_sangoma_ss7 information:\n");
stream->write_function(stream, "ftdm ss7 show status link X\n");
@@ -1064,7 +1064,7 @@ static ftdm_status_t handle_show_status(ftdm_stream_handle_t *stream, int span,
/* grab the signaling_status */
ftdm_channel_get_sig_status(ftdmchan, &sigstatus);
- stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|sig_status=%s|state=%s|",
+ stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|sig_status=%4s|state=%s|",
ckt->span,
ckt->chan,
ckt->cic,
@@ -1281,13 +1281,17 @@ static ftdm_status_t handle_status_link(ftdm_stream_handle_t *stream, char *name
(sta.t.ssta.s.snDLSAP.remBlkd) ? "Y":"N",
(sta.t.ssta.s.snDLSAP.locInhbt) ? "Y":"N",
(sta.t.ssta.s.snDLSAP.rmtInhbt) ? "Y":"N");
- break;
+
+ goto success;
}
/* move to the next link */
x++;
} /* while (id != 0) */
+ stream->write_function(stream, "Failed to find link=\"%s\"\n", name);
+
+success:
return FTDM_SUCCESS;
}
@@ -1313,13 +1317,17 @@ static ftdm_status_t handle_status_linkset(ftdm_stream_handle_t *stream, char *n
name,
DECODE_LSN_LINKSET_STATUS(sta.t.ssta.s.snLnkSet.state),
sta.t.ssta.s.snLnkSet.nmbActLnks);
- break;
+
+ goto success;
}
/* move to the next linkset */
x++;
} /* while (id != 0) */
+ stream->write_function(stream, "Failed to find link=\"%s\"\n", name);
+
+success:
return FTDM_SUCCESS;
}
@@ -1342,13 +1350,16 @@ static ftdm_status_t handle_set_inhibit(ftdm_stream_handle_t *stream, char *name
/* print the new status of the link */
handle_status_link(stream, &name[0]);
- break;
+ goto success;
}
/* move to the next linkset */
x++;
} /* while (id != 0) */
+ stream->write_function(stream, "Failed to find link=\"%s\"\n", name);
+
+success:
return FTDM_SUCCESS;
}
@@ -1371,13 +1382,16 @@ static ftdm_status_t handle_set_uninhibit(ftdm_stream_handle_t *stream, char *na
/* print the new status of the link */
handle_status_link(stream, &name[0]);
- break;
+ goto success;
}
/* move to the next linkset */
x++;
} /* while (id != 0) */
+ stream->write_function(stream, "Failed to find link=\"%s\"\n", name);
+
+success:
return FTDM_SUCCESS;
}
@@ -1440,6 +1454,10 @@ static ftdm_status_t handle_tx_rsc(ftdm_stream_handle_t *stream, int span, int c
/* go the next circuit */
x++;
} /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */
+
+ /* print the status of channels */
+ handle_show_status(stream, span, chan, verbose);
+
return FTDM_SUCCESS;
@@ -1505,6 +1523,24 @@ static ftdm_status_t handle_tx_grs(ftdm_stream_handle_t *stream, int span, int c
x++;
} /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */
+ x=1;
+ while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
+ if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) {
+
+ sngss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj;
+ ftdmchan = sngss7_info->ftdmchan;
+ sngss7_span = ftdmchan->span->mod_data;
+
+ if ((ftdmchan->physical_span_id == span) &&
+ ((ftdmchan->physical_chan_id >= chan) && (ftdmchan->physical_chan_id < (chan+range)))) {
+
+ handle_show_status(stream, span, chan, verbose);
+ }
+ } /* if ( cic == voice) */
+
+ /* go the next circuit */
+ x++;
+ } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */
return FTDM_SUCCESS;
}
@@ -1585,6 +1621,25 @@ static ftdm_status_t handle_tx_cgb(ftdm_stream_handle_t *stream, int span, int c
/* send the circuit group block */
ft_to_sngss7_cgb(main_chan);
+
+ x=1;
+ while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
+ if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) {
+
+ sngss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj;
+ ftdmchan = sngss7_info->ftdmchan;
+ sngss7_span = ftdmchan->span->mod_data;
+
+ if ((ftdmchan->physical_span_id == span) &&
+ ((ftdmchan->physical_chan_id >= chan) && (ftdmchan->physical_chan_id < (chan+range)))) {
+
+ handle_show_status(stream, span, chan, verbose);
+ }
+ } /* if ( cic == voice) */
+
+ /* go the next circuit */
+ x++;
+ } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */
return FTDM_SUCCESS;
@@ -1666,6 +1721,25 @@ static ftdm_status_t handle_tx_cgu(ftdm_stream_handle_t *stream, int span, int c
/* send the circuit group block */
ft_to_sngss7_cgu(main_chan);
+
+ x=1;
+ while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
+ if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) {
+
+ sngss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj;
+ ftdmchan = sngss7_info->ftdmchan;
+ sngss7_span = ftdmchan->span->mod_data;
+
+ if ((ftdmchan->physical_span_id == span) &&
+ ((ftdmchan->physical_chan_id >= chan) && (ftdmchan->physical_chan_id < (chan+range)))) {
+
+ handle_show_status(stream, span, chan, verbose);
+ }
+ } /* if ( cic == voice) */
+
+ /* go the next circuit */
+ x++;
+ } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */
return FTDM_SUCCESS;
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c
index ac58abd412..807b3b62c7 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c
@@ -51,6 +51,8 @@ ftdm_status_t handle_dat_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
ftdm_status_t handle_fac_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt);
ftdm_status_t handle_fac_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt);
ftdm_status_t handle_umsg_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit);
+ftdm_status_t handle_susp_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiSuspEvnt *siSuspEvnt);
+ftdm_status_t handle_resm_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiResmEvnt *siResmEvnt);
ftdm_status_t handle_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt);
ftdm_status_t handle_reattempt(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt);
@@ -298,8 +300,21 @@ ftdm_status_t handle_con_sta(uint32_t suInstId, uint32_t spInstId, uint32_t circ
/* need to grab the sp instance id */
sngss7_info->spInstId = spInstId;
- /* go to PROGRESS */
- ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS);
+ if ((siCnStEvnt->optBckCalInd.eh.pres) &&
+ (siCnStEvnt->optBckCalInd.inbndInfoInd.pres)) {
+
+ if (siCnStEvnt->optBckCalInd.inbndInfoInd.val) {
+ /* go to PROGRESS_MEDIA */
+ ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
+ } else {
+ /* go to PROGRESS */
+ ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS);
+ } /* if (inband) */
+ } else {
+ /* go to PROGRESS_MEDIA */
+ ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
+ }
+
break;
/**********************************************************************/
default: /* incorrect state...reset the CIC */
@@ -733,6 +748,60 @@ ftdm_status_t handle_umsg_ind(uint32_t suInstId, uint32_t spInstId, uint32_t cir
return FTDM_SUCCESS;
}
+/******************************************************************************/
+ftdm_status_t handle_susp_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiSuspEvnt *siSuspEvnt)
+{
+ SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+
+ sngss7_chan_data_t *sngss7_info ;
+ ftdm_channel_t *ftdmchan;
+
+ /* get the ftdmchan and ss7_chan_data from the circuit */
+ if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
+ SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
+ SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+ return FTDM_FAIL;
+ }
+
+ /* lock the channel */
+ ftdm_mutex_lock(ftdmchan->mutex);
+
+ SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx Call-Suspend msg\n", sngss7_info->circuit->cic);
+
+ /* unlock the channel */
+ ftdm_mutex_unlock(ftdmchan->mutex);
+
+ SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+ return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
+ftdm_status_t handle_resm_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiResmEvnt *siResmEvnt)
+{
+ SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+
+ sngss7_chan_data_t *sngss7_info ;
+ ftdm_channel_t *ftdmchan;
+
+ /* get the ftdmchan and ss7_chan_data from the circuit */
+ if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
+ SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
+ SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+ return FTDM_FAIL;
+ }
+
+ /* lock the channel */
+ ftdm_mutex_lock(ftdmchan->mutex);
+
+ SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx Call-Resume msg\n", sngss7_info->circuit->cic);
+
+ /* unlock the channel */
+ ftdm_mutex_unlock(ftdmchan->mutex);
+
+ SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+ return FTDM_SUCCESS;
+}
+
/******************************************************************************/
ftdm_status_t handle_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt)
{
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_in.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_in.c
index 34893cf5aa..06fae0cd37 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_in.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_in.c
@@ -52,7 +52,9 @@ void sngss7_dat_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiIn
void sngss7_fac_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt);
void sngss7_fac_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt);
void sngss7_umsg_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit);
-
+void sngss7_resm_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiResmEvnt *siResmEvnt);
+void sngss7_susp_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiSuspEvnt *siSuspEvnt);
+void sngss7_ssp_sta_cfm(uint32_t infId);
/******************************************************************************/
/* FUNCTIONS ******************************************************************/
@@ -442,7 +444,127 @@ void sngss7_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint
}
/******************************************************************************/
+void sngss7_susp_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiSuspEvnt *siSuspEvnt)
+{
+ SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+ sngss7_chan_data_t *sngss7_info = NULL;
+ ftdm_channel_t *ftdmchan = NULL;
+ sngss7_event_data_t *sngss7_event = NULL;
+
+ /* get the ftdmchan and ss7_chan_data from the circuit */
+ if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
+ SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
+ SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+ return;
+ }
+
+ /* initalize the sngss7_event */
+ sngss7_event = ftdm_malloc(sizeof(*sngss7_event));
+ if (sngss7_event == NULL) {
+ SS7_ERROR("Failed to allocate memory for sngss7_event!\n");
+ SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+ return;
+ }
+ memset(sngss7_event, 0x0, sizeof(*sngss7_event));
+
+ /* fill in the sngss7_event struct */
+ sngss7_event->spInstId = spInstId;
+ sngss7_event->suInstId = suInstId;
+ sngss7_event->circuit = circuit;
+ sngss7_event->event_id = SNGSS7_SUSP_IND_EVENT;
+ if (siSuspEvnt != NULL) {
+ memcpy(&sngss7_event->event.siSuspEvnt, siSuspEvnt, sizeof(*siSuspEvnt));
+ }
+
+ /* enqueue this event */
+ ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->mod_data)->event_queue, sngss7_event);
+
+ SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+
+}
+
+/******************************************************************************/
+void sngss7_resm_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiResmEvnt *siResmEvnt)
+{
+ SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+
+ sngss7_chan_data_t *sngss7_info = NULL;
+ ftdm_channel_t *ftdmchan = NULL;
+ sngss7_event_data_t *sngss7_event = NULL;
+
+ /* get the ftdmchan and ss7_chan_data from the circuit */
+ if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
+ SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
+ SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+ return;
+ }
+
+ /* initalize the sngss7_event */
+ sngss7_event = ftdm_malloc(sizeof(*sngss7_event));
+ if (sngss7_event == NULL) {
+ SS7_ERROR("Failed to allocate memory for sngss7_event!\n");
+ SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+ return;
+ }
+ memset(sngss7_event, 0x0, sizeof(*sngss7_event));
+
+ /* fill in the sngss7_event struct */
+ sngss7_event->spInstId = spInstId;
+ sngss7_event->suInstId = suInstId;
+ sngss7_event->circuit = circuit;
+ sngss7_event->event_id = SNGSS7_RESM_IND_EVENT;
+ if (siResmEvnt != NULL) {
+ memcpy(&sngss7_event->event.siResmEvnt, siResmEvnt, sizeof(*siResmEvnt));
+ }
+
+ /* enqueue this event */
+ ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->mod_data)->event_queue, sngss7_event);
+
+ SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+
+}
+
+/******************************************************************************/
+void sngss7_ssp_sta_cfm(uint32_t infId)
+{
+ SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+#if 0
+ sngss7_chan_data_t *sngss7_info = NULL;
+ ftdm_channel_t *ftdmchan = NULL;
+ sngss7_event_data_t *sngss7_event = NULL;
+
+ /* get the ftdmchan and ss7_chan_data from the circuit */
+ if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
+ SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
+ SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+ return;
+ }
+
+ /* initalize the sngss7_event */
+ sngss7_event = ftdm_malloc(sizeof(*sngss7_event));
+ if (sngss7_event == NULL) {
+ SS7_ERROR("Failed to allocate memory for sngss7_event!\n");
+ SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+ return;
+ }
+ memset(sngss7_event, 0x0, sizeof(*sngss7_event));
+
+ /* fill in the sngss7_event struct */
+ sngss7_event->spInstId = spInstId;
+ sngss7_event->suInstId = suInstId;
+ sngss7_event->circuit = circuit;
+ sngss7_event->event_id = SNGSS7_RESM_IND_EVENT;
+ if (siSuspEvnt != NULL) {
+ memcpy(&sngss7_event->event.siResmEvnt, siResmEvnt, sizeof(*siResmEvnt));
+ }
+
+ /* enqueue this event */
+ ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->mod_data)->event_queue, sngss7_event);
+#endif
+ SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+
+}
/******************************************************************************/
/* For Emacs:
* Local Variables:
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c
index 30cb31691d..587242d94e 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c
@@ -208,7 +208,7 @@ ftdm_state_map_t sangoma_ss7_state_map = {
{FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_TERMINATING,
FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS,
- FTDM_CHANNEL_STATE_UP, FTDM_END}
+ FTDM_CHANNEL_STATE_PROGRESS_MEDIA ,FTDM_CHANNEL_STATE_UP, FTDM_END}
},
{
ZSD_OUTBOUND,
@@ -448,6 +448,17 @@ static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_ev
handle_sta_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, sngss7_event->globalFlg, sngss7_event->evntType, &sngss7_event->event.siStaEvnt);
break;
/**************************************************************************/
+ case (SNGSS7_SUSP_IND_EVENT):
+ handle_susp_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, &sngss7_event->event.siSuspEvnt);
+ break;
+ /**************************************************************************/
+ case (SNGSS7_RESM_IND_EVENT):
+ handle_resm_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, &sngss7_event->event.siResmEvnt);
+ break;
+ /**************************************************************************/
+ case (SNGSS7_SSP_STA_CFM_EVENT):
+ break;
+ /**************************************************************************/
default:
SS7_ERROR("Unknown Event Id!\n");
break;
@@ -469,6 +480,7 @@ static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_ev
void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
{
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
+ sng_isup_inf_t *isup_intf = NULL;
int i = 0;
ftdm_sigmsg_t sigev;
@@ -589,17 +601,16 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
}
/*check if the channel is inbound or outbound */
- if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
+ 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_PROGRESS;
ftdm_span_send_signal (ftdmchan->span, &sigev);
+ /* move to progress media */
ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
} else {
/* inbound call so we need to send out ACM */
- ft_to_sngss7_acm (ftdmchan);
-
- ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
+ ft_to_sngss7_acm(ftdmchan);
}
break;
@@ -611,6 +622,13 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
break;
}
+ if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
+ /* inform the user there is media avai */
+ sigev.event_id = FTDM_SIGEVENT_PROGRESS_MEDIA;
+ ftdm_span_send_signal (ftdmchan->span, &sigev);
+ }
+
+
/* nothing to do at this time */
break;
/**************************************************************************/
@@ -1155,11 +1173,15 @@ suspend_goto_restart:
ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_RESTART);
break;
-/**************************************************************************/
+ /**************************************************************************/
case FTDM_CHANNEL_STATE_IN_LOOP: /* COT test */
- /* send the lpa */
- ft_to_sngss7_lpa (ftdmchan);
+ isup_intf = &g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId];
+
+ if (sngss7_test_options(isup_intf, SNGSS7_LPA_FOR_COT)) {
+ /* send the lpa */
+ ft_to_sngss7_lpa (ftdmchan);
+ }
break;
/**************************************************************************/
@@ -1332,7 +1354,7 @@ static ftdm_status_t ftdm_sangoma_ss7_start(ftdm_span_t * span)
sngss7_clear_flag(sngss7_info, FLAG_INFID_PAUSED);
sngss7_set_flag(sngss7_info, FLAG_INFID_RESUME);
}
-#if 1
+#if 0
/* throw the grp reset flag */
sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_TX);
if (x == 1) {
@@ -1480,7 +1502,7 @@ static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_ss7_init)
sngss7_id = 0;
- cmbLinkSetId = 1;
+ cmbLinkSetId = 0;
/* initalize the global gen_config flag */
g_ftdm_sngss7_data.gen_config = 0;
@@ -1507,9 +1529,9 @@ static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_ss7_init)
sng_event.cc.sng_fac_cfm = sngss7_fac_cfm;
sng_event.cc.sng_sta_ind = sngss7_sta_ind;
sng_event.cc.sng_umsg_ind = sngss7_umsg_ind;
- sng_event.cc.sng_susp_ind = NULL;
- sng_event.cc.sng_resm_ind = NULL;
- sng_event.cc.sng_ssp_sta_cfm = NULL;
+ sng_event.cc.sng_susp_ind = sngss7_susp_ind;
+ sng_event.cc.sng_resm_ind = sngss7_resm_ind;
+ sng_event.cc.sng_ssp_sta_cfm = sngss7_ssp_sta_cfm;
sng_event.sm.sng_log = handle_sng_log;
sng_event.sm.sng_mtp1_alarm = handle_sng_mtp1_alarm;
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h
index a358236ed0..27833cb2a2 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h
@@ -58,6 +58,8 @@
#define SNGSS7_EVENT_QUEUE_SIZE 100
+#define MAX_SIZEOF_SUBADDR_IE 24 /* as per Q931 4.5.9 */
+
typedef enum {
SNGSS7_CON_IND_EVENT = 0,
SNGSS7_CON_CFM_EVENT,
@@ -68,7 +70,10 @@ typedef enum {
SNGSS7_FAC_IND_EVENT,
SNGSS7_FAC_CFM_EVENT,
SNGSS7_UMSG_IND_EVENT,
- SNGSS7_STA_IND_EVENT
+ SNGSS7_STA_IND_EVENT,
+ SNGSS7_SUSP_IND_EVENT,
+ SNGSS7_RESM_IND_EVENT,
+ SNGSS7_SSP_STA_CFM_EVENT
} sng_event_type_t;
typedef enum {
@@ -83,6 +88,16 @@ typedef enum {
SNGSS7_PAUSED = (1 << 7)
} sng_flag_t;
+typedef enum {
+ SNGSS7_LPA_FOR_COT = (1 << 0), /* send LPA when COT arrives */
+ SNGSS7_ACM_OBCI_BITA = (1 << 10) /* in-band indication */
+} sng_intf_options_t;
+
+typedef enum {
+ SNG_CALLED = 1,
+ SNG_CALLING = 2
+} sng_addr_type_t;
+
typedef struct sng_mtp_link {
char name[MAX_NAME_LEN];
uint32_t id;
@@ -198,6 +213,7 @@ typedef struct sng_route {
typedef struct sng_isup_intf {
uint32_t id;
char name[MAX_NAME_LEN];
+ uint32_t options;
uint32_t flags;
uint32_t spc;
uint32_t dpc;
@@ -385,6 +401,8 @@ typedef struct sngss7_event_data
SiInfoEvnt siInfoEvnt;
SiFacEvnt siFacEvnt;
SiStaEvnt siStaEvnt;
+ SiSuspEvnt siSuspEvnt;
+ SiResmEvnt siResmEvnt;
} event;
} sngss7_event_data_t;
@@ -514,6 +532,9 @@ void sngss7_fac_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint
void sngss7_fac_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt);
void sngss7_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt);
void sngss7_umsg_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit);
+void sngss7_resm_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiResmEvnt *siResmEvnt);
+void sngss7_susp_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiSuspEvnt *siSuspEvnt);
+void sngss7_ssp_sta_cfm(uint32_t infId);
/* in ftmod_sangoma_ss7_handle.c */
ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt);
@@ -525,6 +546,8 @@ ftdm_status_t handle_dat_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
ftdm_status_t handle_fac_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt);
ftdm_status_t handle_fac_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt);
ftdm_status_t handle_umsg_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit);
+ftdm_status_t handle_susp_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiSuspEvnt *siSuspEvnt);
+ftdm_status_t handle_resm_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiResmEvnt *siResmEvnt);
ftdm_status_t handle_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt);
ftdm_status_t handle_reattempt(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt);
@@ -579,6 +602,8 @@ ftdm_status_t clear_rx_grs_data(sngss7_chan_data_t *sngss7_info);
ftdm_status_t clear_rx_gra_data(sngss7_chan_data_t *sngss7_info);
ftdm_status_t clear_tx_grs_data(sngss7_chan_data_t *sngss7_info);
+ftdm_status_t encode_subAddrIE_nsap(const char *subAddr, char *subAddrIE, int type);
+ftdm_status_t encode_subAddrIE_nat(const char *subAddr, char *subAddrIE, int type);
/* in ftmod_sangoma_ss7_timers.c */
void handle_isup_t35(void *userdata);
@@ -712,6 +737,11 @@ void handle_isup_t35(void *userdata);
#define sngss7_clear_flag(obj, flag) ((obj)->flags &= ~(flag))
#define sngss7_set_flag(obj, flag) ((obj)->flags |= (flag))
+#define sngss7_test_options(obj, option) ((obj)->options & option)
+#define sngss7_clear_options(obj, option) ((obj)->options &= ~(option))
+#define sngss7_set_options(obj, option) ((obj)->options |= (option))
+
+
#ifdef SS7_PRODUCTION
# define SS7_ASSERT \
SS7_INFO_CHAN(ftdmchan,"Production Mode, continuing%s\n", "");
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c
index 973fbf47c7..8cbe6d9498 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c
@@ -76,6 +76,9 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;;
const char *clg_nadi = NULL;
const char *cld_nadi = NULL;
+ const char *clg_subAddr = NULL;
+ const char *cld_subAddr = NULL;
+ char subAddrIE[MAX_SIZEOF_SUBADDR_IE];
SiConEvnt iam;
sngss7_info->suInstId = get_unique_id ();
@@ -186,7 +189,7 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
/* check if the user would like a custom NADI value for the calling Pty Num */
clg_nadi = ftdm_channel_get_var(ftdmchan, "ss7_clg_nadi");
if ((clg_nadi != NULL) && (*clg_nadi)) {
- SS7_DEBUG_CHAN(ftdmchan,"Found user supplied NADI value \"%s\"\n", clg_nadi);
+ SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Calling NADI value \"%s\"\n", clg_nadi);
iam.cgPtyNum.natAddrInd.val = atoi(clg_nadi);
} else {
iam.cgPtyNum.natAddrInd.val = g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId].clg_nadi;
@@ -195,14 +198,93 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
cld_nadi = ftdm_channel_get_var(ftdmchan, "ss7_cld_nadi");
if ((cld_nadi != NULL) && (*cld_nadi)) {
- SS7_DEBUG_CHAN(ftdmchan,"Found user supplied NADI value \"%s\"\n", cld_nadi);
+ SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Called NADI value \"%s\"\n", cld_nadi);
iam.cdPtyNum.natAddrInd.val = atoi(cld_nadi);
} else {
iam.cdPtyNum.natAddrInd.val = g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId].cld_nadi;
SS7_DEBUG_CHAN(ftdmchan,"No user supplied NADI value found for CLD, using \"%d\"\n", iam.cdPtyNum.natAddrInd.val);
-
}
+ /* check if the user would like us to send a clg_sub-address */
+ clg_subAddr = ftdm_channel_get_var(ftdmchan, "ss7_clg_subaddr");
+ if ((clg_subAddr != NULL) && (*clg_subAddr)) {
+ SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Calling Sub-Address value \"%s\"\n", clg_subAddr);
+
+ /* clean out the subAddrIE */
+ memset(subAddrIE, 0x0, sizeof(subAddrIE));
+
+ /* check the first character in the sub-address to see what type of encoding to use */
+ switch (clg_subAddr[0]) {
+ case '0': /* NSAP */
+ encode_subAddrIE_nsap(&clg_subAddr[1], subAddrIE, SNG_CALLING);
+ break;
+ case '1': /* national variant */
+ encode_subAddrIE_nat(&clg_subAddr[1], subAddrIE, SNG_CALLING);
+ break;
+ default:
+ SS7_ERROR_CHAN(ftdmchan,"Invalid Calling Sub-Address encoding requested: %c\n", clg_subAddr[0]);
+ break;
+ } /* switch (cld_subAddr[0]) */
+
+
+ /* if subaddIE is still empty don't copy it in */
+ if (subAddrIE[0] != '0') {
+ /* check if the clg_subAddr has already been added */
+ if (iam.accTrnspt.eh.pres == PRSNT_NODEF) {
+ /* append the subAddrIE */
+ memcpy(&iam.accTrnspt.infoElmts.val[iam.accTrnspt.infoElmts.len], subAddrIE, (subAddrIE[1] + 2));
+ iam.accTrnspt.infoElmts.len = iam.accTrnspt.infoElmts.len +subAddrIE[1] + 2;
+ } else {
+ /* fill in from the beginning */
+ iam.accTrnspt.eh.pres = PRSNT_NODEF;
+ iam.accTrnspt.infoElmts.pres = PRSNT_NODEF;
+ memcpy(iam.accTrnspt.infoElmts.val, subAddrIE, (subAddrIE[1] + 2));
+ iam.accTrnspt.infoElmts.len = subAddrIE[1] + 2;
+ } /* if (iam.accTrnspt.eh.pres */
+ } /* if (subAddrIE[0] != '0') */
+ }
+
+ /* check if the user would like us to send a cld_sub-address */
+ cld_subAddr = ftdm_channel_get_var(ftdmchan, "ss7_cld_subaddr");
+ if ((cld_subAddr != NULL) && (*cld_subAddr)) {
+ SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Called Sub-Address value \"%s\"\n", cld_subAddr);
+
+ /* clean out the subAddrIE */
+ memset(subAddrIE, 0x0, sizeof(subAddrIE));
+
+ /* check the first character in the sub-address to see what type of encoding to use */
+ switch (cld_subAddr[0]) {
+ case '0': /* NSAP */
+ encode_subAddrIE_nsap(&cld_subAddr[1], subAddrIE, SNG_CALLED);
+ break;
+ case '1': /* national variant */
+ encode_subAddrIE_nat(&cld_subAddr[1], subAddrIE, SNG_CALLED);
+ break;
+ default:
+ SS7_ERROR_CHAN(ftdmchan,"Invalid Called Sub-Address encoding requested: %c\n", cld_subAddr[0]);
+ break;
+ } /* switch (cld_subAddr[0]) */
+
+ /* if subaddIE is still empty don't copy it in */
+ if (subAddrIE[0] != '0') {
+ /* check if the cld_subAddr has already been added */
+ if (iam.accTrnspt.eh.pres == PRSNT_NODEF) {
+ /* append the subAddrIE */
+ memcpy(&iam.accTrnspt.infoElmts.val[iam.accTrnspt.infoElmts.len], subAddrIE, (subAddrIE[1] + 2));
+ iam.accTrnspt.infoElmts.len = iam.accTrnspt.infoElmts.len +subAddrIE[1] + 2;
+ } else {
+ /* fill in from the beginning */
+ iam.accTrnspt.eh.pres = PRSNT_NODEF;
+ iam.accTrnspt.infoElmts.pres = PRSNT_NODEF;
+ memcpy(iam.accTrnspt.infoElmts.val, subAddrIE, (subAddrIE[1] + 2));
+ iam.accTrnspt.infoElmts.len = subAddrIE[1] + 2;
+ } /* if (iam.accTrnspt.eh.pres */
+ } /* if (subAddrIE[0] != '0') */
+ } /* if ((cld_subAddr != NULL) && (*cld_subAddr)) */
+
+
+
+
sng_cc_con_request (sngss7_info->spId,
sngss7_info->suInstId,
sngss7_info->spInstId,
@@ -226,7 +308,8 @@ void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan)
{
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
- sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
+ sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
+ sng_isup_inf_t *isup_intf = &g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId];
SiCnStEvnt acm;
memset (&acm, 0x0, sizeof (acm));
@@ -255,7 +338,18 @@ void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan)
acm.bckCallInd.echoCtrlDevInd.val = 0x1; /* ec device present */
acm.bckCallInd.sccpMethInd.pres = PRSNT_NODEF;
acm.bckCallInd.sccpMethInd.val = SCCPMTH_NOIND;
-
+
+ /* fill in any optional parameters */
+ if (sngss7_test_options(isup_intf, SNGSS7_ACM_OBCI_BITA)) {
+ acm.optBckCalInd.eh.pres = PRSNT_NODEF;
+ acm.optBckCalInd.inbndInfoInd.pres = PRSNT_NODEF;
+ acm.optBckCalInd.inbndInfoInd.val = sngss7_test_options(isup_intf, SNGSS7_ACM_OBCI_BITA);
+ acm.optBckCalInd.caFwdMayOcc.pres = PRSNT_DEF;
+ acm.optBckCalInd.simpleSegmInd.pres = PRSNT_DEF;
+ acm.optBckCalInd.mlppUserInd.pres = PRSNT_DEF;
+ acm.optBckCalInd.usrNetIneractInd.pres = PRSNT_DEF;
+ } /* if (sngss7_test_options(isup_intf, SNGSS7_ACM_OBCI_BITA)) */
+
/* send the ACM request to LibSngSS7 */
sng_cc_con_status (1,
sngss7_info->suInstId,
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sta.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sta.c
index d238462046..1235238452 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sta.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sta.c
@@ -50,27 +50,41 @@ int ftmod_ss7_mtplinkSet_sta(uint32_t id, SnMngmt *cfm);
int ftmod_ss7_mtplink_sta(uint32_t id, SnMngmt *cfm)
{
SnMngmt sta;
+ Pst pst;
memset(&sta, 0x0, sizeof(sta));
+ /* initalize the post structure */
+ smPstInit(&pst);
+
+ /* insert the destination Entity */
+ pst.dstEnt = ENTSN;
+
sta.hdr.elmId.elmnt = STDLSAP;
sta.hdr.elmId.elmntInst1 = g_ftdm_sngss7_data.cfg.mtpLink[id].id;
- return(sng_sta_mtp3(&sta, cfm));
+ return(sng_sta_mtp3(&pst, &sta, cfm));
}
/******************************************************************************/
int ftmod_ss7_mtplinkSet_sta(uint32_t id, SnMngmt *cfm)
{
SnMngmt sta;
+ Pst pst;
memset(&sta, 0x0, sizeof(sta));
+ /* initalize the post structure */
+ smPstInit(&pst);
+
+ /* insert the destination Entity */
+ pst.dstEnt = ENTSN;
+
sta.hdr.elmId.elmnt = STLNKSET;
sta.hdr.elmId.elmntInst1 = g_ftdm_sngss7_data.cfg.mtpLinkSet[id].id;
sta.hdr.elmId.elmntInst2 = g_ftdm_sngss7_data.cfg.mtpLinkSet[id].links[0];
- return(sng_sta_mtp3(&sta, cfm));
+ return(sng_sta_mtp3(&pst, &sta, cfm));
}
/******************************************************************************/
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c
index 41db1fe140..718663950a 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c
@@ -71,6 +71,9 @@ ftdm_status_t clear_tx_rsc_flags(sngss7_chan_data_t *sngss7_info);
ftdm_status_t clear_rx_grs_data(sngss7_chan_data_t *sngss7_info);
ftdm_status_t clear_rx_gra_data(sngss7_chan_data_t *sngss7_info);
ftdm_status_t clear_tx_grs_data(sngss7_chan_data_t *sngss7_info);
+
+ftdm_status_t encode_subAddrIE_nsap(const char *subAddr, char *subAddrIE, int type);
+ftdm_status_t encode_subAddrIE_nat(const char *subAddr, char *subAddrIE, int type);
/******************************************************************************/
/* FUNCTIONS ******************************************************************/
@@ -884,6 +887,214 @@ ftdm_status_t clear_tx_rsc_flags(sngss7_chan_data_t *sngss7_info)
}
/******************************************************************************/
+ftdm_status_t encode_subAddrIE_nsap(const char *subAddr, char *subAddrIE, int type)
+{
+ /* Q931 4.5.9
+ * 8 7 6 5 4 3 2 1 (octet)
+ *
+ * 0 1 1 1 0 0 0 1 (spare 8) ( IE id 1-7)
+ * X X X X X X X X (length of IE contents)
+ * 1 0 0 0 Z 0 0 0 (ext 8) (NSAP type 5-7) (odd/even 4) (spare 1-3)
+ * X X X X X X X X (sub address encoded in ia5)
+ */
+
+ int x = 0;
+ int p = 0;
+ int len = 0;
+ char tmp[2];
+
+ /* initalize the second element of tmp to \0 so that atoi doesn't go to far */
+ tmp[1]='\0';
+
+ /* set octet 1 aka IE id */
+ p = 0;
+ switch(type) {
+ /**************************************************************************/
+ case SNG_CALLED: /* called party sub address */
+ subAddrIE[p] = 0x71;
+ break;
+ /**************************************************************************/
+ case SNG_CALLING: /* calling party sub address */
+ subAddrIE[p] = 0x6d;
+ break;
+ /**************************************************************************/
+ default: /* not good */
+ SS7_ERROR("Sub-Address type is invalid: %d\n", type);
+ return FTDM_FAIL;
+ break;
+ /**************************************************************************/
+ } /* switch(type) */
+
+ /* set octet 3 aka type and o/e */
+ p = 2;
+ subAddrIE[p] = 0x80;
+
+ /* set the subAddrIE pointer octet 4 */
+ p = 3;
+
+ /* loop through all digits in subAddr and insert them into subAddrIE */
+ while (subAddr[x] != '\0') {
+
+ /* grab a character */
+ tmp[0] = subAddr[x];
+
+ /* confirm it is a digit */
+ if (!isdigit(tmp[0])) {
+ /* move to the next character in subAddr */
+ x++;
+
+ /* restart the loop */
+ continue;
+ }
+
+ /* convert the character to IA5 encoding and write into subAddrIE */
+ subAddrIE[p] = atoi(&tmp[0]); /* lower nibble is the digit */
+ subAddrIE[p] |= 0x3 << 4; /* upper nibble is 0x3 */
+
+ /* increment address length counter */
+ len++;
+
+ /* increment the subAddrIE pointer */
+ p++;
+
+ /* move to the next character in subAddr */
+ x++;
+
+ } /* while (subAddr[x] != '\0') */
+
+ /* set octet 2 aka length of subaddr */
+ p = 1;
+ subAddrIE[p] = len + 1;
+
+
+ return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
+ftdm_status_t encode_subAddrIE_nat(const char *subAddr, char *subAddrIE, int type)
+{
+ /* Q931 4.5.9
+ * 8 7 6 5 4 3 2 1 (octet)
+ *
+ * 0 1 1 1 0 0 0 1 (spare 8) ( IE id 1-7)
+ * X X X X X X X X (length of IE contents)
+ * 1 0 0 0 Z 0 0 0 (ext 8) (NSAP type 5-7) (odd/even 4) (spare 1-3)
+ * X X X X X X X X (sub address encoded in ia5)
+ */
+
+ int x = 0;
+ int p = 0;
+ int len = 0;
+ char tmp[2];
+ int flag = 0;
+ int odd = 0;
+ uint8_t lower = 0x0;
+ uint8_t upper = 0x0;
+
+ /* initalize the second element of tmp to \0 so that atoi doesn't go to far */
+ tmp[1]='\0';
+
+ /* set octet 1 aka IE id */
+ p = 0;
+ switch(type) {
+ /**************************************************************************/
+ case SNG_CALLED: /* called party sub address */
+ subAddrIE[p] = 0x71;
+ break;
+ /**************************************************************************/
+ case SNG_CALLING: /* calling party sub address */
+ subAddrIE[p] = 0x6d;
+ break;
+ /**************************************************************************/
+ default: /* not good */
+ SS7_ERROR("Sub-Address type is invalid: %d\n", type);
+ return FTDM_FAIL;
+ break;
+ /**************************************************************************/
+ } /* switch(type) */
+
+ /* set the subAddrIE pointer octet 4 */
+ p = 3;
+
+ /* loop through all digits in subAddr and insert them into subAddrIE */
+ while (1) {
+
+ /* grab a character */
+ tmp[0] = subAddr[x];
+
+ /* confirm it is a hex digit */
+ while ((!isxdigit(tmp[0])) && (tmp[0] != '\0')) {
+ /* move to the next character in subAddr */
+ x++;
+ tmp[0] = subAddr[x];
+ }
+
+ /* check if tmp is null or a digit */
+ if (tmp[0] != '\0') {
+ /* push it into the lower nibble using strtol to allow a-f chars */
+ lower = strtol(&tmp[0], (char **)NULL, 16);
+ /* move to the next digit */
+ x++;
+ /* grab a digit from the ftdm digits */
+ tmp[0] = subAddr[x];
+
+ /* check if the digit is a hex digit and that is not null */
+ while (!(isxdigit(tmp[0])) && (tmp[0] != '\0')) {
+ x++;
+ tmp[0] = subAddr[x];
+ } /* while(!(isdigit(tmp))) */
+
+ /* check if tmp is null or a digit */
+ if (tmp[0] != '\0') {
+ /* push the digit into the upper nibble using strtol to allow a-f chars */
+ upper = (strtol(&tmp[0], (char **)NULL, 16)) << 4;
+ } else {
+ /* there is no upper ... fill in spare */
+ upper = 0x00;
+ /* throw the odd flag since we need to buffer */
+ odd = 1;
+ /* throw the end flag */
+ flag = 1;
+ } /* if (tmp != '\0') */
+ } else {
+ /* keep the odd flag down */
+ odd = 0;
+
+ /* throw the flag */
+ flag = 1;
+
+ /* bounce out right away */
+ break;
+ }
+
+ /* fill in the octet */
+ subAddrIE[p] = upper | lower;
+
+ /* increment address length counter */
+ len++;
+
+ /* if the flag is we're through all the digits */
+ if (flag) break;
+
+ /* increment the subAddrIE pointer */
+ p++;
+
+ /* move to the next character in subAddr */
+ x++;
+
+ } /* while (subAddr[x] != '\0') */
+
+ /* set octet 2 aka length of subaddr */
+ p = 1;
+ subAddrIE[p] = len + 1;
+
+ /* set octet 3 aka type and o/e */
+ p = 2;
+ subAddrIE[p] = 0xa0 | (odd << 3);
+
+
+ return FTDM_SUCCESS;
+}
/******************************************************************************/
/* For Emacs:
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c
index 359055fe2a..0f81d61f25 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c
@@ -1249,6 +1249,30 @@ static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface)
sng_isup.cld_nadi = atoi(parm->val);
SS7_DEBUG("\tFound default CLD_NADI value = %d\n", sng_isup.cld_nadi);
/**********************************************************************/
+ } else if (!strcasecmp(parm->var, "obci_bita")) {
+ /**********************************************************************/
+ if (*parm->val == '1') {
+ sngss7_set_options(&sng_isup, SNGSS7_ACM_OBCI_BITA);
+ SS7_DEBUG("\tFound Optional Backwards Indicator: Bit A (early media) enable option\n");
+ } else if (*parm->val == '0') {
+ sngss7_clear_options(&sng_isup, SNGSS7_ACM_OBCI_BITA);
+ SS7_DEBUG("\tFound Optional Backwards Indicator: Bit A (early media) disable option\n");
+ } else {
+ SS7_DEBUG("\tInvalid value for \"obci_bita\" option\n");
+ }
+ /**********************************************************************/
+ } else if (!strcasecmp(parm->var, "lpa_on_cot")) {
+ /**********************************************************************/
+ if (*parm->val == '1') {
+ sngss7_set_options(&sng_isup, SNGSS7_LPA_FOR_COT);
+ SS7_DEBUG("\tFound Tx LPA on COT enable option\n");
+ } else if (*parm->val == '0') {
+ sngss7_clear_options(&sng_isup, SNGSS7_LPA_FOR_COT);
+ SS7_DEBUG("\tFound Tx LPA on COT disable option\n");
+ } else {
+ SS7_DEBUG("\tInvalid value for \"lpa_on_cot\" option\n");
+ }
+ /**********************************************************************/
} else {
SS7_ERROR("\tFound an invalid parameter \"%s\"!\n", parm->val);
return FTDM_FAIL;
@@ -1671,7 +1695,7 @@ static int ftmod_ss7_fill_in_isup_interface(sng_isup_inf_t *sng_isup)
g_ftdm_sngss7_data.cfg.isupIntf[i].isap = sng_isup->isap;
g_ftdm_sngss7_data.cfg.isupIntf[i].cld_nadi = sng_isup->cld_nadi;
g_ftdm_sngss7_data.cfg.isupIntf[i].clg_nadi = sng_isup->clg_nadi;
-
+ g_ftdm_sngss7_data.cfg.isupIntf[i].options = sng_isup->options;
if (sng_isup->t4 != 0) {
g_ftdm_sngss7_data.cfg.isupIntf[i].t4 = sng_isup->t4;
} else {
diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c
index 23463e9088..314a34a091 100644
--- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c
+++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c
@@ -1166,6 +1166,11 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event)
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);
}
diff --git a/libs/openzap/src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c b/libs/openzap/src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c
index 40cf2a5a7c..8423aac34b 100644
--- a/libs/openzap/src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c
+++ b/libs/openzap/src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c
@@ -1119,7 +1119,14 @@ ZIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event)
event_id = ZAP_OOB_NOOP;
//zap_log(ZAP_LOG_WARNING, "%d:%d queue hardware dtmf %s %s\n", zchan->span_id, zchan->chan_id, tmp_dtmf,
- //tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_type == WAN_EC_TONE_PRESENT ? "on" : "off");
+ //tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_type == WAN_EC_TONE_PRESENT ? "on" : "off");
+ if (tmp_dtmf[0] == 'f') {
+ if (zap_test_flag(zchan, ZAP_CHANNEL_INUSE)) {
+ zap_channel_queue_dtmf(zchan, tmp_dtmf);
+ }
+ break;
+ }
+
if (tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_type == WAN_EC_TONE_PRESENT) {
zap_set_flag_locked(zchan, ZAP_CHANNEL_MUTE);
}
diff --git a/libs/win32/json/libjson.2008.vcproj b/libs/win32/json/libjson.2008.vcproj
index 91a371b48c..5c09e5413c 100644
--- a/libs/win32/json/libjson.2008.vcproj
+++ b/libs/win32/json/libjson.2008.vcproj
@@ -172,7 +172,7 @@
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="."
- PreprocessorDefinitions="WIN32;_DEBUG;_LIB;HAVE_CONFIG_H;HAVE_STDARG_H;STDC_HEADERS"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB;HAVE_CONFIG_H;HAVE_STDARG_H;STDC_HEADERS"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
@@ -236,7 +236,7 @@
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="."
- PreprocessorDefinitions="WIN32;_DEBUG;_LIB;HAVE_CONFIG_H;HAVE_STDARG_H;STDC_HEADERS"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB;HAVE_CONFIG_H;HAVE_STDARG_H;STDC_HEADERS"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
diff --git a/libs/win32/json/libjson.2010.vcxproj b/libs/win32/json/libjson.2010.vcxproj
index 5846ff3e92..a371ac2f46 100644
--- a/libs/win32/json/libjson.2010.vcxproj
+++ b/libs/win32/json/libjson.2010.vcxproj
@@ -96,7 +96,7 @@
MaxSpeed
true
.;%(AdditionalIncludeDirectories)
- WIN32;_DEBUG;_LIB;HAVE_CONFIG_H;HAVE_STDARG_H;STDC_HEADERS;%(PreprocessorDefinitions)
+ WIN32;NDEBUG;_LIB;HAVE_CONFIG_H;HAVE_STDARG_H;STDC_HEADERS;%(PreprocessorDefinitions)
MultiThreadedDLL
true
Level3
@@ -110,7 +110,7 @@
MaxSpeed
true
.;%(AdditionalIncludeDirectories)
- WIN32;_DEBUG;_LIB;HAVE_CONFIG_H;HAVE_STDARG_H;STDC_HEADERS;%(PreprocessorDefinitions)
+ WIN32;NDEBUG;_LIB;HAVE_CONFIG_H;HAVE_STDARG_H;STDC_HEADERS;%(PreprocessorDefinitions)
MultiThreadedDLL
true
Level3
diff --git a/src/include/private/switch_core_pvt.h b/src/include/private/switch_core_pvt.h
index ea02f22fa0..3df9001b0c 100644
--- a/src/include/private/switch_core_pvt.h
+++ b/src/include/private/switch_core_pvt.h
@@ -193,6 +193,11 @@ struct switch_media_bug {
struct switch_media_bug *next;
};
+typedef enum {
+ DBTYPE_DEFAULT = 0,
+ DBTYPE_MSSQL = 1,
+} switch_dbtype_t;
+
struct switch_runtime {
switch_time_t initiated;
switch_time_t reference;
@@ -237,6 +242,7 @@ struct switch_runtime {
double min_idle_time;
int sql_buffer_len;
int max_sql_buffer_len;
+ switch_dbtype_t odbc_dbtype;
};
extern struct switch_runtime runtime;
diff --git a/src/include/switch_event.h b/src/include/switch_event.h
index 1864e397e6..41bc75cada 100644
--- a/src/include/switch_event.h
+++ b/src/include/switch_event.h
@@ -345,11 +345,15 @@ SWITCH_DECLARE(switch_status_t) switch_event_create_pres_in_detailed(_In_z_ char
*/
#define switch_event_create(event, id) switch_event_create_subclass(event, id, SWITCH_EVENT_SUBCLASS_ANY)
- static inline switch_status_t switch_event_create_plain(switch_event_t **event, switch_event_types_t event_id)
+static inline switch_status_t switch_event_create_plain(switch_event_t **event, switch_event_types_t event_id)
{
switch_status_t status = switch_event_create(event, SWITCH_EVENT_CLONE);
if (status == SWITCH_STATUS_SUCCESS) {
(*event)->event_id = event_id;
+
+ if (event_id == SWITCH_EVENT_REQUEST_PARAMS || event_id == SWITCH_EVENT_CHANNEL_DATA) {
+ (*event)->flags |= EF_UNIQ_HEADERS;
+ }
}
return status;
diff --git a/src/include/switch_odbc.h b/src/include/switch_odbc.h
index 81039f113d..b8d4bc2f17 100644
--- a/src/include/switch_odbc.h
+++ b/src/include/switch_odbc.h
@@ -58,6 +58,8 @@ SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_exec(switch_odbc_handle_
char **err);
SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_exec_string(switch_odbc_handle_t *handle, const char *sql, char *resbuf, size_t len, char **err);
SWITCH_DECLARE(switch_bool_t) switch_odbc_available(void);
+SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_SQLSetAutoCommitAttr(switch_odbc_handle_t *handle, switch_bool_t on);
+SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_SQLEndTran(switch_odbc_handle_t *handle, switch_bool_t commit);
SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_statement_handle_free(switch_odbc_statement_handle_t *stmt);
/*!
diff --git a/src/include/switch_utils.h b/src/include/switch_utils.h
index 945583ee07..924dcd2b9b 100644
--- a/src/include/switch_utils.h
+++ b/src/include/switch_utils.h
@@ -322,7 +322,7 @@ SWITCH_DECLARE(unsigned char) switch_char_to_rfc2833(char key);
\param key the key to test
\return TRUE or FALSE
*/
-#define is_dtmf(key) ((key > 47 && key < 58) || (key > 64 && key < 69) || (key > 96 && key < 101) || key == 35 || key == 42 || key == 87 || key == 119 || key == 70)
+#define is_dtmf(key) ((key > 47 && key < 58) || (key > 64 && key < 69) || (key > 96 && key < 101) || key == 35 || key == 42 || key == 87 || key == 119 || key == 70 || key == 102)
#define end_of(_s) *(*_s == '\0' ? _s : _s + strlen(_s) - 1)
#define end_of_p(_s) (*_s == '\0' ? _s : _s + strlen(_s) - 1)
diff --git a/src/mod/applications/mod_callcenter/mod_callcenter.c b/src/mod/applications/mod_callcenter/mod_callcenter.c
index 56c817ab33..5abc567149 100644
--- a/src/mod/applications/mod_callcenter/mod_callcenter.c
+++ b/src/mod/applications/mod_callcenter/mod_callcenter.c
@@ -850,7 +850,7 @@ cc_status_t cc_agent_del(const char *agent)
return result;
}
-cc_agent_status_t cc_agent_get(const char *key, const char *agent, char *ret_result, size_t ret_result_size)
+cc_status_t cc_agent_get(const char *key, const char *agent, char *ret_result, size_t ret_result_size)
{
cc_status_t result = CC_STATUS_SUCCESS;
char *sql;
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 4b43487034..63086d6018 100644
--- a/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c
+++ b/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c
@@ -408,9 +408,9 @@ static switch_status_t switch_sangoma_encode(switch_codec_t *codec, switch_codec
* whether the buffer passed in by the core (encoded_data) will be big enough */
switch_frame_t ulaw_frame;
switch_frame_t encoded_frame;
- switch_status_t sres;
- switch_time_t now_time, difftime;
- switch_time_t func_start_time, func_end_time;
+ switch_status_t sres = SWITCH_STATUS_FALSE;
+ switch_time_t now_time = 0, difftime = 0;
+ switch_time_t func_start_time = 0, func_end_time = 0;
unsigned char ebuf_ulaw[decoded_data_len / 2];
short *dbuf_linear;
int i = 0;
@@ -596,9 +596,9 @@ static switch_status_t switch_sangoma_decode(switch_codec_t *codec, /* codec ses
* whether the buffer passed in by the core will be enough */
switch_frame_t encoded_frame;
switch_frame_t ulaw_frame;
- switch_status_t sres;
- switch_time_t now_time, difftime;
- switch_time_t func_start_time, func_end_time;
+ switch_status_t sres = SWITCH_STATUS_FALSE;
+ switch_time_t now_time = 0, difftime = 0;
+ switch_time_t func_start_time = 0, func_end_time = 0;
short *dbuf_linear;
int i = 0;
int res = 0;
diff --git a/src/mod/endpoints/mod_gsmopen/alsa_nogsmlib_nocplusplus/mod_gsmopen/Makefile b/src/mod/endpoints/mod_gsmopen/alsa_nogsmlib_nocplusplus/mod_gsmopen/Makefile
index 070f941a94..d67bdbbabf 100644
--- a/src/mod/endpoints/mod_gsmopen/alsa_nogsmlib_nocplusplus/mod_gsmopen/Makefile
+++ b/src/mod/endpoints/mod_gsmopen/alsa_nogsmlib_nocplusplus/mod_gsmopen/Makefile
@@ -1,6 +1,7 @@
MODNAME=mod_gsmopen
SVNDEF := -D'GSMOPEN_SVN_VERSION="$(shell svnversion -n .)"'
-LOCAL_CFLAGS += $(SVNDEF) -Wno-error=address -DNO_GSMLIB -I../../../../../../libs/spandsp/src -I../../../../../..//libs/tiff-3.8.2/libtiff
+#LOCAL_CFLAGS += $(SVNDEF) -Wno-error=address -DNO_GSMLIB -I../../../../../../libs/spandsp/src -I../../../../../..//libs/tiff-3.8.2/libtiff
+LOCAL_CFLAGS += $(SVNDEF) -DNO_GSMLIB -I../../../../../../libs/spandsp/src -I../../../../../..//libs/tiff-3.8.2/libtiff
LOCAL_LDFLAGS=-lasound -L../../../../../../libs/spandsp/src -lspandsp
LOCAL_OBJS=gsmopen_protocol.o
include ../../../../../../build/modmake.rules
diff --git a/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp b/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp
index 40a716671d..cb440d3bcb 100644
--- a/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp
+++ b/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp
@@ -1209,7 +1209,7 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
switch_call_cause_t *cancel_cause)
{
private_t *tech_pvt = NULL;
- if ((*new_session = switch_core_session_request(gsmopen_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, pool)) != 0) {
+ if ((*new_session = switch_core_session_request(gsmopen_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, flags, pool)) != 0) {
switch_channel_t *channel = NULL;
switch_caller_profile_t *caller_profile;
char *rdest;
diff --git a/src/mod/endpoints/mod_khomp/Install/files/khomp.conf.xml b/src/mod/endpoints/mod_khomp/Install/files/khomp.conf.xml
new file mode 100644
index 0000000000..7255fb8555
--- /dev/null
+++ b/src/mod/endpoints/mod_khomp/Install/files/khomp.conf.xml
@@ -0,0 +1,549 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/mod/endpoints/mod_khomp/Makefile b/src/mod/endpoints/mod_khomp/Makefile
new file mode 100644
index 0000000000..94923c7cda
--- /dev/null
+++ b/src/mod/endpoints/mod_khomp/Makefile
@@ -0,0 +1,41 @@
+MODNAME := mod_khomp
+VERBOSE := 1
+
+ifeq ($(strip $(FREESWITCH_PATH)),)
+ BASE := ../../../../
+else
+ BASE := $(FREESWITCH_PATH)
+endif
+
+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 += $(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 += ./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
+
+conf_file_name := khomp.conf.xml
+conf_file_dir := $(curr_dir)/Install/files
+conf_file_dir_alt := $(curr_dir)/conf
+conf_file_install = $(sysconfdir)/autoload_configs
+
+include $(BASE)/build/modmake.rules
+
+depend_install:
+ @echo "Copy $(conf_file_name)"
+ @if test -d $(conf_file_install) ; then \
+ if test -f $(conf_file_dir)/$(conf_file_name) ; then \
+ cp $(conf_file_dir)/$(conf_file_name) $(conf_file_install)/$(conf_file_name).new ;\
+ else \
+ cp $(conf_file_dir_alt)/$(conf_file_name) $(conf_file_install)/$(conf_file_name).new ;\
+ fi; \
+ if test ! -f "$(conf_file_install)/$(conf_file_name)" ; then \
+ mv $(conf_file_install)/$(conf_file_name).new $(conf_file_install)/$(conf_file_name) ;\
+ fi; \
+ fi;
diff --git a/src/mod/endpoints/mod_khomp/commons/atomic.hpp b/src/mod/endpoints/mod_khomp/commons/atomic.hpp
new file mode 100644
index 0000000000..daa598c9b4
--- /dev/null
+++ b/src/mod/endpoints/mod_khomp/commons/atomic.hpp
@@ -0,0 +1,189 @@
+/*
+ KHOMP generic endpoint/channel library.
+
+ This code was based on FreeBSD 7.X SVN (sys/i386/include/atomic.h),
+ with changes regarding optimizations and generalizations, and a
+ remake of the interface to fit use C++ features.
+
+ Code is distributed under original license.
+ Original copyright follows:
+
+ * Copyright (c) 1998 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 _ATOMIC_HPP_
+#define _ATOMIC_HPP_
+
+namespace Atomic
+{
+ // Macros used to insert compare and exchange instructions easily into functions.
+
+ #define MAKE_CMPXCHG_FUNCTION(INS, PTR, EXP, VAL, TYPE) \
+ PunnedType pexp; pexp.valtype = EXP; \
+ PunnedType pval; pval.valtype = VAL; \
+ TYPE vexp = *(pexp.podtype); \
+ TYPE vval = *(pval.podtype); \
+ TYPE res; \
+ unsigned char chg = 0; \
+ asm volatile("lock;" INS "sete %1;" \
+ : "=a" (res), /* 0 */ \
+ "=q" (chg), /* 1 */ \
+ "=m" (*(unsigned char **)(PTR)) /* 2 */ \
+ : "r" (vval), /* 3 */ \
+ "a" (vexp), /* 4 */ \
+ "m" (*(unsigned char **)(PTR)) /* 5 */ \
+ : "memory"); \
+ *(pexp.podtype) = res; \
+ return (chg != 0 ? true : false);
+
+ #define MAKE_CMPXCHG8B_FUNCTION(PTR,EXP,VAL) \
+ PunnedType pexp; pexp.valtype = EXP; \
+ 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 char chg = 0; \
+ asm volatile("lock; cmpxchg8b %2; sete %1;" \
+ : "+A" (vexp), /* 0 (result) */ \
+ "=q" (chg) /* 1 */ \
+ : "m" (*(unsigned char**)(PTR)), /* 2 */ \
+ "b" ((unsigned long)(vval)), \
+ "c" ((unsigned long)(vval >> 32))); \
+ *(pexp.podtype) = vexp; \
+ return (chg != 0 ? true : false);
+
+ // Types used for making CMPXCHG instructions independent from base type.
+
+ template < typename ValType, typename PodType >
+ union PunnedTypeTemplate
+ {
+ ValType * valtype;
+ PodType * podtype;
+ };
+
+ template < int SizeOfType, typename ReturnType >
+ struct HelperCreateCAS;
+
+ template < typename ValType >
+ struct HelperCreateCAS<4, ValType>
+ {
+ #if !defined(__LP64__) && !defined(__LP64)
+ typedef unsigned long BaseType;
+ #else
+ typedef unsigned int BaseType;
+ #endif
+
+ typedef PunnedTypeTemplate< ValType, BaseType > PunnedType;
+
+ inline static bool apply(volatile void *p, ValType * exp, ValType now)
+ {
+ #if !defined(__LP64__) && !defined(__LP64)
+ MAKE_CMPXCHG_FUNCTION("cmpxchgl %3,%5;", p, exp, &now, BaseType);
+ #else
+ MAKE_CMPXCHG_FUNCTION("cmpxchgl %k3,%5;", p, exp, &now, BaseType);
+ #endif
+ }
+ };
+
+ template < typename ValType >
+ struct HelperCreateCAS<8, ValType>
+ {
+ #if !defined(__LP64__) && !defined(__LP64)
+ typedef unsigned long long BaseType;
+ #else
+ typedef unsigned long BaseType;
+ #endif
+
+ typedef PunnedTypeTemplate< ValType, BaseType > PunnedType;
+
+ inline static volatile ValType apply(volatile void *p, ValType * exp, ValType now)
+ {
+ #if !defined(__LP64__) && !defined(__LP64)
+ MAKE_CMPXCHG8B_FUNCTION(p, exp, &now);
+ #else
+ MAKE_CMPXCHG_FUNCTION("cmpxchgq %3,%5;", p, exp, &now, BaseType);
+ #endif
+ }
+
+ };
+
+ // The CAS function itself.
+
+ template < typename ValType >
+ inline bool doCAS(volatile ValType * p, ValType * o, ValType n)
+ {
+ return HelperCreateCAS::apply(static_cast(p), o, n);
+ };
+
+ template < typename ValType >
+ inline bool doCAS(volatile ValType * p, ValType o, ValType n)
+ {
+ return HelperCreateCAS::apply(static_cast(p), &o, n);
+ };
+
+ #undef MAKE_CMPXCHG_32_FUNCTION
+ #undef MAKE_CMPXCHG_64_FUNCTION
+
+ #define MAKE_LOCKED_TEMPLATE(NAME) \
+ template < typename ValType > inline void do##NAME(volatile ValType * p, ValType v); \
+ template < typename ValType > inline void do##NAME(volatile ValType * p);
+
+ #define MAKE_LOCKED_FUNCTION(NAME, TYPE, INS, CONS, VAL) \
+ template < > inline void do##NAME < TYPE > (volatile TYPE * p, TYPE v){ asm volatile("lock;" INS : "=m" (*p) : CONS (VAL), "m" (*p)); } \
+ template < > inline void do##NAME < TYPE > (volatile TYPE * p) { asm volatile("lock;" INS : "=m" (*p) : CONS (1), "m" (*p)); }
+
+ #define MAKE_LOCKED_FUNCTIONS(NAME, TYPE, INS, CONS, VAL) \
+ MAKE_LOCKED_FUNCTION(NAME, TYPE, INS, CONS, VAL) \
+ MAKE_LOCKED_FUNCTION(NAME, unsigned TYPE, INS, CONS, VAL)
+
+ MAKE_LOCKED_TEMPLATE(Add);
+ MAKE_LOCKED_TEMPLATE(Sub);
+ MAKE_LOCKED_TEMPLATE(SetBits);
+ MAKE_LOCKED_TEMPLATE(ClearBits);
+
+ MAKE_LOCKED_FUNCTIONS(Add, int, "addl %1,%0", "ir", v);
+ MAKE_LOCKED_FUNCTIONS(Sub, int, "subl %1,%0", "ir", v);
+ MAKE_LOCKED_FUNCTIONS(SetBits, int, "orl %1,%0", "ir", v);
+ MAKE_LOCKED_FUNCTIONS(ClearBits, int, "andl %1,%0", "ir", ~v);
+
+ #if !defined(__LP64__) && !defined(__LP64)
+
+ MAKE_LOCKED_FUNCTIONS(Add, long, "addl %1,%0", "ir", v);
+ MAKE_LOCKED_FUNCTIONS(Sub, long, "subl %1,%0", "ir", v);
+ MAKE_LOCKED_FUNCTIONS(SetBits, long, "orl %1,%0", "ir", v);
+ MAKE_LOCKED_FUNCTIONS(ClearBits, long, "andl %1,%0", "ir", ~v);
+
+ #else
+
+ MAKE_LOCKED_FUNCTIONS(Add, long, "addq %1,%0", "ir", v);
+ MAKE_LOCKED_FUNCTIONS(Sub, long, "subq %1,%0", "ir", v);
+ MAKE_LOCKED_FUNCTIONS(SetBits, long, "orq %1,%0", "ir", v);
+ MAKE_LOCKED_FUNCTIONS(ClearBits, long, "andq %1,%0", "ir", ~v);
+
+ #endif
+};
+
+#endif /* _ATOMIC_HPP_ */
diff --git a/src/mod/endpoints/mod_khomp/commons/config_commons.hpp b/src/mod/endpoints/mod_khomp/commons/config_commons.hpp
new file mode 100644
index 0000000000..de8f327df4
--- /dev/null
+++ b/src/mod/endpoints/mod_khomp/commons/config_commons.hpp
@@ -0,0 +1,69 @@
+/*
+ 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_COMMONS_HPP_
+#define _CONFIG_COMMONS_HPP_
+
+/****************************************************************************/
+/* ASTERISK */
+#if defined(COMMONS_LIBRARY_USING_ASTERISK)
+ #define COMMONS_IMPLEMENTATION asterisk
+/****************************************************************************/
+/* CALLWEAVER */
+#elif defined(COMMONS_LIBRARY_USING_CALLWEAVER)
+ #define COMMONS_IMPLEMENTATION callweaver
+/****************************************************************************/
+/* FREESWITCH */
+#elif defined(COMMONS_LIBRARY_USING_FREESWITCH)
+ #define COMMONS_IMPLEMENTATION freeswitch
+/****************************************************************************/
+/* GNU/LINUX (generic) */
+#elif defined(COMMONS_LIBRARY_USING_GNU_LINUX)
+ #define COMMONS_IMPLEMENTATION gnulinux
+/****************************************************************************/
+#else
+ #error Unknown implementation selected. Please define COMMONS_LIBRARY_USING_* correctly.
+#endif
+
+#define COMMONS_INCLUDE(file)
+
+#endif /* _CONFIG_COMMONS_HPP_ */
+
diff --git a/src/mod/endpoints/mod_khomp/commons/config_options.cpp b/src/mod/endpoints/mod_khomp/commons/config_options.cpp
new file mode 100644
index 0000000000..5383855f65
--- /dev/null
+++ b/src/mod/endpoints/mod_khomp/commons/config_options.cpp
@@ -0,0 +1,710 @@
+/*
+ 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
new file mode 100644
index 0000000000..3cfe2e1c78
--- /dev/null
+++ b/src/mod/endpoints/mod_khomp/commons/config_options.hpp
@@ -0,0 +1,286 @@
+/*
+ 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