make t38 terminal mode more reliable
This commit is contained in:
parent
19dc1ab0f2
commit
83da7bd318
|
@ -74,6 +74,8 @@ static struct {
|
|||
char header[50];
|
||||
char *prepend_string;
|
||||
char *spool;
|
||||
switch_thread_cond_t *cond;
|
||||
switch_mutex_t *cond_mutex;
|
||||
} globals;
|
||||
|
||||
struct pvt_s {
|
||||
|
@ -121,24 +123,16 @@ static struct {
|
|||
static int add_pvt(pvt_t *pvt)
|
||||
{
|
||||
int r = 0;
|
||||
uint32_t sanity = 50;
|
||||
|
||||
switch_mutex_lock(t38_state_list.mutex);
|
||||
if (!t38_state_list.thread_running) {
|
||||
|
||||
launch_timer_thread();
|
||||
|
||||
while(--sanity && !t38_state_list.thread_running) {
|
||||
switch_yield(10000);
|
||||
}
|
||||
}
|
||||
switch_mutex_unlock(t38_state_list.mutex);
|
||||
|
||||
if (t38_state_list.thread_running) {
|
||||
switch_mutex_lock(t38_state_list.mutex);
|
||||
pvt->next = t38_state_list.head;
|
||||
t38_state_list.head = pvt;
|
||||
switch_mutex_unlock(t38_state_list.mutex);
|
||||
r = 1;
|
||||
switch_thread_cond_broadcast(globals.cond);
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error launching thread\n");
|
||||
}
|
||||
|
||||
return r;
|
||||
|
@ -151,9 +145,9 @@ static int del_pvt(pvt_t *del_pvt)
|
|||
pvt_t *p, *l = NULL;
|
||||
int r = 0;
|
||||
|
||||
if (!t38_state_list.thread_running) goto end;
|
||||
|
||||
|
||||
switch_mutex_lock(t38_state_list.mutex);
|
||||
|
||||
for (p = t38_state_list.head; p; p = p->next) {
|
||||
if (p == del_pvt) {
|
||||
if (l) {
|
||||
|
@ -163,42 +157,48 @@ static int del_pvt(pvt_t *del_pvt)
|
|||
}
|
||||
p->next = NULL;
|
||||
r = 1;
|
||||
goto end;
|
||||
break;
|
||||
}
|
||||
|
||||
l = p;
|
||||
}
|
||||
|
||||
end:
|
||||
|
||||
switch_mutex_unlock(t38_state_list.mutex);
|
||||
|
||||
return r;
|
||||
switch_thread_cond_broadcast(globals.cond);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void *SWITCH_THREAD_FUNC timer_thread_run(switch_thread_t *thread, void *obj)
|
||||
{
|
||||
switch_timer_t timer = { 0 };
|
||||
pvt_t *pvt;
|
||||
int samples = 240;
|
||||
int ms = 30;
|
||||
int samples = 160;
|
||||
int ms = 20;
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "timer thread started.\n");
|
||||
switch_mutex_lock(t38_state_list.mutex);
|
||||
t38_state_list.thread_running = 1;
|
||||
switch_mutex_unlock(t38_state_list.mutex);
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FAX timer thread started.\n");
|
||||
|
||||
if (switch_core_timer_init(&timer, "soft", ms, samples, NULL) != SWITCH_STATUS_SUCCESS) {
|
||||
return NULL;
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "timer init failed.\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
t38_state_list.thread_running = 1;
|
||||
|
||||
while(t38_state_list.thread_running) {
|
||||
|
||||
switch_mutex_lock(globals.cond_mutex);
|
||||
|
||||
switch_mutex_lock(t38_state_list.mutex);
|
||||
|
||||
if (!t38_state_list.head) {
|
||||
switch_mutex_unlock(t38_state_list.mutex);
|
||||
goto end;
|
||||
switch_thread_cond_wait(globals.cond, globals.cond_mutex);
|
||||
switch_core_timer_sync(&timer);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (pvt = t38_state_list.head; pvt; pvt = pvt->next) {
|
||||
|
@ -214,10 +214,15 @@ static void *SWITCH_THREAD_FUNC timer_thread_run(switch_thread_t *thread, void *
|
|||
|
||||
end:
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "timer thread ended.\n");
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FAX timer thread ended.\n");
|
||||
|
||||
switch_mutex_lock(t38_state_list.mutex);
|
||||
t38_state_list.thread_running = 0;
|
||||
switch_core_timer_destroy(&timer);
|
||||
switch_mutex_unlock(t38_state_list.mutex);
|
||||
|
||||
if (timer.timer_interface) {
|
||||
switch_core_timer_destroy(&timer);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -468,49 +473,61 @@ static switch_status_t spanfax_init(pvt_t *pvt, transport_mode_t trans_mode)
|
|||
}
|
||||
break;
|
||||
case T38_MODE:
|
||||
if (pvt->t38_state == NULL) {
|
||||
pvt->t38_state = (t38_terminal_state_t *) switch_core_session_alloc(pvt->session, sizeof(t38_terminal_state_t));
|
||||
}
|
||||
if (pvt->t38_state == NULL) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
if (pvt->udptl_state == NULL) {
|
||||
pvt->udptl_state = (udptl_state_t *) switch_core_session_alloc(pvt->session, sizeof(udptl_state_t));
|
||||
}
|
||||
if (pvt->udptl_state == NULL) {
|
||||
t38_terminal_free(pvt->t38_state);
|
||||
pvt->t38_state = NULL;
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
{
|
||||
switch_core_session_message_t msg = { 0 };
|
||||
|
||||
/* add to timer thread processing */
|
||||
add_pvt(pvt);
|
||||
if (pvt->t38_state == NULL) {
|
||||
pvt->t38_state = (t38_terminal_state_t *) switch_core_session_alloc(pvt->session, sizeof(t38_terminal_state_t));
|
||||
}
|
||||
if (pvt->t38_state == NULL) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
if (pvt->udptl_state == NULL) {
|
||||
pvt->udptl_state = (udptl_state_t *) switch_core_session_alloc(pvt->session, sizeof(udptl_state_t));
|
||||
}
|
||||
if (pvt->udptl_state == NULL) {
|
||||
t38_terminal_free(pvt->t38_state);
|
||||
pvt->t38_state = NULL;
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
t38 = pvt->t38_state;
|
||||
t30 = t38_terminal_get_t30_state(t38);
|
||||
|
||||
memset(t38, 0, sizeof(t38_terminal_state_t));
|
||||
|
||||
if (t38_terminal_init(t38, pvt->caller, t38_tx_packet_handler, pvt) == NULL) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot initialize my T.38 structs\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
pvt->t38_core = t38_terminal_get_t38_core_state(pvt->t38_state);
|
||||
|
||||
if (udptl_init(pvt->udptl_state, UDPTL_ERROR_CORRECTION_REDUNDANCY, 3, 3,
|
||||
(udptl_rx_packet_handler_t *) t38_core_rx_ifp_packet, (void *) pvt->t38_core) == NULL) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot initialize my UDPTL structs\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
msg.from = __FILE__;
|
||||
msg.message_id = SWITCH_MESSAGE_INDICATE_UDPTL_MODE;
|
||||
switch_core_session_receive_message(pvt->session, &msg);
|
||||
|
||||
t38 = pvt->t38_state;
|
||||
t30 = t38_terminal_get_t30_state(t38);
|
||||
/* add to timer thread processing */
|
||||
if (!add_pvt(pvt)) {
|
||||
if (channel) {
|
||||
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
|
||||
}
|
||||
}
|
||||
|
||||
span_log_set_message_handler(&t38->logging, spanfax_log_message);
|
||||
span_log_set_message_handler(&t30->logging, spanfax_log_message);
|
||||
|
||||
memset(t38, 0, sizeof(t38_terminal_state_t));
|
||||
|
||||
if (t38_terminal_init(t38, pvt->caller, t38_tx_packet_handler, pvt) == NULL) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot initialize my T.38 structs\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
pvt->t38_core = t38_terminal_get_t38_core_state(pvt->t38_state);
|
||||
|
||||
if (udptl_init(pvt->udptl_state, UDPTL_ERROR_CORRECTION_REDUNDANCY, 3, 3,
|
||||
(udptl_rx_packet_handler_t *) t38_core_rx_ifp_packet, (void *) pvt->t38_core) == NULL) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot initialize my UDPTL structs\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
span_log_set_message_handler(&t38->logging, spanfax_log_message);
|
||||
span_log_set_message_handler(&t30->logging, spanfax_log_message);
|
||||
|
||||
if (pvt->verbose) {
|
||||
span_log_set_level(&t38->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW);
|
||||
span_log_set_level(&t30->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW);
|
||||
}
|
||||
if (pvt->verbose) {
|
||||
span_log_set_level(&t38->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW);
|
||||
span_log_set_level(&t30->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case T38_GATEWAY_MODE:
|
||||
if (pvt->t38_gateway_state == NULL) {
|
||||
|
@ -1145,8 +1162,6 @@ void mod_spandsp_fax_process_fax(switch_core_session_t *session, const char *dat
|
|||
//switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "READ %d udptl bytes\n", read_frame->packetlen);
|
||||
|
||||
udptl_rx_packet(pvt->udptl_state, read_frame->packet, read_frame->packetlen);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
continue;
|
||||
|
@ -1282,6 +1297,8 @@ void mod_spandsp_fax_event_handler(switch_event_t *event)
|
|||
|
||||
void mod_spandsp_fax_load(switch_memory_pool_t *pool)
|
||||
{
|
||||
uint32_t sanity = 200;
|
||||
|
||||
memset(&globals, 0, sizeof(globals));
|
||||
memset(&t38_state_list, 0, sizeof(t38_state_list));
|
||||
|
||||
|
@ -1289,6 +1306,9 @@ void mod_spandsp_fax_load(switch_memory_pool_t *pool)
|
|||
|
||||
switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, globals.pool);
|
||||
switch_mutex_init(&t38_state_list.mutex, SWITCH_MUTEX_NESTED, globals.pool);
|
||||
|
||||
switch_mutex_init(&globals.cond_mutex, SWITCH_MUTEX_NESTED, globals.pool);
|
||||
switch_thread_cond_create(&globals.cond, globals.pool);
|
||||
|
||||
globals.enable_t38 = 1;
|
||||
globals.total_sessions = 0;
|
||||
|
@ -1301,10 +1321,22 @@ void mod_spandsp_fax_load(switch_memory_pool_t *pool)
|
|||
strncpy(globals.header, "SpanDSP Fax Header", sizeof(globals.header) - 1);
|
||||
|
||||
load_configuration(0);
|
||||
|
||||
|
||||
launch_timer_thread();
|
||||
|
||||
while(--sanity && !t38_state_list.thread_running) {
|
||||
switch_yield(20000);
|
||||
}
|
||||
}
|
||||
|
||||
void mod_spandsp_fax_shutdown(void)
|
||||
{
|
||||
switch_status_t tstatus = SWITCH_STATUS_SUCCESS;
|
||||
|
||||
t38_state_list.thread_running = 0;
|
||||
switch_thread_cond_broadcast(globals.cond);
|
||||
switch_thread_join(&tstatus, t38_state_list.thread);
|
||||
memset(&globals, 0, sizeof(globals));
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue