Merge branch 'master' of git.freeswitch.org:freeswitch

This commit is contained in:
Andrew Thompson 2010-10-23 02:06:52 -04:00
commit 6a83988674
140 changed files with 43524 additions and 159 deletions

View File

@ -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

View File

@ -86,6 +86,7 @@
<!-- <param name="core-db-dsn" value="dsn:username:password" /> -->
<!-- The system will create all the db schemas automatically, set this to false to avoid this behaviour-->
<!--<param name="auto-create-schemas" value="true"/>-->
<!-- <param name="core-dbtype" value="MSSQL"/> -->
</settings>
</configuration>

View File

@ -426,6 +426,7 @@
<prompt phrase="Barracuda Networks" filename="ivr-barracuda_networks.wav"/>
<prompt phrase="CudaTel Communication Server" filename="ivr-cudatel_communication_server.wav"/>
<prompt phrase="Please enter the first few letters of the person's first or last name" filename="dir-enter_person_first_or_last.wav"/>
<prompt phrase="There are no calls waiting in this queue." filename="ivr-no_calls_waiting_in_queue.wav"/>
<prompt phrase="Brian West" filename="misc-Brian_West.wav"/>
<prompt phrase="Anthony Minessale" filename="misc-Anthony_Minessale.wav"/>
<prompt phrase="Michael Jerris" filename="misc-Michael_Jerris.wav"/>
@ -437,7 +438,7 @@
<prompt phrase="Andrew Thompson" filename="misc-Andrew_Thompson.wav"/>
<prompt phrase="Graham Saathoff" filename="misc-Graham_Saathoff.wav"/>
<prompt phrase="Nicholaus Belluni" filename="misc-Nicholaus_Belluni.wav"/>
<prompt phrase="Sean Heiney" filename="misc-Sean_Heiney.wav">
<prompt phrase="Sean Heiney" filename="misc-Sean_Heiney.wav"/>
</ivr>
<misc>
<prompt phrase="This call has been secured" filename="call_secured.wav"/>

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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)
{

View File

@ -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:

View File

@ -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;

View File

@ -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", "");

View File

@ -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,

View File

@ -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));
}
/******************************************************************************/

View File

@ -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:

View File

@ -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 {

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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"

View File

@ -96,7 +96,7 @@
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;HAVE_CONFIG_H;HAVE_STDARG_H;STDC_HEADERS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;HAVE_CONFIG_H;HAVE_STDARG_H;STDC_HEADERS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<WarningLevel>Level3</WarningLevel>
@ -110,7 +110,7 @@
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;HAVE_CONFIG_H;HAVE_STDARG_H;STDC_HEADERS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;HAVE_CONFIG_H;HAVE_STDARG_H;STDC_HEADERS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<WarningLevel>Level3</WarningLevel>

View File

@ -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;

View File

@ -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;

View File

@ -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);
/*!

View File

@ -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)

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -0,0 +1,549 @@
<configuration name="khomp.conf" description="Khomp Configuration">
<!-- Config for all boards -->
<settings>
<!--
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;; This is the configuration file for the Khomp ;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Endpoint 1.0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-->
<channels>
<!-- Section for main configurations about channels. -->
<!--
Enable/disable generalized echo cancellation in the channel, for calls
passing inside FreeSWITCH (disabled for bridged calls).
(default = yes)
<param name="echo-canceller" value="yes"/>
-->
<!--
Enable/disable AGC (auto gain control). Should be used carefully, as it
can make line noise really loud.
(default = yes)
<param name="auto-gain-control" value="yes"/>
-->
<!--
Enable/disable sending DTMFs out-band as a way to pass detected DTMFs to
FreeSWITCH. Needed if FreeSWITCH generates digits for us in bridge application
or is being used for IVR ("URA", in pt_BR).
(default = yes)
<param name="out-of-band-dtmfs" value="yes"/>
-->
<!--
Enable/disable DTMF suppression delay. WARNING: if you disable this, DTMFs
will not be suppressed anymore! You should only use this option if
"out-of-band-dtmfs" is "no".
(default = yes)
<param name="suppression-delay" value="yes"/>
-->
<!--
Adjust connection automagically if a FAX tone is detected.
(default = yes)
<param name="auto-fax-adjustment" value="yes"/>
-->
<!--
Time (is seconds) since connection, when we may detect FAX tone and perform
automagical adjustment. After this, FAX tone detection is ignored.
Possible values: 0 - 9999
(default = 30).
<param name="fax-adjustment-timeout" value="30"/>
-->
<!--
Enable/disable pulse detection (reported as DTMF digits).
(default = yes)
<param name="pulse-forwarding" value="yes"/>
-->
<!--
Enable correct standard following for R2/MFC protocol. Disabled by default,
as using FreeSWITCH behind a PBX may timeout all outgoing calls without this.
However, you can set this to "yes" if FreeSWITCH is directly connected to a
CO (central office) or to a fast signaling PBX, and have a correct
behaviour for condition obtaining/reporting.
(default = no)
<param name="r2-strict-behaviour" value="no"/>
-->
<!--
Set the delay (in ms) after sending ringback condition where audio stream
should be opened for the channel. Limited to 25ms min, 500ms max.
(default = 250)
<param name="r2-preconnect-wait" value="250"/>
-->
<!--
Enable/disable native bridge mode (known in pt_BR as "trombone") for calls
in the Khomp channel, passing the audio inside the board when both channels
(incoming and outgoing) are of type Khomp. This reduces the echo and the
audio delay, and frees the host from most audio processing.
(default = yes)
<param name="native-bridge" value="yes"/>
-->
<!--
Defines the incoming context for calls on E1 channels. Some wildcards are
accepted, and described in the bottom of this file.
(default = khomp-DD-LL)
<param name="context-digital" value="khomp-DD-LL"/>
-->
<!--
Defines the incoming context for calls on FXS channels. Some wildcards are
accepted, and described in the bottom of this file.
(default = khomp-DD-CC)
<param name="context-fxs" value="khomp-DD-CC"/>
-->
<!--
Defines the "alternative" context for calls on FXS channels, which will be
checked if the main context does not match for a call. Some wildcards are
accepted, and described in the bottom of this file.
(default = khomp-DD)
<param name="context-fxs-alt" value="khomp-DD"/>
-->
<!--
Defines the incoming context for calls on FXO channels. Some wildcards are
accepted, and described in the bottom of this file.
(default = khomp-DD-CC)
<param name="context-fxo" value="khomp-DD-CC"/>
-->
<!--
Defines the "alternative" context for calls on FXO channels, which will be
checked if the main context does not match for a call. Some wildcards are
accepted, and described in the bottom of this file.
(default = khomp-DD)
<param name="context-fxo-alt" value="khomp-DD"/>
-->
<!--
Defines the incoming context for calls on GSM channels. Some wildcards are
accepted, and described in the bottom of this file.
(default = khomp-DD-CC)
<param name="context-gsm-call" value="khomp-DD-CC"/>
-->
<!--
Defines the "alternative" context for calls on GSM channels, which will be
checked if the main context does not match for a call. Some wildcards are
accepted, and described in the bottom of this file.
(default = khomp-DD)
<param name="context-gsm-call-alt" value="khomp-DD"/>
-->
<!--
Defines the incoming context for messages on GSM channels. Some wildcards are
accepted, and described in the bottom of this file.
(default = khomp-sms-DD-CC)
<param name="context-gsm-sms" value="khomp-sms-DD-CC"/>
-->
<!--
Defines the incoming context for calls on Passive Record boards (KPR). Some
wildcards are accepted, and described in the bottom of this file.
(default = khomp-DD-CC)
<param name="context-pr" value="khomp-DD-CC"/>
-->
<!--
Set the logging of messages to console. Possible values (to set more than one,
separate the values with comma):
errors - Error messages, when something goes really wrong.
warnings - Warnings, used when something might not be going as expected.
messages - Generic messages, used to indicate some information.
events - Show received K3L events as console messages.
commands - Show sent K3L commands as console messages.
audio - Enable messages for K3L audio events (very verbose!).
modem - Enable messages for data received from KGSM modems.
link - Enable logging of link status changes.
standard - Special, enable default messages (RECOMMENDED).
all - Special, enable ALL messages (should not be used naively).
(default = standard)
<param name="log-to-console" value="standard"/>
-->
<!--
Set the logging of messages to disk. Possible values (to set more than one,
separate the values with comma):
errors - Error messages, when something goes really wrong.
warnings - Warnings, used when something might not be going as expected.
messages - Generic messages, used to indicate some information.
events - Record received K3L events as log messages.
commands - Record sent K3L commands as log messages.
audio - Enable messages for K3L audio events (very verbose!).
modem - Enable messages for data received from KGSM modems.
link - Enable logging of link status changes.
functions - Enable debugging for functions. Should not be used naively!).
threads - Enable debugging for threads. Should not be used naively!).
locks - Enable debugging for locks. Should not be used naively!).
streams - Enable debugging for streams. Should not be used naively!).
standard - Special, enable default messages (RECOMMENDED).
debugging - Special, enable debug messages (should not be used naively).
all - Special, enable ALL messages (DO NOT USE THIS!).
(default = standard)
<param name="log-to-disk" value="standard"/>
-->
<!--
Set the low level tracing. DO NOT USE THIS UNLESS YOU WERE ADVISED TO DO SO.
Possible values (to set more than one, separate the values with comma):
k3l - Enable the low level tracing of board's API.
If you are using 'kserver', this option will take no effect. For
the k3l tracing to proceed, you will need to (re)start kserver
with 'debug' option. E.g. '#> kserver start -debug'.
rdsi - Enable ISDN low level debugging.
r2 - Enable r2 protocol low level debugging.
(default = <empty>)
<param name="trace" value=""/>
-->
<!--
Set output volume level. Possible values:
* '+ N' = increase N times;
* '- N' = decrease N times.
* '0' = leave default.
(default = 0)
<param name="output-volume" value="0"/>
-->
<!--
Set input volume level. Can only be used if AGC (and not pulse detection)
is enabled on the board configuration. Possible values:
* '+ N' = increase N times;
* '- N' = decrease N times.
* '0' = leave default.
(default = 0)
<param name="input-volume" value="0"/>
-->
<!--
Sets the default AMA flags, affecting the categorization of entries in
the call detail records.
(default = default)
<param name="amaflags" value="default"/>
-->
<!--
Sets the account code for calls placed on the channel. The account code may
be any alphanumeric string
(default = KhompBoard)
<param name="accountcode" value="KhompBoard"/>
-->
<!--
Set the language of the channel (useful for selecting audio messages of a
specific language on answer).
(default = <empty>)
<param name="language" value="pt_BR"/>
-->
<!--
Set the music on hold class of the channel (useful for selecting a group of
songs to play on hold).
(default = default)
<param name="mohclass" value="default"/>
-->
<!--
Sets the global orig (CALLERID) base for FXS boards. This number is added
to a sequencial number, which is incremented for each FXS board and FXS
channel in the system.
For more example of how to use this option, see channel README file,
section 'Opcoes do application Bridge', item '<action application="bridge" data="Khomp/r304" />'.
(default = 0)
<param name="fxs-global-orig" value="0200"/>
-->
<!--
Sets the numbers (separated by comma) in which the 'pbx-dialtone' from
FXS boards will be changed to 'co-dialtone' (public tone), when they are
pressed.
(default = <empty>)
<param name="fxs-co-dialtone" value="0,90"/>
-->
<!--
Enable or disable sending number of A throught BINA DTMF signalization to
a FXS branch.
(default = yes)
<param name="fxs-bina" value="yes"/>
-->
<!--
Enable/disable using CTbus for Khomp CTI boards in native bridge.
(WARNING: just used for internal testings!)
(default = no)
<param name="has-ctbus" value="no"/>
-->
<!--
This is the delay time to really disconnect a channel after the disconnect
event arrive. If a connect event comes up in this interval, then the
disconnection is ignored and the call keeps going on. Values in ms.
(default = 0)
<param name="disconnect-delay" value="0"/>
-->
<!--
This timer controls the delay associated with ringback generation in the
Khomp channel, when the other side *does not send audio* - in other words,
this is used when calling peers located at VoIP channels.
Values are in milliseconds.
(default = 1500)
<param name="delay-ringback-co" value="1500"/>
-->
<!--
This timer controls the delay associated with ringback generation in the
Khomp channel when the other side report a continuous stream of audio in
silence - in other words, this is used when the audio is present but does
not have any tone. Values are in milliseconds.
(default = 2500)
<param name="delay-ringback-pbx" value="2500"/>
-->
<!--
Defines if the channel should optimize audio delay by droping longstanding
packets from audio buffer. This guarantees the minimal audio delay for the
user, and avoid delays associated with miscoded SIP clients. However,
depending on the system's scheduling policy (some 2.6 kernel releases),
this may result on excessive drop of packets, and audible audio skipping.
This should not be changed naively.
(default = no)
<param name="optimize-audio-path" value="no"/>
-->
<!--
Defines if the channel should ignore some uncommon DTMF digits detected by
the board (A, B, C and D). This reduces the number of false positives which
may happen sometimes, without affecting correctness on traditional
scenarios. However, if you need to pass those digits througth the board,
you may need to set this option to 'no'.
(default = yes)
<param name="ignore-letter-dtmfs" value="yes"/>
-->
<!--
For KFXO series boards, defines if audio will be allowed being sent into
outgoing calls before it has been connected.
(default = yes)
<param name="fxo-send-pre-audio" value="yes"/>
-->
<!--
Defines the timeout, in seconds, between digits of a FXS board's extension.
(default = 7)
<param name="fxs-digit-timeout" value="7"/>
-->
<!--
Enables/Disables the action of dropping collect calls. If enabled, all
collect calls will be dropped no matter what KDropCollectCall is set to.
(default = no)
<param name="drop-collect-call" value="no"/>
-->
<!--
Defines if the activation and deactivation of Kommuter is done automatically by the channel,
or manually by the user. Possible values:
auto - Khomp channel driver starts all kommuter devices at initialization and stops them if the module is unloaded.
manual - The user must explicity call the CLI command < khomp kommuter on/off >, that starts or stops the kommuter devices connected to this machine.
(default = auto)
<param name="kommuter-activation" value="auto"/>
-->
<!--
Defines the default value for the Kommuter watchdog in seconds.
All kommuters conected to this machine will be initialized with this value,
and will commute the links after reaching this time with no response of the channel.
The minimum is 0 (will never commute the links), and maximum value is 255 seconds.
(default = 10)
<param name="kommuter-timeout" value="10"/>
-->
<!--
When adjusted to some DTMF digit sequence, it will define those as the digits
to be used to initialize a call transfer using PBX-to-PBX signaling.
(default = empty)
<param name="user-transfer-digits" value="#2"/>
-->
<!--
;;;;;;;;;;;;;;;;;;;; CONTEXTS WILDCARDS ;;;;;;;;;;;;;;;;;;;;;;
For incoming contexts, you can use the following wildcards:
'DD' (device number): the sequence number of the board on the
system (can be checked using "khomp summary", valid for all
board models);
'LL' (link number): the sequence number of link where the call
has arrived on the board. valid only for E1 boards.
'SSSS' (serial number): the serial number of the board (can
be checked using "khomp summary", and it's valid for all
board models);
'CC' (channel number): the channel number on which the call
or message has arrived (valid for FXO, FXS and GSM boards);
'CCC' (channel number): same as above, but valid only for E1
channels;
-->
</channels>
<!-- Section for configuring allocation groups. -->
<groups>
<!--
In this section, you should define options using the following syntax:
<groupname> = <allocation-string>[:<context>]
<param name="pstn" value="b0l0 + b1c38"/>
<param name="pstn" value="b0l0 + b1c38:from-pstn"/>
You may define your own groups. In the example above, the group
called pstn can be used in the bridge string as <action application="brigde" data="Khomp/Gpstn/..." />
or <action application="brigde" data="Khomp/Gpstn/..." />. As a result, the allocation string will be
replaced with the one associated with the group "pstn". This is the same
of doing <action application="brigde" data="Khomp/b0l0 + b1c38/... />.
In the second example, a context is also defined which can be used in
extensions.conf for inbound calls on that allocation string's range.
-->
</groups>
<!--
Section for configuring cadences used on FXS boards and the whole
channel (fast busy, ringback tones, etc).
-->
<cadences>
<!--
Default value for cadences. You may define your own cadences, and
also use them in the bridge arguments as "cadence=your_cadence_name".
"0,0" means a continuous dialtone.
(default as defined below)
<param name="fast-busy" value="100,100" />
<param name="ringback" value="1000,4000" />
<param name="pbx-dialtone" value="1000,100" />
<param name="vm-dialtone " value="1000,100,100,100" />
<param name="co-dialtone " value="0,0" />
-->
</cadences>
<!-- Section for configuring CALLERID's associated with FXS boards. -->
<fxs-branches>
<!--
In this section, you should define options using the following syntax:
'orig_prefix = serial number 0, serial number 1, ...'
ex: <param name="880" value="111,222"/>
In the example above (assuming KFXS-SPX boards 1234 and 4535), the
branches will be numbered from 800 to 829 in board 1234, and from
830 to 859 in board 4535.
-->
</fxs-branches>
<!-- Section for configuring FXS hotlines. -->
<fxs-hotlines>
<!--
In this section, you should define options using the following syntax:
'orig_prefix = destination_number'
ex: <param name="804" value="32332933" />
In the example above, the branch numbered 804 will call the number
3233-2933 (Khomp support number) every time the FXS branch goes off hook.
-->
</fxs-hotlines>
<!-- Section for configuring specific options for FXS branches. -->
<fxs-options>
<!--
In this section, you should define options using the following syntax:
'orig_prefix = option1:value | option2:value | option3:value' ...
ex: <param name="804" value="output-volume:+2' />
In the example above, the branch numbered 804 will have specific
configuration for default output volume set to +2.
Possible values to options is:
context, input-volume, output-volume language,
mohclass, amaflags, accountcode, calleridnum, calleridname, mailbox.
-->
</fxs-options>
</settings>
</configuration>

View File

@ -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;

View File

@ -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<sizeof(ValType), ValType>::apply(static_cast<volatile void *>(p), o, n);
};
template < typename ValType >
inline bool doCAS(volatile ValType * p, ValType o, ValType n)
{
return HelperCreateCAS<sizeof(ValType), ValType>::apply(static_cast<volatile void *>(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_ */

View File

@ -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) <COMMONS_IMPLEMENTATION/file>
#endif /* _CONFIG_COMMONS_HPP_ */

View File

@ -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 <config_options.hpp>
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<StringType &>(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<StringType &>(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<SignedIntType &>(value), defvalue, Range<SignedIntType>(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<UnsignedIntType &>(value), defvalue, Range<UnsignedIntType>(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<BooleanType &>(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<StringData>();
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<FunctionData>();
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<SignedIntData>();
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<UnsignedIntData>();
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<BooleanData>();
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<SignedIntData>();
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<UnsignedIntData>();
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<StringData>();
_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<FunctionData>();
_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<BooleanData>();
tmp.bool_val = tmp.bool_default;
}
catch(ValueType::InvalidType & e)
{
throw;
}
break;
}
case ConfigOption::ID_SINT:
{
try
{
SignedIntData & tmp = _value_data.get<SignedIntData>();
tmp.sint_val = tmp.sint_default;
}
catch(ValueType::InvalidType & e)
{
throw;
}
break;
}
case ConfigOption::ID_UINT:
{
try
{
UnsignedIntData & tmp = _value_data.get<UnsignedIntData>();
tmp.uint_val = tmp.uint_default;
}
catch(ValueType::InvalidType & e)
{
throw;
}
break;
}
case ConfigOption::ID_STRING:
{
try
{
StringData & tmp = _value_data.get<StringData>();
tmp.string_val = tmp.string_default;
}
catch(ValueType::InvalidType & e)
{
throw;
}
break;
}
case ConfigOption::ID_FUN:
{
try
{
FunctionData & tmp = _value_data.get<FunctionData>();
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>();
BooleanData & dtmp = _value_data.get<BooleanData>();
/* 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>();
SignedIntData & dtmp = _value_data.get<SignedIntData>();
/* 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>();
UnsignedIntData & dtmp = _value_data.get<UnsignedIntData>();
/* 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>();
StringData & dtmp = _value_data.get<StringData>();
/* 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<FunctionData>(_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<option_map_type::iterator, bool> 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<syn_option_map_type::iterator, bool> 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<ConfigOption::SignedIntType>((*iter).first, Strings::toulong(value));
return;
case ConfigOption::ID_UINT:
set<ConfigOption::UnsignedIntType>((*iter).first, Strings::tolong(value));
return;
case ConfigOption::ID_BOOL:
set<ConfigOption::BooleanType>((*iter).first, Strings::toboolean(value));
return;
case ConfigOption::ID_STRING:
case ConfigOption::ID_FUN:
set<ConfigOption::StringType>((*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;
}

View File

@ -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 <set>
#include <map>
#include <vector>
#include <strings.hpp>
#include <function.hpp>
#include <variant.hpp>
#include <format.hpp>
#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<SignedIntType> 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<UnsignedIntType> 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<BooleanData>().bool_val; }
std::string get_str(){ return _value_data.get<StringData>().string_val; }
SignedIntType get_sint(){ return _value_data.get<SignedIntData>().sint_val; }
UnsignedIntType get_uint(){ return _value_data.get<UnsignedIntData>().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 <typename ValueType>
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_ */

View File

@ -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 <errno.h>
#include <configurator/configfile.hpp>
#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(&section))
{
_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(&section, 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

View File

@ -0,0 +1,90 @@
/*
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 <vector>
#include <fstream>
#include <sstream>
#include <set>
#include <format.hpp>
#include <configurator/section.hpp>
#ifndef _CONFIG_CONFIGFILE_HPP_
#define _CONFIG_CONFIGFILE_HPP_
struct Configfile: public Section
{
typedef std::list < std::string > ErrorVector;
typedef std::set < std::string > NameSet;
Configfile(std::string name, std::string desc)
: Section(name, desc), _good(false) {};
virtual ~Configfile() {};
bool good() { return _good; };
std::string & filename() { return _filename; };
ErrorVector & errors() { return _errors; };
void ignore(std::string);
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 deserialize(std::ifstream &);
virtual bool serialize(std::ofstream &);
void recurse(std::ofstream &, Section *);
protected:
bool _good;
ErrorVector _errors;
NameSet _ignores;
std::string _filename;
};
#endif /* _CONFIG_CONFIGFILE_HPP_ */

View File

@ -0,0 +1,185 @@
/*
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 <configurator/option.hpp>
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);
}

View File

@ -0,0 +1,122 @@
/*
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 <iostream>
#include <string>
#include <list>
#include <vector>
#include <strings.hpp>
#include <configurator/restriction.hpp>
#ifndef _CONFIG_OPTION_HPP_
#define _CONFIG_OPTION_HPP_
struct Option
{
enum FlagTypes
{
F_MODIFIED = 0x0, /* if option was modified */
F_ADJUSTED = 0x1, /* if option was correctly formated */
};
struct Flags: public std::vector<bool>
{
Flags(): std::vector<bool>(2) {};
};
typedef Restriction::Value Value;
typedef Restriction::Vector Vector;
/* exception */
struct InvalidDefaultValue
{
InvalidDefaultValue(std::string name, std::string value)
: _name(name), _value(value) {};
std::string & name() { return _name; };
std::string & value() { return _value; };
protected:
std::string _name;
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);
if (!(set(value)[F_ADJUSTED]))
throw InvalidDefaultValue(name, defvalue);
}
const std::string & name() { return _name; };
const std::string & description() { return _desc; };
Restriction & restriction() { return _restriction; };
bool modified() { return _modified; };
public:
bool load(std::string &);
bool change(std::string &);
bool store(std::string &);
Flags set(const char *);
Flags set(Value &);
Flags set(Vector &);
bool get(Value &);
bool get(Vector &);
bool equals(std::string &);
protected:
std::string _name;
std::string _desc;
Restriction _restriction;
bool _modified;
};
#endif /* _CONFIG_OPTION_HPP_ */

View File

@ -0,0 +1,353 @@
/*
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 <math.h>
#include <string.h>
#include <iostream>
#include <strings.hpp>
#include <configurator/restriction.hpp>
/* 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();
}

View File

@ -0,0 +1,321 @@
/*
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 <stdarg.h>
#include <string>
#include <list>
#include <vector>
#include <map>
#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_ */

View File

@ -0,0 +1,130 @@
/*
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 <configurator/section.hpp>
void Section::options(Section::OptionVector & vec)
{
for (OptionMap::iterator it = _options.begin(); it != _options.end();)
{
vec.push_back(&((*it).second));
++it;
}
}
void Section::sections(Section::SectionVector & vec)
{
for (SectionMap::iterator it = _sections.begin(); it != _sections.end();)
{
vec.push_back((*it).second);
++it;
}
}
/*********/
Option * Section::option_find(std::string & str, bool recurse)
{
OptionMap::iterator i = _options.find(str);
if (i == _options.end())
{
if (!recurse)
throw not_found();
for (SectionMap::iterator i = _sections.begin(); i != _sections.end(); i++)
{
try
{
return i->second->option_find(str, recurse);
}
catch (not_found & e)
{
/* keep looping! */
};
}
throw not_found();
}
return &((*i).second);
}
Option * Section::option_find(const char * str, bool recurse)
{
std::string sstr(str);
return option_find(sstr, recurse);
}
/*********/
Section * Section::section_find(std::string & str, bool recurse)
{
SectionMap::iterator i = _sections.find(str);
if (i == _sections.end())
{
if (!recurse)
throw not_found();
for (SectionMap::iterator i = _sections.begin(); i != _sections.end(); i++)
{
try
{
return i->second->section_find(str, recurse);
}
catch (not_found & e)
{
/* keep looping! */
};
}
throw not_found();
}
return ((*i).second);
}
Section * Section::section_find(const char * str, bool recurse)
{
std::string sstr(str);
return section_find(sstr, recurse);
}

View File

@ -0,0 +1,226 @@
/*
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 <string>
#include <vector>
#include <map>
#include <algorithm>
#include <iostream>
#include <configurator/option.hpp>
#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<std::string,Option>(o.name(), o));
};
void del(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() { 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 <typename F>
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_ */

View File

@ -0,0 +1,102 @@
/*
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 <map>
#include <initializer.hpp>
#ifndef _FLAGGER_HPP_
#define _FLAGGER_HPP_
template < typename Flag >
struct Flagger
{
protected:
struct Bool
{
Bool(): value(false) {};
Bool(bool &v): value(v) {};
bool value;
};
typedef std::map< Flag, Bool > Map;
public:
typedef Initializer< Flag > InitFlags;
Flagger() {};
Flagger(InitFlags flags)
{
for (typename InitFlags::iterator i = flags.begin(); i != flags.end(); i++)
{
Flag & flag = (*i);
_map[flag].value = true;
};
};
void set(Flag elt, bool value = true)
{
_map[elt].value = value;
}
bool is_set(Flag elt)
{
return _map[elt].value;
}
Flagger & operator&(Flag elt)
{
set(elt);
return *this;
};
bool operator[](Flag elt)
{
return is_set(elt);
};
protected:
Map _map;
};
#endif /* _FLAGGER_HPP_ */

View File

@ -0,0 +1,331 @@
/*
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 "format.hpp"
//#include <iostream>
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)
{
std::string txt;
const char * ptr = format_string;
while (*ptr != '\0')
{
if (*ptr != '%')
{
txt += *ptr;
++ptr;
continue;
}
const char * ptr2 = ptr+1;
if (*ptr2 == '%')
{
txt += *ptr;
ptr += 2;
continue;
}
if (!txt.empty())
push_argument(txt, T_LITERAL);
std::string arg(1, *ptr);
++ptr;
bool finished = false;
short long_count = 0;
short short_count = 0;
while(*ptr != '\0' && !finished)
{
switch (*ptr)
{
case ' ':
// uncomplete format with ' ', make it a literal.
arg += *ptr;
push_argument(arg, T_LITERAL);
finished = true;
break;
case '%':
// uncomplete format with '%', make it a literal and start a new format.
push_argument(arg, T_LITERAL);
arg += *ptr;
break;
case 'h':
short_count = std::min<short>(short_count+1, 2);
long_count = 0;
arg += *ptr;
break;
case 'l':
long_count = std::min<short>(long_count+1, 2);
short_count = 0;
arg += *ptr;
break;
case 'd':
case 'i':
arg += *ptr;
switch (long_count - short_count)
{
case 2:
push_argument(arg, T_SIGNED_LONG_LONG);
break;
case 1:
push_argument(arg, T_SIGNED_LONG);
break;
case 0:
push_argument(arg, T_SIGNED_INT);
break;
case -1:
push_argument(arg, T_SIGNED_SHORT);
break;
case -2:
push_argument(arg, T_SIGNED_SHORT_SHORT);
break;
default:
break;
}
finished = true;
break;
case 'o':
case 'u':
case 'x':
case 'X':
arg += *ptr;
switch (long_count - short_count)
{
case 2:
push_argument(arg, T_UNSIGNED_LONG_LONG);
break;
case 1:
push_argument(arg, T_UNSIGNED_LONG);
break;
case 0:
push_argument(arg, T_UNSIGNED_INT);
break;
case -1:
push_argument(arg, T_UNSIGNED_SHORT);
break;
case -2:
push_argument(arg, T_UNSIGNED_SHORT_SHORT);
break;
default:
break;
}
finished = true;
break;
case 'e':
case 'E':
case 'f':
case 'F':
case 'g':
case 'G':
case 'a':
case 'A':
arg += *ptr;
push_argument(arg, T_FLOAT);
finished = true;
break;
case 'c':
arg += *ptr;
push_argument(arg, T_CHAR);
finished = true;
break;
case 's':
arg += *ptr;
push_argument(arg, T_STRING);
finished = true;
break;
case 'p':
arg += *ptr;
push_argument(arg, T_POINTER);
finished = true;
break;
case 'C':
case 'S':
case 'm':
case 'n': // unsupported for now.
arg += *ptr;
push_argument(arg, T_ANYTHING);
finished = true;
break;
default:
arg += *ptr;
break;
}
++ptr;
}
if (!arg.empty())
push_argument(arg, T_LITERAL);
}
if (!txt.empty())
push_argument(txt, T_LITERAL);
}
void Format::mark_invalid(std::string & msg)
{
if (_valid)
{
_valid = false;
std::string finalmsg;
finalmsg += "** INVALID FORMAT: ";
finalmsg += msg;
finalmsg += " **";
_result = finalmsg;
}
}
void Format::raise_check(void)
{
if (!_valid && _raise)
throw InvalidFormat(_result);
}
bool Format::validity_check(void)
{
raise_check();
return _valid;
}
const Format::Argument * Format::next_argument(void)
{
// std::cerr << "size: " << _args.size() << std::endl;
while (true)
{
// std::cerr << "loop size: " << _args.size() << std::endl;
if (_args.empty())
return NULL; // throw NoArgumentLeft();
const Argument & top = _args.front();
if (top.type() == T_LITERAL)
{
// std::cerr << "top type == LITERAL, looping..." << std::endl;
_result += top.fmts();
pop_argument();
}
else
{
// std::cerr << "top type: " << top.type() << std::endl;
return &top;
}
}
}
void Format::pop_argument(void)
{
_args.pop();
}
void Format::push_argument(std::string & data, Format::Type type)
{
// std::cerr << "pushing type (" << type << ") with format (" << data << ")" << std::endl;
_args.push(Argument(data, type));
data.clear();
}
std::string Format::str()
{
if (!validity_check())
return _result;
if (next_argument() == NULL)
return _result;
std::string msg;
msg += "too few arguments passed for format '";
msg += _format;
msg += "' (";
msg += _format;
msg += ")";
mark_invalid(msg);
return _result;
}

View File

@ -0,0 +1,512 @@
/*
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 _FORMAT_H_
#define _FORMAT_H_
#include <cstring>
#include <cstdlib>
#include <typeinfo>
#include <stdexcept>
#include <string>
#include <queue>
#include <iostream>
#include <stdio.h>
#ifdef WIN32 // WINDOWS
#include <KHostSystem.h>
#endif
/* macros used for shortening lines and making the code clearer */
#define STG(x) (x).str()
#define FMT(x) Format(x)
struct Format
{
static const unsigned int strings_base_length = 64;
static const unsigned int generic_base_length = 64;
struct InvalidFormat
{
InvalidFormat(std::string msg) : _msg(msg) {}
std::string _msg;
};
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:
enum Type
{
T_ANYTHING = 1,
T_SIGNED_SHORT,
T_SIGNED_SHORT_SHORT,
T_SIGNED_INT,
T_SIGNED_LONG,
T_SIGNED_LONG_LONG,
T_UNSIGNED_SHORT,
T_UNSIGNED_SHORT_SHORT,
T_UNSIGNED_INT,
T_UNSIGNED_LONG,
T_UNSIGNED_LONG_LONG,
T_FLOAT,
T_CHAR,
T_POINTER,
T_STRING,
T_LITERAL
};
struct Argument
{
Argument(std::string fmts, Type type)
: _fmts(fmts), _type(type) {};
Type type(void) const { return _type; }
const std::string & fmts(void) const { return _fmts; }
protected:
std::string _fmts;
Type _type;
};
typedef std::queue < Argument > ArgumentQueue;
////////////////////////////////////////////////////////////
public:
template < typename V >
Format & operator%( V value )
{
if (!validity_check())
return *this;
const Argument * top = next_argument();
if (top == NULL)
{
std::string msg;
msg += "too many arguments passed for format '";
msg += _format;
msg += "'";
mark_invalid(msg);
}
else
{
char temp[generic_base_length];
if (!generic_verify(value, top->type()))
{
std::string msg;
msg += "type mismatch: got type '";
msg += typeid(value).name();
msg += "' in format '";
msg += top->fmts();
msg += "' (";
msg += _format;
msg += ")";
mark_invalid(msg);
return *this;
}
snprintf(temp, sizeof(temp), top->fmts().c_str(), value);
_result += temp;
pop_argument();
}
raise_check();
return *this;
}
template < typename V >
Format & operator%( V * value )
{
if (!validity_check())
return *this;
const Argument * top = next_argument();
if (top == NULL)
{
std::string msg;
msg += "too many arguments passed for format '";
msg += _format;
msg += "'";
mark_invalid(msg);
}
else
{
switch (top->type())
{
case T_POINTER:
{
char temp[generic_base_length];
snprintf(temp, sizeof(temp), top->fmts().c_str(), value);
_result += temp;
break;
}
case T_STRING:
{
if ((typeid(const char) == typeid(V)) ||
(typeid(char) == typeid(V)) ||
(typeid(const unsigned char) == typeid(V)) ||
(typeid(unsigned char) == typeid(V)) ||
(typeid(const void) == typeid(V)) ||
(typeid(void) == typeid(V)))
{
int len = strlen((const char*)value)+strings_base_length+1;
char * temp = new char[len];
snprintf(temp, len, top->fmts().c_str(), value);
_result += temp;
delete[] temp;
}
else
{
std::string msg;
msg += "type mismatch: got type '";
msg += typeid(value).name();
msg += "' in string format (";
msg += _format;
msg += ")";
mark_invalid(msg);
}
break;
}
default:
{
std::string msg;
msg += "type mismatch: got pointer/string type in format '";
msg += top->fmts();
msg += "' (";
msg += _format;
msg += ")";
mark_invalid(msg);
break;
}
}
pop_argument();
}
raise_check();
return *this;
}
/*
Format & operator%( std::string value )
{
return operator%(value);
}
*/
Format & operator%( const std::string value )
{
if (!validity_check())
return *this;
const Argument * top = next_argument();
if (top == NULL)
{
std::string msg;
msg += "too many arguments passed for format '";
msg += _format;
msg += "'";
mark_invalid(msg);
}
else
{
if (top->type() == T_STRING)
{
int len = value.length()+strings_base_length+1;
char * temp = new char[len];
snprintf(temp, len, top->fmts().c_str(), value.c_str());
_result += temp;
delete[] temp;
}
else
{
std::string msg;
msg += "type mismatch: got string type in format '";
msg += top->fmts();
msg += "' (";
msg += _format;
msg += ")";
mark_invalid(msg);
}
pop_argument();
}
raise_check();
return *this;
}
protected:
template < typename V >
bool number_verify_signed_short( V value )
{
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)
{
/* 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;
};
void mark_invalid(std::string &);
bool validity_check(void);
void raise_check(void);
/*
struct NoArgumentLeft
{
NoArgumentLeft(): empty(0) {};
unsigned int empty;
};
*/
const Argument * next_argument(void);
void pop_argument(void);
void push_argument(std::string & data, Type type);
private:
std::string _format;
bool _valid;
bool _raise;
std::string _result;
ArgumentQueue _args;
};
#endif /* _FORMAT_H_ */

View File

@ -0,0 +1,62 @@
/*
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 "saved_condition.hpp"
bool SavedCondition::wait(unsigned int msec)
{
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;
}
_signaled = false;
switch_mutex_unlock(_mutex);
return ret;
}

View File

@ -0,0 +1,136 @@
/*
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 _SAVED_CONDITION_
#define _SAVED_CONDITION_
#include <saved_condition.hpp>
extern "C"
{
#include <switch.h>
}
struct SavedCondition : public SavedConditionCommon// : public RefCounter < SavedCondition >
{
typedef switch_thread_cond_t BaseConditionType;
typedef switch_mutex_t BaseMutexType;
SavedCondition(switch_memory_pool_t *pool=NULL):
_pool(pool),
_can_delete_pool(false)
{
if(!_pool)
{
switch_core_new_memory_pool(&_pool);
_can_delete_pool = true;
}
switch_thread_cond_create(&_condition, _pool);
switch_mutex_init(&_mutex, SWITCH_MUTEX_DEFAULT, _pool);
}
//SavedCondition(const SavedCondition &);
~SavedCondition()
{
switch_thread_cond_destroy(_condition);
switch_mutex_destroy(_mutex);
if(_can_delete_pool)
switch_core_destroy_memory_pool(&_pool);
}
void signal(void)
{
switch_mutex_lock(_mutex);
_signaled = true;
switch_thread_cond_signal(_condition);
switch_mutex_unlock(_mutex);
}
void broadcast(void)
{
switch_mutex_lock(_mutex);
_signaled = true;
switch_thread_cond_broadcast(_condition);
switch_mutex_unlock(_mutex);
}
void wait(void)
{
switch_mutex_lock(_mutex);
if (!_signaled)
switch_thread_cond_wait(_condition, _mutex);
_signaled = false;
switch_mutex_unlock(_mutex);
}
bool wait(unsigned int);
void reset(void)
{
switch_mutex_lock(_mutex);
_signaled = false;
switch_mutex_unlock(_mutex);
}
BaseMutexType * mutex() { return _mutex; };
BaseConditionType * condition() { return _condition; };
protected:
BaseConditionType *_condition;
BaseMutexType *_mutex;
switch_memory_pool_t *_pool;
bool _can_delete_pool;
};
#endif /* _SAVED_CONDITION_ */

View File

@ -0,0 +1,177 @@
/*
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 _SIMPLE_LOCK_HPP_
#define _SIMPLE_LOCK_HPP_
#include <simple_lock.hpp>
extern "C"
{
#include <switch.h>
}
template < typename Implementor >
struct SimpleLockBasic: public SimpleLockCommon < Implementor >
{
typedef SimpleLockCommon < Implementor > Super;
typedef typename Super::Result Result;
typedef switch_mutex_t BaseMutexType;
SimpleLockBasic(switch_memory_pool_t *pool = NULL)
: _pool(pool), _can_delete_pool( (_pool == NULL) )
{
if(!_pool)
switch_core_new_memory_pool(&_pool);
//switch_mutex_init(&_mutex, SWITCH_MUTEX_DEFAULT, _pool);
switch_mutex_init(&_mutex, SWITCH_MUTEX_NESTED, _pool);
}
virtual ~SimpleLockBasic()
{
/* do nothing */
};
void unreference()
{
switch_mutex_destroy(_mutex);
if (_can_delete_pool)
switch_core_destroy_memory_pool(&_pool);
}
Result trylock()
{
switch (switch_mutex_trylock(_mutex))
{
case SWITCH_STATUS_SUCCESS:
return Super::SUCCESS;
case SWITCH_STATUS_FALSE:
case SWITCH_STATUS_TERM:
case SWITCH_STATUS_NOTIMPL:
case SWITCH_STATUS_MEMERR:
case SWITCH_STATUS_GENERR:
case SWITCH_STATUS_SOCKERR:
case SWITCH_STATUS_NOTFOUND:
case SWITCH_STATUS_UNLOAD:
case SWITCH_STATUS_NOUNLOAD:
case SWITCH_STATUS_NOT_INITALIZED:
return Super::FAILURE;
//case SWITCH_STATUS_INUSE:
default:
return Super::ISINUSE;
}
}
void unlock()
{
switch_mutex_unlock(_mutex);
}
BaseMutexType * mutex() { return _mutex; };
protected:
BaseMutexType *_mutex;
switch_memory_pool_t *_pool;
bool _can_delete_pool;
};
struct SimpleLock: public SimpleLockBasic < SimpleLock >
{
typedef SimpleLockBasic < SimpleLock > Super;
typedef Super::Result Result;
SimpleLock(switch_memory_pool_t *pool = NULL)
: Super(pool) {};
Result lock()
{
switch (switch_mutex_lock(_mutex))
{
case SWITCH_STATUS_SUCCESS:
return Super::SUCCESS;
case SWITCH_STATUS_FALSE:
case SWITCH_STATUS_TERM:
case SWITCH_STATUS_NOTIMPL:
case SWITCH_STATUS_MEMERR:
case SWITCH_STATUS_GENERR:
case SWITCH_STATUS_SOCKERR:
case SWITCH_STATUS_NOTFOUND:
case SWITCH_STATUS_UNLOAD:
case SWITCH_STATUS_NOUNLOAD:
case SWITCH_STATUS_NOT_INITALIZED:
return Super::FAILURE;
//case SWITCH_STATUS_INUSE:
default:
return Super::ISINUSE;
}
}
};
template < unsigned int Retries = 10, unsigned int Interval = 50 >
struct SimpleNonBlockLock: public SimpleLockBasic < SimpleNonBlockLock < Retries, Interval > >
{
typedef SimpleLockBasic < SimpleNonBlockLock < Retries, Interval > > Super;
typedef typename Super::Result Result;
SimpleNonBlockLock(switch_memory_pool_t *pool = NULL)
: Super(pool) {};
inline Result lock()
{
for (unsigned int i = 0; i < Retries; i++)
{
Result ret = Super::trylock();
if (ret != Super::ISINUSE)
return ret;
usleep(Interval * 1000);
}
return Super::ISINUSE;
}
};
#endif /* _SIMPLE_LOCK_HPP_ */

View File

@ -0,0 +1,327 @@
/*
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 _THREAD_HPP_
#define _THREAD_HPP_
#include <thread.hpp>
extern "C"
{
#include <switch.h>
}
struct Thread : ThreadCommon
{
typedef switch_thread_t BaseThreadType;
template<typename T, typename R, typename A>
struct ThreadData : ThreadDataCommon
{
ThreadData(T data, A arg) : _data(data), _arg(arg) {}
int run()
{
return _data(_arg);
}
T _data;
A _arg;
};
template<typename T, typename R>
struct ThreadData < T, R, void > : ThreadDataCommon
{
ThreadData(T data) : _data(data) {}
int run()
{
return _data();
}
T _data;
};
template<typename T, typename A>
struct ThreadData < T, void, A > : ThreadDataCommon
{
ThreadData(T data, A arg) : _data(data), _arg(arg) {}
int run()
{
_data(_arg);
return 0;
}
T _data;
A _arg;
};
template<typename T>
struct ThreadData < T, void, void > : ThreadDataCommon
{
ThreadData(T data) : _data(data) {}
int run()
{
_data();
return 0;
}
T _data;
};
template<typename T>
Thread(T obj, switch_memory_pool_t *pool=NULL) :
_thread_info(new ThreadData<T, typename DecomposeFunction<T>::Return, void>(obj)),
_pool(pool),
_can_delete_pool(false)
{
if(!_pool)
{
switch_core_new_memory_pool(&_pool);
_can_delete_pool = true;
}
_thread_info->_thread = this;
_thread_info->_self = NULL;
_thread_info->_attribute = NULL;
if(switch_threadattr_create(
(switch_threadattr_t **)&_thread_info->_attribute, _pool) != 0)
{
_thread_info->_attribute = NULL;
return;
}
switch_threadattr_stacksize_set(
(switch_threadattr_t *)_thread_info->_attribute,
SWITCH_THREAD_STACKSIZE);
if(!priority())
{
_thread_info->_attribute = NULL;
}
}
template<typename T, typename A>
Thread(T obj, A arg, switch_memory_pool_t *pool=NULL) :
_thread_info(new ThreadData<T, typename DecomposeFunction<T>::Return, A>(obj, arg)),
_pool(pool),
_can_delete_pool(false)
{
if(!_pool)
{
switch_core_new_memory_pool(&_pool);
_can_delete_pool = true;
}
_thread_info->_thread = this;
_thread_info->_self = NULL;
_thread_info->_attribute = NULL;
if(switch_threadattr_create(
(switch_threadattr_t **)&_thread_info->_attribute, _pool) != 0)
{
_thread_info->_attribute = NULL;
return;
}
switch_threadattr_stacksize_set(
(switch_threadattr_t *)_thread_info->_attribute,
SWITCH_THREAD_STACKSIZE);
if(!priority())
{
_thread_info->_attribute = NULL;
}
}
~Thread()
{
if(_thread_info)
delete _thread_info;
if (_can_delete_pool)
switch_core_destroy_memory_pool(&_pool);
}
void detach(bool d = true)
{
if(!_thread_info->_attribute)
return;
/* Non-zero if detached threads should be created. */
switch_threadattr_detach_set(
(switch_threadattr_t *)_thread_info->_attribute, d ? 1 : 0);
}
bool start()
{
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,
_pool);
if(!_thread_info->_self)
return false;
return true;
}
int join()
{
/*
* block until the desired thread stops executing.
* @param retval The return value from the dead thread.
* @param thd The thread to join
*
* 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,
(switch_thread_t *)_thread_info->_self) != 0)
return -1;
return retval;
}
BaseThreadType * self()
{
//switch_thread_self();
//apr_os_thread_current();
return (BaseThreadType *)_thread_info->_self;
}
private:
void exit(int status)
{
/**
* stop the current thread
* @param thd The thread to stop
* @param retval The return value to pass back to any thread that cares
*/
//SWITCH_DECLARE(switch_status_t) switch_thread_exit(switch_thread_t *thd, switch_status_t retval);
switch_thread_exit((switch_thread_t *)_thread_info->_self, (switch_status_t)status);
}
#ifndef WIN32
struct apr_threadattr_t {
apr_pool_t *pool;
pthread_attr_t attr;
};
#endif
bool priority()
{
#ifndef WIN32
struct sched_param param;
struct apr_threadattr_t *myattr = (struct apr_threadattr_t *)_thread_info->_attribute;
if (pthread_attr_setschedpolicy(
(pthread_attr_t *)&myattr->attr, SCHED_RR) < 0)
return false;
if (pthread_attr_getschedparam(
(pthread_attr_t *)&myattr->attr, &param) < 0)
return false;
param.sched_priority = sched_get_priority_max(SCHED_RR);
if (pthread_attr_setschedparam(
(pthread_attr_t *)&myattr->attr, &param) < 0)
return false;
#endif
return true;
/*
//BUG in Freeswitch
if(switch_threadattr_priority_increase(
(switch_threadattr_t *)_thread_info->_attribute) != 0)
return false;
return true;
*/
}
protected:
ThreadDataCommon * _thread_info;
switch_memory_pool_t *_pool;
bool _can_delete_pool;
protected:
static void *SWITCH_THREAD_FUNC run(BaseThreadType *thread, void * obj)
{
//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,
// "Stopping new Thread = %d\n", retval);
((Thread *)(data->_thread))->exit(retval);
return NULL;
}
};
#endif /* _THREAD_HPP_ */

View File

@ -0,0 +1,337 @@
/*
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 <refcounter.hpp>
#ifndef _FUNCTION_HPP_
#define _FUNCTION_HPP_
namespace Function
{
struct EmptyFunction {};
/**/
template < typename FunctionTraits >
struct StorageBase: NEW_REFCOUNTER(StorageBase < FunctionTraits >)
{
typedef typename FunctionTraits::BaseType BaseType;
typedef typename FunctionTraits::FunType FunType;
typedef typename FunctionTraits::ObjType ObjType;
template < typename Functor >
StorageBase(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<ObjType>((malloced ? new Functor(f) : &f))),
_function(reinterpret_cast<FunType>(&(Functor::operator()))),
_malloced(malloced)
{};
StorageBase()
: _object(reinterpret_cast<ObjType>(0)),
_function(reinterpret_cast<FunType>(0)),
_malloced(false)
{};
StorageBase(const StorageBase & o)
: INC_REFCOUNTER(o, StorageBase < FunctionTraits >),
_object(o._object), _function(o._function), _malloced(o._malloced)
{};
virtual ~StorageBase() {};
void unreference()
{
// TODO: will this work if we delete a different type? //
if (_malloced)
delete _object;
};
template < typename Functor >
void operator=(Functor f)
{
_object = reinterpret_cast<ObjType>(new Functor(f)),
_function = reinterpret_cast<FunType>(&(Functor::operator()));
_malloced = false;
}
protected:
ObjType _object;
FunType _function;
bool _malloced;
};
/**/
template < typename R >
struct VTable0
{
R operator()(void) { return R(); };
};
template < >
struct VTable0< void >
{
void operator()(void) { return; };
};
template < typename R >
struct Function0Traits
{
typedef VTable0<R> BaseType;
typedef R (BaseType::* FunType)(void);
typedef BaseType * ObjType;
};
/**/
template < typename R, typename A0 >
struct VTable1
{
R operator()(A0 a0) { return R(); };
};
template < typename A0 >
struct VTable1< void, A0 >
{
void operator()(A0 a0) { return; };
};
template < typename R, typename A0 >
struct Function1Traits
{
typedef VTable1<R, A0> BaseType;
typedef R (BaseType::* FunType)(A0);
typedef BaseType * ObjType;
};
/**/
template < typename R, typename A0, typename A1 >
struct VTable2
{
R operator()(A0 a0, A1) { return R(); };
};
template < typename A0, typename A1 >
struct VTable2< void, A0, A1 >
{
void operator()(A0 a0, A1 a1) { return; };
};
template < typename R, typename A0, typename A1 >
struct Function2Traits
{
typedef VTable2<R, A0, A1> BaseType;
typedef R (BaseType::* FunType)(A0, A1);
typedef BaseType * ObjType;
};
/**/
template < typename R, typename A0, typename A1, typename A2 >
struct VTable3
{
R operator()(A0 a0, A1 a1, A2 a2) { return R(); };
};
template < typename A0, typename A1, typename A2 >
struct VTable3< void, A0, A1, A2 >
{
void operator()(A0 a0, A1 a1, A2 a2) { return; };
};
template < typename R, typename A0, typename A1, typename A2 >
struct Function3Traits
{
typedef VTable3<R, A0, A1, A2> BaseType;
typedef R (BaseType::* FunType)(A0, A1, A2);
typedef BaseType * ObjType;
};
/**/
template < typename R, typename A0, typename A1, typename A2, typename A3 >
struct VTable4
{
R operator()(A0 a0, A1 a1, A2 a2, A3 a3) { return R(); };
};
template < typename A0, typename A1, typename A2, typename A3 >
struct VTable4< void, A0, A1, A2, A3 >
{
void operator()(A0 a0, A1 a1, A2 a2, A3 a3) { return; };
};
template < typename R, typename A0, typename A1, typename A2, typename A3 >
struct Function4Traits
{
typedef VTable4<R, A0, A1, A2, A3> BaseType;
typedef R (BaseType::* FunType)(A0, A1, A2, A3);
typedef BaseType * ObjType;
};
/**/
template < typename R, typename A0 >
struct Function0 : public StorageBase < Function0Traits < R > >
{
typedef StorageBase < Function0Traits < R > > Storage;
template < typename Functor >
Function0(Functor f): Storage(f) {};
template < typename Functor >
Function0(Functor & f, bool m): Storage(f, m) {};
Function0() {};
R operator()(void)
{
if (reinterpret_cast<void *>(Storage::_object) == 0)
throw EmptyFunction();
return ((Storage::_object)->*(Storage::_function))();
}
};
template < typename R, typename A0 >
struct Function1 : public StorageBase < Function1Traits < R, A0 > >
{
typedef StorageBase < Function1Traits < R, A0 > > Storage;
template < typename Functor >
Function1(Functor f): Storage(f) {};
template < typename Functor >
Function1(Functor & f, bool m): Storage(f, m) {};
Function1() {};
R operator()(A0 a0)
{
if (reinterpret_cast<void *>(Storage::_object) == 0)
throw EmptyFunction();
return ((Storage::_object)->*(Storage::_function))(a0);
}
};
template < typename R, typename A0, typename A1 >
struct Function2 : public StorageBase < Function2Traits < R, A0, A1 > >
{
typedef StorageBase < Function2Traits < R, A0, A1 > > Storage;
template < typename Functor >
Function2(Functor f): Storage(f) {};
template < typename Functor >
Function2(Functor & f, bool m): Storage(f, m) {};
Function2() {};
R operator()(A0 a0, A1 a1)
{
if (reinterpret_cast<void *>(Storage::_object) == 0)
throw EmptyFunction();
return ((Storage::_object)->*(Storage::_function))(a0, a1);
}
};
template < typename R, typename A0, typename A1, typename A2 >
struct Function3 : public StorageBase < Function3Traits < R, A0, A1, A2 > >
{
typedef StorageBase < Function3Traits < R, A0, A1, A2 > > Storage;
template < typename Functor >
Function3(Functor f): Storage(f) {};
template < typename Functor >
Function3(Functor & f, bool m): Storage(f, m) {};
Function3() {};
R operator()(A0 a0, A1 a1, A2 a2)
{
if (reinterpret_cast<void *>(Storage::_object) == 0)
throw EmptyFunction();
return ((Storage::_object)->*(Storage::_function))(a0, a1, a2);
}
};
template < typename R, typename A0, typename A1, typename A2, typename A3 >
struct Function4 : public StorageBase < Function4Traits < R, A0, A1, A2, A3 > >
{
typedef StorageBase < Function4Traits < R, A0, A1, A2, A3 > > Storage;
template < typename Functor >
Function4(Functor f): Storage(f) {};
template < typename Functor >
Function4(Functor & f, bool m): Storage(f, m) {};
Function4() {};
R operator()(A0 a0, A1 a1, A2 a2, A3 a3)
{
if (reinterpret_cast<void *>(Storage::_object) == 0)
throw EmptyFunction();
return ((Storage::_object)->*(Storage::_function))(a0, a1, a2, a3);
}
};
};
#endif /* _FUNCTION_HPP_ */

View File

@ -0,0 +1,80 @@
/*
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 <vector>
#ifndef _INITIALIZER_HPP_
#define _INITIALIZER_HPP_
template < typename Type >
struct Initializer: public std::vector< Type >
{
typedef std::vector< Type > super;
Initializer(Type e) { push_back(e); };
Initializer(Type & e) { push_back(e); };
Initializer & operator&(Initializer v)
{
insert(super::end(), v.begin(), v.end());
return *this;
};
Initializer & operator&(Initializer & v)
{
insert(super::end(), v.begin(), v.end());
return *this;
};
Initializer & operator&(Type v)
{
insert(super::end(), v);
return *this;
};
Initializer & operator&(Type & v)
{
insert(super::end(), v);
return *this;
};
};
#endif /* _INITIALIZER_HPP_ */

View File

@ -0,0 +1,313 @@
/*
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 <k3lapi.hpp>
#include <format.hpp>
#include <verbose.hpp>
K3LAPI::K3LAPI(bool has_exceptions)
: _has_exceptions(has_exceptions),
_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)
{
/* tie the used k3l to the compiled k3l version */
char *ret = k3lStart(k3lApiMajorVersion, k3lApiMinorVersion, 0); //k3lApiBuildVersion);
if (ret && *ret)
throw start_failed(ret);
/* call init automagically */
init();
}
void K3LAPI::stop(void)
{
k3lStop();
fini();
}
/* envio de comandos para placa */
void K3LAPI::mixer(int32 dev, int32 obj, byte track, KMixerSource src, int32 index)
{
KMixerCommand mix;
mix.Track = track;
mix.Source = src;
mix.SourceIndex = index;
command(dev, obj, CM_MIXER, (const char *) &mix);
}
void K3LAPI::mixerRecord(int32 dev, int32 obj, byte track, KMixerSource src, int32 index)
{
/* estes buffers *NAO PODEM SER ESTATICOS*! */
char cmd[] = { 0x3f, 0x03, (char)obj, (char)track, 0xff, 0xff };
switch (src)
{
case kmsChannel:
cmd[4] = 0x05;
cmd[5] = (char)index;
break;
case kmsNoDelayChannel:
cmd[4] = 0x0a;
cmd[5] = (char)index;
break;
case kmsGenerator:
cmd[4] = 0x09;
switch ((KMixerTone)index)
{
case kmtSilence:
cmd[5] = 0x0F;
break;
case kmtDial:
cmd[5] = 0x08;
break;
case kmtBusy:
cmd[5] = 0x0D;
break;
case kmtFax:
case kmtVoice:
case kmtEndOf425:
case kmtCollect:
case kmtEndOfDtmf:
/* TODO: exception, unable to generate */
break;
}
break;
case kmsCTbus:
case kmsPlay:
/* TODO: exception, not implemented! */
break;
}
int32 dsp = get_dsp(dev, DSP_AUDIO);
raw_command(dev, dsp, cmd, sizeof(cmd));
}
void K3LAPI::mixerCTbus(int32 dev, int32 obj, byte track, KMixerSource src, int32 index)
{
KMixerCommand mix;
mix.Track = track;
mix.Source = src;
mix.SourceIndex = index;
command(dev, obj, CM_MIXER_CTBUS, (const char *) &mix);
}
void K3LAPI::command(int32 dev, int32 obj, int32 code, std::string & str)
{
command(dev, obj, code, str.c_str());
}
void K3LAPI::command (int32 dev, int32 obj, int32 code, const char * parms)
{
K3L_COMMAND cmd;
cmd.Cmd = code;
cmd.Object = obj;
cmd.Params = (byte *)parms;
int32 rc = k3lSendCommand(dev, &cmd);
if (rc != ksSuccess)
throw failed_command(code, dev, obj, rc);
}
void K3LAPI::raw_command(int32 dev, int32 dsp, std::string & str)
{
raw_command(dev, dsp, str.data(), str.size());
}
void K3LAPI::raw_command(int32 dev, int32 dsp, const char * cmds, int32 size)
{
std::string str(cmds, size);
int32 rc = k3lSendRawCommand(dev, dsp, (void *)cmds, size);
if (rc != ksSuccess)
throw failed_raw_command(dev, dsp, rc);
}
KLibraryStatus K3LAPI::get_param(K3L_EVENT *ev, const char *name, std::string &res)
{
char tmp_param[256];
memset((void*)tmp_param, 0, sizeof(tmp_param));
int32 rc = k3lGetEventParam (ev, (sbyte *)name, (sbyte *)tmp_param, sizeof(tmp_param)-1);
if (rc != ksSuccess)
return (KLibraryStatus)rc;
res.append(tmp_param, strlen(tmp_param));
return ksSuccess;
}
std::string K3LAPI::get_param(K3L_EVENT *ev, const char *name)
{
std::string res;
KLibraryStatus rc = get_param(ev, name, res);
if (rc != ksSuccess)
throw get_param_failed(name, rc);
return res;
}
void K3LAPI::init(void)
{
if (_device_count != 0) return;
_device_count = k3lGetDeviceCount();
_device_type = new KDeviceType[_device_count];
_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];
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)));
/* adjust channel/link count for device */
_channel_count[dev] = _device_config[dev].ChannelCount;
_link_count[dev] = _device_config[dev].LinkCount;
/* caches each channel config */
_channel_config[dev] = new channel_conf_type[_channel_count[dev]];
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)));
}
/* adjust link count for device */
_link_count[dev] = _device_config[dev].LinkCount;
/* caches each link config */
_link_config[dev] = new link_conf_type[_link_count[dev]];
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)));
}
}
}
void K3LAPI::fini(void)
{
for (unsigned int dev = 0; dev < _device_count; dev++)
{
if (_channel_config[dev])
{
delete[] _channel_config[dev];
_channel_config[dev] = NULL;
}
if (_link_config[dev])
{
delete[] _link_config[dev];
_link_config[dev] = NULL;
}
}
_device_count = 0;
if (_device_type) { delete[] _device_type; _device_type = NULL; }
if (_device_config) { delete[] _device_config; _device_config = NULL; }
if (_channel_config) { delete[] _channel_config; _channel_config = NULL; }
if (_link_config) { delete[] _link_config; _link_config = NULL; }
if (_channel_count) { delete[] _channel_count; _channel_count = NULL; }
if (_link_count) { delete[] _link_count; _link_count = NULL; }
}
int32 K3LAPI::get_dsp(int32 dev, K3LAPI::DspType type)
{
switch (device_type(dev))
{
case kdtFXO:
case kdtFXOVoIP:
#if K3L_AT_LEAST(1,6,0)
case kdtGSM:
case kdtGSMSpx:
#endif
#if K3L_AT_LEAST(2,1,0)
case kdtGSMUSB:
case kdtGSMUSBSpx:
#endif
return 0;
default:
return (type == DSP_AUDIO ? 1 : 0);
}
}

View File

@ -0,0 +1,408 @@
/*
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 <string>
#include <k3l.h>
/* if using full k3l.h (for softpbx), version already defined. */
#ifndef k3lApiMajorVersion
# include <k3lVersion.h>
#endif
#ifdef __GNUC_PREREQ
#if __GNUC_PREREQ(4,3)
#include <cstring>
#endif
#endif
#include <types.hpp>
#ifndef _K3LAPI_HPP_
#define _K3LAPI_HPP_
struct K3LAPI
{
/* exceptions */
struct start_failed
{
start_failed(const char * _msg) : msg(_msg) {};
start_failed(std::string _msg) : msg(_msg) {};
std::string msg;
};
struct failed_command
{
failed_command(int32 _code, unsigned short _dev, unsigned short _obj, int32 _rc)
: code(_code), dev(_dev), obj(_obj), rc(_rc) {};
int32 code;
unsigned short dev;
unsigned short obj;
int32 rc;
};
struct failed_raw_command
{
failed_raw_command(unsigned short _dev, unsigned short _dsp, int32 _rc)
: dev(_dev), dsp(_dsp), rc(_rc) {};
unsigned short dev;
unsigned short dsp;
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)
: name(_name), rc((KLibraryStatus)_rc) {};
std::string name;
KLibraryStatus rc;
};
typedef K3L_DEVICE_CONFIG device_conf_type;
typedef K3L_CHANNEL_CONFIG channel_conf_type;
typedef K3L_CHANNEL_CONFIG * channel_ptr_conf_type;
typedef K3L_LINK_CONFIG link_conf_type;
typedef K3L_LINK_CONFIG * link_ptr_conf_type;
/* constructors/destructors */
K3LAPI(bool has_exceptions = false);
virtual ~K3LAPI() {};
/* (init|final)ialize the whole thing! */
void start(void);
void stop(void);
/* verificacao de intervalos */
inline bool valid_device(int32 dev)
{
return (dev >= 0 && dev < ((int32)_device_count));
}
inline bool valid_channel(int32 dev, int32 obj)
{
return (valid_device(dev) && obj >= 0 && obj < ((int32)_channel_count[dev]));
}
inline bool valid_link(int32 dev, int32 obj)
{
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);
/* obter dados 'cacheados' (geral) */
inline unsigned int device_count(void)
{
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 command (int32 dev, int32 obj, int32 code, std::string & str);
void command (int32 dev, int32 obj, int32 code, const char * parms = NULL);
/* 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)
{
mixer((int32)tgt.device, (int32)tgt.object, track, src, index);
}
void mixerRecord(target & tgt, byte track, KMixerSource src, int32 index)
{
mixerRecord((int32)tgt.device, (int32)tgt.object, track, src, index);
}
void mixerCTbus(target & tgt, byte track, KMixerSource src, int32 index)
{
mixerCTbus((int32)tgt.device, (int32)tgt.object, track, src, index);
}
void command (target & tgt, int32 code, std::string & str)
{
command((int32)tgt.device, (int32)tgt.object, code, str);
};
void command (target & tgt, int32 code, const char * parms = NULL)
{
command((int32)tgt.device, (int32)tgt.object, code, parms);
};
/* obter dados 'cacheados' (com indentificadores) */
inline unsigned int channel_count(target & tgt)
{
return _channel_count[tgt.device];
}
inline unsigned int link_count(target & tgt)
{
return _link_count[tgt.device];
}
KDeviceType device_type(target & tgt)
{
return _device_type[tgt.device];
}
K3L_DEVICE_CONFIG & device_config(target & tgt)
{
return _device_config[tgt.device];
}
K3L_CHANNEL_CONFIG & channel_config(target & tgt)
{
return _channel_config[tgt.device][tgt.object];
}
K3L_LINK_CONFIG & link_config(target & tgt)
{
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);
/* inicializa valores em cache */
void init(void);
void fini(void);
/* utilidades diversas e informacoes */
enum DspType
{
DSP_AUDIO,
DSP_SIGNALING,
};
int32 get_dsp(int32, DspType);
protected:
const bool _has_exceptions;
unsigned int _device_count;
unsigned int * _channel_count;
unsigned int * _link_count;
device_conf_type * _device_config;
channel_ptr_conf_type * _channel_config;
link_ptr_conf_type * _link_config;
KDeviceType * _device_type;
};
#endif /* _K3LAPI_HPP_ */

View File

@ -0,0 +1,234 @@
/*
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 <k3lutil.hpp>
std::string K3LUtil::channelStatus(int32 dev, int32 channel,
Verbose::Presentation fmt)
{
try
{
K3L_CHANNEL_CONFIG & config = _k3lapi.channel_config(dev, channel);
K3L_CHANNEL_STATUS status;
KLibraryStatus ret = (KLibraryStatus) k3lGetDeviceStatus (dev,
channel + ksoChannel, &status, sizeof(status));
switch (ret)
{
case ksSuccess: return Verbose::channelStatus(config.Signaling,
status.AddInfo, fmt);
default: return (fmt == Verbose::EXACT ? "<unknown[fail]>"
: "Unknown (fail)");
}
}
catch(K3LAPI::invalid_channel & e)
{
return (fmt == Verbose::EXACT ? "<unknown[fail]>" : "Unknown (fail)");
}
}
std::string K3LUtil::callStatus(int32 dev, int32 channel,
Verbose::Presentation fmt)
{
K3L_CHANNEL_STATUS status;
KLibraryStatus ret = (KLibraryStatus) k3lGetDeviceStatus(dev,
channel + ksoChannel, &status, sizeof(status));
switch (ret)
{
case ksSuccess: return Verbose::callStatus(status.CallStatus, fmt);
default: return (fmt == Verbose::EXACT ? "<unknown[fail]>"
: "Unknown (fail)");
}
}
std::string K3LUtil::linkStatus(int32 dev, int32 link,
Verbose::Presentation fmt, KSignaling sig)
{
try
{
if (sig == ksigInactive)
{
K3L_LINK_CONFIG & config = _k3lapi.link_config(dev, link);
sig = config.Signaling;
}
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);
default: return (fmt == Verbose::EXACT ?
"<unknown[failure]>" : "Unknown (failure)");
}
}
catch(K3LAPI::invalid_channel & e)
{
return (fmt == Verbose::EXACT ? "<unknown[failure]>"
: "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)
{
unsigned int number = 0;
try
{
switch (_k3lapi.device_type(dev))
{
#if K3L_AT_LEAST(1,6,0)
case kdtFXS:
number = (count_virtual ? (_k3lapi.channel_count(dev) < 50 ? 1 : 2) : 0);
break;
case kdtFXSSpx:
number = (count_virtual ? (_k3lapi.channel_count(dev) < 30 ? 1 : 2) : 0);
break;
#endif
#if K3L_AT_LEAST(2,1,0)
case kdtE1FXSSpx:
number = (count_virtual ? 2 : 1);
break;
#endif
/* E1 boards */
case kdtE1:
case kdtE1Spx:
case kdtE1IP:
number = _k3lapi.link_count(dev);
break;
case kdtPR:
case kdtE1GW:
number = 1;
break;
#if K3L_AT_LEAST(1,6,0)
case kdtFXO:
case kdtFXOVoIP:
case kdtGSM:
case kdtGSMSpx:
#else
case kdtFX:
case kdtFXVoIP:
#endif
case kdtConf:
case kdtGWIP:
#if K3L_AT_LEAST(2,1,0)
case kdtGSMUSB:
case kdtGSMUSBSpx:
case kdtReserved1: // just to avoid warnings.
case kdtDevTypeCount: // just to avoid warnings.
#endif
number = 0;
break;
}
}
catch(K3LAPI::invalid_device & e)
{
return 0;
}
return number;
}
K3LUtil::ErrorCountType K3LUtil::linkErrorCount(int32 dev, int32 link,
Verbose::Presentation fmt)
{
ErrorCountType result;
K3L_LINK_ERROR_COUNTER status;
KLibraryStatus ret = (KLibraryStatus) k3lGetDeviceStatus (dev,
link + ksoLinkMon, &status, sizeof(status));
switch (ret)
{
case ksSuccess:
for (unsigned int i = klecChangesToLock; i < klecCount; i++)
{
result.push_back(ErrorCountPairType(Verbose::linkErrorCounter
((KLinkErrorCounter)i, fmt), status.ErrorCounters[i]));
}
/* fall */
default:
return result;
}
}

View File

@ -0,0 +1,82 @@
/*
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 <string>
#include <utility>
#include <list>
#include <k3lapi.hpp>
#include <verbose.hpp>
#ifndef _K3LUTIL_HPP_
#define _K3LUTIL_HPP_
struct K3LUtil
{
typedef std::pair < std::string, unsigned int > ErrorCountPairType;
typedef std::list < ErrorCountPairType > ErrorCountType;
K3LUtil(K3LAPI & k3lapi): _k3lapi(k3lapi) {};
std::string callStatus(int32 dev, int32 channel,
Verbose::Presentation fmt = Verbose::HUMAN);
std::string channelStatus(int32, int32,
Verbose::Presentation fmt = Verbose::HUMAN);
std::string linkStatus(int32, int32,
Verbose::Presentation fmt = Verbose::HUMAN,
KSignaling sig = ksigInactive);
std::string getLinkStatus(int32, int32,
Verbose::Presentation fmt = Verbose::HUMAN);
unsigned int physicalLinkCount(int32 dev, bool count_virtual = false);
ErrorCountType linkErrorCount(int32, int32,
Verbose::Presentation fmt = Verbose::HUMAN);
protected:
K3LAPI & _k3lapi;
};
#endif /* _K3LUTIL_HPP_ */

View File

@ -0,0 +1,644 @@
/*
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 <stdio.h>
#include <sys/time.h>
#include <time.h>
#include <map>
#include <string>
#include <iostream>
#include <tagged_union.hpp>
#include <format.hpp>
#include <refcounter.hpp>
#include <flagger.hpp>
#if defined(COMMONS_LIBRARY_USING_ASTERISK)
extern "C"
{
#include <asterisk/localtime.h>
}
#elif defined(COMMONS_LIBRARY_USING_CALLWEAVER)
extern "C"
{
#include <callweaver/localtime.h>
}
#elif defined(COMMONS_LIBRARY_USING_FREESWITCH)
extern "C"
{
#include <time.h>
}
#endif
/*
********************************************************************************
***************************** 'Logger' user manual *****************************
********************************************************************************
* Description:
This class does the management of log messages for applications. It works with
the following axioms:
<*> There are several class of messages.
<*> There are some outputs, which may be files, sockets, or a console device.
<*> There are options for classes, for outputs and for the association of both.
The last rule also shows the order in which options are processed: first the
'classes' options are processed, then 'output' options are processed, and then
the options for the tuple '(class, output)' are processed.
The options are mapped like this:
<class-of-message> -> options [prefix, flags]
<output-sink> -> options [prefix]
( <class-of-message>, <output-sink> ) -> options [prefix, flags]
- "prefix" means a fixed string prefix before the real message.
- "flags" means auxiliary flags (DATETIME, THREADID) which are
used to add information based on OS or process context info.
* Example of use:
typedef enum
{
C_DBG_FUNC,
C_DBG_LOCK,
C_WARNING,
C_ERROR,
C_CLI,
}
AstClassId;
typedef enum
{
F_CONSOLE,
F_GENERIC,
F_TRACE,
}
AstOutputId;
// used to indicate the console log //
struct AstConsoleLog {};
struct AstPrinter: public Logger::DefaultPrinter
{
typedef Logger::DefaultPrinter Super;
using namespace Tagged;
using Super::operator()(int);
// just 2 type of descriptors //
typedef Union < int, Union < AstConsoleLog > > Container;
ast_printer(std::string & msg): Super(msg) {};
bool operator()(const AstConsoleLog & log)
{
ast_console_puts(_msg.c_str());
return true;
};
#if 0
bool operator()(int log)
{
return Super::operator()(log);
};
#endif
};
bool start_log()
{
typedef Logger::Manager<AstClassId, AstOutputId, AstPrinter, SimpleLock> LogManager;
LogManager logger;
// shortcut definition //
typedef LogManager::Option LogOption;
FILE * log_file = fopen( "output.log", "a");
if (!log_file)
return false;
logger.add( F_CONSOLE, AstConsoleLog(), "chan_khomp: ");
logger.add( F_GENERIC, log_file);
logger.classe( C_WARNING )
& LogOption(F_CONSOLE, "WARNING: ", LogOption::Flags(LogOption::Flag(LogOption::DATETIME)))
& LogOption(F_GENERIC, "W: ", LogOption::Flags(LogOption::Flag(LogOption::DATETIME)))
logger.classe( C_DBG_LOCK ).enabled(false);
logger.classe( C_DBG_LOCK )
& LogOption(F_GENERIC, "L: ", LogOption::Flags
(LogOption::flag_type(LogOption::ENABLED) &
LogOption::flag_type(LogOption::DATETIME))
logger(C_WARNING, "eu sou uma mensagem de warning");
logger.classe(C_WARNING).set(F_GENERIC, LogOption::ENABLED, true);
logger.classe(C_WARNING).set(F_CONSOLE, LogOption::ENABLED, false);
logger.classe(C_CLI).prefix("<K>");
return true;
}
void message_the_user(int fd)
{
logger(C_CLI, fd, "eu sou uma mensagem de cli!");
logger(C_WARNING, "eu sou um warning");
}
********************************************************************************
********************************************************************************
Now, the code..!
*/
#ifndef _LOGGER_HPP_
#define _LOGGER_HPP_
#include <tagged_union.hpp>
struct Logger
{
/*** a base struct for printing messages in many ways ***/
struct DefaultPrinter
{
typedef Tagged::Union < int, Tagged::Union < FILE *, Tagged::Union < std::ostream * > > > BaseType;
typedef bool ReturnType;
DefaultPrinter(std::string & msg): _msg(msg) {};
bool operator()(std::ostream * out)
{
(*out) << _msg;
out->flush();
return out->good();
}
bool operator()(FILE * out)
{
if (fputs(_msg.c_str(), out) < 0)
return false;
if (fflush(out) < 0)
return false;
return true;
}
bool operator()(int out)
{
#ifndef KWIN32
return (write(out, _msg.c_str(), _msg.size()) == (int)_msg.size());
#else
// no need for file descriptors on windows
return false;
#endif
}
std::string & msg() { return _msg; }
protected:
std::string & _msg;
};
/*** manage the printing of messages ***/
template <class ClassId, class OutputId, class Printer, class LockType>
struct Manager
{
typedef typename Printer::BaseType BaseType;
protected:
/* holds a stream, and an optimal message prefix */
struct OutputOptions
{
OutputOptions(BaseType & stream, std::string & prefix)
: _stream(stream), _prefix(prefix) {};
BaseType _stream;
std::string _prefix;
LockType _lock;
};
typedef std::map < OutputId, OutputOptions > OutputMap;
public:
/* print in a specific 'message class' */
struct ClassType
{
ClassType(void)
: _enabled(true)
{};
// ClassType(ClassType & o)
// : _stream_map(o._stream_map), _prefix(o.prefix),
// _lock(o._lock),_enabled(o._enabled)
// {};
/* initializes the options of the (class, stream) pair */
struct Option
{
typedef enum { ENABLED, DATETIME, THREADID, DATETIMEMS } EnumType;
typedef Flagger< EnumType > Flags;
typedef typename Flags::InitFlags InitFlags;
Option(OutputId output, const char * prefix,
Flags flags = InitFlags(ENABLED))
: _output(output), _prefix(prefix), _flags(flags) {};
Option(OutputId output, std::string prefix,
Flags flags = InitFlags(ENABLED))
: _output(output), _prefix(prefix), _flags(flags) {};
Option(OutputId output,
Flags flags = InitFlags(ENABLED))
: _output(output), _flags(flags) {};
OutputId _output;
std::string _prefix;
Flags _flags;
};
protected:
/* holds a prefix and a activation status */
struct OptionContainer
{
OptionContainer(std::string prefix, typename Option::Flags flags)
: _prefix(prefix), _flags(flags) {};
std::string _prefix;
typename Option::Flags _flags;
};
typedef std::multimap < OutputId, OptionContainer > OptionMap;
/* utility function for printing */
bool print(std::string & msg, BaseType & stream, LockType & lock)
{
lock.lock();
Printer p(msg);
bool ret = stream.visit(p);
lock.unlock();
return ret;
};
/*
bool print(std::string & msg, BaseType & stream, LockType & lock)
{
lock.lock();
Printer p(msg);
bool ret = stream.visit(p);
lock.unlock();
return ret;
};
*/
public:
ClassType & operator&(const Option & value)
{
add(value._output, value._prefix, value._flags);
return *this;
}
void add(OutputId output_id, std::string prefix,
typename Option::Flags flags)
{
typedef std::pair < OutputId, OptionContainer > pair_type;
_stream_map.insert(pair_type(output_id, OptionContainer(prefix, flags)));
}
/* get and set methods for active mode */
void set(OutputId id, typename Option::EnumType flag, bool value = true)
{
typename OptionMap::iterator iter = _stream_map.find(id);
if (iter == _stream_map.end())
return;
(*iter).second._flags.set(flag, value);
}
bool get(OutputId idx, typename Option::EnumType flag)
{
typename OptionMap::iterator iter = _stream_map.find(idx);
if (iter == _stream_map.end())
return false;
return (*iter).second._flags.is_set(flag);
}
/* get/adjust the enable/disable value for the class */
void enabled(bool enabled) { _enabled = enabled; };
bool enabled() { return _enabled; };
/* get/adjust the classe prefix */
void prefix(const char * prefix) { _prefix = prefix; }
void prefix(std::string & prefix) { _prefix = prefix; }
std::string & prefix() { return _prefix; }
/* printing function (operator, actually) */
bool operator()(OutputMap & out_map, std::string & msg)
{
if (!_enabled)
return true;
typedef typename OptionMap::iterator Iter;
bool ret = true;
for (Iter iter = _stream_map.begin(); iter != _stream_map.end(); iter++)
{
OptionContainer & opt = (*iter).second;
if (!opt._flags[Option::ENABLED])
continue;
typename OutputMap::iterator out_iter = out_map.find((*iter).first);
/* this stream have been added already? if not, skip! */
if (out_iter == out_map.end())
continue;
/* final message */
std::string out_msg;
if (opt._flags[Option::DATETIME])
{
#if defined(COMMONS_LIBRARY_USING_ASTERISK)
#if ASTERISK_AT_LEAST(1,6,0)
struct timeval tv;
struct ast_tm lt;
gettimeofday(&tv, NULL);
#else
time_t tv;
struct tm lt;
time (&tv);
#endif
#if ASTERISK_AT_LEAST(1,4,5)
ast_localtime (&tv, &lt, NULL);
#else
localtime_r (&tv, &lt);
#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)
time_t tv;
struct tm lt;
time (&tv);
localtime_r (&tv, &lt);
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, &lt);
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
}
if (opt._flags[Option::DATETIMEMS])
{
#if defined(COMMONS_LIBRARY_USING_ASTERISK)
#if ASTERISK_AT_LEAST(1,6,0)
struct timeval tv;
struct ast_tm lt;
gettimeofday(&tv, NULL);
#else
time_t tv;
struct tm lt;
time (&tv);
#endif
#if ASTERISK_AT_LEAST(1,4,5)
ast_localtime (&tv, &lt, NULL);
#else
localtime_r (&tv, &lt);
#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
% 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
% lt.tm_sec % (tv * 1000));
#endif
#elif defined(COMMONS_LIBRARY_USING_CALLWEAVER)
time_t tv;
struct tm lt;
time (&tv);
localtime_r (&tv, &lt);
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));
#elif defined(COMMONS_LIBRARY_USING_FREESWITCH)
time_t tv;
struct tm lt;
time (&tv);
localtime_r (&tv, &lt);
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
}
OutputOptions & out_opt = (*out_iter).second;
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()));
#endif
}
out_msg += _prefix;
out_msg += out_opt._prefix;
out_msg += opt._prefix;
out_msg += msg;
out_msg += "\n";
ret |= print(out_msg, out_opt._stream, out_opt._lock);
}
return ret;
}
bool operator()(BaseType & stream, std::string & msg)
{
std::string final_msg;
final_msg += _prefix;
final_msg += msg;
final_msg += "\n";
return print(final_msg, stream, _lock);
}
protected:
OptionMap _stream_map;
std::string _prefix;
LockType _lock;
bool _enabled;
};
/* util declaration */
typedef typename ClassType::Option Option;
/* class_id_type -> ClassType mapper */
typedef std::map < ClassId, ClassType > ClassMap;
/* local option pair */
typedef std::pair < OutputId, OutputOptions > OutputOptionPair;
void add(OutputId output, BaseType stream, const char * prefix = "")
{
std::string str_prefix(prefix);
_output_map.insert(OutputOptionPair(output, OutputOptions(stream, str_prefix)));
}
void add(OutputId output, BaseType stream, std::string prefix)
{
_output_map.insert(OutputOptionPair(output, OutputOptions(stream, prefix)));
}
ClassType & classe(ClassId classeid)
{
return _classe_map[classeid];
}
bool operator()(ClassId classeid, const char * msg)
{
std::string str_msg(msg);
return _classe_map[classeid](_output_map, str_msg);
}
bool operator()(ClassId classeid, std::string & msg)
{
return _classe_map[classeid](_output_map, msg);
}
bool operator()(ClassId classeid, Format fmt)
{
std::string str_fmt = STG(fmt);
return _classe_map[classeid](_output_map, str_fmt);
}
bool operator()(ClassId classeid, BaseType stream, const char * msg)
{
std::string str_msg(msg);
return _classe_map[classeid](stream, str_msg);
}
bool operator()(ClassId classeid, BaseType stream, std::string & msg)
{
return _classe_map[classeid](stream, msg);
}
bool operator()(ClassId classeid, BaseType stream, Format fmt)
{
std::string str_fmt = STG(fmt);
return _classe_map[classeid](stream, str_fmt);
}
protected:
ClassMap _classe_map;
OutputMap _output_map;
};
private:
Logger();
};
#endif /* _LOGGER_HPP_ */

View File

@ -0,0 +1,54 @@
/*
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 _NONCOPYABLE_HPP_
#define _NONCOPYABLE_HPP_
struct NonCopyable
{
NonCopyable() {};
private:
NonCopyable(NonCopyable const &) { };
NonCopyable & operator=(NonCopyable const &) { return *this; };
};
#endif /* _NONCOPYABLE_HPP_ */

View File

@ -0,0 +1,263 @@
/*
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
*/
/* This struct uses static polymorphism, and derived classes should implement *
* the "unreference()" method, which should release all resources when called */
#ifndef _REFCOUNTER_HPP_
#define _REFCOUNTER_HPP_
#define NEW_REFCOUNTER(...) public ReferenceCounter< __VA_ARGS__ >
#define INC_REFCOUNTER(o, ...) ReferenceCounter< __VA_ARGS__ >(static_cast< const ReferenceCounter < __VA_ARGS__ > & >(o))
#include <stdlib.h>
#include <noncopyable.hpp>
#include <atomic.hpp>
#ifdef DEBUG
# include <iostream>
#endif
struct ReferenceData: public NonCopyable
{
ReferenceData()
: _data_count(1)
{};
inline unsigned int increment(void)
{
if (!_data_count)
abort();
Atomic::doAdd(&_data_count);
return _data_count;
}
inline unsigned int decrement(void)
{
if (!_data_count)
abort();
Atomic::doSub(&_data_count);
return _data_count;
}
volatile unsigned int _data_count;
};
template < typename T >
struct ReferenceCounter
{
typedef T Type;
ReferenceCounter(bool create_counter = true)
: _reference_count(0)
{
reference_restart(create_counter);
#ifdef DEBUG
std::cerr << ((void*)this) << ": ReferenceCounter() [ref_count="
<< (_reference_count ? (*_reference_count) : -1) << "]" << std::endl;
#endif
};
ReferenceCounter(const ReferenceCounter & o)
: _reference_count(0)
{
reference_reflect(o);
#ifdef DEBUG
std::cerr << ((void*)this) << ": ReferenceCounter(" << ((void*)(&o)) << ") [ref_count="
<< (_reference_count ? (*_reference_count) : -1) << "]" << std::endl;
#endif
};
virtual ~ReferenceCounter()
{
#ifdef DEBUG
std::cerr << ((void*)this) << ": ~ReferenceCounter() [ref_count="
<< (_reference_count ? (*_reference_count) : -1) << "]" << std::endl;
#endif
reference_disconnect(_reference_count);
}
ReferenceCounter & operator=(const ReferenceCounter & o)
{
reference_reflect(o);
#ifdef DEBUG
std::cerr << ((void*)this) << ": ReferenceCounter::operator=(" << ((void*)(&o)) << ") [ref_count="
<< (_reference_count ? (*_reference_count) : -1) << "]" << std::endl;
#endif
return *this;
};
protected:
inline void reference_restart(bool create_counter = false)
{
ReferenceData * oldref = _reference_count;
_reference_count = (create_counter ? new ReferenceData() : 0);
if (oldref) reference_disconnect(oldref);
}
inline void reference_reflect(const ReferenceCounter & other)
{
ReferenceData * newref = other._reference_count;
ReferenceData * oldref = _reference_count;
/* NOTE: increment before, avoid our reference being zero, even *
* for a short period of time. */
if (newref) newref->increment();
_reference_count = newref;
if (oldref) reference_disconnect(oldref);
};
inline void reference_disconnect(ReferenceData *& counter)
{
if (counter)
{
unsigned int result = counter->decrement();
if (!result)
{
static_cast< Type * >(this)->unreference();
delete counter;
}
counter = 0;
}
};
private:
ReferenceData * _reference_count;
};
template < typename T >
struct ReferenceContainer: NEW_REFCOUNTER(ReferenceContainer< T >)
{
/* type */
typedef T Type;
/* shorthand */
typedef ReferenceCounter < ReferenceContainer< Type > > Counter;
// TODO: make this a generic exception someday
struct NotFound {};
ReferenceContainer()
: Counter(false),
_reference_value(0)
{};
ReferenceContainer(Type * value)
: _reference_value(value)
{};
ReferenceContainer(const ReferenceContainer & value)
: Counter(false),
_reference_value(0)
{
operator()(value);
};
virtual ~ReferenceContainer()
{};
ReferenceContainer operator=(const ReferenceContainer & value)
{
operator()(value);
return *this;
};
/**/
void unreference()
{
if (_reference_value)
{
delete _reference_value;
_reference_value = 0;
}
}
// simulates a copy constructor
void operator()(const ReferenceContainer & value)
{
Counter::reference_reflect(value);
_reference_value = const_cast<Type *>(value._reference_value);
};
// shortcut for operator below
void operator=(const Type * value)
{
operator()(value);
};
// accept value (pointer)!
void operator()(const Type * value)
{
Counter::reference_restart((value != 0));
_reference_value = const_cast<Type *>(value);
};
// return value (pointer)!
Type * operator()(void)
{
return _reference_value;
};
protected:
Type * _reference_value;
protected:
};
#endif /* _REFCOUNTER_HPP_ */

View File

@ -0,0 +1,148 @@
/*
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 <regex.hpp>
#include <string.h>
void Regex::Expression::initialize(void)
{
unsigned int tmplen = strlen(_expression);
bool extflag = (_flags & E_EXTENDED);
for (unsigned int i = 0; i < tmplen; ++i)
{
switch (_expression[i])
{
case '\\':
++i;
if (!extflag && i < tmplen)
if (_expression[i] == '(')
++_subcounter;
break;
case '(':
if (extflag)
++_subcounter;
default:
break;
}
}
_errorstate = regcomp(&_comp_regex, _expression, _flags);
}
std::string Regex::Expression::regerror_as_string(void)
{
unsigned int count = regerror(_errorstate, &_comp_regex, 0, 0) + 1;
char * msg = new char[count];
regerror(_errorstate, &_comp_regex, msg, count);
std::string tmp(msg, count);
delete[] msg;
return tmp;
}
void Regex::Match::initialize(void)
{
if (_expression.valid())
{
_subcounter = (_expression.subcount() + 2); // 0 + N.. + invalid
_submatches = new regmatch_t[_subcounter];
_have_match = (regexec(_expression.repr(), _basestring.c_str(),
_subcounter, _submatches, _flags) == 0);
}
}
std::string Regex::Match::replace(std::string rep, unsigned int index)
{
ReplaceMap tmp;
tmp.insert(ReplacePair(index,rep));
return replace(tmp);
}
std::string Regex::Match::replace(Regex::ReplaceMap & map)
{
if (!_have_match)
return _basestring;
std::string buffer = _basestring;
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);
for (unsigned int n = 1; (_submatches[n].rm_so != -1) && (n < _subcounter); n++)
{
//// s f RRR s f RRR s f RRRR s f
//// XXXYYY(ZZZ)AAA(BBB)CCCEEE(FFFF)GGGG
bool globalsubs = false;
if (map.find(n) == map.end())
{
if (map.find(UINT_MAX) == map.end())
continue;
globalsubs = true;
}
buffer = buffer.replace(_submatches[n].rm_so,
_submatches[n].rm_eo - _submatches[n].rm_so,
map.find((globalsubs ? UINT_MAX : n))->second);
}
}
catch (std::out_of_range e)
{
return "";
}
return buffer;
}

View File

@ -0,0 +1,252 @@
/*
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 <sys/types.h>
#include <limits.h>
#include <stdarg.h>
#include <string.h>
#include <regex.h>
#include <iostream>
#include <string>
#include <stdexcept>
#include <map>
#include <refcounter.hpp>
#include <noncopyable.hpp>
#ifndef _REGEX_HPP_
#define _REGEX_HPP_
struct Regex
{
enum
{
E_EXTENDED = REG_EXTENDED,
E_IGNORE_CASE = REG_ICASE,
E_NO_SUB_MATCH = REG_NOSUB,
E_EXPLICIT_NEWLINE = REG_NEWLINE,
};
enum
{
M_NO_BEGIN_OF_LINE = REG_NOTBOL,
M_NO_END_OF_LINE = REG_NOTEOL,
};
enum
{
/* mark replace for full match (submatch "0"). */
REP_BASE = 0u,
/* mark global string for replace. */
REP_ALL = UINT_MAX,
};
typedef std::pair < unsigned int, std::string > ReplacePair;
typedef std::map < unsigned int, std::string > ReplaceMap;
struct Expression : public NonCopyable
{
Expression(const char * expression, unsigned int flags = 0)
: _expression(expression), _alloced(false),
_subcounter(0), _errorstate(INT_MAX), _flags(flags)
{
initialize();
}
Expression(std::string & expression, unsigned int flags = 0)
: _expression(strdup(expression.c_str())), _alloced(true),
_subcounter(0), _errorstate(INT_MAX), _flags(flags)
{
initialize();
}
~Expression()
{
if (_errorstate != INT_MAX)
regfree(&_comp_regex);
if (_alloced)
{
delete _expression;
_expression = 0;
}
}
bool valid(void) { return (_errorstate == 0); }
unsigned int subcount(void) { return _subcounter; }
const regex_t * repr(void) { return &_comp_regex; }
std::string error(void)
{
switch (_errorstate)
{
case 0: return "";
case INT_MAX: return "uninitialized";
default: return regerror_as_string();
}
}
private:
void initialize(void);
std::string regerror_as_string(void);
protected:
const char * _expression;
bool _alloced;
unsigned int _subcounter;
int _errorstate;
regex_t _comp_regex;
unsigned int _flags;
};
struct Match: NEW_REFCOUNTER(Match)
{
Match(const char * basestring, 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)
: _basestring(basestring), _expression(expression), _subcounter(0), _submatches(0),
_have_match(false), _flags(flags)
{
initialize();
}
Match(const Match & o)
: INC_REFCOUNTER(o, Match),
_basestring(o._basestring), _expression(o._expression),
_subcounter(o._subcounter), _submatches(o._submatches),
_have_match(o._have_match), _flags(o._flags)
{
}
void unreference()
{
delete[] _submatches;
}
bool matched(void)
{
return _have_match;
}
bool matched(unsigned int number)
{
if (_have_match && number < _subcounter)
return (_submatches[number].rm_so != -1);
return false;
}
std::string submatch(int number)
{
if (!matched(number))
return "";
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<int,std::string> 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<int, std::string> obtain_match_map()
{
int match_counter = 0;
std::map<int,std::string> tmp_map;
while(matched(match_counter))
{
tmp_map.insert(std::make_pair(match_counter,submatch(match_counter)));
match_counter++;
}
return tmp_map;
}
/**
* \brief replaces strings matched by parentesis
* \param each item of the vector is a parentesis replaced
* \return string replaced
* \note The overload method match only one string in parentesis.
* \author Eduardo Nunes Pereira
*
* If fails the empty string is returned.
*/
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;
unsigned int _subcounter;
regmatch_t * _submatches;
bool _have_match;
unsigned int _flags;
};
};
#endif /* _REGEX_HPP_ */

View File

@ -0,0 +1,575 @@
/*
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 <ringbuffer.hpp>
/********** 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;
}

View File

@ -0,0 +1,416 @@
/*
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
*/
/* WARNING: This is a generic ringbuffer abstraction, which works for single-sized elements,
partial elements, single/multi-elements read/writes. It is not wise to mix some
functions (partial element write / full element write), since it was not designed
with this use in mind.
Also, it works only for single-reader + single-writer, since it does not depends
on external mutex functions.
*/
#include <string.h>
#include <cmath>
#include <iostream>
#include <noncopyable.hpp>
#include <atomic.hpp>
#ifndef _RINGBUFFER_HPP_
#define _RINGBUFFER_HPP_
struct Buffer_pointer
{
Buffer_pointer(unsigned int _complete = 0u, unsigned short _partial = 0u)
: complete(_complete), partial(_partial)
{};
Buffer_pointer(const Buffer_pointer & o)
: complete(o.complete), partial(o.partial)
{};
Buffer_pointer(const volatile Buffer_pointer & o)
: complete(o.complete), partial(o.partial)
{};
void operator=(const volatile Buffer_pointer o)
{
complete = o.complete;
partial = o.partial;
}
void operator=(const Buffer_pointer o) volatile
{
complete = o.complete;
partial = o.partial;
}
bool operator==(const Buffer_pointer & o)
{
return (complete == o.complete && partial == o.partial);
}
unsigned int complete:20;
unsigned short partial:12;
}
__attribute__((packed));
struct Buffer_table
{
Buffer_table()
: reader(0,0),
writer(1,1)
{};
Buffer_table(const Buffer_table & o)
: reader(o.reader), writer(o.writer)
{};
Buffer_table(const volatile Buffer_table & o)
: reader(o.reader), writer(o.writer)
{};
void operator=(const volatile Buffer_table o)
{
reader = o.reader;
writer = o.writer;
}
void operator=(const Buffer_table o) volatile
{
reader = o.reader;
writer = o.writer;
}
bool operator==(const Buffer_table & o)
{
return (reader == o.reader && writer == o.writer);
}
Buffer_pointer reader;
Buffer_pointer writer;
}
__attribute__((packed));
struct Ringbuffer_traits
{
Ringbuffer_traits(unsigned int block, unsigned int size)
: _block(block), _size(size)
{};
bool traits_provide( char *, const char *, unsigned int, bool);
unsigned int traits_consume(const char *, char *, unsigned int, bool);
unsigned int traits_consume_begins(const char *, char *, unsigned int, bool);
bool traits_consume_commit(unsigned int);
bool traits_provide_partial( char *, const char *, unsigned int);
unsigned int traits_consume_partial(const char *, char *, unsigned int);
unsigned int traits_get( char *, std::istream &, unsigned int);
unsigned int traits_put(const char *, std::ostream &, unsigned int);
bool update(Buffer_pointer & cache, Buffer_pointer & update)
{
return Atomic::doCAS(&(_pointers.reader), &cache, update);
}
protected:
const unsigned int _block;
const unsigned int _size;
volatile Buffer_table _pointers;
};
template <typename T>
struct Ringbuffer: protected Ringbuffer_traits, public NonCopyable
{
struct BufferFull {};
struct BufferEmpty {};
Ringbuffer(unsigned int size)
: Ringbuffer_traits(sizeof(T), size)
{
_buffer = new T[_size];
_malloc = true;
};
Ringbuffer(unsigned int size, T * buffer)
: Ringbuffer_traits(sizeof(T), size)
{
_buffer = buffer;
_malloc = false;
};
~Ringbuffer()
{
if (_malloc)
delete[] _buffer;
}
/***** GENERIC RANGE/INDEX CALCULATION FUNCTIONS *****/
bool may_write(Buffer_table & cache)
{
const unsigned int r = cache.reader.complete;
const unsigned int w = cache.writer.complete;
return (((r - w) != 1) && (!(r == 0 && w == _size)));
}
bool may_read(Buffer_table & cache)
{
if ((cache.writer.complete - cache.reader.complete) == 1)
return false;
return true;
}
unsigned int writer_next(Buffer_pointer & cache, Buffer_pointer & index)
{
unsigned int dest = cache.complete - 1,
temp = cache.complete + 1;
if (temp > _size) index.complete = 1;
else index.complete = temp;
index.partial = 1;
return dest;
};
void reader_next(Buffer_pointer & cache, Buffer_pointer & index)
{
unsigned int temp = cache.complete + 1;
if (temp == _size) index.complete = 0;
else index.complete = temp;
index.partial = 0;
}
/***** BUFFER FUNCTIONS *****/
bool provide(const T & value)
{
Buffer_table cache = _pointers;
Buffer_pointer index = _pointers.writer;
if (!may_write(cache))
return false;
// fprintf(stderr, "%p> provide %d/%d!\n", this, reader, writer);
unsigned int dest = writer_next(cache.writer, index);
_buffer[dest] = value;
_pointers.writer = index;
// fprintf(stderr, "%p> write: %d/%d [%d/%d]\n", this, _pointers.reader, _pointers.writer, _pointers.reader_partial, _pointers.writer_partial);
return true;
}
bool consume(T & value)
{
Buffer_table cache = _pointers;
Buffer_pointer index = _pointers.reader;
if (!may_read(cache))
return false;
// fprintf(stderr, "%p> consume %d/%d!\n", this, reader, writer);
value = _buffer[index.complete];
do
{
reader_next(cache.reader, index);
if (update(cache.reader, index))
break;
cache.reader = index;
}
while (true);
// fprintf(stderr, "%p> read: %d/%d [%d/%d]\n", this, _pointers.reader, _pointers.writer, _pointers.reader_partial, _pointers.writer_partial);
return true;
}
/* writes everything or nothing */
inline bool provide(const T * value, unsigned int amount, bool skip_overwrite = true)
{
return traits_provide((char *)_buffer, (const char *) value, amount, skip_overwrite);
}
/* returns the number of items that have been read (atomic_mode == true means 'all or nothing') */
inline unsigned int consume(T * value, unsigned int amount, bool atomic_mode = false)
{
return traits_consume((const char *)_buffer, (char *) value, amount, atomic_mode);
}
/***** TWO-PHASE BUFFER FUNCTIONS *****/
/* returns the number of items that have been read (atomic_mode == true means 'all or nothing') */
inline unsigned int consume_begins(T * value, unsigned int amount, bool atomic_mode = false)
{
return traits_consume_begins((const char *)_buffer, (char *) value, amount, atomic_mode);
}
/* returns true if we could commit that much of buffer (use only after consume_begins). *
* note: you may commit less bytes that have been read to keep some data inside the buffer */
inline bool consume_commit(unsigned int amount)
{
return traits_consume_commit(amount);
}
/***** TWO-PHASE SINGLE-ELEMENT BUFFER FUNCTIONS *****/
T & provider_start(void)
{
Buffer_table cache = _pointers;
if (!may_write(cache))
throw BufferFull();
unsigned writer = _pointers.writer.complete - 1;
// fprintf(stderr, "%p> provider start %d/%d!\n", this, reader, writer);
return _buffer[writer];
}
void provider_commit(void)
{
unsigned int temp = _pointers.writer.complete + 1;
// fprintf(stderr, "%p> provider commit %d!\n", this, temp);
if (temp > _size)
temp = 1;
_pointers.writer.complete = temp;
_pointers.writer.partial = 1;
// fprintf(stderr, "%p> write: %d/%d [%d/%d]\n", this, _pointers.reader, _pointers.writer, _pointers.reader_partial, _pointers.writer_partial);
}
T & consumer_start(void)
{
Buffer_table cache = _pointers;
if (!may_read(cache))
throw BufferEmpty();
unsigned int reader = _pointers.reader.complete;
// fprintf(stderr, "%p> consumer start %d/%d!\n", this, reader, writer);
return _buffer[reader];
}
void consumer_commit(void)
{
Buffer_pointer cache = _pointers.reader;
Buffer_pointer index(cache);
do
{
reader_next(cache, index);
if (update(cache, index))
break;
cache = index;
}
while (true);
// fprintf(stderr, "%p> consumer commit %d!\n", this, temp);
// fprintf(stderr, "%p> read: %d/%d [%d/%d]\n", this, _pointers.reader, _pointers.writer, _pointers.reader_partial, _pointers.writer_partial);
}
/* writes everything or nothing, but works on bytes (may write incomplete elements) */
/* WARNING: do not mix this with full element provider */
inline bool provider_partial(const char *buffer, unsigned int amount)
{
return traits_provide_partial((char *)_buffer, buffer, amount);
}
/* returns the number of bytes that have been read (may read incomplete elements) */
/* WARNING: do not mix this with full element consumer */
inline unsigned int consumer_partial(char *buffer, unsigned int amount)
{
return traits_consume_partial((const char *)_buffer, buffer, amount);
}
/***** IO FUNCTIONS *****/
/* 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);
}
/* 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);
}
void clear()
{
_pointers.reader.complete = 0;
_pointers.reader.partial = 0;
_pointers.writer.complete = 1;
_pointers.writer.partial = 1;
}
protected:
T * _buffer;
bool _malloc;
};
#endif /* _RINGBUFFER_HPP_ */

View File

@ -0,0 +1,46 @@
/*
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 <config_commons.hpp>
#include COMMONS_INCLUDE(saved_condition.cpp)

View File

@ -0,0 +1,61 @@
/*
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 _SAVED_CONDITION_COMMON_HPP_
#define _SAVED_CONDITION_COMMON_HPP_
#include <config_commons.hpp>
//#include <refcounter.hpp>
struct SavedConditionCommon
{
SavedConditionCommon() : _signaled(false) {}
protected:
bool _signaled;
};
#include COMMONS_INCLUDE(saved_condition.hpp)
#endif /* _SAVED_CONDITION_COMMON_HPP_ */

View File

@ -0,0 +1,95 @@
/*
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 <simple_lock.hpp>
struct ScopedLockBasic
{
ScopedLockBasic(void)
: _locked(true) {};
ScopedLockBasic(bool locked)
: _locked(locked) {};
virtual ~ScopedLockBasic() {};
protected:
bool _locked;
};
struct ScopedLock : public ScopedLockBasic
{
struct LockFailed {};
ScopedLock(SimpleLock & mutex)
: ScopedLockBasic(false), _mutex(mutex)
{
switch (_mutex.lock())
{
case SimpleLock::ISINUSE:
case SimpleLock::FAILURE:
throw LockFailed();
default:
break;
}
_locked = true;
}
~ScopedLock()
{
unlock();
}
void unlock()
{
if (_locked)
{
_locked = false;
_mutex.unlock();
}
}
protected:
SimpleLock & _mutex;
};

View File

@ -0,0 +1,104 @@
/*
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 _SIMPLE_LOCK_COMMON_HPP_
#define _SIMPLE_LOCK_COMMON_HPP_
#include <config_commons.hpp>
#include <unistd.h>
#include <noncopyable.hpp>
#include <refcounter.hpp>
/* This struct uses static polymorphism, and derived classes should implement *
* the "lock/trylock/unlock()" methods for correct code compilation. *
* The base class also features reference counting, so derived classes should *
* implement the "unreference()" method for releasing resources. */
template < typename Implementor >
struct SimpleLockCommon: NEW_REFCOUNTER( SimpleLockCommon < Implementor > )
{
friend class ReferenceCounter < SimpleLockCommon < Implementor > >;
typedef enum
{
ISINUSE = 0, // operation not succeded (no error)
SUCCESS = 1, // operation succeded (no error)
FAILURE = 2, // mutex or state is somehow invalid (error! run for your life!)
}
Result;
SimpleLockCommon()
{};
SimpleLockCommon(const SimpleLockCommon & o)
: INC_REFCOUNTER(o, SimpleLockCommon)
{};
virtual ~SimpleLockCommon()
{};
inline Result lock()
{
return static_cast<Implementor*>(this)->lock();
}
inline Result trylock()
{
return static_cast<Implementor*>(this)->trylock();
}
inline void unlock()
{
static_cast<Implementor*>(this)->unlock();
}
protected:
void unreference(void)
{
static_cast<Implementor*>(this)->unreference();
}
};
#include COMMONS_INCLUDE(simple_lock.hpp)
#endif /* _SIMPLE_LOCK_COMMON_HPP_ */

View File

@ -0,0 +1,247 @@
/*
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 <strings.hpp>
void Strings::Merger::add(std::string s)
{
_list.push_back(s);
};
std::string Strings::Merger::merge(const std::string & sep)
{
list_type::iterator i = _list.begin();
std::string res;
if (i != _list.end())
{
res += (*i);
++i;
};
while (i != _list.end())
{
res += sep;
res += (*i);
++i;
}
return res;
};
std::string Strings::Merger::merge(const char *sep)
{
std::string ssep(sep);
return merge(ssep);
}
unsigned int Strings::tokenize(const std::string & str, Strings::vector_type & tokens,
const std::string & delims, long int max_tokens, bool keep_empty)
{
std::string::size_type base = 0;
std::string::size_type init = str.find_first_not_of(delims, 0);
std::string::size_type fini = str.find_first_of(delims, init);
long int cur_token = 1;
while (std::string::npos != init)
{
if (keep_empty && base < init)
{
std::string::size_type cur_empty = init - base;
while (cur_empty && cur_token < max_tokens)
{
tokens.push_back("");
++cur_token;
--cur_empty;
}
}
if (std::string::npos != fini && cur_token < max_tokens)
{
base = fini + 1;
tokens.push_back(str.substr(init, fini - init));
++cur_token;
}
else
{
base = str.size(); // find_first_of(delims, init);
tokens.push_back(str.substr(init, str.size() - init));
break;
}
init = str.find_first_not_of(delims, fini);
fini = str.find_first_of(delims, init);
}
if (keep_empty && base != str.size())
{
std::string::size_type cur_empty = str.size() - base + 1;
while (cur_empty && cur_token < max_tokens)
{
tokens.push_back("");
++cur_token;
--cur_empty;
}
if (cur_empty)
{
std::string::size_type pos = base + cur_empty - 1;
tokens.push_back(str.substr(pos, str.size() - pos));
++cur_token;
}
}
return (cur_token - 1);
}
bool Strings::toboolean(std::string str)
{
std::string tmp(str);
Strings::lower(tmp);
if ((tmp == "true") || (tmp == "yes")) return true;
if ((tmp == "false") || (tmp == "no")) return false;
throw invalid_value(str);
}
long Strings::tolong(std::string str, int base)
{
char *str_end = 0;
unsigned long value = strtol(str.c_str(), &str_end, base);
if (str_end && *str_end == 0)
return value;
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)
{
#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);
if (str_end && *str_end == 0)
return value;
throw invalid_value(str);
#endif
}
double Strings::todouble(std::string str)
{
char *str_end = 0;
double value = strtod(str.c_str(), &str_end);
if (str_end && *str_end == 0)
return value;
throw invalid_value(str);
}
std::string Strings::fromboolean(bool value)
{
if (value) return "true";
else return "false";
}
std::string Strings::lower(std::string str)
{
std::string res;
for (std::string::iterator i = str.begin(); i != str.end(); i++)
res += tolower((*i));
return res;
}
std::string Strings::hexadecimal(std::string value)
{
std::string result;
for (std::string::iterator i = value.begin(); i != value.end(); i++)
{
if (i != value.begin())
result += " ";
result += STG(FMT("%2x") % (unsigned int)(*i));
}
return result;
}
std::string Strings::trim(const std::string& str, const std::string& trim_chars)
{
std::string result(str);
result.erase( result.find_last_not_of( trim_chars ) + 1 );
result.erase( 0, result.find_first_not_of( trim_chars ) );
return result;
}

View File

@ -0,0 +1,106 @@
/*
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 <limits.h>
#include <list>
#include <vector>
#include <string>
#include <types.hpp>
#include <format.hpp>
/* Generic string funcions */
#ifndef _STRINGS_HPP_
#define _STRINGS_HPP_
struct Strings
{
typedef std::list<std::string> list_type;
typedef std::vector<std::string> vector_type;
struct Merger
{
void add(std::string);
std::string merge(const std::string &);
std::string merge(const char *);
bool empty() { return _list.empty(); };
protected:
list_type _list;
};
public:
struct invalid_value
{
invalid_value(const char * value): _value(value) {};
invalid_value(std::string value): _value(value) {};
std::string & value() { return _value; }
protected:
std::string _value;
};
struct not_implemented {};
static unsigned int tokenize(const std::string &, vector_type &, const std::string & delims = ",;:",
long int max_toxens = LONG_MAX, bool keep_empty = true);
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 std::string lower(std::string);
static std::string hexadecimal(std::string);
static std::string trim(const std::string&, const std::string& trim_chars = " \f\n\r\t\v");
};
#endif // _STRINGS_HPP_ //

View File

@ -0,0 +1,307 @@
/*
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 _TAGGED_UNION_HPP_
#define _TAGGED_UNION_HPP_
#include <stdexcept>
#include <iostream>
#include <unistd.h>
namespace Tagged
{
struct EmptyUnion
{
friend class Value;
EmptyUnion()
: _adjusted(false) {};
// copy constructor
EmptyUnion(const EmptyUnion & o)
: _adjusted(o._adjusted) {};
// copy assignment operator
EmptyUnion & operator=(const EmptyUnion & o)
{
_adjusted = o._adjusted;
return *this;
};
~EmptyUnion() { _adjusted = false; };
bool operator==(const EmptyUnion & o)
{
return true;
};
public:
void clear(void) { _adjusted = false; };
protected:
void setup(void) { _adjusted = true; };
protected:
bool value_set(void) { return false; };
bool value_get(void) { return false; };
bool value_check(void) { return false; };
template < typename S >
bool value_visit(S & visitor, typename S::ReturnType & ret)
{
return false;
};
template < typename S >
bool value_visit_void(S & visitor)
{
return false;
};
bool adjusted() { return _adjusted; };
private:
bool _adjusted;
};
template < typename V, typename E = EmptyUnion >
struct Union: public E
{
friend class Value;
// default constructor
Union()
: _value(0) {};
// constructor with initializer
template < typename U >
Union( U value )
: _value(0)
{
set(value);
};
// copy constructor
Union(const Union & o)
: E(static_cast<const E&>(o)),
_value( (o._value ? new const V(*(o._value)) : 0) )
{};
// copy assignment operator
Union & operator=(const Union & o)
{
if (_value)
{
delete _value;
_value = 0;
}
if (o._value)
{
_value = new const V(*(o._value));
}
E::operator=(static_cast<const E&>(o));
return *this;
};
// destructor
~Union()
{
if (_value)
{
delete _value;
_value = 0;
}
};
// equal sign operator
template < typename U >
void operator=(U value)
{
set(value);
}
template < typename U >
bool check(void)
{
return value_check(static_cast<const U * const>(0));
};
template < typename U >
const U & get(void)
{
const U * res = 0;
if (!value_get(&res) || !res)
throw std::runtime_error("type mismatch");
return *res;
};
template < typename U >
void set(U val)
{
if (E::adjusted())
clear();
if (!value_set(val))
throw std::runtime_error("unable to set value of invalid type");
};
template < typename S >
typename S::ReturnType visit(S visitor)
{
typename S::ReturnType ret;
if (!value_visit(visitor, ret))
throw std::runtime_error("unable to visit empty value");
return ret;
};
template < typename S >
void visit_void(S visitor)
{
if (!value_visit_void(visitor))
throw std::runtime_error("unable to visit empty value");
};
void clear()
{
if (_value)
{
delete _value;
_value = 0;
}
E::clear();
};
// compare (equal) operator
bool operator==(const Union & o)
{
bool are_equal = false;
if (!_value && !(o._value))
are_equal = true;
if (_value && o._value)
are_equal = (*_value == *(o._value));
if (are_equal)
return E::operator==(static_cast<const E&>(o));
return false;
};
// compare types
bool sameType(const Union & o)
{
if ((!(_value) && !(o._value)) || (_value && o._value))
return E::operator==(static_cast<const E&>(o));
return false;
};
protected:
using E::value_set;
using E::value_get;
using E::value_check;
using E::value_visit;
using E::value_visit_void;
bool value_set(V val)
{
_value = new const V(val);
E::setup();
return true;
};
bool value_get(const V ** val)
{
if (!_value)
return false;
*val = _value;
return true;
}
bool value_check(const V * const junk)
{
(void)junk;
return (_value != 0);
};
template < typename S >
bool value_visit(S & visitor, typename S::ReturnType & ret)
{
if (_value)
{
ret = visitor(*const_cast<V*>(_value));
return true;
};
return E::value_visit(visitor, ret);
};
template < typename S >
bool value_visit_void(S & visitor)
{
if (_value)
{
visitor(*const_cast<V*>(_value));
return true;
};
return E::value_visit_void(visitor);
};
private:
const V * _value;
};
};
#endif /* _TAGGED_UNION_HPP_ */

View File

@ -0,0 +1,103 @@
/*
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 _THREAD_COMMON_HPP_
#define _THREAD_COMMON_HPP_
#include <config_commons.hpp>
#include <types.hpp>
//#include <function.hpp>
struct ThreadCommon
{
protected:
template<typename FuncPtrType>
struct DecomposeFuncPtr;
template<typename ReturnType, typename ArgType>
struct DecomposeFuncPtr<ReturnType(*)(ArgType)>
{
typedef ReturnType Return;
};
template<typename SomeClass>
struct DecomposeFuncPtr
{
typedef void Return;
};
template<typename ReturnType>
struct DecomposeFuncPtr<ReturnType(*)()>
{
typedef ReturnType Return;
};
template< typename FunctionType >
struct DecomposeFunction
{
typedef typename Select < IsClass< FunctionType >::Result, int,
typename DecomposeFuncPtr< FunctionType >::Return >::Result
Return;
};
public:
struct ThreadDataCommon
{
ThreadDataCommon() {}
virtual ~ThreadDataCommon() {}
virtual int run() = 0;
ThreadCommon * _thread;
void * _self;
void * _attribute;
};
ThreadCommon() {}
};
#include COMMONS_INCLUDE(thread.hpp)
#endif /* _THREAD_COMMON_HPP_ */

View File

@ -0,0 +1,352 @@
/*
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 <timer.hpp>
TimerTraits::TimerTraits()
: _thread((Thread*)0), _purify(false), _last_tick(0), _age_count(0), _shutdown(false)
{};
bool TimerTraits::start (void)
{
_shutdown = false;
_condition.reset();
_finalized.reset();
if (!_thread)
{
_thread = new Thread(TimerTraits::loop_thread(this));
_purify = true;
}
#if defined(_WINDOWS) || defined(_Windows) || defined(_WIN32) || defined(WIN32)
// set priority ...
#else
pthread_attr_t attrs;
sched_param param;
if (pthread_attr_init(&attrs) < 0)
return false;
if (pthread_attr_setschedpolicy(&attrs, SCHED_RR) < 0)
return false;
if (pthread_attr_getschedparam(&attrs, &param) < 0)
return false;
param.sched_priority = sched_get_priority_max(SCHED_RR);
if (pthread_attr_setschedparam(&attrs, &param) < 0)
return false;
// set priority...
// if (pthread_create(&_thread, &attrs, TimerTraits::loop_thread, NULL) < 0)
// return false;
_thread->start();
#endif
return true;
}
bool TimerTraits::stop (void)
{
_shutdown = true;
_condition.signal();
_finalized.wait(10000); /* 10 seconds max wait */
if (_thread && _purify)
{
delete _thread;
_thread = (Thread *)0;
_purify = false;
}
return true;
}
//-----------------------------------------
int TimerTraits::loop_thread::operator()(void)
{
try
{
_timer->loop();
}
catch( ... )
{
/* something wrong happened! */
}
_timer->_finalized.signal();
return 0;
}
void TimerTraits::execute(ControlSet::iterator init, const TimerTraits::Control & ctrl)
{
volatile CallbackFuncType func = (volatile CallbackFuncType) ctrl._func;
volatile CallbackDataType data = (volatile CallbackDataType) ctrl._data;
_timer_set.erase(init);
_mutex.unlock();
func(data);
}
void TimerTraits::loop (void)
{
while (true)
{
if (_shutdown) break;
_mutex.lock();
ControlSet::iterator init = _timer_set.begin();
if (init == _timer_set.end())
{
_mutex.unlock();
_condition.wait();
}
else
{
const Control & ctrl = *init;
unsigned int ts_now = TimerTraits::tick();
if (_age_count == ctrl._age)
{
if (ts_now < ctrl._msecs)
{
/* age is right, but it is not time to expire yet... */
volatile unsigned int wait_time = ctrl._msecs - ts_now;
_mutex.unlock();
_condition.wait(wait_time); /* expire - now */
}
else
{
/* age is right, and we should expire! */
execute(init, ctrl); /* called locked, return unlocked */
}
}
else if (_age_count < ctrl._age)
{
/* age is not there yet (need some time to overlap)... */
volatile unsigned int wait_time = (UINT_MAX - ts_now) + ctrl._msecs;
_mutex.unlock();
_condition.wait(wait_time); /* MAX - now + expire */
}
else
{
/* age has passed, we should have expired before! */
execute(init, ctrl); /* called locked, return unlocked */
}
}
}
_finalized.signal();
}
unsigned int TimerTraits::tick()
{
#if defined(_WINDOWS) || defined(_Windows) || defined(_WIN32) || defined(WIN32)
unsigned int tick = GetTickCount();
#else
struct timespec ticks;
// error condition, make the user notice this..
if (clock_gettime(CLOCK_MONOTONIC, &ticks) < 0)
return 0;
unsigned int tick = ( ticks.tv_sec * 1000 ) + ( ticks.tv_nsec / 1000000 );
#endif
if (_last_tick > tick)
++_age_count;
_last_tick = tick;
return tick;
}
//-----------------------------------------
TimerTraits::Index TimerTraits::traits_add_unlocked (unsigned int msecs, const void * func, const void * data, unsigned int value)
{
unsigned int ms_tick = TimerTraits::tick();
unsigned int ms_left = UINT_MAX - ms_tick;
unsigned int ms_real = msecs;
unsigned int age_num = _age_count;
if (ms_left < msecs)
{
ms_real -= ms_left;
++age_num;
}
else
{
ms_real += ms_tick;
}
ControlSet::iterator it = _timer_set.insert(Control(age_num,ms_real,func,data,value));
if (_timer_set.size() == 1 || _timer_set.begin() == it)
{
_condition.signal();
};
return Index(age_num, ms_real, msecs, func, data, value);
}
TimerTraits::Index TimerTraits::traits_add (unsigned int msecs, const void * func, const void * data, unsigned int value)
{
_mutex.lock();
Index idx = traits_add_unlocked(msecs, func, data, value);
_mutex.unlock();
return idx;
}
bool TimerTraits::traits_restart (TimerTraits::Index & idx, bool force)
{
bool ret = false;
_mutex.lock();
if (idx.valid)
{
if (traits_del_unlocked(idx) || force)
{
idx = traits_add_unlocked(idx.delta, idx.func, idx.data, idx.value);
ret = true;
}
}
_mutex.unlock();
return ret;
}
bool TimerTraits::traits_del_unlocked (TimerTraits::Index & idx)
{
bool ret = false;
if (idx.valid)
{
ControlSet::iterator i = _timer_set.lower_bound(Control(idx.era, idx.msec));
ControlSet::iterator j = _timer_set.upper_bound(Control(idx.era, idx.msec));
for (; i != j; i++)
{
const Control & ctrl = (*i);
if ((idx.value && !(ctrl._value & idx.value)))
continue;
if (((idx.func && ctrl._func == idx.func) || !idx.func) && ((idx.data && ctrl._data == idx.data) || !idx.data))
{
if (_timer_set.begin() == i)
_condition.signal();
_timer_set.erase(i);
ret = true;
break;
}
}
idx.valid = false;
}
return ret;
}
bool TimerTraits::traits_del (TimerTraits::Index & idx)
{
_mutex.lock();
bool ret = traits_del_unlocked(idx);
_mutex.unlock();
return ret;
}
bool TimerTraits::traits_del (const void * func, const void * data, unsigned int value)
{
bool ret = false;
_mutex.lock();
for (ControlSet::iterator i = _timer_set.begin(); i != _timer_set.end(); i++)
{
const Control & ctrl = (*i);
if ((value && !(ctrl._value & value)))
continue;
if (((func && ctrl._func == func) || !func) && ((data && ctrl._data == data) || !data))
{
if (_timer_set.begin() == i)
_condition.signal();
_timer_set.erase(i);
ret = true;
break;
}
}
_mutex.unlock();
return ret;
}

View File

@ -0,0 +1,224 @@
/*
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
*/
#if defined(_WINDOWS) || defined(_Windows) || defined(_WIN32) || defined(WIN32)
#include <windows.h>
#else
#include <sched.h>
#endif
#include <set>
#include <simple_lock.hpp>
#include <saved_condition.hpp>
#include <thread.hpp>
#include <refcounter.hpp>
#ifndef _TIMER_HPP_
#define _TIMER_HPP_
struct TimerTraits
{
typedef bool (* CallbackFuncType)(const void * volatile);
typedef const void * CallbackDataType;
TimerTraits();
virtual ~TimerTraits() {};
protected:
/* pre-declaration, used below */
struct ControlCompare;
struct Control
{
Control(unsigned int age, unsigned int msecs, const void * func = 0, const void * data = 0, unsigned int value = 0)
: _age(age), _msecs(msecs), _func(func), _data(data), _value(value) {}
unsigned int _age;
unsigned int _msecs;
const void * _func;
const void * _data;
unsigned int _value;
};
struct ControlCompare
{
bool operator()(const Control & c1, const Control & c2) const
{
return (c1._age < c2._age ? true : c1._msecs < c2._msecs);
}
};
typedef std::multiset < Control, ControlCompare > ControlSet;
public:
struct Index
{
Index(): era(0), msec(0), valid(false) {};
Index(unsigned int _era, unsigned int _msec, unsigned int _delta, const void * _func, const void * _data, unsigned int _value)
: era(_era), msec(_msec), delta(_delta), func(_func), data(_data), value(_value), valid(true) {};
unsigned int era;
unsigned int msec;
unsigned int delta;
const void * func;
const void * data;
unsigned int value;
bool valid;
void reset(void) { era = 0; msec = 0; valid = false; };
};
/* timer add/remove functions */
Index traits_add (unsigned int msecs, const void * func, const void * data = 0, unsigned int value = 0);
bool traits_restart (Index & idx, bool force);
bool traits_del (Index & idx);
bool traits_del (const void * func, const void * data = 0, unsigned int value = 0);
/* timer start/stop functions */
bool start(void);
bool stop(void);
protected:
Index traits_add_unlocked (unsigned int msecs, const void * func, const void * data, unsigned int value);
bool traits_del_unlocked (Index & idx);
protected:
void execute(ControlSet::iterator, const Control &);
void loop(void);
struct loop_thread
{
loop_thread(TimerTraits *timer) : _timer(timer) {};
int operator()(void);
protected:
TimerTraits * _timer;
};
unsigned int tick();
/* variables */
SavedCondition _condition;
SimpleLock _mutex;
Thread * _thread;
bool _purify;
ControlSet _timer_set;
unsigned int _last_tick;
unsigned int _age_count;
SavedCondition _finalized;
bool _shutdown;
};
template < typename F, typename D >
struct TimerTemplate: NEW_REFCOUNTER(TimerTemplate< F, D >)
{
typedef TimerTraits::Index Index;
typedef TimerTraits::Control Control;
TimerTemplate()
: _timer(new TimerTraits())
{};
TimerTemplate(const TimerTemplate< F, D > & o)
: INC_REFCOUNTER(o, TimerTemplate< F, D >),
_timer(o._timer)
{};
void unreference(void)
{
if (_timer)
delete _timer;
};
bool start() { return _timer->start(); }
bool stop() { return _timer->stop(); }
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);
}
inline bool restart(Index & idx, bool force = false)
{
return _timer->traits_restart(idx, force);
}
inline bool del(Index & idx)
{
return _timer->traits_del(idx);
}
inline bool del(F * func, D data, unsigned int value = 0)
{
return _timer->traits_del((const void *)func, (void *)(data), value);
}
inline bool del(unsigned int value)
{
return _timer->traits_del((const void *)0, (void *)0, value);
}
protected:
TimerTraits * _timer;
};
#endif /* _TIMER_HPP_ */

View File

@ -0,0 +1,81 @@
/*
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 _TYPES_HPP_
#define _TYPES_HPP_
/*** Used for conditional compilation based on K3L version ***/
#define K3L_AT_LEAST(major,minor,build) \
(((k3lApiMajorVersion == major) && ((k3lApiMinorVersion == minor) && (k3lApiBuildVersion >= build)) || \
((k3lApiMajorVersion == major) && (k3lApiMinorVersion > minor))) || \
(k3lApiMajorVersion > major))
#define K3L_EXACT(major,minor,build) \
((k3lApiMajorVersion == major) && (k3lApiMinorVersion == minor) && (k3lApiBuildVersion >= build))
/*** Used for checking information on classes and stuff.. ***/
template< typename T >
class IsClass
{
protected:
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;
};
/*** Used for template metaprogramming ***/
template < bool Value, typename Then, typename Else >
struct Select
{
typedef Then Result;
};
template < typename Then, typename Else >
struct Select < false, Then, Else >
{
typedef Else Result;
};
#endif /* _TYPES_HPP_ */

View File

@ -0,0 +1,127 @@
/*
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 <refcounter.hpp>
#include <typeinfo>
#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
{
typedef UserReturnType ReturnType;
typedef UserArgumentType ArgumentType;
virtual ~VariantBaseType() {};
virtual int which() = 0;
virtual ReturnType visit(void) { return ReturnType(); };
virtual ReturnType visit(ArgumentType) { return ReturnType(); };
};
template < typename BaseType = VariantBaseType < void > >
struct Variant: NEW_REFCOUNTER(Variant < BaseType >)
{
typedef typename BaseType::ReturnType ReturnType;
typedef typename BaseType::ArgumentType ArgumentType;
struct InvalidType {};
Variant(BaseType * value, bool is_owner = false)
: _value(value), _is_owner(is_owner) {};
Variant(const Variant & v)
: INC_REFCOUNTER(v, Variant < BaseType >),
_value(v._value), _is_owner(v._is_owner) {};
virtual ~Variant() {};
void unreference()
{
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();
}
ReturnType visit(void)
{
return _value->visit();
}
ReturnType visit(ArgumentType arg)
{
return _value->visit(arg);
}
protected:
BaseType * _value;
bool _is_owner;
};
#endif /* _VARIANT_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,505 @@
/*
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 <string>
#include <sstream>
#include <map>
#include <k3l.h>
// k3lApiMajorVersion
#ifndef CM_PING
# include <k3lVersion.h>
# include <KTools.h>
#endif
#include <types.hpp>
#include <k3lapi.hpp>
#include <format.hpp>
#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_ */

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -0,0 +1,39 @@
<html><head><meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"><title>Mod Khomp: README</title></head><body><a name="Guia_R.C3.A1pido" id="Guia_R.C3.A1pido"></a><h1> <span class="mw-headline"> Guia Rápido </span></h1>
<p>Depois de instalar a placa no sistema, e executar o programa de instalação pela primeira vez, os <i>drivers</i> e serviços da Khomp serão adicionados na inicialização do sistema, e automaticamente carregados.
</p><p>Se o sistema possuir pelo menos uma placa de tronco E1 e/ou uma placa FXO, uma tela de configuração básica deverá ser apresentada ao final do processo, questionando parâmetros de sinalização - no caso de existirem placas E1 - e/ou realizando o ajuste de cadências - no caso de existirem placas FXO.
</p><p>Se todas estas etapas foram executadas com sucesso, prossiga para o item <b>Utilizando o <i>Endpoint</i> da Khomp</b>. Caso algum problema ocorra, consulte o <a href=".htmlMod_Khomp/Manual" title="Mod Khomp/Manual">Manual do Endpoint</a>, seguindo para a seção de <a href=".htmlMod_Khomp/Manual#Solu.C3.A7.C3.A3o_de_problemas" title="Mod Khomp/Manual">Solução de problemas</a>.
</p>
<a name="Utilizando_o_Endpoint_da_Khomp" id="Utilizando_o_Endpoint_da_Khomp"></a><h1> <span class="mw-headline"> Utilizando o <i>Endpoint</i> da Khomp </span></h1>
<p>Após a instalação e inicialização dos serviços necessários pela Khomp, o FreeSWITCH já pode ser carregado ou inicializado.
</p>
<ul><li> <b>AVISO</b>: É imprescindível que o <b>FreeSWITCH</b> não seja executado utilizando a opção que desabilita o escalonamento em tempo real (-nort), <b>especialmente</b> se este estiver sendo executado lado-a-lado com servidores <i>web</i> ou servidores de banco de dados. Não realizar este procedimento pode resultar em perda de qualidade do áudio, gerando um sério comprometimento no andamento das ligações do sistema.
</li></ul>
<p>Após a inicialização do FreeSWITCH, pode-se verificar se o módulo da Khomp foi carregado através do seguinte comando:<br />
</p>
<pre> freeswitch@hostname&gt; module_exists mod_khomp
</pre>
<p>A próxima linha deverá responder algo tipo:
</p>
<pre> true
</pre>
<p>Para verificar se o FreeSWITCH reconheceu todas as placas, digite:
</p>
<pre> freeswitch@hostname&gt; khomp summary
</pre>
<p>A saída desse comando mostrará detalhes de todas placas reconhecidas.
</p><p>No caso de uma placa de tronco E1, pode-se verificar o estado dos links com o seguinte comando:
</p>
<pre> freeswitch@hostname&gt; khomp show links
</pre>
<p>O estado dos canais individuais, por sua vez, pode ser aferido com o comando:
</p>
<pre> freeswitch@hostname&gt; khomp show channels
</pre>
<p>Para mais detalhes sobre os comandos do Endpoint da khomp digite no console do FreeSWITCH:
</p>
<pre> freeswitch@hostname&gt; help khomp
</pre>
<ul><li> <b>IMPORTANTE</b>: Para fazer completo uso da sua placa Khomp, será preciso configurar suas regras de discagem, seja através do arquivo <i>default.xml</i> ou de um aplicativo externo, definindo regras específicas para realizar ao receber ligações.<br /><br />No <a href=".htmlMod_Khomp/Manual" title="Mod Khomp/Manual">Manual do Endpoint</a>, podem ser encontradas informações sobre o formato dos contextos de entrada (responsáveis por receber as ligações) e sobre as opções disponíveis no application Bridge (responsável por realizar ligações) que podem ser utilizadas com o Endpoint da Khomp, além de outras funcionalidades especiais providas pelo mesmo.
</li></ul>
<p><br />
</p></body></html>

Binary file not shown.

View File

@ -0,0 +1,40 @@
<html><head><meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"><title>Mod Khomp: README: en</title></head><body><a name="Quick_guide" id="Quick_guide"></a><h1> <span class="mw-headline"> Quick guide </span></h1>
<p>After installing the card in the system and run the installation program for the first time, the <i>drivers</i> and Khomp services will be added at system startup, and automatically loaded.
</p><p>If your system has at least one E1 trunk card and / or an FXO card, a basic setup screen will be presented at the end of the process, questioning signaling parameters - if there are signs E1 - and/or performing the adjustment cadences - where that FXO cards.
</p><p>If all these steps were performed successfully, proceed to the item <b>Using Khomp Endpoint</b>. If a problem occurs, see the <a href=".htmlMod_Khomp/User_Guide" title="Mod Khomp/User Guide">User Guide</a>, in the section <a href=".htmlMod_Khomp/User_Guide#Troubleshooting" title="Mod Khomp/User Guide">Troubleshooting</a>.
</p>
<a name="Using_the_Khomp_Endpoint" id="Using_the_Khomp_Endpoint"></a><h1> <span class="mw-headline"> Using the Khomp Endpoint </span></h1>
<p>After installation and startup services required by Khomp, FreeSWITCH can now be loaded or initialized.
</p>
<ul><li><b>WARNING</b>: It is imperative that the<b>FreeSWITCH</b> is not executed using the option that disables the escalation in real time (-nort), <b>especially</b> if this is running side-by server-side with web servers or database. Failure to do so may result in loss of audio quality, causing a serious commitment on the progress of system connections.
</li></ul>
<p>After initialization of FreeSWITCH, you can verify that the module was loaded Khomp through the following command: <br />
</p><p><br />
</p>
<pre> freeswitch@hostname&gt; module_exists mod_khomp
</pre>
<p>The next line should answer something like:
</p>
<pre> true
</pre>
<p>To verify that the FreeSwitch recognize all the cards, type:
</p>
<pre> freeswitch@hostname&gt; khomp summary
</pre>
<p>The output of this command will show details of all cards accepted.
</p><p>In the case of an E1 card, you can check the status of links with the following command:
</p>
<pre> freeswitch@hostname&gt; khomp show links
</pre>
<p>The state of individual channels, in turn, can be measured with the command:
</p>
<pre> freeswitch@hostname&gt; khomp show channels
</pre>
<p>For more details on the commands of the Endpoint khomp type in the console of FreeSWITCH:
</p>
<pre> freeswitch@hostname&gt; help khomp
</pre>
<ul><li><b>IMPORTANT</b>: To make full use of your card Khomp, you must configure your dialing rules, either through the extension.conf or from an external application by setting specific rules for conduct by receiving connections. <br /> In the <a href=".htmlMod_Khomp/User_Guide" title="Mod Khomp/User Guide">User Guide</a>, information can be found on the format of input contexts (responsible for receiving calls) and on the options available on application Dial (responsible for make calls) that can be used with the Endpoint Khomp, and other special features provided by it.
</li></ul>
<p><br />
</p></body></html>

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -0,0 +1,962 @@
/*******************************************************************************
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2010 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 _APPLICATIONS_H_
#define _APPLICATIONS_H_
#include "lock.h"
#include "khomp_pvt.h"
struct Application
{
Application(Board::KhompPvt * pvt) : _pvt(pvt) {}
~Application() {}
Statistics * statistics() { return _app_statistics; }
template <typename T>
T* statistics() { return static_cast<T*>(_app_statistics); }
Board::KhompPvt *_pvt;
Statistics *_app_statistics;
};
/*************************** FAX **********************************************/
struct Fax
{
Fax(Board::KhompPvt * pvt) : _pvt(pvt) {}
/*
bool clear(Board::KhompPvt * pvt)
{
_pvt = pvt;
return true;
}
*/
bool adjustForFax();
bool sendFax(switch_core_session_t * session, const char *data);
bool receiveFax(switch_core_session_t * session, const char *data);
bool onFaxChannelRelease(K3L_EVENT *e);
bool startFaxTX(const char * orig_addr = NULL);
bool stopFaxTX();
bool startFaxRX(const char * filename, const char * orig_addr = NULL);
bool stopFaxRX();
bool addFaxFile(const char * filename, bool last = true);
Board::KhompPvt *_pvt;
/* used by app FAX */
SavedCondition _fax_cond;
KFaxResult _fax_result;
};
/*************************** TRANSFER *****************************************/
template <typename T, bool flash = true>
struct Transfer
{
Transfer(Board::KhompPvt * pvt) : _pvt(pvt), _is_ok(false) {}
bool clear()
{
if(!_is_ok)
{
_call = dynamic_cast<T *>(_pvt->call());
_is_ok = true;
if(!_call)
{
DBG(FUNC, D("Error in cast"));
_is_ok = false;
}
}
_call->_flags.clear(Kflags::XFER_DIALING);
return true;
}
bool userTransfer(switch_core_session_t * session, const char *data)
{
DBG(FUNC, PVT_FMT(_pvt->target(), "c"));
std::string dest("");
std::string opts("");
try
{
Strings::vector_type params;
Strings::tokenize((const char *)data, params, "|,", 2);
dest = params[0];
if (params.size() > 1)
{
// other options go here...
}
ScopedPvtLock lock(_pvt);
int timeout = 5;
if(!_pvt->call()->_flags.check(Kflags::REALLY_CONNECTED) && !_pvt->loopWhileFlagTimed(Kflags::REALLY_CONNECTED, timeout, false))
return false;
DBG(FUNC, PVT_FMT(_pvt->target(), "flashing channel!"));
_pvt->command(KHOMP_LOG, CM_FLASH);
lock.unlock();
timeout = 15; // 15 * 200000 = 3s
do
{
usleep(200000);
timeout--;
ScopedPvtLock lock2(_pvt);
if(!_pvt->call()->_flags.check(Kflags::IS_INCOMING) && !_pvt->call()->_flags.check(Kflags::IS_OUTGOING))
{
DBG(FUNC, PVT_FMT(_pvt->target(), "unable to do a user transfer, channel disconnected"));
return false;
}
}
while(timeout);
ScopedPvtLock lock3(_pvt);
_pvt->command(KHOMP_LOG, CM_DIAL_DTMF, dest.c_str());
_pvt->call()->_flags.set(Kflags::WAIT_SEND_DTMF);
lock3.unlock();
timeout = 300; // 300 * 200000 = 60s
do
{
usleep(200000);
timeout--;
ScopedPvtLock lock4(_pvt);
if(!_pvt->call()->_flags.check(Kflags::WAIT_SEND_DTMF))
break;
}
while(timeout);
}
catch (ScopedLockFailed & err)
{
LOG(ERROR, PVT_FMT(_pvt->target(),"r (unable to lock %s!)") % err._msg.c_str() );
return false;
}
DBG(FUNC, PVT_FMT(_pvt->target(), "r"));
return true;
}
/* User transfer functions */
bool doUserXferUnlocked()
{
DBG(FUNC, PVT_FMT(_pvt->target(), "c (flashing channel!)"));
bool ret = false;
ret = _pvt->command(KHOMP_LOG, CM_FLASH);
DBG(FUNC, PVT_FMT(_pvt->target(), "r (%s)") % (ret ? "true" : "false"));
return ret;
}
bool checkUserXferUnlocked(std::string digit)
{
DBG(FUNC, PVT_FMT(_pvt->target(), "c (CM_FLASH)"));
if (_call->_user_xfer_digits.empty())
{
_call->_digits_buffer += digit;
DBG(FUNC, PVT_FMT(_pvt->target(), "r (disabled)"));
return false;
}
_call->_user_xfer_buffer += digit;
/* temporary buffer */
std::string tmp = _call->_user_xfer_buffer;
unsigned int amount = tmp.size();
try
{
if (amount == _call->_user_xfer_digits.size())
{
if (tmp == _call->_user_xfer_digits)
{
bool ret = doUserXferUnlocked();
_call->_user_xfer_buffer.clear();
_call->_digits_buffer.clear();
Board::board(_pvt->target().device)->_timers.del(_idx_xfer_dial);
DBG(FUNC, PVT_FMT(_pvt->target(), "r (ret=%s, done xfer)") % (ret ? "true" : "false"));
return ret;
}
_call->_digits_buffer += tmp[0];
_call->_user_xfer_buffer.erase(0, 1);
DBG(FUNC, PVT_FMT(_pvt->target(), "r (false, no xfer)"));
return false;
}
if (tmp == _call->_user_xfer_digits.substr(0,amount))
{
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);
}
else
{
Board::board(_pvt->target().device)->_timers.restart(_idx_xfer_dial);
}
DBG(FUNC, PVT_FMT(_pvt->target(), "r (true, buffering)"));
return true;
}
}
catch (K3LAPI::invalid_device & err)
{
LOG(ERROR, PVT_FMT(_pvt->target(), "Unable to get device: %d!") % err.device);
}
_call->_digits_buffer += tmp[0];
_call->_user_xfer_buffer.erase(0, 1);
DBG(FUNC, PVT_FMT(_pvt->target(), "r (false, buffering)"));
return false;
}
static void userXferTimer(Board::KhompPvt * pvt)
{
DBG(FUNC, PVT_FMT(pvt->target(), "c"));
T * call = static_cast<T *>(pvt->call());
try
{
ScopedPvtLock lock(pvt);
if (!call->_user_xfer_buffer.empty())
{
pvt->command(KHOMP_LOG, CM_DIAL_DTMF, call->_user_xfer_buffer.c_str());
/* clear the buffer that has been send */
call->_user_xfer_buffer.clear();
}
call->_flags.clear(Kflags::XFER_DIALING);
}
catch (ScopedLockFailed & err)
{
LOG(ERROR, PVT_FMT(pvt->target(),"r (unable to lock %s!)") % err._msg.c_str() );
return;
}
DBG(FUNC, PVT_FMT(pvt->target(), "r"));
}
bool _is_ok;
T * _call;
Board::KhompPvt * _pvt;
Board::ChanTimer::Index _idx_xfer_dial;
};
template<typename T>
struct Transfer<T, false>
{
Transfer(Board::KhompPvt * pvt) : _pvt(pvt), _is_ok(false) {}
bool clear()
{
if(!_is_ok)
{
_call = dynamic_cast<T *>(_pvt->call());
_is_ok = true;
if(!_call)
{
DBG(FUNC, D("Error in cast"));
_is_ok = false;
}
}
_call->_flags.clear(Kflags::XFER_DIALING);
_call->_flags.clear(Kflags::XFER_QSIG_DIALING);
return true;
}
bool userTransfer(switch_core_session_t * session, const char *data)
{
DBG(FUNC, PVT_FMT(_pvt->target(), "c"));
std::string dest("");
bool opt_nowait = false;
try
{
Strings::vector_type params;
Strings::tokenize((const char *)data, params, "|,", 2);
dest = params[0];
if (params.size() > 1)
{
opt_nowait = (params[1].find('n') != std::string::npos);
// other options go here...
}
ScopedPvtLock lock(_pvt);
int timeout = 5;
if(!_pvt->call()->_flags.check(Kflags::REALLY_CONNECTED) && !_pvt->loopWhileFlagTimed(Kflags::REALLY_CONNECTED, timeout, false))
return false;
DBG(FUNC, PVT_FMT(_pvt->target(), "ss_transfer on channel!"));
_pvt->command(KHOMP_LOG, CM_SS_TRANSFER,
STG(FMT("transferred_to=\"%s\" await_connect=\"%d\"")
% dest % (opt_nowait ? 0 : 1)).c_str());
}
catch (ScopedLockFailed & err)
{
LOG(ERROR, PVT_FMT(_pvt->target(),"r (unable to lock %s!)") % err._msg.c_str() );
return false;
}
DBG(FUNC, PVT_FMT(_pvt->target(), "r"));
return true;
}
/* User transfer functions */
bool doUserXferUnlocked(void)
{
DBG(FUNC, PVT_FMT(_pvt->target(), "c"));
bool ret = false;
if (_call->_flags.check(Kflags::XFER_QSIG_DIALING))
{
DBG(FUNC, PVT_FMT(_pvt->target(), "ss_transfer on channel!"));
_call->_flags.clear(Kflags::XFER_DIALING);
_call->_flags.clear(Kflags::XFER_QSIG_DIALING);
ret = _pvt->command(KHOMP_LOG, CM_SS_TRANSFER,
STG(FMT("transferred_to=\"%s\" await_connect=\"1\"") % _call->_qsig_number).c_str());
}
else
{
DBG(FUNC, PVT_FMT(_pvt->target(), "starting to store digits for ss_transfer..."));
_call->_flags.set(Kflags::XFER_QSIG_DIALING);
_xfer_thread = threadCreate(Transfer<T, false>::userXferPlayback,(void*) _pvt);
_xfer_thread->start();
ret = true;
}
DBG(FUNC, PVT_FMT(_pvt->target(), "r (%s)") % (ret ? "true" : "false"));
return ret;
}
bool checkUserXferUnlocked(std::string digit)
{
DBG(FUNC, PVT_FMT(_pvt->target(), "c (CM_SS_TRANSFER)"));
if (_call->_user_xfer_digits.empty())
{
_call->_digits_buffer += digit;
DBG(FUNC, PVT_FMT(_pvt->target(), "r (disabled)"));
return false;
}
_call->_user_xfer_buffer += digit;
DBG(FUNC, PVT_FMT(_pvt->target(), "c digits=[%s] buffer=[%s]") % _call->_user_xfer_digits % _call->_user_xfer_buffer );
/* temporary buffer */
std::string tmp = _call->_user_xfer_buffer;
unsigned int amount = tmp.size();
try
{
if (amount == _call->_user_xfer_digits.size())
{
if (tmp == _call->_user_xfer_digits)
{
bool ret = doUserXferUnlocked();
_call->_user_xfer_buffer.clear();
_call->_qsig_number.clear();
_call->_digits_buffer.clear();
if(!_call->_flags.check(Kflags::XFER_QSIG_DIALING))
{
Board::board(_pvt->target().device)->_timers.del(_idx_xfer_dial);
DBG(FUNC, PVT_FMT(_pvt->target(), "r (ret=%s, done xfer)") % (ret ? "true" : "false"));
}
else
{
Board::board(_pvt->target().device)->_timers.restart(_idx_xfer_dial);
DBG(FUNC, PVT_FMT(_pvt->target(), "r (waiting digits for transfer)"));
}
return ret;
}
if (_call->_flags.check(Kflags::XFER_QSIG_DIALING))
{
DBG(FUNC, PVT_FMT(_pvt->target(), "putting digits ('%s') on transfer-to number!") % tmp);
_call->_qsig_number += tmp[0];
_call->_user_xfer_buffer.erase(0, 1);
Board::board(_pvt->target().device)->_timers.restart(_idx_xfer_dial);
DBG(FUNC, PVT_FMT(_pvt->target(), "r (true, qsig transfer)"));
return true;
}
_call->_digits_buffer += tmp[0];
_call->_user_xfer_buffer.erase(0, 1);
DBG(FUNC, PVT_FMT(_pvt->target(), "r (false, no qsig)"));
return false;
}
if (tmp == _call->_user_xfer_digits.substr(0,amount))
{
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);
}
else
{
Board::board(_pvt->target().device)->_timers.restart(_idx_xfer_dial);
}
DBG(FUNC, PVT_FMT(_pvt->target(), "r (true, buffering)"));
return true;
}
if (_call->_flags.check(Kflags::XFER_QSIG_DIALING))
{
DBG(FUNC, PVT_FMT(_pvt->target(), "putting digits ('%s') on transfer-to number!") % tmp);
_call->_qsig_number += tmp[0];
_call->_user_xfer_buffer.erase(0, 1);
Board::board(_pvt->target().device)->_timers.restart(_idx_xfer_dial);
DBG(FUNC, PVT_FMT(_pvt->target(), "r (true, qsig buffering)"));
return true;
}
}
catch (K3LAPI::invalid_device & err)
{
LOG(ERROR, PVT_FMT(_pvt->target(), "Unable to get device: %d!") % err.device);
}
_call->_digits_buffer += tmp[0];
_call->_user_xfer_buffer.erase(0, 1);
DBG(FUNC, PVT_FMT(_pvt->target(), "r (false, buffering)"));
return false;
}
static void userXferTimer(Board::KhompPvt * pvt)
{
DBG(FUNC, PVT_FMT(pvt->target(), "c"));
T * call = static_cast<T *>(pvt->call());
try
{
ScopedPvtLock lock(pvt);
if (!call->_user_xfer_buffer.empty())
{
pvt->command(KHOMP_LOG, CM_DIAL_DTMF, call->_user_xfer_buffer.c_str());
/* clear the buffer that has been send */
call->_user_xfer_buffer.clear();
}
if (!call->_qsig_number.empty())
{
pvt->command(KHOMP_LOG, CM_SS_TRANSFER,
STG(FMT("transferred_to=\"%s\" await_connect=\"1\"") % call->_qsig_number).c_str());
/* clear the buffer that has been send */
call->_qsig_number.clear();
}
call->_flags.clear(Kflags::XFER_DIALING);
call->_flags.clear(Kflags::XFER_QSIG_DIALING);
}
catch (ScopedLockFailed & err)
{
LOG(ERROR, PVT_FMT(pvt->target(),"r (unable to lock %s!)") % err._msg.c_str() );
return;
}
DBG(FUNC, PVT_FMT(pvt->target(), "r"));
}
static switch_status_t dtmfCallback(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen)
{
char sbuf[3];
if(!session)
{
DBG(FUNC,D("session is NULL"))
return SWITCH_STATUS_FALSE;
}
switch_channel_t * chan = switch_core_session_get_channel(session);
if(!chan)
{
DBG(FUNC,D("channel is NULL"))
return SWITCH_STATUS_FALSE;
}
switch_core_session_t *peer_session = switch_core_session_locate(switch_channel_get_variable(chan,SWITCH_SIGNAL_BOND_VARIABLE));
if(!peer_session)
{
DBG(FUNC,D("session is NULL"))
return SWITCH_STATUS_FALSE;
}
switch (itype)
{
case SWITCH_INPUT_TYPE_DTMF:
{
switch_dtmf_t *dtmf = (switch_dtmf_t *) input;
Board::KhompPvt * tech_pvt = static_cast< Board::KhompPvt* >(switch_core_session_get_private(peer_session));
if(!tech_pvt)
{
DBG(FUNC,D("Init: pvt is NULL"))
switch_core_session_rwunlock(peer_session);
return SWITCH_STATUS_FALSE;
}
char s[] = { dtmf->digit, '\0' };
tech_pvt->sendDtmf(s);
break;
}
default:
break;
}
switch_core_session_rwunlock(peer_session);
return SWITCH_STATUS_SUCCESS;
}
static int userXferPlayback(void * pvt_ptr)
{
/* get pointer... */
Board::KhompPvt * pvt = static_cast < Board::KhompPvt * > (pvt_ptr);
DBG(FUNC, PVT_FMT(pvt->target(), "c"));
try
{
ScopedPvtLock lock(pvt);
/* get the owner */
switch_channel_t * chan = pvt->getFSChannel();
/* get other side of the bridge */
switch_core_session_t * peer_session = NULL;
switch_core_session_get_partner(pvt->session(),&peer_session);
if(!peer_session)
{
DBG(FUNC, PVT_FMT(pvt->target(), "r (session is null)"));
return NULL;
}
switch_channel_t * peer = switch_core_session_get_channel(peer_session);
/* put the channel in hold */
//switch_core_session_t *session = switch_core_session_locate(switch_channel_get_variable(chan,SWITCH_SIGNAL_BOND_VARIABLE));
//switch_channel_t *chan_core = switch_core_session_get_channel(session);
const char *stream;
if (!(stream = switch_channel_get_variable(chan, SWITCH_HOLD_MUSIC_VARIABLE)))
{
stream = "silence";
}
DBG(FUNC, PVT_FMT(pvt->target(), "stream=%s") % stream);
if (stream && strcasecmp(stream, "silence"))
{
/* Freeswitch not get/put frames */
//switch_channel_set_flag(channel, CF_HOLD);
switch_ivr_broadcast(switch_core_session_get_uuid(pvt->session()),stream, SMF_ECHO_ALEG | SMF_LOOP | SMF_PRIORITY);
}
switch_core_session_rwunlock(peer_session);
lock.unlock();
/* kickstart my heart */
switch_input_args_t args = {0};
args.input_callback = dtmfCallback;
/* wait while xfering... */
while (true)
{
switch_ivr_collect_digits_callback(peer_session,&args,1000,0);
ScopedPvtLock lock2(pvt);
if (!pvt->call()->_flags.check(Kflags::XFER_QSIG_DIALING))
{
break;
}
lock2.unlock();
}
//switch_channel_clear_flag(channel, CF_HOLD);
switch_channel_stop_broadcast(chan);
switch_channel_wait_for_flag(chan, CF_BROADCAST, SWITCH_FALSE, 5000, NULL);
switch_core_session_rwunlock(pvt->session());
switch_core_session_rwunlock(peer_session);
//switch_ivr_unhold_uuid(switch_channel_get_variable(chan,SWITCH_SIGNAL_BOND_VARIABLE));
}
catch (ScopedLockFailed & err)
{
LOG(ERROR, PVT_FMT(pvt->target(),"r (unable to lock %s!)") % err._msg.c_str() );
return NULL;
}
catch (Board::KhompPvt::InvalidSwitchChannel & err)
{
LOG(ERROR, PVT_FMT(pvt->target(), "r (%s)") % err._msg.c_str() );
return NULL;
}
DBG(FUNC, PVT_FMT(pvt->target(), "r"));
return NULL;
}
bool _is_ok;
T * _call;
Board::KhompPvt * _pvt;
Thread * _xfer_thread;
Board::ChanTimer::Index _idx_xfer_dial;
};
/*************************** SMS **********************************************/
struct SMS : public Application
{
typedef std::list< switch_core_session_t *> OwnersList;
struct SMSStatistics : public Statistics
{
SMSStatistics():
_sms_number_incoming(0),
_sms_number_outgoing(0),
_sms_number_confirm(0),
_sms_number_broadcast(0) {};
void incrementIncoming()
{
_sms_number_incoming++;
}
void incrementOutgoing()
{
_sms_number_outgoing++;
}
void incrementConfirm()
{
_sms_number_confirm++;
}
void incrementBroadcast()
{
_sms_number_broadcast++;
}
std::string getDetailed()
{
std::string tmpBuffer;
tmpBuffer.append(STG(FMT("Number of incoming SMS: \t%d\n") % _sms_number_incoming));
tmpBuffer.append(STG(FMT("Number of outgoing SMS: \t%d\n") % _sms_number_outgoing));
tmpBuffer.append(STG(FMT("Number of broadcast SMS: \t%d\n") % _sms_number_broadcast));
tmpBuffer.append(STG(FMT("Number of confirm SMS: \t%d\n") % _sms_number_confirm));
return tmpBuffer;
}
void clear()
{
_sms_number_incoming = 0;
_sms_number_outgoing = 0;
_sms_number_confirm = 0;
_sms_number_broadcast = 0;
}
unsigned int _sms_number_incoming;
unsigned int _sms_number_outgoing;
unsigned int _sms_number_confirm;
unsigned int _sms_number_broadcast;
};
SMS(Board::KhompPvt * pvt) :
Application(pvt),
_thread(NULL),
_shutdown(false),
_can_receive(false),
_can_send(false),
_result(0),
_mutex(Globals::module_pool),
_cond(Globals::module_pool),
_buffer(8)
{
_cond.reset();
_app_statistics = new SMSStatistics();
}
~SMS()
{
stop();
delete _app_statistics;
}
struct ReceiveData
{
ReceiveData() {};
ReceiveData(const ReceiveData & o)
{
_type = o._type;
_from = o._from;
_date = o._date;
_size = o._size;
_coding = o._coding;
_serial = o._serial;
_id = o._id;
_page = o._page;
_pages = o._pages;
_sc_date = o._sc_date;
_status = o._status;
_body = o._body;
};
void clear(void)
{
/* reset data stuff */
_type.clear();
_from.clear();
_date.clear();
_size.clear();
_coding.clear();
_serial.clear();
_id.clear();
_page.clear();
_pages.clear();
_sc_date.clear();
_status.clear();
_body.clear();
};
std::string _type;
std::string _from;
std::string _date;
std::string _size;
std::string _coding;
std::string _serial;
std::string _id;
std::string _page;
std::string _pages;
std::string _sc_date;
std::string _status;
std::string _body;
};
struct SendData
{
SendData(): _conf(false) {};
SendData(const SendData & o)
{
_dest = o._dest;
_body = o._body;
_conf = o._conf;
};
void clear(void)
{
/* reset data stuff */
_dest.clear();
_body.clear();
_conf = false;
};
std::string _dest;
std::string _body;
bool _conf;
};
struct Request
{
/* "empty" constructor */
Request(): _finished(NULL), _cause(NULL) {};
/* "real" constructor */
Request(SendData & send_sms, volatile bool * finished, volatile KGsmCallCause * cause)
: _send_sms(send_sms), _finished(finished), _cause(cause)
{};
SendData _send_sms;
volatile bool * _finished;
volatile KGsmCallCause * _cause;
};
bool start()
{
_pvt->call()->_flags.clear(Kflags::SMS_DOING_UPLOAD);
_thread = threadCreate(&smsThread, (void*) this);
_thread->start();
}
bool stop()
{
if(!_thread)
{
return false;
}
_shutdown = true;
_cond.signal();
_thread->join();
delete _thread;
_thread = NULL;
return true;
}
bool justAlloc(unsigned int count = 0);
bool justStart();
bool sendSMS(switch_core_session_t * session, const char *data);
bool onNewSMS(K3L_EVENT *e);
bool onSMSInfo(K3L_EVENT *e);
bool onSMSData(K3L_EVENT *e);
bool onSMSSendResult(K3L_EVENT *e);
Thread *_thread;
bool _shutdown;
bool _can_receive;
bool _can_send;
ReceiveData _got_sms;
SendData _send_sms;
int _result;
SavedCondition _cond;
Globals::Mutex _mutex;
Ringbuffer < SMS::Request > _buffer;
OwnersList _owners;
static int smsThread(void * sms_ptr);
};
/******************************************************************************/
#endif /* _APPLICATIONS_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,211 @@
/*******************************************************************************
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2010 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 _DEFS_H_
#define _DEFS_H_
/* formatation macros */
#include "switch_version.h"
#include "revision.h"
#define KHOMP_LOG __FILE__, __SWITCH_FUNC__, __LINE__
#define KHOMP_EVENT_MAINT "khomp::maintenance"
#define OBJ_FMT(dev,obj,msg) \
FMT("%s (d=%02d,c=%03d) " msg) % __SWITCH_FUNC__ % dev % obj
#define OBJ_MSG(dev,obj,msg) \
"%s (d=%02d,c=%03d) " msg, __SWITCH_FUNC__, dev, obj
#define PVT_FMT(tgt,msg) \
FMT("%s (d=%02hu,c=%03hu) " msg) % __SWITCH_FUNC__ % tgt.device % tgt.object
#define PVT_MSG(tgt,msg) \
"%s (d=%02hu,c=%03hu) " msg, __SWITCH_FUNC__, tgt.device, tgt.object
#define D(x) ( FMT( "%s: " x ) % __func__ )
#define STR(fmt) \
STG(fmt).c_str()
/* version controller macro */
#define SWITCH_LESS_THAN(x,y,z) \
(FS_VERSION_MICRO != -1) && \
(((FS_VERSION_MAJOR == x) && (FS_VERSION_MINOR == y) && (FS_VERSION_MICRO <= z)) || \
((FS_VERSION_MAJOR == x) && (FS_VERSION_MINOR < y)) || (FS_VERSION_MAJOR < x))
/* signalling groups macro */
#define CASE_R2_SIG \
case ksigR2Digital: \
case ksigContinuousEM: \
case ksigPulsedEM: \
case ksigUserR2Digital: \
case ksigOpenCAS: \
case ksigOpenR2
/*
case ksigLineSide: \
case ksigCAS_EL7: \
case ksigE1LC
*/
#define CASE_RDSI_SIG \
case ksigPRI_EndPoint: \
case ksigPRI_Network: \
case ksigPRI_Passive: \
case ksigOpenCCS
#define CASE_FLASH_GRP \
case ksigLineSide: \
case ksigCAS_EL7: \
case ksigE1LC
/******************************************************************************/
/* Buffering size constants */
#define SILENCE_PACKS 2
#define KHOMP_READ_PACKET_TIME 16 // board sample (ms)
#define KHOMP_READ_PACKET_SIZE (KHOMP_READ_PACKET_TIME * 8) // asterisk sample size (bytes)
#define KHOMP_MIN_READ_PACKET_SIZE (10 * 8) // min size to return on khomp_read
#define KHOMP_MAX_READ_PACKET_SIZE (30 * 8) // max size to return on khomp_read
#define KHOMP_AUDIO_BUFFER_SIZE (KHOMP_READ_PACKET_SIZE * 8) // buffer size (bytes)
/* debug and log macros */
#define DBG(x,y) \
{ \
if (K::Logger::Logg.classe( C_DBG_##x ).enabled()) \
K::Logger::Logg( C_DBG_##x , y ); \
}
#define LOG(x,y) \
{ \
K::Logger::Logg( C_##x , y ); \
}
#define LOGC(x,y) \
{ \
if (K::Logger::Logg.classe( C_##x ).enabled()) \
LOG( x , y ); \
}
/* useful to debug arguments */
#define DEBUG_CLI_CMD() \
{ \
K::Logger::Logg2(C_CLI,stream,FMT("argc: %d ") % argc); \
for(int i = 0;i< argc;i++) \
K::Logger::Logg2(C_CLI,stream,FMT("argv[%d]:%s ") % i % argv[i]); \
}
/* macros to cli commands */
#define ARG_CMP(a,b) (argv[a] && !strncasecmp(argv[a],b,sizeof(b)))
#define EXEC_CLI_CMD(command) Cli::command.execute(argc,argv)
/* macro to string treats */
#define SAFE_sprintf(a, ...) snprintf(a,sizeof(a), __VA_ARGS__)
#define SAFE_strcasecmp(a,b) strncasecmp(a, b, sizeof(b))
/* tags for timers */
#define TM_VAL_CALL (unsigned int)0x01
#define TM_VAL_CHANNEL (unsigned int)0x02
/* macro to creating contexts */
#define BEGIN_CONTEXT do
#define END_CONTEXT while(false);
/* Define log type */
typedef enum
{
C_CLI, /* cli msgs */
C_ERROR, /* errors */
C_WARNING, /* warnings */
C_MESSAGE, /* normal msgs */
C_EVENT, /* k3l events */
C_COMMAND, /* k3l commands */
C_AUDIO_EV, /* k3l audio events */
C_MODEM_EV, /* gsm modem events */
C_LINK_STT, /* link status msgs */
C_CAS_MSGS, /* cas events msgs */
C_DBG_FUNC,
C_DBG_LOCK,
C_DBG_THRD,
C_DBG_STRM,
C_DBG_CONF,
}
class_type;
typedef enum
{
O_CONSOLE,
O_GENERIC,
O_R2TRACE,
}
output_type;
typedef enum
{
SCE_SHOW_WARNING,
SCE_SHOW_DEBUG,
SCE_SHOW_SAME,
SCE_HIDE
}
send_cmd_error_type;
typedef enum
{
T_UNKNOWN = 2,
T_TRUE = 1,
T_FALSE = 0,
}
TriState;
#endif

View File

@ -0,0 +1,160 @@
/*******************************************************************************
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2010 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 _FRAME_HPP_
#define _FRAME_HPP_
#include <stdlib.h>
#include <sys/mman.h>
#include <ringbuffer.hpp>
#include "globals.h"
struct FrameStorage
{
static const unsigned int frame_count = 24;//6;
static const unsigned int audio_count = 24;//4;
FrameStorage(switch_codec_t * codec, int packet_size);
virtual ~FrameStorage();
inline switch_frame_t * next_frame(void)
{
return &(_frames[next_index()]);
}
inline unsigned int next_index()
{
unsigned int tmp = _index;
if (++_index >= frame_count)
_index = 0;
return tmp;
}
inline switch_frame_t * cng_frame(void)
{
return &_cng_frame;
}
char * audio_buffer()
{
return _buffer;
};
private:
switch_frame_t _cng_frame;
switch_frame_t * _frames;
char * _buffer;
unsigned int _index;
};
/* Internal frame array structure. */
template < int S >
struct FrameManager: protected FrameStorage
{
typedef char Packet[ S ];
typedef Ringbuffer < Packet > AudioBuffer;
FrameManager(switch_codec_t * codec)
: FrameStorage(codec, S),
_audio(audio_count, (Packet*)audio_buffer())
{};
// ~FrameManager();
// may throw Ringbuffer::BufferEmpty
switch_frame_t * pick(void)
{
try
{
/* try to consume from buffer.. */
Packet & a = _audio.consumer_start();
switch_frame * f = next_frame();
/* adjust pointer */
f->data = (char *)(&a);
/* advance now */
_audio.consumer_commit();
return f;
}
catch (...) // AudioBuffer::BufferEmpty & e)
{
return NULL;
}
}
// may throw Ringbuffer::BufferFull
bool give(const char * buf, unsigned int size)
{
return _audio.provider_partial(buf, size);
}
switch_frame_t * cng(void)
{
return cng_frame();
}
void clear()
{
_audio.clear();
}
protected:
AudioBuffer _audio;
unsigned int _index;
};
typedef FrameManager < Globals::switch_packet_size > FrameSwitchManager;
typedef FrameManager < Globals::boards_packet_size > FrameBoardsManager;
#endif /* _FRAME_HPP_ */

View File

@ -0,0 +1,119 @@
/*******************************************************************************
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2010 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 _GLOBALS_H_
#define _GLOBALS_H_
#include "k3lapi.hpp"
#include <config_options.hpp>
#include <k3lutil.hpp>
#include <verbose.hpp>
#include <regex.hpp>
#include <timer.hpp>
#include <vector>
#include <string>
#include <fstream>
#include <simple_lock.hpp>
extern "C"
{
#include <switch.h>
}
/* As this is a static-variable-only struct, member variable *
* names need not to get "_" in front of the name */
struct Globals
{
typedef void * global_timer_data;
typedef void (global_timer_func)(global_timer_data);
typedef TimerTemplate < global_timer_func, global_timer_data > GlobalTimer;
typedef SimpleNonBlockLock<25,100> Mutex;
/* FreeSWITCH variables for packets and buffer */
// in ms
static const unsigned int switch_packet_duration = 30;
static const unsigned int boards_packet_duration = 24;
// in bytes
static const unsigned int switch_packet_size = switch_packet_duration * 8;
static const unsigned int boards_packet_size = boards_packet_duration * 8;
static const unsigned int cng_buffer_size = (switch_packet_size > boards_packet_size ? switch_packet_size : boards_packet_size);
/* Father */
static K3LAPI k3lapi;
/* Son */
static K3LUtil k3lutil;
/* Holy Spirit */
static Verbose verbose;
/* Global timer */
static GlobalTimer * global_timer;
/* Mutex to KhompPvt allocation */
static Mutex khomp_alloc_mutex;
/* Config options class */
static ConfigOptions options;
/* FreeSWITCH Articular Ligaments */
static switch_endpoint_interface_t * khomp_endpoint_interface;
static switch_endpoint_interface_t * khomp_sms_endpoint_interface;
static switch_endpoint_interface_t * khomp_pr_endpoint_interface;
static switch_application_interface_t * khomp_app_inteface;
static switch_api_interface_t * api_interface;
static switch_memory_pool_t * module_pool;
/* Still a nice workaround */
volatile static bool logs_being_rotated;
/* Trace flags */
static bool flag_trace_rdsi;
};
#endif /* _GLOBALS_H_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,376 @@
/*******************************************************************************
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2010 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 _KHOMP_PVT_FXO_H_
#define _KHOMP_PVT_FXO_H_
#include "khomp_pvt.h"
#include "applications.h"
/******************************************************************************/
/********************************* FXO Board **********************************/
/******************************************************************************/
struct BoardFXO: public Board
{
/******************************************************************************/
/******************************** FXO Channel *********************************/
struct KhompPvtFXO: public KhompPvt
{
/********************************** FXO Call **********************************/
struct CallFXO : public Call
{
CallFXO() {}
bool process(std::string name, std::string value = "")
{
if (name == "pre")
{
DBG(FUNC, D("pre digits adjusted (%s).") % value);
_pre_digits = value;
}
else if (name == "answer_info")
{
_call_info_report = true;
}
else if (name == "drop_on")
{
_call_info_report = true;
Strings::vector_type drop_item;
Strings::tokenize (value, drop_item, ".+");
for (Strings::vector_type::iterator i = drop_item.begin(); i != drop_item.end(); i++)
{
if ((*i) == "message_box") _call_info_drop |= CI_MESSAGE_BOX;
else if ((*i) == "human_answer") _call_info_drop |= CI_HUMAN_ANSWER;
else if ((*i) == "answering_machine") _call_info_drop |= CI_ANSWERING_MACHINE;
else if ((*i) == "carrier_message") _call_info_drop |= CI_CARRIER_MESSAGE;
else if ((*i) == "unknown") _call_info_drop |= CI_UNKNOWN;
else
{
LOG(ERROR, FMT("unknown paramenter to 'calldrop' Dial option: '%s'.") % (*i));
continue;
}
DBG(FUNC, FMT("droping call on '%s'.") % (*i));
}
}
else if (name == "usr_xfer")
{
_user_xfer_digits = value;
}
else
{
return Call::process(name, value);
}
return true;
}
bool clear()
{
_pre_digits.clear();
_call_info_report = false;
_call_info_drop = 0;
_user_xfer_digits = Opt::_user_xfer;
_user_xfer_buffer.clear();
_digits_buffer.clear();
_var_fax_adjust = T_UNKNOWN;
return Call::clear();
}
std::string _pre_digits;
/* report what we got? */
bool _call_info_report;
/* what call info flags should make us drop the call? */
long int _call_info_drop;
/* used for xfer on user signaling */
std::string _user_xfer_digits;
std::string _user_xfer_buffer;
std::string _digits_buffer;
TriState _var_fax_adjust;
//ChanTimer::Index _idx_disconnect;
};
/******************************************************************************/
KhompPvtFXO(K3LAPI::target & target) : KhompPvt(target)
{
_fax = new Fax(this);
_transfer = new Transfer<CallFXO>(this);
command(KHOMP_LOG, CM_ENABLE_CALL_ANSWER_INFO);
}
~KhompPvtFXO()
{
delete _fax;
delete _transfer;
}
CallFXO * callFXO()
{
return (CallFXO *)call();
}
int makeCall(std::string params = "");
bool doChannelAnswer(CommandRequest &);
bool onNewCall(K3L_EVENT *e);
bool onDisconnect(K3L_EVENT *e);
bool onChannelRelease(K3L_EVENT *e);
bool onCallSuccess(K3L_EVENT *e);
bool onCallFail(K3L_EVENT *e);
bool onAudioStatus(K3L_EVENT *e);
bool onSeizeSuccess(K3L_EVENT *e);
bool onDtmfDetected(K3L_EVENT *e);
bool onDtmfSendFinish(K3L_EVENT *);
bool onCallAnswerInfo(K3L_EVENT *e);
virtual bool eventHandler(K3L_EVENT *e)
{
DBG(STRM, D("(FXO) c"));
bool ret = true;
switch(e->Code)
{
case EV_NEW_CALL:
ret = onNewCall(e);
break;
case EV_DISCONNECT:
ret = onDisconnect(e);
break;
case EV_CHANNEL_FREE:
case EV_CHANNEL_FAIL:
ret = onChannelRelease(e);
break;
case EV_CALL_SUCCESS:
ret = onCallSuccess(e);
break;
case EV_CALL_FAIL:
ret = onCallFail(e);
break;
case EV_AUDIO_STATUS:
ret = onAudioStatus(e);
break;
case EV_SEIZE_SUCCESS:
ret = onSeizeSuccess(e);
break;
case EV_DTMF_DETECTED:
case EV_PULSE_DETECTED:
ret = onDtmfDetected(e);
break;
case EV_DTMF_SEND_FINISH:
ret = onDtmfSendFinish(e);
break;
case EV_CALL_ANSWER_INFO:
ret = onCallAnswerInfo(e);
break;
case EV_FAX_CHANNEL_FREE:
ret = _fax->onFaxChannelRelease(e);
break;
case EV_FAX_FILE_SENT:
case EV_FAX_FILE_FAIL:
case EV_FAX_TX_TIMEOUT:
case EV_FAX_PAGE_CONFIRMATION:
case EV_FAX_REMOTE_INFO:
break;
case EV_POLARITY_REVERSAL:
break;
default:
ret = KhompPvt::eventHandler(e);
break;
}
DBG(STRM, D("(FXO) r"));
return ret;
}
bool application(ApplicationType type, switch_core_session_t * session, const char *data);
bool setupConnection();
bool autoGainControl(bool enable);
void setAnswerInfo(int answer_info);
bool indicateBusyUnlocked(int cause, bool sent_signaling = false);
void reportFailToReceive(int fail_code);
bool validContexts(Board::KhompPvt::ContextListType & contexts, std::string extra_context = "");
bool isOK(void);
bool isPhysicalFree()
{
K3L_CHANNEL_STATUS status;
if (k3lGetDeviceStatus (_target.device, _target.object + ksoChannel, &status, sizeof (status)) != ksSuccess)
return false;
bool physically_free = (status.AddInfo == kfcsEnabled);
if(status.CallStatus != kcsFree || !physically_free)
{
DBG(FUNC, PVT_FMT(_target, "call status not free, or not physically free!"));
return false;
}
return true;
}
virtual bool cleanup(CleanupType type = CLN_HARD)
{
//Board::board(_target.device)->_timers.del(callFXO()->_idx_disconnect);
//callFXO()->_idx_disconnect.reset();
call()->_flags.clear(Kflags::CALL_WAIT_SEIZE);
call()->_flags.clear(Kflags::EARLY_RINGBACK);
_transfer->clear();
switch (type)
{
case CLN_HARD:
case CLN_FAIL:
call()->_flags.clear(Kflags::FAX_DETECTED);
break;
case CLN_SOFT:
break;
}
return KhompPvt::cleanup(type);
}
virtual void getSpecialVariables()
{
try
{
const char * str_fax = getFSChannelVar("KAdjustForFax");
callFXO()->_var_fax_adjust = (str_fax ? (!SAFE_strcasecmp(str_fax, "true") ? T_TRUE : T_FALSE) : T_UNKNOWN);
}
catch(Board::KhompPvt::InvalidSwitchChannel & err)
{
LOG(ERROR, PVT_FMT(_target, "(FXO) %s") % err._msg.c_str());
}
KhompPvt::getSpecialVariables();
}
bool sendDtmf(std::string digit);
/* used by app FAX */
Fax * _fax;
Transfer<CallFXO> * _transfer;
// static void delayedDisconnect(Board::KhompPvt * pvt);
};
/******************************************************************************/
/******************************************************************************/
BoardFXO(int id) : Board(id) {}
void initializeChannels(void)
{
LOG(MESSAGE, "(FXO) loading channels ...");
for (unsigned obj = 0; obj < Globals::k3lapi.channel_count(_device_id); obj++)
{
K3LAPI::target tgt(Globals::k3lapi, K3LAPI::target::CHANNEL, _device_id, obj);
KhompPvt * pvt;
switch(Globals::k3lapi.channel_config(_device_id, obj).Signaling)
{
case ksigAnalog:
pvt = new BoardFXO::KhompPvtFXO(tgt);
pvt->_call = new BoardFXO::KhompPvtFXO::CallFXO();
DBG(FUNC, "(FXO) FXO channel");
break;
default:
pvt = new Board::KhompPvt(tgt);
pvt->_call = new Board::KhompPvt::Call();
DBG(FUNC, FMT("(FXO) signaling %d unknown") % Globals::k3lapi.channel_config(_device_id, obj).Signaling);
break;
}
_channels.push_back(pvt);
pvt->cleanup();
}
}
/*
virtual bool eventHandler(const int obj, K3L_EVENT *e)
{
DBG(STRM, D("(FXO Board) c"));
bool ret = true;
switch(e->Code)
{
case :
break;
default:
ret = Board::eventHandler(obj, e);
break;
}
DBG(STRM, D("(FXO Board) r"));
return ret;
}
*/
};
/******************************************************************************/
/******************************************************************************/
/******************************************************************************/
#endif /* _KHOMP_PVT_FXO_H_*/

View File

@ -0,0 +1,332 @@
/*******************************************************************************
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2010 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 _KHOMP_PVT_GSM_H_
#define _KHOMP_PVT_GSM_H_
#include "khomp_pvt.h"
#include "applications.h"
/******************************************************************************/
/********************************* GSM Board **********************************/
/******************************************************************************/
struct BoardGSM: public Board
{
/******************************************************************************/
/******************************** GSM Channel *********************************/
struct KhompPvtGSM: public KhompPvt
{
/********************************** GSM Call **********************************/
struct CallGSM : public Call
{
CallGSM() {}
bool process(std::string name, std::string value = "")
{
if (name == "answer_info")
{
_call_info_report = true;
}
else if (name == "drop_on")
{
_call_info_report = true;
Strings::vector_type drop_item;
Strings::tokenize (value, drop_item, ".+");
for (Strings::vector_type::iterator i = drop_item.begin(); i != drop_item.end(); i++)
{
if ((*i) == "message_box") _call_info_drop |= CI_MESSAGE_BOX;
else if ((*i) == "human_answer") _call_info_drop |= CI_HUMAN_ANSWER;
else if ((*i) == "answering_machine") _call_info_drop |= CI_ANSWERING_MACHINE;
else if ((*i) == "carrier_message") _call_info_drop |= CI_CARRIER_MESSAGE;
else if ((*i) == "unknown") _call_info_drop |= CI_UNKNOWN;
else
{
LOG(ERROR, FMT("unknown paramenter to 'calldrop' Dial option: '%s'.") % (*i));
continue;
}
DBG(FUNC, FMT("droping call on '%s'.") % (*i));
}
}
else
{
return Call::process(name, value);
}
return true;
}
bool clear()
{
_call_info_report = false;
_call_info_drop = 0;
return Call::clear();
}
/* report what we got? */
bool _call_info_report;
/* what call info flags should make us drop the call? */
long int _call_info_drop;
};
/******************************************************************************/
KhompPvtGSM(K3LAPI::target & target) : KhompPvt(target)
{
_sms = new SMS(this);
command(KHOMP_LOG, CM_ENABLE_CALL_ANSWER_INFO);
}
~KhompPvtGSM()
{
delete _sms;
}
CallGSM * callGSM()
{
return (CallGSM *)call();
}
int makeCall(std::string params = "");
bool doChannelAnswer(CommandRequest &);
bool doChannelHangup(CommandRequest &);
//bool onNewCall(K3L_EVENT *e);
bool onChannelRelease(K3L_EVENT *e);
bool onCallFail(K3L_EVENT *e);
bool onCallSuccess(K3L_EVENT *e);
bool onCallAnswerInfo(K3L_EVENT *e);
bool onDisconnect(K3L_EVENT *e);
//bool onDtmfDetected(K3L_EVENT *e);
virtual bool eventHandler(K3L_EVENT *e)
{
DBG(STRM, D("(GSM) c"));
bool ret = true;
switch(e->Code)
{
/*
case EV_NEW_CALL:
onNewCall(e);
break;
*/
case EV_CHANNEL_FREE:
case EV_CHANNEL_FAIL:
ret = onChannelRelease(e);
break;
case EV_CALL_SUCCESS:
ret = onCallSuccess(e);
break;
case EV_DISCONNECT:
ret = onDisconnect(e);
break;
case EV_CALL_FAIL:
ret = onCallFail(e);
break;
case EV_CALL_ANSWER_INFO:
ret = onCallAnswerInfo(e);
break;
case EV_RECV_FROM_MODEM:
break;
case EV_NEW_SMS:
ret = _sms->onNewSMS(e);
break;
case EV_SMS_INFO:
ret = _sms->onSMSInfo(e);
break;
case EV_SMS_DATA:
ret = _sms->onSMSData(e);
break;
case EV_SMS_SEND_RESULT:
ret = _sms->onSMSSendResult(e);
break;
default:
ret = KhompPvt::eventHandler(e);
break;
}
DBG(STRM, D("(GSM) r"));
return ret;
}
bool application(ApplicationType type, switch_core_session_t * session, const char *data);
bool setupConnection();
void setAnswerInfo(int answer_info);
bool indicateBusyUnlocked(int cause, bool sent_signaling = false);
void reportFailToReceive(int fail_code);
int causeFromCallFail(int fail);
int callFailFromCause(int cause);
bool isOK(void);
bool isPhysicalFree()
{
K3L_CHANNEL_STATUS status;
if (k3lGetDeviceStatus (_target.device, _target.object + ksoChannel, &status, sizeof (status)) != ksSuccess)
return false;
bool physically_free = (status.AddInfo == kgsmIdle);
if(status.CallStatus != kcsFree || !physically_free)
{
DBG(FUNC, PVT_FMT(_target, "call status not free, or not physically free!"));
return false;
}
return true;
}
bool sendPreAudio(int rb_value = RingbackDefs::RB_SEND_NOTHING)
{
return false;
}
bool selectSimCard(const char * sim_card)
{
return command(KHOMP_LOG, CM_SIM_CARD_SELECT, sim_card);
}
std::string getStatistics(Statistics::Type type)
{
switch(type)
{
case Statistics::DETAILED:
{
/* buffer our data to return at the end */
std::string strBuffer;
strBuffer.append(_pvt_statistics->getDetailed());
strBuffer.append(_sms->statistics()->getDetailed());
return strBuffer;
}
case Statistics::ROW:
{
return _pvt_statistics->getRow();
}
default:
return "";
}
}
void clearStatistics()
{
KhompPvt::clearStatistics();
_sms->statistics()->clear();
}
bool validContexts(Board::KhompPvt::ContextListType & contexts, std::string extra_context = "");
SMS * _sms;
};
/******************************************************************************/
/******************************************************************************/
BoardGSM(int id) : Board(id) {}
void initializeChannels(void)
{
LOG(MESSAGE, "(GSM) loading channels ...");
for (unsigned obj = 0; obj < Globals::k3lapi.channel_count(_device_id); obj++)
{
K3LAPI::target tgt(Globals::k3lapi, K3LAPI::target::CHANNEL, _device_id, obj);
KhompPvt * pvt;
switch(Globals::k3lapi.channel_config(_device_id, obj).Signaling)
{
case ksigGSM:
pvt = new BoardGSM::KhompPvtGSM(tgt);
pvt->_call = new BoardGSM::KhompPvtGSM::CallGSM();
((BoardGSM::KhompPvtGSM *)pvt)->_sms->start();
DBG(FUNC, "(GSM) GSM channel");
break;
default:
pvt = new Board::KhompPvt(tgt);
pvt->_call = new Board::KhompPvt::Call();
DBG(FUNC, FMT("(GSM) signaling %d unknown") % Globals::k3lapi.channel_config(_device_id, obj).Signaling);
break;
}
_channels.push_back(pvt);
pvt->cleanup();
}
}
/*
virtual bool eventHandler(const int obj, K3L_EVENT *e)
{
DBG(STRM, D("(GSM Board) c"));
bool ret = true;
switch(e->Code)
{
case :
break;
default:
ret = Board::eventHandler(obj, e);
break;
}
DBG(STRM, D("(GSM Board) r"));
return ret;
}
*/
};
/******************************************************************************/
/******************************************************************************/
/******************************************************************************/
#endif /* _KHOMP_PVT_GSM_H_*/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,304 @@
/*******************************************************************************
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2010 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 _KHOMP_PVT_PASSIVE_H_
#define _KHOMP_PVT_PASSIVE_H_
#include "khomp_pvt.h"
#include "applications.h"
/******************************************************************************/
/******************************** Passive Board *******************************/
/******************************************************************************/
struct BoardPassive: public Board
{
/******************************************************************************/
/******************************** Passive Channel *****************************/
struct KhompPvtPassive: public KhompPvt
{
/******************************** Passive Call ********************************/
/*
struct CallPassive : public Call
{
CallPassive() {}
bool process(std::string name, std::string value = "")
{
}
else
{
return Call::process(name, value);
}
return true;
}
bool clear()
{
return Call::clear();
}
};
*/
/******************************************************************************/
KhompPvtPassive(K3LAPI::target & target) : KhompPvt(target)
{
}
~KhompPvtPassive()
{
}
/*
CallPassive * callPassive()
{
return (CallPassive *)call();
}
*/
virtual bool eventHandler(K3L_EVENT *e)
{
DBG(STRM, D("(Passive) c"));
bool ret = true;
switch(e->Code)
{
case EV_CHANNEL_FREE:
case EV_CHANNEL_FAIL:
ret = onChannelRelease(e);
break;
/*
case EV_CALL_SUCCESS:
case EV_CALL_FAIL:
case EV_PULSE_DETECTED:
*/
case EV_DISCONNECT:
case EV_DTMF_DETECTED:
case EV_AUDIO_STATUS:
break;
default:
ret = true;
break;
}
DBG(STRM, D("(Passive) r"));
return ret;
}
bool validContexts(Board::KhompPvt::ContextListType & contexts, std::string extra_context = "");
/*
virtual bool cleanup(CleanupType type = CLN_HARD)
{
switch (type)
{
case CLN_HARD:
case CLN_FAIL:
break;
case CLN_SOFT:
break;
}
return KhompPvt::cleanup(type);
}
*/
};
/******************************************************************************/
/********************************** HI Channel ********************************/
struct KhompPvtHI: public KhompPvtPassive
{
KhompPvtHI(K3LAPI::target & target) : KhompPvtPassive(target)
{
}
~KhompPvtHI()
{
}
bool onSeizureStart(K3L_EVENT *e);
virtual bool eventHandler(K3L_EVENT *e)
{
DBG(STRM, D("(HI) c"));
bool ret = true;
switch(e->Code)
{
case EV_SEIZURE_START:
ret = onSeizureStart(e);
break;
case EV_RING_DETECTED:
case EV_POLARITY_REVERSAL:
break;
default:
ret = KhompPvtPassive::eventHandler(e);
break;
}
DBG(STRM, D("(HI) r"));
return ret;
}
};
/******************************************************************************/
/********************************* KPR Channel ********************************/
struct KhompPvtKPR: public KhompPvtPassive
{
KhompPvtKPR(K3LAPI::target & target) : KhompPvtPassive(target)
{
}
~KhompPvtKPR()
{
}
bool onNewCall(K3L_EVENT *e);
/*
bool onConnect(K3L_EVENT *e);
*/
virtual bool eventHandler(K3L_EVENT *e)
{
DBG(STRM, D("(KPR) c"));
bool ret = true;
switch(e->Code)
{
case EV_NEW_CALL:
ret = onNewCall(e);
break;
case EV_CONNECT:
break;
case EV_SEIZURE_START:
case EV_CAS_MFC_RECV:
case EV_CAS_LINE_STT_CHANGED:
case EV_LINK_STATUS:
break;
default:
ret = KhompPvtPassive::eventHandler(e);
break;
}
DBG(STRM, D("(KPR) r"));
return ret;
}
bool obtainBoth();
};
/******************************************************************************/
/******************************************************************************/
BoardPassive(int id) : Board(id) {}
void initializeChannels(void)
{
LOG(MESSAGE, "(Passive) loading channels ...");
for (unsigned obj = 0; obj < Globals::k3lapi.channel_count(_device_id); obj++)
{
K3LAPI::target tgt(Globals::k3lapi, K3LAPI::target::CHANNEL, _device_id, obj);
KhompPvt * pvt;
switch(Globals::k3lapi.channel_config(_device_id, obj).Signaling)
{
case ksigAnalog:
pvt = new BoardPassive::KhompPvtHI(tgt);
pvt->_call = new BoardPassive::KhompPvtHI::Call();
DBG(FUNC, "(Passive) HI channel");
break;
CASE_RDSI_SIG:
CASE_R2_SIG:
CASE_FLASH_GRP:
case ksigAnalogTerminal:
pvt = new BoardPassive::KhompPvtKPR(tgt);
pvt->_call = new BoardPassive::KhompPvtKPR::Call();
DBG(FUNC, "(Passive) KPR channel");
break;
default:
pvt = new Board::KhompPvt(tgt);
pvt->_call = new Board::KhompPvt::Call();
DBG(FUNC, FMT("(Passive) signaling %d unknown") % Globals::k3lapi.channel_config(_device_id, obj).Signaling);
break;
}
_channels.push_back(pvt);
pvt->cleanup();
}
}
/*
virtual bool eventHandler(const int obj, K3L_EVENT *e)
{
DBG(STRM, D("(Passive Board) c"));
bool ret = true;
switch(e->Code)
{
case :
break;
default:
ret = Board::eventHandler(obj, e);
break;
}
DBG(STRM, D("(Passive Board) r"));
return ret;
}
*/
};
/******************************************************************************/
/******************************************************************************/
/******************************************************************************/
#endif /* _KHOMP_PVT_PASSIVE_H_*/

View File

@ -0,0 +1,86 @@
/*******************************************************************************
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2010 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 CHAN_LOCK_H
#define CHAN_LOCK_H
#include <scoped_lock.hpp>
#include "khomp_pvt.h"
struct ScopedLockFailed
{
typedef enum { NULL_PVT, NULL_SOFT_CHAN, FAILED, ALLOC_FAILED } FailType;
ScopedLockFailed(FailType fail, std::string msg)
: _fail(fail), _msg(msg) {};
FailType _fail;
std::string _msg;
};
struct ScopedPvtLock: public ScopedLockBasic
{
typedef Board::KhompPvt KhompPvt;
ScopedPvtLock(KhompPvt * pvt);
~ScopedPvtLock();
void unlock();
protected:
KhompPvt * _pvt;
};
struct ScopedAllocLock : public ScopedLockBasic
{
ScopedAllocLock();
~ScopedAllocLock();
void unlock();
};
#endif /* CHAN_LOCK_H */

View File

@ -0,0 +1,141 @@
/*******************************************************************************
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2010 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 _Logger_H_
#define _Logger_H_
#include <switch.h>
#include <string>
#include <simple_lock.hpp>
#include <logger.hpp>
#include <configurator/configfile.hpp>
#include <klog-config.hpp>
#include "defs.h"
#include "format.hpp"
namespace K
{
struct LogConfig
{
static bool set(Logfile &, const char *, const char *, bool);
static bool commit(Logfile &);
};
struct SwitchConsoleLog {};
struct SwitchPrinter: public Logger::DefaultPrinter
{
typedef Logger::DefaultPrinter Super;
typedef Tagged::Union < std::ostream *, Tagged::Union < int, Tagged::Union < SwitchConsoleLog > > > BaseType;
SwitchPrinter(std::string & msg): Super(msg) {};
using Super::operator();
bool operator()(const SwitchConsoleLog & ignored)
{
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN,SWITCH_LOG_CONSOLE,"%s",_msg.c_str());
return true;
};
};
/* Log manager declaration. */
typedef Logger::Manager <class_type, output_type, SwitchPrinter, SimpleLock> LogManager;
/* Forward declaration */
struct LogInternalManager;
struct Logger
{
/* Logger instance. */
static LogManager Logg;
/* Util Logger instance. */
static LogInternalManager Logg2;
static bool start();
static void stop();
static bool rotate();
static void processLogConsole(switch_stream_handle_t *s, const std::string options, bool invert, bool unique);
static void processLogDisk(switch_stream_handle_t *s, const std::string options, bool invert, bool unique);
private:
static std::string base_path;
static std::ofstream generic_file;
};
/* Internal logging facility declaration */
struct LogInternalManager
{
bool operator()(class_type classe, switch_stream_handle_t *stream, const char *args)
{
switch (classe)
{
case C_CLI:
stream->write_function(stream,"%s\n",args);
return true;
default:
return K::Logger::Logg(classe, args);
}
}
bool operator()(class_type classe, switch_stream_handle_t *stream, Format &fmt)
{
return K::Logger::Logg2(classe,stream,(char*) STR(fmt));
}
bool operator()(class_type classe, switch_stream_handle_t *stream, const char *fmt, const char *args)
{
switch (classe)
{
case C_CLI:
stream->write_function(stream,fmt,args);
return true;
default:
return K::Logger::Logg(classe, FMT(fmt) % args);
}
}
};
};
#endif /* _Logger_H_ */

View File

@ -0,0 +1,250 @@
/*******************************************************************************
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2010 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 _OPT_H_
#define _OPT_H_
#include <string>
#include <map>
#include <vector>
#include "switch.h"
#include "utils.h"
struct CadenceType
{
CadenceType(void)
: ring(0), ring_s(0), ring_ext(0), ring_ext_s(0) {};
CadenceType(unsigned int _ring, unsigned int _ring_s)
: ring(_ring), ring_s(_ring_s), ring_ext(0), ring_ext_s(0) {};
CadenceType(unsigned int _ring, unsigned int _ring_s, unsigned int _ring_ext, unsigned int _ring_ext_s)
: ring(_ring), ring_s(_ring_s), ring_ext(_ring_ext), ring_ext_s(_ring_ext_s) {};
unsigned int ring;
unsigned int ring_s;
unsigned int ring_ext;
unsigned int ring_ext_s;
};
struct CSpan {
std::string _dialplan;
std::string _context;
std::string _dialstring;
};
struct Opt
{
typedef std::pair < std::string, CadenceType > CadencesPairType;
typedef std::map < std::string, CadenceType > CadencesMapType;
typedef std::map < std::string, std::string > OrigToDestMapType;
typedef std::pair < std::string, std::string > OrigToDestPairType;
typedef std::vector < std::string > DestVectorType;
typedef std::map < unsigned int, std::string > BoardToOrigMapType;
typedef std::pair < unsigned int, std::string > BoardToOrigPairType;
typedef std::map < std::string, unsigned int > OrigToNseqMapType;
typedef std::pair < std::string, unsigned int > OrigToNseqPairType;
typedef std::pair < unsigned int,unsigned int > ObjectIdType;
typedef std::pair < std::string, ObjectIdType > BranchToObjectPairType;
typedef std::map < std::string, ObjectIdType > BranchToObjectMapType;
typedef std::map < std::string, std::string > BranchToOptMapType;
typedef std::pair < std::string, std::string > BranchToOptPairType;
typedef std::map < std::string, std::string > GroupToDestMapType;
typedef std::pair < std::string, std::string > GroupToDestPairType;
typedef std::pair < std::string, CSpan > SpanPairType;
typedef enum
{
GFLAG_MY_CODEC_PREFS = (1 << 0)
}
GFLAGS;
static void initialize(void);
static void obtain(void);
static void commit(void);
static void printConfiguration(switch_stream_handle_t*);
protected:
static void loadConfiguration(const char *, const char **, bool show_errors = true);
static void cleanConfiguration(void);
static switch_xml_t processSimpleXML(switch_xml_t &xml, const std::string& child_name);
static void processGroupXML(switch_xml_t &xml);
static void processCadenceXML(switch_xml_t &xml);
static void processFXSBranchesXML(switch_xml_t &xml);
static void processFXSHotlines(switch_xml_t &xml);
static void processFXSOptions(switch_xml_t &xml);
public:
static bool _debug;
static std::string _dialplan;
static std::string _context;
static std::map < std::string, CSpan > _spans;
static GroupToDestMapType _groups;
static CadencesMapType _cadences;
static bool _echo_canceller;
static bool _auto_gain_control;
static bool _out_of_band_dtmfs;
static bool _suppression_delay;
static bool _pulse_forwarding;
static bool _native_bridge;
static bool _recording;
static bool _has_ctbus;
static bool _fxs_bina;
static bool _fxo_send_pre_audio;
static bool _drop_collect_call;
static bool _ignore_letter_dtmfs;
static bool _optimize_audio_path;
static bool _auto_fax_adjustment;
static unsigned int _fax_adjustment_timeout;
static bool _r2_strict_behaviour;
static unsigned int _r2_preconnect_wait;
static unsigned int _fxs_digit_timeout;
static unsigned int _transferdigittimeout;
static std::string _blindxfer;
static std::string _atxfer;
static unsigned int _ringback_co_delay;
static unsigned int _ringback_pbx_delay;
static unsigned int _disconnect_delay;
static int _input_volume;
static int _output_volume;
static DestVectorType _fxs_co_dialtone;
static OrigToDestMapType _fxs_hotline;
static std::string _fxs_global_orig_base;
static BoardToOrigMapType _fxs_orig_base;
static BranchToObjectMapType _fxs_branch_map;
static BranchToOptMapType _branch_options;
static std::string _global_mohclass;
static std::string _global_language;
static std::string _record_prefix;
static std::string _context_gsm_call;
static std::string _context2_gsm_call;
static std::string _context_gsm_sms;
static std::string _context_fxo;
static std::string _context2_fxo;
static std::string _context_fxs;
static std::string _context2_fxs;
static std::string _context_digital;
static std::string _context_pr;
static std::string _user_xfer;
static int _amaflags;
static std::string _callgroup;
static std::string _pickupgroup; /* or intercept */
static std::string _accountcode;
static unsigned int _kommuter_timeout;
static std::string _kommuter_activation;
static unsigned int _audio_packet_size;
protected:
struct ProcessFXSCODialtone
{
void operator()(std::string options);
};
struct ProcessRecordPrefix
{
void operator()(std::string path);
};
struct ProcessAMAFlags
{
void operator()(std::string options);
};
struct ProcessCallGroup
{
void operator()(std::string options);
};
struct ProcessPickupGroup
{
void operator()(std::string options);
};
struct ProcessLogOptions
{
ProcessLogOptions(output_type output): _output(output) {};
void operator()(std::string options);
protected:
output_type _output;
};
struct ProcessTraceOptions
{
void operator()(std::string options);
};
};
#endif /* _OPT_H_ */

View File

@ -0,0 +1 @@
#define MOD_KHOMP_VERSION "1.0 - (rev: 5796)"

View File

@ -0,0 +1,98 @@
/*******************************************************************************
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2010 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 _SPEC_HPP_
#define _SPEC_HPP_
#include <function.hpp>
#include "khomp_pvt.h"
typedef enum
{
SPR_CONTINUE,
SPR_SUCCESS,
SPR_FAIL,
}
SpecRetType;
typedef enum
{
SPF_FIRST = 0x01,
SPF_CYCLIC = 0x02,
}
SpecFlagType;
typedef unsigned int SpecFlagsType;
typedef Function::Function3 < bool, unsigned int, unsigned int, SpecFlagsType & > SpecFunType;
//SpecRetType processSpecAtom(std::string &, SpecFlagsType &, SpecFunType &);
//SpecRetType processSpecAtoms(std::string &, SpecFlagsType &, SpecFunType &);
//bool processCallChannelString(std::string &, Board::KhompPvt *&, int *, bool need_free = true);
/* Request a Board::KhompPvt based on dialplan string.
-- Format of dialplan string. --
Dial(Khomp/B2C58/4832625644)
| | | |
| | | |
| | | |
| | | +- Destination number.
| | |
| | +- Identifier for board 2, channel 58.
| |
| +- Khomp channel identifier.
|
+- Dial Application.
*/
Board::KhompPvt * processDialString(const char *, int *);
void processGroupString();
Board::KhompPvt * processSMSString(const char *, int *);
#endif /* _SPEC_HPP_ */

Some files were not shown because too many files have changed in this diff Show More