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

This commit is contained in:
Eric des Courtis 2010-05-25 15:52:21 -04:00
commit c2349da522
15 changed files with 197 additions and 58 deletions

View File

@ -85,7 +85,6 @@ Global
{6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Debug|Win32.ActiveCfg = Debug|Win32
{6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Debug|x64.ActiveCfg = Debug|x64
{6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Release|Win32.ActiveCfg = Release|Win32
{6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Release|Win32.Build.0 = Release|Win32
{6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Release|x64.ActiveCfg = Release|x64
{FE3540C5-3303-46E0-A69E-D92F775687F1}.Debug|Win32.ActiveCfg = Debug|Win32
{FE3540C5-3303-46E0-A69E-D92F775687F1}.Debug|Win32.Build.0 = Debug|Win32
@ -114,7 +113,6 @@ Global
{729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Debug|Win32.ActiveCfg = Debug|Win32
{729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Debug|x64.ActiveCfg = Debug|x64
{729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Release|Win32.ActiveCfg = Release|Win32
{729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Release|Win32.Build.0 = Release|Win32
{729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Release|x64.ActiveCfg = Release|x64
{E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}.Debug|Win32.ActiveCfg = Debug|Win32
{E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}.Debug|x64.ActiveCfg = Debug|x64

View File

@ -2294,6 +2294,7 @@ static switch_status_t load_config(void)
char *hold_music = NULL;
char *fail_dial_regex = NULL;
const char *enable_callerid = "true";
int callwaiting = 1;
uint32_t span_id = 0, to = 0, max = 0;
ftdm_span_t *span = NULL;
@ -2303,6 +2304,7 @@ static switch_status_t load_config(void)
char *var = (char *) switch_xml_attr_soft(param, "name");
char *val = (char *) switch_xml_attr_soft(param, "value");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "analog_spans var = %s\n", var);
if (!strcasecmp(var, "tonegroup")) {
tonegroup = val;
} else if (!strcasecmp(var, "digit_timeout") || !strcasecmp(var, "digit-timeout")) {
@ -2323,6 +2325,8 @@ static switch_status_t load_config(void)
max_digits = val;
} else if (!strcasecmp(var, "hotline")) {
hotline = val;
} else if (!strcasecmp(var, "callwaiting")) {
callwaiting = switch_true(val) ? 1 : 0;
} else if (!strcasecmp(var, "enable-analog-option")) {
analog_options = enable_analog_option(val, analog_options);
}
@ -2332,8 +2336,6 @@ static switch_status_t load_config(void)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "span missing required param 'id'\n");
continue;
}
if (!tonegroup) {
tonegroup = "us";
@ -2373,8 +2375,9 @@ static switch_status_t load_config(void)
"tonemap", tonegroup,
"digit_timeout", &to,
"max_dialstr", &max,
"hotline", hotline,
"hotline", hotline ? hotline : "",
"enable_callerid", enable_callerid,
"callwaiting", &callwaiting,
FTDM_TAG_END) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Error configuring FreeTDM analog span %s\n", ftdm_span_get_name(span));
continue;

View File

@ -197,7 +197,7 @@
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../src/include;../src/isdn/include"
AdditionalIncludeDirectories="../src/include;../src/include/private;../src/isdn/include"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;FREETDM_EXPORTS;TELETONE_EXPORTS"
RuntimeLibrary="2"
DisableLanguageExtensions="false"

View File

@ -1677,8 +1677,10 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open(uint32_t span_id, uint32_t chan_id,
status = FTDM_FAIL;
if (ftdm_test_flag(check, FTDM_CHANNEL_READY) && (!ftdm_test_flag(check, FTDM_CHANNEL_INUSE) ||
(check->type == FTDM_CHAN_TYPE_FXS && check->token_count == 1))) {
/* the channel is only allowed to be open if not in use, or, for FXS devices with a call with call waiting enabled */
if ((!ftdm_test_flag(check, FTDM_CHANNEL_INUSE))
|| ((check->type == FTDM_CHAN_TYPE_FXS && check->token_count == 1) && (ftdm_channel_test_feature(check, FTDM_CHANNEL_FEATURE_CALLWAITING))))
{
if (!ftdm_test_flag(check, FTDM_CHANNEL_OPEN)) {
status = check->fio->open(check);
if (status == FTDM_SUCCESS) {
@ -1692,7 +1694,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open(uint32_t span_id, uint32_t chan_id,
}
ftdm_mutex_unlock(check->mutex);
done:
done:
ftdm_mutex_unlock(globals.mutex);
return status;

View File

@ -161,6 +161,8 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_configure_span)
const char *var, *val;
int *intval;
uint32_t flags = FTDM_ANALOG_CALLERID;
int callwaiting = 1;
unsigned int i = 0;
assert(sig_cb != NULL);
ftdm_log(FTDM_LOG_DEBUG, "Configuring span %s for analog signaling ...\n", span->name);
@ -172,10 +174,13 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_configure_span)
}
analog_data = ftdm_malloc(sizeof(*analog_data));
assert(analog_data != NULL);
ftdm_assert_return(analog_data != NULL, FTDM_FAIL, "malloc failure\n");
memset(analog_data, 0, sizeof(*analog_data));
while ((var = va_arg(ap, char *))) {
ftdm_log(FTDM_LOG_DEBUG, "Analog config var = %s\n", var);
if (!strcasecmp(var, "tonemap")) {
if (!(val = va_arg(ap, char *))) {
break;
@ -196,6 +201,11 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_configure_span)
} else {
flags &= ~FTDM_ANALOG_CALLERID;
}
} else if (!strcasecmp(var, "callwaiting")) {
if (!(intval = va_arg(ap, int *))) {
break;
}
callwaiting = *intval;
} else if (!strcasecmp(var, "max_dialstr")) {
if (!(intval = va_arg(ap, int *))) {
break;
@ -219,6 +229,12 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_configure_span)
if ((max_dialstr < 1 && !strlen(hotline)) || max_dialstr > MAX_DTMF) {
max_dialstr = MAX_DTMF;
}
if (callwaiting) {
for (i = 1; i <= span->chan_count; i++) {
ftdm_channel_set_feature(span->channels[i], FTDM_CHANNEL_FEATURE_CALLWAITING);
}
}
span->start = ftdm_analog_start;
span->stop = ftdm_analog_stop;
@ -329,24 +345,24 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
ftdm_sigmsg_t sig;
ftdm_status_t status;
ftdm_log(FTDM_LOG_DEBUG, "ANALOG CHANNEL thread starting.\n");
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "ANALOG CHANNEL thread starting.\n");
ts.buffer = NULL;
if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "OPEN ERROR [%s]\n", ftdmchan->last_error);
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "OPEN ERROR [%s]\n", ftdmchan->last_error);
goto done;
}
if (ftdm_buffer_create(&dt_buffer, 1024, 3192, 0) != FTDM_SUCCESS) {
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "memory error!");
ftdm_log(FTDM_LOG_ERROR, "MEM ERROR\n");
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "MEM ERROR\n");
goto done;
}
if (ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_DTMF_DETECT, &tt) != FTDM_SUCCESS) {
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "error initilizing tone detector!");
ftdm_log(FTDM_LOG_ERROR, "TONE ERROR\n");
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "TONE ERROR\n");
goto done;
}
@ -500,7 +516,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
indicate = 0;
state_counter = 0;
ftdm_log(FTDM_LOG_DEBUG, "Executing state handler on %d:%d for %s\n",
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Executing state handler on %d:%d for %s\n",
ftdmchan->span_id, ftdmchan->chan_id,
ftdm_channel_state2str(ftdmchan->state));
switch(ftdmchan->state) {
@ -515,7 +531,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
}
if (ftdmchan->fsk_buffer && ftdm_buffer_inuse(ftdmchan->fsk_buffer)) {
ftdm_log(FTDM_LOG_DEBUG, "Cancel FSK transmit due to early answer.\n");
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Cancel FSK transmit due to early answer.\n");
ftdm_buffer_zero(ftdmchan->fsk_buffer);
}
@ -676,7 +692,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
if (last_digit && (!collecting || ((elapsed - last_digit > analog_data->digit_timeout) || strlen(dtmf) >= analog_data->max_dialstr))) {
ftdm_log(FTDM_LOG_DEBUG, "Number obtained [%s]\n", dtmf);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Number obtained [%s]\n", dtmf);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE);
last_digit = 0;
collecting = 0;
@ -691,7 +707,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
}
if (ftdm_channel_read(ftdmchan, frame, &len) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_WARNING, "read error [%s]\n", ftdmchan->last_error);
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "read error [%s]\n", ftdmchan->last_error);
continue;
}
@ -706,7 +722,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
for (i = 1; i < FTDM_TONEMAP_INVALID; i++) {
if (ftdmchan->detected_tones[i]) {
ftdm_log(FTDM_LOG_DEBUG, "Detected tone %s on %d:%d\n", ftdm_tonemap2str(i), ftdmchan->span_id, ftdmchan->chan_id);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Detected tone %s on %d:%d\n", ftdm_tonemap2str(i), ftdmchan->span_id, ftdmchan->chan_id);
sig.raw_data = &i;
ftdm_span_send_signal(ftdmchan->span, &sig);
}
@ -718,15 +734,15 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
ftdmchan->detected_tones[FTDM_TONEMAP_FAIL3] ||
ftdmchan->detected_tones[FTDM_TONEMAP_ATTN]
) {
ftdm_log(FTDM_LOG_ERROR, "Failure indication detected!\n");
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Failure indication detected!\n");
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY);
} else if (ftdmchan->detected_tones[FTDM_TONEMAP_DIAL]) {
if (ftdm_strlen_zero(ftdmchan->caller_data.dnis.digits)) {
ftdm_log(FTDM_LOG_ERROR, "No Digits to send!\n");
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "No Digits to send!\n");
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY);
} else {
if (ftdm_channel_command(ftdmchan, FTDM_COMMAND_SEND_DTMF, ftdmchan->caller_data.dnis.digits) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Send Digits Failed [%s]\n", ftdmchan->last_error);
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Send Digits Failed [%s]\n", ftdmchan->last_error);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY);
} else {
state_counter = 0;
@ -815,7 +831,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
ftdm_set_state_locked(closed_chan, FTDM_CHANNEL_STATE_DOWN);
}
ftdm_log(FTDM_LOG_DEBUG, "ANALOG CHANNEL %d:%d thread ended.\n", closed_chan->span_id, closed_chan->chan_id);
ftdm_log_chan(closed_chan, FTDM_LOG_DEBUG, "ANALOG CHANNEL %d:%d thread ended.\n", closed_chan->span_id, closed_chan->chan_id);
ftdm_clear_flag(closed_chan, FTDM_CHANNEL_INTHREAD);
return NULL;
@ -839,7 +855,7 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e
sig.channel = event->channel;
ftdm_log(FTDM_LOG_DEBUG, "EVENT [%s][%d:%d] STATE [%s]\n",
ftdm_log_chan(event->channel, FTDM_LOG_DEBUG, "EVENT [%s][%d:%d] STATE [%s]\n",
ftdm_oob_event2str(event->enum_id), event->channel->span_id, event->channel->chan_id, ftdm_channel_state2str(event->channel->state));
ftdm_mutex_lock(event->channel->mutex);
@ -849,7 +865,7 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e
case FTDM_OOB_RING_START:
{
if (event->channel->type != FTDM_CHAN_TYPE_FXO) {
ftdm_log(FTDM_LOG_ERROR, "Cannot get a RING_START event on a non-fxo channel, please check your config.\n");
ftdm_log_chan_msg(event->channel, FTDM_LOG_ERROR, "Cannot get a RING_START event on a non-fxo channel, please check your config.\n");
ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_DOWN);
goto end;
}

View File

@ -948,6 +948,7 @@ static void handle_call_answer(ftdm_span_t *span, sangomabc_connection_t *mcon,
}
static __inline__ void advance_chan_states(ftdm_channel_t *ftdmchan);
static __inline__ void stop_loop(ftdm_channel_t *ftdmchan);
/**
* \brief Handler for call start event
@ -959,6 +960,10 @@ static void handle_call_start(ftdm_span_t *span, sangomabc_connection_t *mcon, s
{
ftdm_channel_t *ftdmchan = NULL;
int hangup_cause = FTDM_CAUSE_CALL_REJECTED;
int retry = 1;
tryagain:
if (!(ftdmchan = find_ftdmchan(span, (sangomabc_short_event_t*)event, 0))) {
if ((ftdmchan = find_ftdmchan(span, (sangomabc_short_event_t*)event, 1))) {
int r;
@ -990,6 +995,11 @@ static void handle_call_start(ftdm_span_t *span, sangomabc_connection_t *mcon, s
* the other side to send the call start nack ( or proceed with the call )
* ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING, r);
*/
} else if (ftdmchan->state == FTDM_CHANNEL_STATE_IN_LOOP && retry) {
retry = 0;
stop_loop(ftdmchan);
advance_chan_states(ftdmchan);
goto tryagain;
} else {
ftdm_log(FTDM_LOG_ERROR, "s%dc%d: rejecting incoming call in channel state %s\n",
BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event),
@ -1092,10 +1102,21 @@ static void handle_call_loop_start(ftdm_span_t *span, sangomabc_connection_t *mc
ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_LOOP, NULL);
}
static __inline__ void stop_loop(ftdm_channel_t *ftdmchan)
{
ftdm_status_t res = FTDM_FAIL;
ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_LOOP, NULL);
/* even when we did not sent a msg we set this flag to avoid sending call stop in the DOWN state handler */
ftdm_set_flag(ftdmchan, SFLAG_SENT_FINAL_MSG);
ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_DOWN, res);
if (res != FTDM_SUCCESS) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "yay, could not set the state of the channel from IN_LOOP to DOWN\n");
}
}
static void handle_call_loop_stop(ftdm_span_t *span, sangomabc_connection_t *mcon, sangomabc_short_event_t *event)
{
ftdm_channel_t *ftdmchan;
ftdm_status_t res = FTDM_FAIL;
if (!(ftdmchan = find_ftdmchan(span, (sangomabc_short_event_t*)event, 1))) {
ftdm_log(FTDM_LOG_CRIT, "CANNOT STOP LOOP, INVALID CHAN REQUESTED %d:%d\n", BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event));
return;
@ -1104,13 +1125,7 @@ static void handle_call_loop_stop(ftdm_span_t *span, sangomabc_connection_t *mco
ftdm_log(FTDM_LOG_WARNING, "Got stop loop request in a channel that is not in loop, ignoring ...\n");
return;
}
ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_LOOP, NULL);
/* even when we did not sent a msg we set this flag to avoid sending call stop in the DOWN state handler */
ftdm_set_flag(ftdmchan, SFLAG_SENT_FINAL_MSG);
ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_DOWN, res);
if (res != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "yay, could not set the state of the channel from IN_LOOP to DOWN\n");
}
stop_loop(ftdmchan);
}
/**

View File

@ -281,7 +281,6 @@ typedef enum {
typedef enum {
FTDM_SIGEVENT_START, /*!< Incoming call (ie: incoming SETUP msg or Ring) */
FTDM_SIGEVENT_STOP, /*!< Hangup */
FTDM_SIGEVENT_ANSWER, /*!< Outgoing call has been answered */
FTDM_SIGEVENT_UP, /*!< Outgoing call has been answered */
FTDM_SIGEVENT_FLASH, /*< Flash event (typically on-hook/off-hook for analog devices) */
FTDM_SIGEVENT_PROGRESS, /*!< Outgoing call is making progress */
@ -440,7 +439,6 @@ struct ftdm_memory_handler {
ftdm_free_func_t free;
};
/*! \brief FreeTDM I/O layer interface argument macros
* You don't need these unless your implementing an I/O interface module (most users don't) */
#define FIO_CHANNEL_REQUEST_ARGS (ftdm_span_t *span, uint32_t chan_id, ftdm_direction_t direction, ftdm_caller_data_t *caller_data, ftdm_channel_t **ftdmchan)
@ -985,7 +983,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_group(uint32_t group_id, ftdm_dir
FT_DECLARE(ftdm_status_t) ftdm_channel_close(ftdm_channel_t **ftdmchan);
/*!
* \brief Execute a command in a channel
* \brief Execute a command in a channel (same semantics as the ioctl() unix system call)
*
* \param ftdmchan The channel to execute the command
* \param command The command to execute

View File

@ -561,6 +561,8 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_chan(ftdm_channel_t *ftdmchan);
#define ftdm_channel_lock(chan) ftdm_mutex_lock(chan->mutex)
#define ftdm_channel_unlock(chan) ftdm_mutex_unlock(chan->mutex)
#define ftdm_log_chan(fchan, level, format, ...) ftdm_log(level, "s%dc%d " format, fchan->span_id, fchan->chan_id, __VA_ARGS__)
#define ftdm_log_chan_msg(fchan, level, msg) ftdm_log(level, "s%dc%d " msg, fchan->span_id, fchan->chan_id)
static __inline__ void ftdm_abort(void)
{

View File

@ -158,13 +158,15 @@ typedef enum {
FTDM_SPAN_SUGGEST_CHAN_ID = (1 << 7),
} ftdm_span_flag_t;
/*! \brief Channel supported features */
typedef enum {
FTDM_CHANNEL_FEATURE_DTMF_DETECT = (1 << 0),
FTDM_CHANNEL_FEATURE_DTMF_GENERATE = (1 << 1),
FTDM_CHANNEL_FEATURE_CODECS = (1 << 2),
FTDM_CHANNEL_FEATURE_INTERVAL = (1 << 3),
FTDM_CHANNEL_FEATURE_CALLERID = (1 << 4),
FTDM_CHANNEL_FEATURE_PROGRESS = (1 << 5)
FTDM_CHANNEL_FEATURE_DTMF_DETECT = (1 << 0), /*!< Channel can detect DTMF (read-only) */
FTDM_CHANNEL_FEATURE_DTMF_GENERATE = (1 << 1), /*!< Channel can generate DTMF (read-only) */
FTDM_CHANNEL_FEATURE_CODECS = (1 << 2), /*!< Channel can do transcoding (read-only) */
FTDM_CHANNEL_FEATURE_INTERVAL = (1 << 3), /*!< Channel support i/o interval configuration (read-only) */
FTDM_CHANNEL_FEATURE_CALLERID = (1 << 4), /*!< Channel can detect caller id (read-only) */
FTDM_CHANNEL_FEATURE_PROGRESS = (1 << 5), /*!< Channel can detect inband progress (read-only) */
FTDM_CHANNEL_FEATURE_CALLWAITING = (1 << 6), /*!< Channel will allow call waiting (ie: FXS devices) (read/write) */
} ftdm_channel_feature_t;
typedef enum {

View File

@ -775,6 +775,7 @@ static void handle_call_answer(zap_span_t *span, sangomabc_connection_t *mcon, s
}
static __inline__ void advance_chan_states(zap_channel_t *zchan);
static __inline__ void stop_loop(zap_channel_t *zchan);
/**
* \brief Handler for call start event
@ -786,6 +787,9 @@ static void handle_call_start(zap_span_t *span, sangomabc_connection_t *mcon, sa
{
zap_channel_t *zchan;
int hangup_cause = ZAP_CAUSE_CALL_REJECTED;
int retry = 1;
tryagain:
if (!(zchan = find_zchan(span, (sangomabc_short_event_t*)event, 0))) {
if ((zchan = find_zchan(span, (sangomabc_short_event_t*)event, 1))) {
@ -807,7 +811,12 @@ static void handle_call_start(zap_span_t *span, sangomabc_connection_t *mcon, sa
zap_log(ZAP_LOG_CRIT, "ZCHAN CALL STATE HANGUP -> Changed to HANGUP %d:%d\n", event->span+1,event->chan+1);
zap_set_state_r(zchan, ZAP_CHANNEL_STATE_HANGUP_COMPLETE, 0, r);
/* Do nothing because outgoing STOP will generaate a stop ack */
} else if (zchan->state == ZAP_CHANNEL_STATE_IN_LOOP && retry) {
/* workaround ss7box sending us call start without sending first a loop stop */
stop_loop(zchan);
advance_chan_states(zchan);
retry = 0;
goto tryagain;
} else {
zap_log(ZAP_LOG_CRIT, "ZCHAN CALL ACK STATE INVALID %s s%dc%d\n",
zap_channel_state2str(zchan->state),event->span+1,event->chan+1);
@ -912,10 +921,21 @@ static void handle_call_loop_start(zap_span_t *span, sangomabc_connection_t *mco
zap_channel_command(zchan, ZAP_COMMAND_ENABLE_LOOP, NULL);
}
static __inline__ void stop_loop(zap_channel_t *zchan)
{
zap_status_t res = ZAP_FAIL;
zap_channel_command(zchan, ZAP_COMMAND_DISABLE_LOOP, NULL);
/* even when we did not sent a msg we set this flag to avoid sending call stop in the DOWN state handler */
zap_set_flag(zchan, SFLAG_SENT_FINAL_MSG);
zap_set_state_r(zchan, ZAP_CHANNEL_STATE_DOWN, 0, res);
if (res != ZAP_STATE_CHANGE_SUCCESS) {
zap_log(ZAP_LOG_CRIT, "yay, could not set the state of the channel from IN_LOOP to DOWN\n");
}
}
static void handle_call_loop_stop(zap_span_t *span, sangomabc_connection_t *mcon, sangomabc_short_event_t *event)
{
zap_channel_t *zchan;
zap_status_t res = ZAP_FAIL;
if (!(zchan = find_zchan(span, (sangomabc_short_event_t*)event, 1))) {
zap_log(ZAP_LOG_CRIT, "CANNOT STOP LOOP, INVALID CHAN REQUESTED %d:%d\n", event->span+1,event->chan+1);
return;
@ -924,13 +944,7 @@ static void handle_call_loop_stop(zap_span_t *span, sangomabc_connection_t *mcon
zap_log(ZAP_LOG_ERROR, "Got stop loop request in a channel that is not in loop, ignoring ...\n");
return;
}
zap_channel_command(zchan, ZAP_COMMAND_DISABLE_LOOP, NULL);
/* even when we did not sent a msg we set this flag to avoid sending call stop in the DOWN state handler */
zap_set_flag(zchan, SFLAG_SENT_FINAL_MSG);
zap_set_state_r(zchan, ZAP_CHANNEL_STATE_DOWN, 0, res);
if (res != ZAP_STATE_CHANGE_SUCCESS) {
zap_log(ZAP_LOG_CRIT, "yay, could not set the state of the channel from IN_LOOP to DOWN\n");
}
stop_loop(zchan);
}
/**

View File

@ -33,6 +33,13 @@
*/
#include <switch.h>
#ifdef WIN32
#define FAX_INVALID_SOCKET INVALID_HANDLE_VALUE
typedef HANDLE fax_socket_t;
#else
#define FAX_INVALID_SOCKET -1
typedef int zap_socket_t;
#endif
#define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
#include <spandsp.h>
@ -1453,6 +1460,11 @@ static switch_status_t t38_gateway_on_soft_execute(switch_core_session_t *sessio
pvt = pvt_init(session, FUNCTION_GW);
request_t38(pvt);
msg.message_id = SWITCH_MESSAGE_INDICATE_BRIDGE;
msg.from = __FILE__;
msg.string_arg = peer_uuid;
switch_core_session_receive_message(session, &msg);
while (switch_channel_ready(channel) && switch_channel_up(other_channel) && !switch_channel_test_app_flag(channel, CF_APP_T38)) {
status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
@ -1525,6 +1537,12 @@ static switch_status_t t38_gateway_on_soft_execute(switch_core_session_t *sessio
end_unlock:
msg.message_id = SWITCH_MESSAGE_INDICATE_UNBRIDGE;
msg.from = __FILE__;
msg.string_arg = peer_uuid;
switch_core_session_receive_message(session, &msg);
switch_channel_hangup(other_channel, SWITCH_CAUSE_NORMAL_CLEARING);
switch_core_session_rwunlock(other_session);
@ -1551,9 +1569,14 @@ static switch_status_t t38_gateway_on_consume_media(switch_core_session_t *sessi
int16_t *buf = NULL;
switch_status_t status;
switch_size_t tx;
const char *t38_trace = switch_channel_get_variable(channel, "t38_trace");
char *trace_read, *trace_write;
zap_socket_t read_fd = FAX_INVALID_SOCKET, write_fd = FAX_INVALID_SOCKET;
switch_core_session_message_t msg = { 0 };
switch_event_t *event;
switch_core_session_get_read_impl(session, &read_impl);
buf = switch_core_session_alloc(session, SWITCH_RECOMMENDED_BUFFER_SIZE);
if (!(other_session = switch_core_session_locate(peer_uuid))) {
@ -1563,6 +1586,16 @@ static switch_status_t t38_gateway_on_consume_media(switch_core_session_t *sessi
other_channel = switch_core_session_get_channel(other_session);
msg.message_id = SWITCH_MESSAGE_INDICATE_BRIDGE;
msg.from = __FILE__;
msg.string_arg = peer_uuid;
switch_core_session_receive_message(session, &msg);
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_BRIDGE) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(channel, event);
switch_event_fire(&event);
}
while (switch_channel_ready(channel) && switch_channel_up(other_channel) && !switch_channel_test_app_flag(channel, CF_APP_T38)) {
status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
@ -1627,7 +1660,29 @@ static switch_status_t t38_gateway_on_consume_media(switch_core_session_t *sessi
goto end_unlock;
}
switch_ivr_sleep(session, 250, SWITCH_TRUE, NULL);
switch_ivr_sleep(session, 0, SWITCH_TRUE, NULL);
if (switch_true(t38_trace)) {
trace_read = switch_core_session_sprintf(session, "%s%s%s_read.raw", SWITCH_GLOBAL_dirs.temp_dir,
SWITCH_PATH_SEPARATOR, switch_core_session_get_uuid(session));
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Tracing inbound audio to %s\n", trace_read);
switch_channel_set_variable(channel, "t38_trace_read", trace_read);
trace_write = switch_core_session_sprintf(session, "%s%s%s_write.raw", SWITCH_GLOBAL_dirs.temp_dir,
SWITCH_PATH_SEPARATOR, switch_core_session_get_uuid(session));
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Tracing outbound audio to %s\n", trace_write);
switch_channel_set_variable(channel, "t38_trace_read", trace_write);
if ((write_fd = open(trace_read, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) != FAX_INVALID_SOCKET) {
if ((read_fd = open(trace_write, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) == FAX_INVALID_SOCKET) {
close(write_fd);
write_fd = FAX_INVALID_SOCKET;
}
}
}
while (switch_channel_ready(channel) && switch_channel_up(other_channel)) {
status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
@ -1640,7 +1695,11 @@ static switch_status_t t38_gateway_on_consume_media(switch_core_session_t *sessi
/* Skip CNG frames (auto-generated by FreeSWITCH, usually) */
if (!switch_test_flag(read_frame, SFF_CNG)) {
if (t38_gateway_rx(pvt->t38_gateway_state, (int16_t *) read_frame->data, read_frame->samples)) {
if (read_fd != FAX_INVALID_SOCKET) {
write(read_fd, read_frame->data, read_frame->datalen);
}
if (t38_gateway_rx(pvt->t38_gateway_state, (int16_t *) read_frame->data, read_frame->samples)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "fax_rx reported an error\n");
goto end_unlock;
}
@ -1660,6 +1719,10 @@ static switch_status_t t38_gateway_on_consume_media(switch_core_session_t *sessi
write_frame.samples = tx;
}
if (write_fd != FAX_INVALID_SOCKET) {
write(write_fd, write_frame.data, write_frame.datalen);
}
if (switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) {
goto end_unlock;
}
@ -1667,6 +1730,28 @@ static switch_status_t t38_gateway_on_consume_media(switch_core_session_t *sessi
end_unlock:
msg.message_id = SWITCH_MESSAGE_INDICATE_UNBRIDGE;
msg.from = __FILE__;
msg.string_arg = peer_uuid;
switch_core_session_receive_message(session, &msg);
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_UNBRIDGE) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(channel, event);
switch_event_fire(&event);
}
if (read_fd != FAX_INVALID_SOCKET) {
close(read_fd);
read_fd = FAX_INVALID_SOCKET;
}
if (write_fd != FAX_INVALID_SOCKET) {
close(write_fd);
write_fd = FAX_INVALID_SOCKET;
}
switch_channel_hangup(other_channel, SWITCH_CAUSE_NORMAL_CLEARING);
switch_core_session_rwunlock(other_session);
@ -1694,6 +1779,8 @@ static switch_status_t t38_gateway_on_reset(switch_core_session_t *session)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_channel_set_variable(channel, "rtp_autoflush_during_bridge", "false");
switch_channel_clear_flag(channel, CF_REDIRECT);
if (switch_channel_test_app_flag(channel, CF_APP_TAGGED)) {

View File

@ -0,0 +1 @@
/Win32/

View File

@ -1,6 +1,6 @@
BASE=../../../..
DIR=$(switch_srcdir)/libs/libg723_1
BUILDDIR=$(switch_bulddir)/libs/libg723_1
DIR=$(BASE)/libs/libg723_1
BUILDDIR=$(BASE)/libs/libg723_1
A=$(BUILDDIR)/.libs/libg723.a
LOCAL_INSERT_CFLAGS=if test -f $(A); then echo "-I$(DIR)/src/include" ; else echo "-DG723_PASSTHROUGH" ; fi ;

View File

@ -1,7 +1,7 @@
BASE=../../../..
DIR=$(switch_srcdir)/libs/libg729
BUILDDIR=$(switch_builddir)/libs/libg729
DIR=$(BASE)/libs/libg729
BUILDDIR=$(BASE)/libs/libg729
A=$(BUILDDIR)/.libs/libg729.a
LOCAL_INSERT_CFLAGS=if test -f $(A); then echo "-I$(DIR)/src/include" ; else echo "-DG729_PASSTHROUGH" ; fi ;

View File

@ -0,0 +1 @@
/managed/obj/