mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-04-15 08:29:45 +00:00
cleanup for mod_fax
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@9468 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
parent
a4c95c63f6
commit
07198a8416
@ -14,7 +14,7 @@
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is FreeSWITCH mod_timezone.
|
||||
* The Original Code is FreeSWITCH mod_fax.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Massimo Cetra <devel@navynet.it>
|
||||
@ -27,7 +27,7 @@
|
||||
* Brian West <brian@freeswitch.org>
|
||||
* Anthony Minessale II <anthmct@yahoo.com>
|
||||
* Steve Underwood <steveu@coppice.org>
|
||||
*
|
||||
* Antonio Gallo <agx@linux.it>
|
||||
* mod_fax.c -- Fax applications provided by SpanDSP
|
||||
*
|
||||
*/
|
||||
@ -99,7 +99,8 @@ typedef struct pvt_s pvt_t;
|
||||
LOGGING AND HELPER FUNCTIONS
|
||||
*****************************************************************************/
|
||||
|
||||
static void counter_increment( void ) {
|
||||
static void counter_increment(void)
|
||||
{
|
||||
switch_mutex_lock(globals.mutex);
|
||||
globals.total_sessions++;
|
||||
switch_mutex_unlock(globals.mutex);
|
||||
@ -109,8 +110,7 @@ static void spanfax_log_message(int level, const char *msg)
|
||||
{
|
||||
int fs_log_level;
|
||||
|
||||
switch (level)
|
||||
{
|
||||
switch (level) {
|
||||
case SPAN_LOG_NONE:
|
||||
return;
|
||||
case SPAN_LOG_ERROR:
|
||||
@ -129,9 +129,9 @@ static void spanfax_log_message(int level, const char *msg)
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !switch_strlen_zero(msg) )
|
||||
if (!switch_strlen_zero(msg)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, fs_log_level, "%s", msg);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -144,9 +144,13 @@ static void phase_e_handler(t30_state_t *s, void *user_data, int result)
|
||||
const char *far_ident;
|
||||
switch_core_session_t *session;
|
||||
switch_channel_t *chan;
|
||||
pvt_t *pvt;
|
||||
char *tmp;
|
||||
|
||||
session = ( switch_core_session_t* ) user_data;
|
||||
pvt = (pvt_t *) user_data;
|
||||
switch_assert(pvt);
|
||||
|
||||
session = pvt->session;
|
||||
switch_assert(session);
|
||||
|
||||
chan = switch_core_session_get_channel(session);
|
||||
@ -158,14 +162,19 @@ static void phase_e_handler(t30_state_t *s, void *user_data, int result)
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "==============================================================================\n");
|
||||
|
||||
if (result == T30_ERR_OK)
|
||||
{
|
||||
if (result == T30_ERR_OK) {
|
||||
|
||||
if (pvt->app_mode == FUNCTION_TX) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Fax successfully sent.\n");
|
||||
switch_channel_set_variable(chan, "fax_success", "1");
|
||||
} else if (pvt->app_mode == FUNCTION_RX) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Fax successfully received.\n");
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Fax successfully managed. How ?\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Fax processing not successful - result (%d) %s.\n", result, t30_completion_code_to_str(result));
|
||||
switch_channel_set_variable(chan, "fax_success", "1");
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Fax processing not successful - result (%d) %s.\n", result,
|
||||
t30_completion_code_to_str(result));
|
||||
switch_channel_set_variable(chan, "fax_success", "0");
|
||||
}
|
||||
|
||||
@ -255,21 +264,18 @@ static switch_status_t spanfax_init( pvt_t *pvt, transport_mode_t trans_mode )
|
||||
switch_assert(chan);
|
||||
|
||||
|
||||
switch (trans_mode)
|
||||
{
|
||||
switch (trans_mode) {
|
||||
case AUDIO_MODE:
|
||||
if ( pvt->fax_state == NULL )
|
||||
{
|
||||
if (pvt->fax_state == NULL) {
|
||||
pvt->fax_state = (fax_state_t *) switch_core_session_alloc(pvt->session, sizeof(fax_state_t));
|
||||
}
|
||||
else
|
||||
} else {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
fax = pvt->fax_state;
|
||||
|
||||
memset(fax, 0, sizeof(fax_state_t));
|
||||
if ( fax_init(fax, pvt->caller) == NULL )
|
||||
{
|
||||
if (fax_init(fax, pvt->caller) == NULL) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot initialize my fax structs\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
@ -279,8 +285,7 @@ static switch_status_t spanfax_init( pvt_t *pvt, transport_mode_t trans_mode )
|
||||
span_log_set_message_handler(&fax->logging, spanfax_log_message);
|
||||
span_log_set_message_handler(&fax->t30.logging, spanfax_log_message);
|
||||
|
||||
if( pvt->verbose )
|
||||
{
|
||||
if (pvt->verbose) {
|
||||
span_log_set_level(&fax->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW);
|
||||
span_log_set_level(&fax->t30.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW);
|
||||
}
|
||||
@ -288,7 +293,7 @@ static switch_status_t spanfax_init( pvt_t *pvt, transport_mode_t trans_mode )
|
||||
t30_set_tx_ident(&fax->t30, pvt->ident);
|
||||
t30_set_tx_page_header_info(&fax->t30, pvt->header);
|
||||
|
||||
t30_set_phase_e_handler(&fax->t30, phase_e_handler, pvt->session);
|
||||
t30_set_phase_e_handler(&fax->t30, phase_e_handler, pvt);
|
||||
|
||||
t30_set_supported_image_sizes(&fax->t30,
|
||||
T30_SUPPORT_US_LETTER_LENGTH | T30_SUPPORT_US_LEGAL_LENGTH | T30_SUPPORT_UNLIMITED_LENGTH
|
||||
@ -298,8 +303,7 @@ static switch_status_t spanfax_init( pvt_t *pvt, transport_mode_t trans_mode )
|
||||
| T30_SUPPORT_R8_RESOLUTION | T30_SUPPORT_R16_RESOLUTION);
|
||||
|
||||
|
||||
if ( pvt->disable_v17 )
|
||||
{
|
||||
if (pvt->disable_v17) {
|
||||
t30_set_supported_modems(&fax->t30, T30_SUPPORT_V29 | T30_SUPPORT_V27TER);
|
||||
switch_channel_set_variable(chan, "fax_v17_disabled", "1");
|
||||
} else {
|
||||
@ -307,24 +311,18 @@ static switch_status_t spanfax_init( pvt_t *pvt, transport_mode_t trans_mode )
|
||||
switch_channel_set_variable(chan, "fax_v17_disabled", "0");
|
||||
}
|
||||
|
||||
if ( pvt->use_ecm )
|
||||
{
|
||||
if (pvt->use_ecm) {
|
||||
t30_set_supported_compressions(&fax->t30, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION);
|
||||
t30_set_ecm_capability(&fax->t30, TRUE);
|
||||
switch_channel_set_variable(chan, "fax_ecm_requested", "1");
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
t30_set_supported_compressions(&fax->t30, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION);
|
||||
switch_channel_set_variable(chan, "fax_ecm_requested", "0");
|
||||
}
|
||||
|
||||
if ( pvt->app_mode == FUNCTION_TX )
|
||||
{
|
||||
if (pvt->app_mode == FUNCTION_TX) {
|
||||
t30_set_tx_file(&fax->t30, pvt->filename, pvt->tx_page_start, pvt->tx_page_end);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
t30_set_rx_file(&fax->t30, pvt->filename, -1);
|
||||
}
|
||||
switch_channel_set_variable(chan, "fax_filename", pvt->filename);
|
||||
@ -343,31 +341,34 @@ static switch_status_t spanfax_init( pvt_t *pvt, transport_mode_t trans_mode )
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t spanfax_destroy( pvt_t *pvt ) {
|
||||
static switch_status_t spanfax_destroy(pvt_t * pvt)
|
||||
{
|
||||
int terminate;
|
||||
|
||||
if ( pvt->fax_state )
|
||||
{
|
||||
if ( pvt->t38_state )
|
||||
if (pvt->fax_state) {
|
||||
if (pvt->t38_state) {
|
||||
terminate = 0;
|
||||
else
|
||||
} else {
|
||||
terminate = 1;
|
||||
}
|
||||
|
||||
if ( terminate && &pvt->fax_state->t30 )
|
||||
if (terminate && &pvt->fax_state->t30) {
|
||||
t30_terminate(&pvt->fax_state->t30);
|
||||
}
|
||||
|
||||
fax_release(pvt->fax_state);
|
||||
}
|
||||
|
||||
if ( pvt->t38_state )
|
||||
{
|
||||
if ( pvt->t38_state )
|
||||
if (pvt->t38_state) {
|
||||
if (pvt->t38_state) {
|
||||
terminate = 1;
|
||||
else
|
||||
} else {
|
||||
terminate = 0;
|
||||
}
|
||||
|
||||
if ( terminate && &pvt->t38_state->t30 )
|
||||
if (terminate && &pvt->t38_state->t30) {
|
||||
t30_terminate(&pvt->t38_state->t30);
|
||||
}
|
||||
|
||||
t38_terminal_release(pvt->t38_state);
|
||||
}
|
||||
@ -398,18 +399,19 @@ void process_fax(switch_core_session_t *session, const char *data, application_m
|
||||
channel = switch_core_session_get_channel(session);
|
||||
switch_assert(channel != NULL);
|
||||
|
||||
if (!switch_channel_media_ready(channel)) {
|
||||
switch_channel_answer(channel);
|
||||
}
|
||||
|
||||
/* Allocate our structs */
|
||||
pvt = switch_core_session_alloc(session, sizeof(pvt_t));
|
||||
|
||||
counter_increment();
|
||||
|
||||
if ( !pvt )
|
||||
{
|
||||
if (!pvt) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot allocate application private data\n");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
memset(pvt, 0, sizeof(pvt_t));
|
||||
|
||||
pvt->session = session;
|
||||
@ -418,13 +420,14 @@ void process_fax(switch_core_session_t *session, const char *data, application_m
|
||||
pvt->tx_page_start = -1;
|
||||
pvt->tx_page_end = -1;
|
||||
|
||||
if ( pvt->app_mode == FUNCTION_TX )
|
||||
if (pvt->app_mode == FUNCTION_TX) {
|
||||
pvt->caller = 1;
|
||||
else if ( pvt->app_mode == FUNCTION_RX )
|
||||
} else if (pvt->app_mode == FUNCTION_RX) {
|
||||
pvt->caller = 0;
|
||||
else
|
||||
} else {
|
||||
assert(0); /* UH ? */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
buf = switch_core_session_alloc(session, SWITCH_RECOMMENDED_BUFFER_SIZE);
|
||||
@ -434,55 +437,40 @@ void process_fax(switch_core_session_t *session, const char *data, application_m
|
||||
}
|
||||
|
||||
/* Retrieving our settings from the channel variables */
|
||||
|
||||
if ((tmp = switch_channel_get_variable(channel, "fax_use_ecm"))) {
|
||||
if ( switch_true(tmp) )
|
||||
pvt->use_ecm = 1;
|
||||
else
|
||||
pvt->use_ecm = 0;
|
||||
}
|
||||
else
|
||||
pvt->use_ecm = switch_true(tmp);
|
||||
} else {
|
||||
pvt->use_ecm = globals.use_ecm;
|
||||
}
|
||||
|
||||
if ((tmp = switch_channel_get_variable(channel, "fax_disable_v17"))) {
|
||||
if ( switch_true(tmp) )
|
||||
pvt->disable_v17 = 1;
|
||||
else
|
||||
pvt->disable_v17 = 0;
|
||||
}
|
||||
else
|
||||
pvt->disable_v17 = switch_true(tmp);
|
||||
} else {
|
||||
pvt->disable_v17 = globals.disable_v17;
|
||||
}
|
||||
|
||||
if ((tmp = switch_channel_get_variable(channel, "fax_verbose"))) {
|
||||
if ( switch_true(tmp) )
|
||||
pvt->verbose = 1;
|
||||
else
|
||||
pvt->verbose = 0;
|
||||
}
|
||||
else
|
||||
pvt->verbose = switch_true(tmp);
|
||||
} else {
|
||||
pvt->verbose = globals.verbose;
|
||||
|
||||
if ( (tmp=switch_channel_get_variable(channel, "fax_force_caller")) ) {
|
||||
if ( switch_true(tmp) )
|
||||
pvt->caller = 1;
|
||||
else
|
||||
pvt->caller = 0;
|
||||
}
|
||||
|
||||
pvt->caller = switch_true(switch_channel_get_variable(channel, "fax_force_caller"));
|
||||
|
||||
if ((tmp = switch_channel_get_variable(channel, "fax_ident"))) {
|
||||
pvt->ident = switch_core_session_strdup(session, tmp);
|
||||
}
|
||||
else
|
||||
} else {
|
||||
pvt->ident = switch_core_session_strdup(session, globals.ident);
|
||||
}
|
||||
|
||||
if ((tmp = switch_channel_get_variable(channel, "fax_header"))) {
|
||||
pvt->header = switch_core_session_strdup(session, tmp);
|
||||
}
|
||||
else
|
||||
} else {
|
||||
pvt->header = switch_core_session_strdup(session, globals.header);
|
||||
}
|
||||
|
||||
|
||||
if ( pvt->app_mode == FUNCTION_TX )
|
||||
{
|
||||
if (pvt->app_mode == FUNCTION_TX) {
|
||||
|
||||
if ((tmp = switch_channel_get_variable(channel, "fax_start_page"))) {
|
||||
pvt->tx_page_start = atoi(tmp);
|
||||
@ -492,13 +480,18 @@ void process_fax(switch_core_session_t *session, const char *data, application_m
|
||||
pvt->tx_page_end = atoi(tmp);
|
||||
}
|
||||
|
||||
if ( pvt->tx_page_end < -1 )
|
||||
if (pvt->tx_page_end < -1) {
|
||||
pvt->tx_page_end = -1;
|
||||
if ( pvt->tx_page_start < -1 )
|
||||
}
|
||||
|
||||
if (pvt->tx_page_start < -1) {
|
||||
pvt->tx_page_start = -1;
|
||||
if ( (pvt->tx_page_end < pvt->tx_page_start) && ( pvt->tx_page_end != -1 ) )
|
||||
}
|
||||
|
||||
if ((pvt->tx_page_end < pvt->tx_page_start) && (pvt->tx_page_end != -1)) {
|
||||
pvt->tx_page_end = pvt->tx_page_start;
|
||||
}
|
||||
}
|
||||
|
||||
if (!switch_strlen_zero(data)) {
|
||||
pvt->filename = switch_core_session_strdup(session, data);
|
||||
@ -508,14 +501,11 @@ void process_fax(switch_core_session_t *session, const char *data, application_m
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (pvt->app_mode == FUNCTION_TX) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Fax TX filename not set.\n");
|
||||
goto done;
|
||||
}
|
||||
else if ( pvt->app_mode == FUNCTION_RX )
|
||||
{
|
||||
} else if (pvt->app_mode == FUNCTION_RX) {
|
||||
char *fname;
|
||||
char *prefix;
|
||||
switch_time_t time;
|
||||
@ -527,18 +517,14 @@ void process_fax(switch_core_session_t *session, const char *data, application_m
|
||||
}
|
||||
|
||||
fname = switch_mprintf("%s/%s-%ld-%ld.tif", globals.spool, prefix, globals.total_sessions, time);
|
||||
if ( fname )
|
||||
{
|
||||
if (fname) {
|
||||
pvt->filename = switch_core_session_strdup(session, fname);
|
||||
switch_safe_free(fname);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot automagically set fax RX destination file\n");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
assert(0); /* UH ?? */
|
||||
}
|
||||
}
|
||||
@ -551,23 +537,24 @@ void process_fax(switch_core_session_t *session, const char *data, application_m
|
||||
bypassing AUDIO_MODE.
|
||||
*/
|
||||
|
||||
if ( (spanfax_init(pvt, AUDIO_MODE)!=SWITCH_STATUS_SUCCESS) )
|
||||
{
|
||||
if ((spanfax_init(pvt, AUDIO_MODE) != SWITCH_STATUS_SUCCESS)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot initialize Fax engine\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Note: Disable echocan on the channel, it there is an API call to do that */
|
||||
|
||||
/*
|
||||
Note: We should eventually disable JB before answering. JB is bad for faxing
|
||||
|
||||
switch_channel_set_variable(channel, "jitterbuffer_msec", "0" );
|
||||
Note: Disable echocan on the channel, remember to call app "disable_ec" in the dialplan
|
||||
before invoking fax applications
|
||||
*/
|
||||
|
||||
/*
|
||||
Note: we are disabling the Jitterbuffer, here, before we answer.
|
||||
If you have set it to something else and the channel is pre-answered,
|
||||
it will have no effect. Make sure that if you want more reliable
|
||||
faxes, it is disabled.
|
||||
*/
|
||||
switch_channel_set_variable(channel, "jitterbuffer_msec", "0");
|
||||
|
||||
/* Finally answer the call */
|
||||
switch_channel_answer(channel);
|
||||
|
||||
/* We store the original channel codec before switching both
|
||||
* legs of the calls to a linear 16 bit codec that is the one
|
||||
@ -576,56 +563,42 @@ void process_fax(switch_core_session_t *session, const char *data, application_m
|
||||
*/
|
||||
orig_read_codec = switch_core_session_get_read_codec(session);
|
||||
|
||||
if (switch_core_codec_init(
|
||||
&read_codec,
|
||||
if (switch_core_codec_init(&read_codec,
|
||||
"L16",
|
||||
NULL,
|
||||
orig_read_codec->implementation->samples_per_second,
|
||||
orig_read_codec->implementation->microseconds_per_frame / 1000,
|
||||
1,
|
||||
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
|
||||
NULL,
|
||||
switch_core_session_get_pool(session)) == SWITCH_STATUS_SUCCESS
|
||||
)
|
||||
{
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Raw read codec activation Success L16\n");
|
||||
NULL, switch_core_session_get_pool(session)) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Raw read codec activation Success L16 %u\n",
|
||||
read_codec.implementation->microseconds_per_frame);
|
||||
switch_core_session_set_read_codec(session, &read_codec);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Raw read codec activation Failed L16\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (switch_core_codec_init(
|
||||
&write_codec,
|
||||
if (switch_core_codec_init(&write_codec,
|
||||
"L16",
|
||||
NULL,
|
||||
orig_read_codec->implementation->samples_per_second,
|
||||
orig_read_codec->implementation->microseconds_per_frame / 1000,
|
||||
1,
|
||||
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
|
||||
NULL,
|
||||
switch_core_session_get_pool(session)) == SWITCH_STATUS_SUCCESS
|
||||
)
|
||||
{
|
||||
NULL, switch_core_session_get_pool(session)) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Raw write codec activation Success L16\n");
|
||||
write_frame.codec = &write_codec;
|
||||
write_frame.data = buf;
|
||||
write_frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Raw write codec activation Failed L16\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
switch_ivr_sleep(session, 250, NULL);
|
||||
|
||||
/*
|
||||
* now we enter a loop where we read audio frames to the channels and will pass it to spandsp
|
||||
*/
|
||||
while( switch_channel_ready(channel) )
|
||||
{
|
||||
while (switch_channel_ready(channel)) {
|
||||
int tx = 0;
|
||||
switch_status_t status;
|
||||
|
||||
@ -643,56 +616,38 @@ void process_fax(switch_core_session_t *session, const char *data, application_m
|
||||
/* read new audio frame from the channel */
|
||||
status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
|
||||
|
||||
if ( !SWITCH_READ_ACCEPTABLE(status) )
|
||||
{
|
||||
if (!SWITCH_READ_ACCEPTABLE(status)) {
|
||||
/* Our duty is over */
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Note: more analysys on this. RTP timing maybe inaccurate and, if so,
|
||||
shoule be improved.
|
||||
agx proposes to add a channel variable to disable this check and don't skip CNG frames
|
||||
to improve the compatibility with the problems that another (??)famous pbx that
|
||||
has always had serious problems with timers (or lack of).
|
||||
*/
|
||||
|
||||
/* Skip CNG frames (autogenerated by FreeSWITCH, usually) */
|
||||
if (switch_test_flag(read_frame, SFF_CNG)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Skipping CNG frame\n" );
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!switch_test_flag(read_frame, SFF_CNG)) {
|
||||
/* pass the new incoming audio frame to the fax_rx function */
|
||||
if( fax_rx(pvt->fax_state, (int16_t *)read_frame->data, read_frame->samples) )
|
||||
{
|
||||
if (fax_rx(pvt->fax_state, (int16_t *) read_frame->data, read_frame->samples)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "fax_rx reported an error\n");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if ( (tx = fax_tx(pvt->fax_state, buf, write_codec.implementation->samples_per_frame)) < 0)
|
||||
{
|
||||
if ((tx = fax_tx(pvt->fax_state, buf, write_codec.implementation->samples_per_frame)) < 0) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "fax_tx reported an error\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ( !tx )
|
||||
{
|
||||
if (!tx) {
|
||||
/* switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "No audio samples to send\n"); */
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
/* Set our write_frame data */
|
||||
write_frame.datalen = tx * sizeof(int16_t);
|
||||
write_frame.samples = tx;
|
||||
}
|
||||
|
||||
if ( switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS )
|
||||
{
|
||||
if (switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) {
|
||||
/* something weird has happened */
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
|
||||
"Cannot write frame [datalen: %d, samples: %d]\n",
|
||||
write_frame.datalen, write_frame.samples );
|
||||
"Cannot write frame [datalen: %d, samples: %d]\n", write_frame.datalen, write_frame.samples);
|
||||
goto done;
|
||||
}
|
||||
|
||||
@ -704,18 +659,15 @@ done:
|
||||
|
||||
/* restore the original codecs over the channel */
|
||||
|
||||
if ( read_codec.implementation )
|
||||
{
|
||||
if (read_codec.implementation) {
|
||||
switch_core_codec_destroy(&read_codec);
|
||||
}
|
||||
|
||||
if ( write_codec.implementation )
|
||||
{
|
||||
if (write_codec.implementation) {
|
||||
switch_core_codec_destroy(&write_codec);
|
||||
}
|
||||
|
||||
if ( orig_read_codec )
|
||||
{
|
||||
if (orig_read_codec) {
|
||||
switch_core_session_set_read_codec(session, orig_read_codec);
|
||||
}
|
||||
|
||||
@ -729,12 +681,9 @@ void load_configuration(switch_bool_t reload)
|
||||
{
|
||||
switch_xml_t xml = NULL, x_lists = NULL, x_list = NULL, cfg = NULL;
|
||||
|
||||
if ((xml = switch_xml_open_cfg("fax.conf", &cfg, NULL)))
|
||||
{
|
||||
if ((x_lists = switch_xml_child(cfg, "settings")))
|
||||
{
|
||||
for (x_list = switch_xml_child(x_lists, "param"); x_list; x_list = x_list->next)
|
||||
{
|
||||
if ((xml = switch_xml_open_cfg("fax.conf", &cfg, NULL))) {
|
||||
if ((x_lists = switch_xml_child(cfg, "settings"))) {
|
||||
for (x_list = switch_xml_child(x_lists, "param"); x_list; x_list = x_list->next) {
|
||||
const char *name = switch_xml_attr(x_list, "name");
|
||||
const char *value = switch_xml_attr(x_list, "value");
|
||||
|
||||
@ -751,32 +700,25 @@ void load_configuration(switch_bool_t reload)
|
||||
globals.use_ecm = 1;
|
||||
else
|
||||
globals.use_ecm = 0;
|
||||
}
|
||||
else if ( !strcmp(name, "verbose" ) ) {
|
||||
} else if (!strcmp(name, "verbose")) {
|
||||
if (switch_true(value))
|
||||
globals.verbose = 1;
|
||||
else
|
||||
globals.verbose = 0;
|
||||
}
|
||||
else if ( !strcmp(name, "disable-v17" ) ) {
|
||||
} else if (!strcmp(name, "disable-v17")) {
|
||||
if (switch_true(value))
|
||||
globals.disable_v17 = 1;
|
||||
else
|
||||
globals.disable_v17 = 0;
|
||||
}
|
||||
else if ( !strcmp(name, "ident" ) ) {
|
||||
} else if (!strcmp(name, "ident")) {
|
||||
strncpy(globals.ident, value, sizeof(globals.ident) - 1);
|
||||
}
|
||||
else if ( !strcmp(name, "header" ) ) {
|
||||
} else if (!strcmp(name, "header")) {
|
||||
strncpy(globals.header, value, sizeof(globals.header) - 1);
|
||||
}
|
||||
else if ( !strcmp(name, "spool-dir" ) ) {
|
||||
} else if (!strcmp(name, "spool-dir")) {
|
||||
globals.spool = switch_core_strdup(globals.pool, value);
|
||||
}
|
||||
else if ( !strcmp(name, "file-prefix" ) ) {
|
||||
} else if (!strcmp(name, "file-prefix")) {
|
||||
globals.prepend_string = switch_core_strdup(globals.pool, value);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unknown parameter %s\n", name);
|
||||
}
|
||||
|
||||
@ -821,8 +763,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_fax_init)
|
||||
|
||||
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
|
||||
|
||||
SWITCH_ADD_APP(app_interface, "rxfax", "FAX Receive Application", "FAX Receive Application", spanfax_rx_function, SPANFAX_RX_USAGE, SAF_NONE);
|
||||
SWITCH_ADD_APP(app_interface, "txfax", "FAX Transmit Application", "FAX Transmit Application", spanfax_tx_function, SPANFAX_TX_USAGE, SAF_NONE);
|
||||
SWITCH_ADD_APP(app_interface, "rxfax", "FAX Receive Application", "FAX Receive Application", spanfax_rx_function, SPANFAX_RX_USAGE, SAF_SUPPORT_NOMEDIA);
|
||||
SWITCH_ADD_APP(app_interface, "txfax", "FAX Transmit Application", "FAX Transmit Application", spanfax_tx_function, SPANFAX_TX_USAGE, SAF_SUPPORT_NOMEDIA);
|
||||
|
||||
memset(&globals, 0, sizeof(globals));
|
||||
switch_core_new_memory_pool(&globals.pool);
|
||||
@ -839,13 +781,13 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_fax_init)
|
||||
|
||||
load_configuration(0);
|
||||
|
||||
if ( (switch_event_bind_removable(modname, SWITCH_EVENT_RELOADXML, NULL, event_handler, NULL, &NODE) != SWITCH_STATUS_SUCCESS) )
|
||||
{
|
||||
if ((switch_event_bind_removable(modname, SWITCH_EVENT_RELOADXML, NULL, event_handler, NULL, &NODE) != SWITCH_STATUS_SUCCESS)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind our reloadxml handler!\n");
|
||||
/* Not such severe to prevent loading */
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "mod_fax loaded, using spandsp library version %d [%d]\n", SPANDSP_RELEASE_DATE, SPANDSP_RELEASE_TIME );
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "mod_fax loaded, using spandsp library version %d [%d]\n", SPANDSP_RELEASE_DATE,
|
||||
SPANDSP_RELEASE_TIME);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -190,7 +190,7 @@ typedef enum {
|
||||
TFLAG_VAD_IN = (1 << 11),
|
||||
TFLAG_VAD_OUT = (1 << 12),
|
||||
TFLAG_VAD = (1 << 13),
|
||||
TFLAG_TIMER = (1 << 14),
|
||||
TFLAG_USE_ME = (1 << 14),
|
||||
TFLAG_READY = (1 << 15),
|
||||
TFLAG_REINVITE = (1 << 16),
|
||||
TFLAG_REFER = (1 << 17),
|
||||
|
@ -1409,8 +1409,6 @@ switch_status_t config_sofia(int reload, char *profile_name)
|
||||
|
||||
if (!strcasecmp(var, "debug")) {
|
||||
profile->debug = atoi(val);
|
||||
} else if (!strcasecmp(var, "use-rtp-timer") && switch_true(val)) {
|
||||
switch_set_flag(profile, TFLAG_TIMER);
|
||||
} else if (!strcasecmp(var, "sip-trace") && switch_true(val)) {
|
||||
switch_set_flag(profile, TFLAG_TPORT_LOG);
|
||||
} else if (!strcasecmp(var, "odbc-dsn") && !switch_strlen_zero(val)) {
|
||||
@ -1752,10 +1750,6 @@ switch_status_t config_sofia(int reload, char *profile_name)
|
||||
profile->nonce_ttl = 60;
|
||||
}
|
||||
|
||||
if (switch_test_flag(profile, TFLAG_TIMER) && !profile->timer_name) {
|
||||
profile->timer_name = switch_core_strdup(profile->pool, "soft");
|
||||
}
|
||||
|
||||
if (!profile->username) {
|
||||
profile->username = switch_core_strdup(profile->pool, "FreeSWITCH");
|
||||
}
|
||||
@ -2381,7 +2375,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
|
||||
if (tech_pvt && r_sdp) {
|
||||
sdp_parser_t *parser;
|
||||
sdp_session_t *sdp;
|
||||
uint8_t match = 0;
|
||||
uint8_t match = 0, is_ok = 1;
|
||||
|
||||
if (r_sdp) {
|
||||
if (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
|
||||
@ -2412,6 +2406,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
|
||||
switch_core_session_rwunlock(other_session);
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Re-INVITE to a no-media channel that is not in a bridge.\n");
|
||||
is_ok = 0;
|
||||
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
|
||||
}
|
||||
goto done;
|
||||
@ -2432,21 +2427,25 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
|
||||
switch_set_flag_locked(tech_pvt, TFLAG_REINVITE);
|
||||
if (sofia_glue_activate_rtp(tech_pvt, 0) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Reinvite RTP Error!\n");
|
||||
is_ok = 0;
|
||||
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
|
||||
}
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Processing Reinvite\n");
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Reinvite Codec Error!\n");
|
||||
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
|
||||
is_ok = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (is_ok) {
|
||||
nua_respond(tech_pvt->nh, SIP_200_OK,
|
||||
SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
|
||||
SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str),
|
||||
SOATAG_REUSE_REJECTED(1),
|
||||
SOATAG_ORDERED_USER(1), SOATAG_AUDIO_AUX("cn telephone-event"), NUTAG_INCLUDE_EXTRA_SDP(1), TAG_END());
|
||||
} else {
|
||||
nua_respond(tech_pvt->nh, SIP_488_NOT_ACCEPTABLE, TAG_END());
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -1676,7 +1676,7 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f
|
||||
char tmp[50];
|
||||
uint32_t rtp_timeout_sec = tech_pvt->profile->rtp_timeout_sec;
|
||||
uint32_t rtp_hold_timeout_sec = tech_pvt->profile->rtp_hold_timeout_sec;
|
||||
char *timer_name;
|
||||
char *timer_name = NULL;
|
||||
const char *var;
|
||||
|
||||
switch_assert(tech_pvt != NULL);
|
||||
@ -1807,6 +1807,10 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f
|
||||
timer_name = tech_pvt->profile->timer_name;
|
||||
}
|
||||
|
||||
if ((var = switch_channel_get_variable(tech_pvt->channel, "rtp_timer_name"))) {
|
||||
timer_name = (char *) var;
|
||||
}
|
||||
|
||||
tech_pvt->rtp_session = switch_rtp_new(tech_pvt->local_sdp_audio_ip,
|
||||
tech_pvt->local_sdp_audio_port,
|
||||
tech_pvt->remote_sdp_audio_ip,
|
||||
|
@ -256,6 +256,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi
|
||||
session->raw_read_frame.ssrc = read_frame->ssrc;
|
||||
session->raw_read_frame.seq = read_frame->seq;
|
||||
session->raw_read_frame.m = read_frame->m;
|
||||
session->raw_read_frame.flags = read_frame->flags;
|
||||
session->raw_read_frame.payload = read_frame->payload;
|
||||
read_frame = &session->raw_read_frame;
|
||||
break;
|
||||
@ -278,6 +279,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi
|
||||
session->raw_read_frame.ssrc = read_frame->ssrc;
|
||||
session->raw_read_frame.seq = read_frame->seq;
|
||||
session->raw_read_frame.m = read_frame->m;
|
||||
session->raw_read_frame.flags = read_frame->flags;
|
||||
session->raw_read_frame.payload = read_frame->payload;
|
||||
read_frame = &session->raw_read_frame;
|
||||
status = SWITCH_STATUS_SUCCESS;
|
||||
@ -357,12 +359,13 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi
|
||||
|
||||
}
|
||||
|
||||
if ((*frame)->datalen == session->read_codec->implementation->bytes_per_frame) {
|
||||
if (read_frame->datalen == session->read_codec->implementation->bytes_per_frame) {
|
||||
perfect = TRUE;
|
||||
} else {
|
||||
if (!session->raw_read_buffer) {
|
||||
switch_size_t bytes = session->read_codec->implementation->bytes_per_frame;
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Engaging Read Buffer at %u bytes\n", (uint32_t) bytes);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Engaging Read Buffer at %u bytes vs %u\n",
|
||||
(uint32_t) bytes, (uint32_t) (*frame)->datalen);
|
||||
switch_buffer_create_dynamic(&session->raw_read_buffer, bytes * SWITCH_BUFFER_BLOCK_FRAMES, bytes * SWITCH_BUFFER_START_FRAMES, 0);
|
||||
}
|
||||
if (!switch_buffer_write(session->raw_read_buffer, read_frame->data, read_frame->datalen)) {
|
||||
@ -408,6 +411,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi
|
||||
session->enc_read_frame.ssrc = read_frame->ssrc;
|
||||
session->enc_read_frame.seq = read_frame->seq;
|
||||
session->enc_read_frame.m = read_frame->m;
|
||||
session->enc_read_frame.flags = read_frame->flags;
|
||||
session->enc_read_frame.payload = session->read_codec->implementation->ianacode;
|
||||
}
|
||||
*frame = &session->enc_read_frame;
|
||||
@ -417,6 +421,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi
|
||||
session->raw_read_frame.timestamp = read_frame->timestamp;
|
||||
session->raw_read_frame.payload = enc_frame->codec->implementation->ianacode;
|
||||
session->raw_read_frame.m = read_frame->m;
|
||||
session->enc_read_frame.flags = read_frame->flags;
|
||||
session->raw_read_frame.ssrc = read_frame->ssrc;
|
||||
session->raw_read_frame.seq = read_frame->seq;
|
||||
*frame = &session->raw_read_frame;
|
||||
@ -616,6 +621,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess
|
||||
session->raw_write_frame.timestamp = frame->timestamp;
|
||||
session->raw_write_frame.rate = frame->rate;
|
||||
session->raw_write_frame.m = frame->m;
|
||||
session->raw_write_frame.flags = frame->flags;
|
||||
session->raw_write_frame.ssrc = frame->ssrc;
|
||||
session->raw_write_frame.seq = frame->seq;
|
||||
session->raw_write_frame.payload = frame->payload;
|
||||
@ -768,6 +774,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess
|
||||
session->enc_write_frame.timestamp = frame->timestamp;
|
||||
session->enc_write_frame.payload = session->write_codec->implementation->ianacode;
|
||||
session->enc_write_frame.m = frame->m;
|
||||
session->enc_write_frame.flags = frame->flags;
|
||||
session->enc_write_frame.ssrc = frame->ssrc;
|
||||
session->enc_write_frame.seq = frame->seq;
|
||||
write_frame = &session->enc_write_frame;
|
||||
@ -777,6 +784,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess
|
||||
enc_frame->samples = enc_frame->datalen / sizeof(int16_t);
|
||||
enc_frame->timestamp = frame->timestamp;
|
||||
enc_frame->m = frame->m;
|
||||
enc_frame->flags = frame->flags;
|
||||
enc_frame->seq = frame->seq;
|
||||
enc_frame->ssrc = frame->ssrc;
|
||||
enc_frame->payload = enc_frame->codec->implementation->ianacode;
|
||||
@ -830,6 +838,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess
|
||||
session->enc_write_frame.codec = session->write_codec;
|
||||
session->enc_write_frame.samples = enc_frame->datalen / sizeof(int16_t);
|
||||
session->enc_write_frame.m = frame->m;
|
||||
session->enc_write_frame.flags = frame->flags;
|
||||
session->enc_write_frame.ssrc = frame->ssrc;
|
||||
session->enc_write_frame.payload = session->write_codec->implementation->ianacode;
|
||||
write_frame = &session->enc_write_frame;
|
||||
@ -851,6 +860,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess
|
||||
session->enc_write_frame.codec = session->write_codec;
|
||||
session->enc_write_frame.samples = enc_frame->datalen / sizeof(int16_t);
|
||||
session->enc_write_frame.m = frame->m;
|
||||
session->enc_write_frame.flags = frame->flags;
|
||||
session->enc_write_frame.ssrc = frame->ssrc;
|
||||
session->enc_write_frame.payload = session->write_codec->implementation->ianacode;
|
||||
write_frame = &session->enc_write_frame;
|
||||
@ -865,6 +875,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess
|
||||
enc_frame->codec = session->write_codec;
|
||||
enc_frame->samples = enc_frame->datalen / sizeof(int16_t);
|
||||
enc_frame->m = frame->m;
|
||||
enc_frame->flags = frame->flags;
|
||||
enc_frame->ssrc = frame->ssrc;
|
||||
enc_frame->payload = enc_frame->codec->implementation->ianacode;
|
||||
write_frame = enc_frame;
|
||||
|
@ -797,11 +797,16 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_create(switch_rtp_t **new_rtp_session
|
||||
rtp_session->payload = payload;
|
||||
rtp_session->ms_per_packet = ms_per_packet;
|
||||
rtp_session->samples_per_interval = rtp_session->conf_samples_per_interval = samples_per_interval;
|
||||
rtp_session->timer_name = switch_core_strdup(pool, timer_name);
|
||||
|
||||
if (!strcasecmp(timer_name, "none")) {
|
||||
timer_name = NULL;
|
||||
}
|
||||
|
||||
if (!switch_strlen_zero(timer_name)) {
|
||||
rtp_session->timer_name = switch_core_strdup(pool, timer_name);
|
||||
switch_set_flag_locked(rtp_session, SWITCH_RTP_FLAG_USE_TIMER);
|
||||
switch_clear_flag(rtp_session, SWITCH_RTP_FLAG_USE_TIMER);
|
||||
switch_clear_flag(rtp_session, SWITCH_RTP_FLAG_NOBLOCK);
|
||||
}
|
||||
|
||||
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_USE_TIMER) && switch_strlen_zero(timer_name)) {
|
||||
@ -1238,6 +1243,10 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (bytes == 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bytes && switch_test_flag(rtp_session, SWITCH_RTP_FLAG_AUTOADJ) && switch_sockaddr_get_port(rtp_session->from_addr)) {
|
||||
const char *tx_host;
|
||||
const char *old_host;
|
||||
|
Loading…
x
Reference in New Issue
Block a user