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