char header[50];
char *prepend_string;
char *spool;
+ switch_thread_cond_t *cond;
+ switch_mutex_t *cond_mutex;
} globals;
struct pvt_s {
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;
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) {
}
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) {
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;
}
}
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);
-
- t38 = pvt->t38_state;
- t30 = t38_terminal_get_t30_state(t38);
+ 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;
+ }
- memset(t38, 0, sizeof(t38_terminal_state_t));
+ t38 = pvt->t38_state;
+ t30 = t38_terminal_get_t30_state(t38);
- 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;
- }
+ memset(t38, 0, sizeof(t38_terminal_state_t));
- pvt->t38_core = t38_terminal_get_t38_core_state(pvt->t38_state);
+ 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;
+ }
- 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;
- }
+ pvt->t38_core = t38_terminal_get_t38_core_state(pvt->t38_state);
- span_log_set_message_handler(&t38->logging, spanfax_log_message);
- span_log_set_message_handler(&t30->logging, spanfax_log_message);
+ 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;
+ }
- 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);
- }
+ msg.from = __FILE__;
+ msg.message_id = SWITCH_MESSAGE_INDICATE_UDPTL_MODE;
+ switch_core_session_receive_message(pvt->session, &msg);
+
+ /* 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);
+
+ 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) {
//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;
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));
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;
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));
}