提交 7b3d3f7e authored 作者: Anthony Minessale's avatar Anthony Minessale 提交者: Brian West

Tea for two (or maybe thirty eight?)

上级 7cfe6bb2
...@@ -869,32 +869,33 @@ fi ...@@ -869,32 +869,33 @@ fi
CHECK_ERLANG CHECK_ERLANG
AC_CONFIG_FILES([Makefile AC_CONFIG_FILES([Makefile
build/Makefile build/Makefile
src/Makefile src/Makefile
src/mod/Makefile src/mod/Makefile
src/mod/applications/mod_enum/Makefile src/mod/applications/mod_enum/Makefile
src/mod/applications/mod_expr/Makefile src/mod/applications/mod_expr/Makefile
src/mod/applications/mod_fax/Makefile
src/mod/applications/mod_stress/Makefile src/mod/applications/mod_stress/Makefile
src/mod/applications/mod_t38gateway/Makefile src/mod/applications/mod_t38gateway/Makefile
src/mod/endpoints/mod_portaudio/Makefile src/mod/endpoints/mod_portaudio/Makefile
src/mod/endpoints/mod_skinny/Makefile src/mod/endpoints/mod_skinny/Makefile
src/mod/endpoints/mod_skypopen/Makefile src/mod/endpoints/mod_skypopen/Makefile
src/mod/endpoints/mod_sofia/Makefile src/mod/endpoints/mod_sofia/Makefile
src/mod/formats/mod_portaudio_stream/Makefile src/mod/formats/mod_portaudio_stream/Makefile
src/mod/asr_tts/mod_unimrcp/Makefile src/mod/asr_tts/mod_unimrcp/Makefile
src/mod/languages/mod_java/Makefile src/mod/languages/mod_java/Makefile
src/mod/languages/mod_lua/Makefile src/mod/languages/mod_lua/Makefile
src/mod/languages/mod_python/Makefile src/mod/languages/mod_python/Makefile
src/mod/languages/mod_spidermonkey/Makefile src/mod/languages/mod_spidermonkey/Makefile
src/mod/event_handlers/mod_erlang_event/Makefile src/mod/event_handlers/mod_erlang_event/Makefile
src/include/switch_am_config.h src/include/switch_am_config.h
build/getsounds.sh build/getsounds.sh
build/getlib.sh build/getlib.sh
build/freeswitch.pc build/freeswitch.pc
build/modmake.rules build/modmake.rules
libs/xmlrpc-c/include/xmlrpc-c/config.h libs/xmlrpc-c/include/xmlrpc-c/config.h
libs/xmlrpc-c/xmlrpc_config.h libs/xmlrpc-c/xmlrpc_config.h
scripts/gentls_cert]) scripts/gentls_cert])
AM_CONDITIONAL(ISLINUX, [test `uname -s` = Linux]) AM_CONDITIONAL(ISLINUX, [test `uname -s` = Linux])
AM_CONDITIONAL(ISMAC, [test `uname -s` = Darwin]) AM_CONDITIONAL(ISMAC, [test `uname -s` = Darwin])
......
...@@ -176,6 +176,8 @@ SWITCH_DECLARE(switch_port_t) switch_rtp_get_remote_port(switch_rtp_t *rtp_sessi ...@@ -176,6 +176,8 @@ SWITCH_DECLARE(switch_port_t) switch_rtp_get_remote_port(switch_rtp_t *rtp_sessi
SWITCH_DECLARE(void) switch_rtp_reset_media_timer(switch_rtp_t *rtp_session); SWITCH_DECLARE(void) switch_rtp_reset_media_timer(switch_rtp_t *rtp_session);
SWITCH_DECLARE(void) switch_rtp_set_max_missed_packets(switch_rtp_t *rtp_session, uint32_t max); SWITCH_DECLARE(void) switch_rtp_set_max_missed_packets(switch_rtp_t *rtp_session, uint32_t max);
SWITCH_DECLARE(switch_status_t) switch_rtp_udptl_mode(switch_rtp_t *rtp_session);
/*! /*!
\brief Assign a local address to the RTP session \brief Assign a local address to the RTP session
\param rtp_session an RTP session to assign the local address to \param rtp_session an RTP session to assign the local address to
......
...@@ -499,7 +499,6 @@ typedef enum { ...@@ -499,7 +499,6 @@ typedef enum {
SWITCH_RTP_FLAG_GOOGLEHACK - Convert payload from 102 to 97 SWITCH_RTP_FLAG_GOOGLEHACK - Convert payload from 102 to 97
SWITCH_RTP_FLAG_VAD - Enable VAD SWITCH_RTP_FLAG_VAD - Enable VAD
SWITCH_RTP_FLAG_BREAK - Stop what you are doing and return SWITCH_STATUS_BREAK SWITCH_RTP_FLAG_BREAK - Stop what you are doing and return SWITCH_STATUS_BREAK
SWITCH_RTP_FLAG_MINI - Use mini RTP when possible
SWITCH_RTP_FLAG_DATAWAIT - Do not return from reads unless there is data even when non blocking SWITCH_RTP_FLAG_DATAWAIT - Do not return from reads unless there is data even when non blocking
SWITCH_RTP_FLAG_BUGGY_2833 - Emulate the bug in cisco equipment to allow interop SWITCH_RTP_FLAG_BUGGY_2833 - Emulate the bug in cisco equipment to allow interop
SWITCH_RTP_FLAG_PASS_RFC2833 - Pass 2833 (ignore it) SWITCH_RTP_FLAG_PASS_RFC2833 - Pass 2833 (ignore it)
...@@ -518,7 +517,7 @@ typedef enum { ...@@ -518,7 +517,7 @@ typedef enum {
SWITCH_RTP_FLAG_GOOGLEHACK = (1 << 8), SWITCH_RTP_FLAG_GOOGLEHACK = (1 << 8),
SWITCH_RTP_FLAG_VAD = (1 << 9), SWITCH_RTP_FLAG_VAD = (1 << 9),
SWITCH_RTP_FLAG_BREAK = (1 << 10), SWITCH_RTP_FLAG_BREAK = (1 << 10),
SWITCH_RTP_FLAG_MINI = (1 << 11), SWITCH_RTP_FLAG_UDPTL = (1 << 11),
SWITCH_RTP_FLAG_DATAWAIT = (1 << 12), SWITCH_RTP_FLAG_DATAWAIT = (1 << 12),
SWITCH_RTP_FLAG_BUGGY_2833 = (1 << 13), SWITCH_RTP_FLAG_BUGGY_2833 = (1 << 13),
SWITCH_RTP_FLAG_PASS_RFC2833 = (1 << 14), SWITCH_RTP_FLAG_PASS_RFC2833 = (1 << 14),
...@@ -725,10 +724,13 @@ typedef enum { ...@@ -725,10 +724,13 @@ typedef enum {
SWITCH_MESSAGE_INDICATE_APPLICATION_EXEC, SWITCH_MESSAGE_INDICATE_APPLICATION_EXEC,
SWITCH_MESSAGE_INDICATE_APPLICATION_EXEC_COMPLETE, SWITCH_MESSAGE_INDICATE_APPLICATION_EXEC_COMPLETE,
SWITCH_MESSAGE_INDICATE_PHONE_EVENT, SWITCH_MESSAGE_INDICATE_PHONE_EVENT,
SWITCH_MESSAGE_INDICATE_T38_DESCRIPTION,
SWITCH_MESSAGE_INDICATE_UDPTL_MODE,
SWITCH_MESSAGE_INVALID SWITCH_MESSAGE_INVALID
} switch_core_session_message_types_t; } switch_core_session_message_types_t;
typedef struct { typedef struct {
uint16_t T38FaxVersion;
uint32_t T38MaxBitRate; uint32_t T38MaxBitRate;
switch_bool_t T38FaxFillBitRemoval; switch_bool_t T38FaxFillBitRemoval;
switch_bool_t T38FaxTranscodingMMR; switch_bool_t T38FaxTranscodingMMR;
...@@ -1008,7 +1010,8 @@ typedef enum { ...@@ -1008,7 +1010,8 @@ typedef enum {
typedef enum { typedef enum {
CF_APP_TAGGED = (1 << 0) CF_APP_TAGGED = (1 << 0),
CF_APP_T38 = (1 << 1)
} switch_channel_app_flag_t; } switch_channel_app_flag_t;
...@@ -1034,7 +1037,8 @@ typedef enum { ...@@ -1034,7 +1037,8 @@ typedef enum {
SFF_RFC2833 = (1 << 4), SFF_RFC2833 = (1 << 4),
SFF_PROXY_PACKET = (1 << 5), SFF_PROXY_PACKET = (1 << 5),
SFF_DYNAMIC = (1 << 6), SFF_DYNAMIC = (1 << 6),
SFF_ZRTP = (1 << 7) SFF_ZRTP = (1 << 7),
SFF_UDPTL_PACKET = (1 << 8)
} switch_frame_flag_enum_t; } switch_frame_flag_enum_t;
typedef uint32_t switch_frame_flag_t; typedef uint32_t switch_frame_flag_t;
......
/Makefile /Makefile
/Makefile.in /Makefile.in
/applications/mod_fax/Makefile
/applications/mod_fax/Makefile.in
/applications/mod_commands/Makefile /applications/mod_commands/Makefile
/applications/mod_conference/Makefile /applications/mod_conference/Makefile
/applications/mod_dptools/Makefile /applications/mod_dptools/Makefile
......
BASE=../../../.. include $(top_srcdir)/build/modmake.rulesam
MODNAME=mod_fax
TIFF_DIR=$(switch_srcdir)/libs/tiff-3.8.2 TIFF_DIR=$(switch_srcdir)/libs/tiff-3.8.2
TIFF_BUILDDIR=$(switch_builddir)/libs/tiff-3.8.2 TIFF_BUILDDIR=$(switch_builddir)/libs/tiff-3.8.2
...@@ -8,19 +9,9 @@ SPANDSP_DIR=$(switch_srcdir)/libs/spandsp ...@@ -8,19 +9,9 @@ SPANDSP_DIR=$(switch_srcdir)/libs/spandsp
SPANDSP_BUILDDIR=$(switch_builddir)/libs/spandsp SPANDSP_BUILDDIR=$(switch_builddir)/libs/spandsp
SPANDSP_LA=$(SPANDSP_BUILDDIR)/src/libspandsp.la SPANDSP_LA=$(SPANDSP_BUILDDIR)/src/libspandsp.la
LOCAL_CFLAGS=-I$(SPANDSP_DIR)/src -I$(TIFF_DIR)/libtiff -I$(SPANDSP_BUILDDIR)/src -I$(TIFF_BUILDDIR)/libtiff mod_LTLIBRARIES = mod_fax.la
LOCAL_LIBADD=$(SPANDSP_LA) $(TIFF_LA) mod_fax_la_SOURCES = mod_fax.c ../mod_t38gateway/udptl.c
LOCAL_LDFLAGS=-ljpeg mod_fax_la_CFLAGS = $(AM_CFLAGS) -I$(SPANDSP_DIR)/src -I$(TIFF_DIR)/libtiff -I$(SPANDSP_BUILDDIR)/src -I$(TIFF_BUILDDIR)/libtiff -I../mod_t38gateway
mod_fax_la_LIBADD = $(switch_builddir)/libfreeswitch.la $(SPANDSP_LA) $(TIFF_LA)
include $(BASE)/build/modmake.rules mod_fax_la_LDFLAGS = -avoid-version -module -no-undefined -shared -ljpeg
$(MODNAME).lo: $(SPANDSP_LA) $(TIFF_LA)
$(SPANDSP_LA): $(TIFF_LA) $(SPANDSP_DIR) $(SPANDSP_DIR)/.update
cd $(SPANDSP_BUILDDIR) && $(MAKE) -j1
$(TOUCH_TARGET)
$(TIFF_LA): $(TIFF_DIR) $(TIFF_DIR)/.update
cd $(TIFF_BUILDDIR) && $(MAKE) -j1
$(TOUCH_TARGET)
差异被折叠。
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2009, Steve Underwood <steveu@coppice.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* Contributor(s):
*
* Steve Underwood <steveu@coppice.org>
*
* udptl.h -- UDPTL handling for T.38
*
*/
#if !defined(_UDPTL_H_)
#define _UDPTL_H_
#define LOCAL_FAX_MAX_DATAGRAM 400
#define LOCAL_FAX_MAX_FEC_PACKETS 5
#define UDPTL_BUF_MASK 15
typedef int (udptl_rx_packet_handler_t) (void *user_data, const uint8_t msg[], int len, int seq_no);
typedef struct {
int buf_len;
uint8_t buf[LOCAL_FAX_MAX_DATAGRAM];
} udptl_fec_tx_buffer_t;
typedef struct {
int buf_len;
uint8_t buf[LOCAL_FAX_MAX_DATAGRAM];
int fec_len[LOCAL_FAX_MAX_FEC_PACKETS];
uint8_t fec[LOCAL_FAX_MAX_FEC_PACKETS][LOCAL_FAX_MAX_DATAGRAM];
int fec_span;
int fec_entries;
} udptl_fec_rx_buffer_t;
struct udptl_state_s {
udptl_rx_packet_handler_t *rx_packet_handler;
void *user_data;
/*! This option indicates the error correction scheme used in transmitted UDPTL
packets. */
int error_correction_scheme;
/*! This option indicates the number of error correction entries transmitted in
UDPTL packets. */
int error_correction_entries;
/*! This option indicates the span of the error correction entries in transmitted
UDPTL packets (FEC only). */
int error_correction_span;
/*! This option indicates the maximum size of a datagram that can be accepted by
the remote device. */
int far_max_datagram_size;
/*! This option indicates the maximum size of a datagram that we are prepared to
accept. */
int local_max_datagram_size;
int verbose;
int tx_seq_no;
int rx_seq_no;
int rx_expected_seq_no;
udptl_fec_tx_buffer_t tx[UDPTL_BUF_MASK + 1];
udptl_fec_rx_buffer_t rx[UDPTL_BUF_MASK + 1];
};
enum {
UDPTL_ERROR_CORRECTION_NONE,
UDPTL_ERROR_CORRECTION_FEC,
UDPTL_ERROR_CORRECTION_REDUNDANCY
};
typedef struct udptl_state_s udptl_state_t;
#if defined(__cplusplus)
extern "C" {
#endif
/*! \brief Process an arriving UDPTL packet.
\param s The UDPTL context.
\param buf The UDPTL packet buffer.
\param len The length of the packet.
\return 0 for OK. */
int udptl_rx_packet(udptl_state_t *s, const uint8_t buf[], int len);
/*! \brief Construct a UDPTL packet, ready for transmission.
\param s The UDPTL context.
\param buf The UDPTL packet buffer.
\param msg The primary packet.
\param len The length of the primary packet.
\return The length of the constructed UDPTL packet. */
int udptl_build_packet(udptl_state_t *s, uint8_t buf[], const uint8_t msg[], int msg_len);
/*! \brief Change the error correction settings of a UDPTL context.
\param s The UDPTL context.
\param ec_scheme One of the optional error correction schemes.
\param span The packet span over which error correction should be applied.
\param entries The number of error correction entries to include in packets.
\return 0 for OK. */
int udptl_set_error_correction(udptl_state_t *s, int ec_scheme, int span, int entries);
/*! \brief Check the error correction settings of a UDPTL context.
\param s The UDPTL context.
\param ec_scheme One of the optional error correction schemes.
\param span The packet span over which error correction is being applied.
\param entries The number of error correction being included in packets.
\return 0 for OK. */
int udptl_get_error_correction(udptl_state_t *s, int *ec_scheme, int *span, int *entries);
int udptl_set_local_max_datagram(udptl_state_t *s, int max_datagram);
int udptl_get_local_max_datagram(udptl_state_t *s);
int udptl_set_far_max_datagram(udptl_state_t *s, int max_datagram);
int udptl_get_far_max_datagram(udptl_state_t *s);
/*! \brief Initialise a UDPTL context.
\param s The UDPTL context.
\param ec_scheme One of the optional error correction schemes.
\param span The packet span over which error correction should be applied.
\param entries The number of error correction entries to include in packets.
\param rx_packet_handler The callback function, used to report arriving IFP packets.
\param user_data An opaque pointer supplied to rx_packet_handler.
\return A pointer to the UDPTL context, or NULL if there was a problem. */
udptl_state_t *udptl_init(udptl_state_t *s, int ec_scheme, int span, int entries, udptl_rx_packet_handler_t rx_packet_handler, void *user_data);
/*! \brief Release a UDPTL context.
\param s The UDPTL context.
\return 0 for OK. */
int udptl_release(udptl_state_t *s);
#if defined(__cplusplus)
}
#endif
#endif
/*- End of file ------------------------------------------------------------*/
include $(top_srcdir)/build/modmake.rulesam include $(top_srcdir)/build/modmake.rulesam
MODNAME=mod_t38gateway MODNAME=mod_t38gateway
TIFF_DIR=$(switch_srcdir)/libs/tiff-3.8.2
TIFF_BUILDDIR=$(switch_builddir)/libs/tiff-3.8.2
TIFF_LA=$(TIFF_BUILDDIR)/libtiff/libtiff.la
SPANDSP_DIR=$(switch_srcdir)/libs/spandsp
SPANDSP_BUILDDIR=$(switch_builddir)/libs/spandsp
SPANDSP_LA=$(SPANDSP_BUILDDIR)/src/libspandsp.la
mod_LTLIBRARIES = mod_t38gateway.la mod_LTLIBRARIES = mod_t38gateway.la
mod_t38gateway_la_SOURCES = mod_t38gateway.c udptl.c mod_t38gateway_la_SOURCES = mod_t38gateway.c udptl.c
mod_t38gateway_la_CFLAGS = $(AM_CFLAGS) mod_t38gateway_la_CFLAGS = $(AM_CFLAGS) -I$(SPANDSP_DIR)/src -I$(TIFF_DIR)/libtiff -I$(SPANDSP_BUILDDIR)/src -I$(TIFF_BUILDDIR)/libtiff
mod_t38gateway_la_LIBADD = $(switch_builddir)/libfreeswitch.la mod_t38gateway_la_LIBADD = $(switch_builddir)/libfreeswitch.la $(SPANDSP_LA) $(TIFF_LA)
mod_t38gateway_la_LDFLAGS = -avoid-version -module -no-undefined -shared mod_t38gateway_la_LDFLAGS = -avoid-version -module -no-undefined -shared -ljpeg
...@@ -199,7 +199,7 @@ SWITCH_STANDARD_APP(t38gateway_start_function) ...@@ -199,7 +199,7 @@ SWITCH_STANDARD_APP(t38gateway_start_function)
t38gateway_info->t38_core = t38_gateway_get_t38_core_state(t38gateway_info->t38); t38gateway_info->t38_core = t38_gateway_get_t38_core_state(t38gateway_info->t38);
t38gateway_info->udptl = udptl_init(NULL, UDPTL_ERROR_CORRECTION_REDUNDANCY, 3, 3, rx_packet_handler, (void *) t38gateway_info); t38gateway_info->udptl = udptl_init(NULL, UDPTL_ERROR_CORRECTION_REDUNDANCY, 3, 3, rx_packet_handler, (void *) t38gateway_info);
status = switch_core_media_bug_add(session, t38gateway_callback, t38gateway_info, 0, SMBF_READ_STREAM, &bug); status = switch_core_media_bug_add(session, "T.38 gateway", NULL, t38gateway_callback, t38gateway_info, 0, SMBF_READ_STREAM, &bug);
if (status != SWITCH_STATUS_SUCCESS) { if (status != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failure hooking to stream\n"); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failure hooking to stream\n");
...@@ -316,7 +316,7 @@ SWITCH_STANDARD_API(t38gateway_api_main) ...@@ -316,7 +316,7 @@ SWITCH_STANDARD_API(t38gateway_api_main)
/* Add a media bug that allows me to intercept the /* Add a media bug that allows me to intercept the
* reading leg of the audio stream */ * reading leg of the audio stream */
status = switch_core_media_bug_add(t38gateway_session, t38gateway_callback, t38gateway_info, 0, SMBF_READ_STREAM, &bug); status = switch_core_media_bug_add(t38gateway_session, "T.38 gateway", NULL, t38gateway_callback, t38gateway_info, 0, SMBF_READ_STREAM, &bug);
/* If adding a media bug fails exit */ /* If adding a media bug fails exit */
if (status != SWITCH_STATUS_SUCCESS) { if (status != SWITCH_STATUS_SUCCESS) {
......
...@@ -977,9 +977,9 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f ...@@ -977,9 +977,9 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f
if (tech_pvt->last_codec_ms && tech_pvt->last_codec_ms == codec_ms) { if (tech_pvt->last_codec_ms && tech_pvt->last_codec_ms == codec_ms) {
tech_pvt->mismatch_count++; tech_pvt->mismatch_count++;
} }
tech_pvt->last_codec_ms = codec_ms; tech_pvt->last_codec_ms = codec_ms;
if (tech_pvt->mismatch_count > MAX_MISMATCH_FRAMES) { if (tech_pvt->mismatch_count > MAX_MISMATCH_FRAMES) {
if (switch_rtp_ready(tech_pvt->rtp_session) && codec_ms != tech_pvt->codec_ms) { if (switch_rtp_ready(tech_pvt->rtp_session) && codec_ms != tech_pvt->codec_ms) {
const char *val; const char *val;
...@@ -996,19 +996,23 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f ...@@ -996,19 +996,23 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f
} }
tech_pvt->read_frame.datalen = 0; tech_pvt->read_frame.datalen = 0;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
"We were told to use ptime %d but what they meant to say was %d\n"
"This issue has so far been identified to happen on the following broken platforms/devices:\n"
"Linksys/Sipura aka Cisco\n"
"ShoreTel\n"
"Sonus/L3\n"
"We will try to fix it but some of the devices on this list are so broken who knows what will happen..\n",
(int) tech_pvt->codec_ms, (int) codec_ms);
switch_channel_set_variable_printf(channel, "sip_h_X-Broken-PTIME", "Adv=%d;Sent=%d", if (codec_ms != tech_pvt->codec_ms) {
(int) tech_pvt->codec_ms, (int) codec_ms); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
"We were told to use ptime %d but what they meant to say was %d\n"
tech_pvt->codec_ms = codec_ms; "This issue has so far been identified to happen on the following broken platforms/devices:\n"
"Linksys/Sipura aka Cisco\n"
"ShoreTel\n"
"Sonus/L3\n"
"We will try to fix it but some of the devices on this list are so broken,\n"
"who knows what will happen..\n",
(int) tech_pvt->codec_ms, (int) codec_ms);
switch_channel_set_variable_printf(channel, "sip_h_X-Broken-PTIME", "Adv=%d;Sent=%d",
(int) tech_pvt->codec_ms, (int) codec_ms);
tech_pvt->codec_ms = codec_ms;
}
if (sofia_glue_tech_set_codec(tech_pvt, 2) != SWITCH_STATUS_SUCCESS) { if (sofia_glue_tech_set_codec(tech_pvt, 2) != SWITCH_STATUS_SUCCESS) {
*frame = NULL; *frame = NULL;
...@@ -1049,6 +1053,7 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f ...@@ -1049,6 +1053,7 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f
tech_pvt->last_ts = 0; tech_pvt->last_ts = 0;
/* inform them of the codec they are actually sending */ /* inform them of the codec they are actually sending */
if (++tech_pvt->codec_reinvites > 2) { if (++tech_pvt->codec_reinvites > 2) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
"Ok, some devices *cough* X-lite *cough*\n" "Ok, some devices *cough* X-lite *cough*\n"
...@@ -1065,7 +1070,10 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f ...@@ -1065,7 +1070,10 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f
} else { } else {
tech_pvt->mismatch_count = 0; tech_pvt->mismatch_count = 0;
} }
tech_pvt->last_ts = tech_pvt->read_frame.timestamp; tech_pvt->last_ts = tech_pvt->read_frame.timestamp;
} else { } else {
tech_pvt->mismatch_count = 0; tech_pvt->mismatch_count = 0;
tech_pvt->last_ts = 0; tech_pvt->last_ts = 0;
...@@ -1512,16 +1520,70 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi ...@@ -1512,16 +1520,70 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
} }
break; break;
case SWITCH_MESSAGE_INDICATE_UDPTL_MODE:
{
switch_t38_options_t *t38_options = switch_channel_get_private(tech_pvt->channel, "t38_options");
if (!t38_options) {
nua_respond(tech_pvt->nh, SIP_488_NOT_ACCEPTABLE, TAG_END());
goto end_lock;
}
case SWITCH_MESSAGE_INDICATE_REQUEST_IMAGE_MEDIA: if (switch_rtp_ready(tech_pvt->rtp_session)) {
switch_rtp_udptl_mode(tech_pvt->rtp_session);
}
}
break;
case SWITCH_MESSAGE_INDICATE_T38_DESCRIPTION:
{ {
switch_t38_options_t *t38_options = (switch_t38_options_t *) msg->pointer_arg; switch_t38_options_t *t38_options = switch_channel_get_private(tech_pvt->channel, "t38_options");
if (!t38_options) {
nua_respond(tech_pvt->nh, SIP_488_NOT_ACCEPTABLE, TAG_END());
goto end_lock;
}
if (switch_rtp_ready(tech_pvt->rtp_session)) {
switch_rtp_udptl_mode(tech_pvt->rtp_session);
}
sofia_glue_set_image_sdp(tech_pvt, t38_options, msg->numeric_arg);
sofia_glue_set_image_sdp(tech_pvt, t38_options); if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) {
char *extra_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_RESPONSE_HEADER_PREFIX);
if (sofia_use_soa(tech_pvt)) {
nua_respond(tech_pvt->nh, SIP_200_OK,
NUTAG_AUTOANSWER(0),
SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
SIPTAG_CALL_INFO_STR(switch_channel_get_variable(tech_pvt->channel, SOFIA_SIP_HEADER_PREFIX "call_info")),
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_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)),
TAG_END());
} else {
nua_respond(tech_pvt->nh, SIP_200_OK,
NUTAG_AUTOANSWER(0),
NUTAG_MEDIA_ENABLE(0),
SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
SIPTAG_CALL_INFO_STR(switch_channel_get_variable(tech_pvt->channel, SOFIA_SIP_HEADER_PREFIX "call_info")),
SIPTAG_CONTENT_TYPE_STR("application/sdp"),
SIPTAG_PAYLOAD_STR(tech_pvt->local_sdp_str),
TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)),
TAG_END());
}
switch_safe_free(extra_headers);
sofia_set_flag_locked(tech_pvt, TFLAG_ANS);
}
}
break;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Sending request for image media. %s\n", case SWITCH_MESSAGE_INDICATE_REQUEST_IMAGE_MEDIA:
switch_channel_get_name(channel), tech_pvt->local_sdp_str); {
switch_t38_options_t *t38_options = switch_channel_get_private(tech_pvt->channel, "t38_options");
sofia_glue_set_image_sdp(tech_pvt, t38_options, msg->numeric_arg);
switch_channel_set_flag(channel, CF_REQ_MEDIA); switch_channel_set_flag(channel, CF_REQ_MEDIA);
sofia_set_flag_locked(tech_pvt, TFLAG_SENT_UPDATE); sofia_set_flag_locked(tech_pvt, TFLAG_SENT_UPDATE);
sofia_glue_do_invite(session); sofia_glue_do_invite(session);
......
...@@ -930,7 +930,7 @@ void sofia_glue_toggle_hold(private_object_t *tech_pvt, int sendonly); ...@@ -930,7 +930,7 @@ void sofia_glue_toggle_hold(private_object_t *tech_pvt, int sendonly);
const char *sofia_state_string(int state); const char *sofia_state_string(int state);
switch_status_t sofia_glue_tech_set_codec(private_object_t *tech_pvt, int force); switch_status_t sofia_glue_tech_set_codec(private_object_t *tech_pvt, int force);
void sofia_wait_for_reply(struct private_object *tech_pvt, nua_event_t event, uint32_t timeout); void sofia_wait_for_reply(struct private_object *tech_pvt, nua_event_t event, uint32_t timeout);
void sofia_glue_set_image_sdp(private_object_t *tech_pvt, switch_t38_options_t *t38_options); void sofia_glue_set_image_sdp(private_object_t *tech_pvt, switch_t38_options_t *t38_options, int insist);
/* /*
* SLA (shared line appearance) entrypoints * SLA (shared line appearance) entrypoints
......
...@@ -4578,6 +4578,11 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, ...@@ -4578,6 +4578,11 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
sdp_parser_free(parser); sdp_parser_free(parser);
} }
} }
if (match && switch_channel_test_app_flag(tech_pvt->channel, CF_APP_T38)) {
goto done;
}
if (match) { if (match) {
if (sofia_glue_tech_choose_port(tech_pvt, 0) != SWITCH_STATUS_SUCCESS) { if (sofia_glue_tech_choose_port(tech_pvt, 0) != SWITCH_STATUS_SUCCESS) {
goto done; goto done;
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
#include <switch_stun.h> #include <switch_stun.h>
void sofia_glue_set_image_sdp(private_object_t *tech_pvt, switch_t38_options_t *t38_options) void sofia_glue_set_image_sdp(private_object_t *tech_pvt, switch_t38_options_t *t38_options, int insist)
{ {
char buf[2048]; char buf[2048];
const char *ip = t38_options->ip; const char *ip = t38_options->ip;
...@@ -45,6 +45,9 @@ void sofia_glue_set_image_sdp(private_object_t *tech_pvt, switch_t38_options_t * ...@@ -45,6 +45,9 @@ void sofia_glue_set_image_sdp(private_object_t *tech_pvt, switch_t38_options_t *
const char *family = "IP4"; const char *family = "IP4";
const char *username = tech_pvt->profile->username; const char *username = tech_pvt->profile->username;
//sofia_clear_flag(tech_pvt, TFLAG_ENABLE_SOA);
if (!ip) { if (!ip) {
if (!(ip = tech_pvt->adv_sdp_audio_ip)) { if (!(ip = tech_pvt->adv_sdp_audio_ip)) {
ip = tech_pvt->proxy_sdp_audio_ip; ip = tech_pvt->proxy_sdp_audio_ip;
...@@ -76,15 +79,29 @@ void sofia_glue_set_image_sdp(private_object_t *tech_pvt, switch_t38_options_t * ...@@ -76,15 +79,29 @@ void sofia_glue_set_image_sdp(private_object_t *tech_pvt, switch_t38_options_t *
} }
tech_pvt->session_id++; tech_pvt->session_id++;
family = strchr(ip, ':') ? "IP6" : "IP4"; family = strchr(ip, ':') ? "IP6" : "IP4";
switch_snprintf(buf, sizeof(buf), switch_snprintf(buf, sizeof(buf),
"v=0\n" "v=0\n"
"o=%s %010u %010u IN %s %s\n" "o=%s %010u %010u IN %s %s\n"
"s=%s\n" "s=%s\n"
"c=IN %s %s\n" "c=IN %s %s\n"
"t=0 0\n" "t=0 0\n",
username,
tech_pvt->owner_id,
tech_pvt->session_id,
family,
ip,
username,
family,
ip);
switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
"m=image %d udptl t38\n" "m=image %d udptl t38\n"
"a=T38FaxVersion:%d\n"
"a=T38MaxBitRate:%d\n" "a=T38MaxBitRate:%d\n"
"%s" "%s"
"%s" "%s"
...@@ -94,23 +111,32 @@ void sofia_glue_set_image_sdp(private_object_t *tech_pvt, switch_t38_options_t * ...@@ -94,23 +111,32 @@ void sofia_glue_set_image_sdp(private_object_t *tech_pvt, switch_t38_options_t *
"a=T38FaxMaxDatagram:%d\n" "a=T38FaxMaxDatagram:%d\n"
"a=T38FaxUdpEC:%s\n" "a=T38FaxUdpEC:%s\n"
"a=T38VendorInfo:%s\n", "a=T38VendorInfo:%s\n",
username,
tech_pvt->owner_id,
tech_pvt->session_id,
family,
ip,
username,
family,
ip,
port, port,
t38_options->T38FaxVersion,
t38_options->T38MaxBitRate, t38_options->T38MaxBitRate,
t38_options->T38FaxFillBitRemoval ? "a=T38FaxFillBitRemoval\n" : "", t38_options->T38FaxFillBitRemoval ? "a=T38FaxFillBitRemoval\n" : "",
t38_options->T38FaxTranscodingMMR ? "a=T38FaxTranscodingMMR\n" : "", t38_options->T38FaxTranscodingMMR ? "a=T38FaxTranscodingMMR\n" : "",
t38_options->T38FaxTranscodingJBIG ? "a=T38FaxTranscodingJBIG\n" : "", t38_options->T38FaxTranscodingJBIG ? "a=T38FaxTranscodingJBIG\n" : "",
t38_options->T38FaxRateManagement, t38_options->T38FaxRateManagement,
t38_options->T38FaxMaxBuffer, t38_options->T38FaxMaxDatagram, t38_options->T38FaxUdpEC, t38_options->T38VendorInfo); t38_options->T38FaxMaxBuffer,
t38_options->T38FaxMaxDatagram,
t38_options->T38FaxUdpEC,
t38_options->T38VendorInfo);
if (insist) {
switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
"m=audio 0 RTP/AVP 19\n");
}
sofia_glue_tech_set_local_sdp(tech_pvt, buf, SWITCH_TRUE); sofia_glue_tech_set_local_sdp(tech_pvt, buf, SWITCH_TRUE);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "%s image media sdp:\n%s\n",
switch_channel_get_name(tech_pvt->channel), tech_pvt->local_sdp_str);
} }
void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, uint32_t port, const char *sr, int force) void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, uint32_t port, const char *sr, int force)
...@@ -1582,7 +1608,9 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session) ...@@ -1582,7 +1608,9 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
return status; return status;
} }
sofia_glue_set_local_sdp(tech_pvt, NULL, 0, NULL, 0); if (!switch_channel_get_private(tech_pvt->channel, "t38_options") || zstr(tech_pvt->local_sdp_str)) {
sofia_glue_set_local_sdp(tech_pvt, NULL, 0, NULL, 0);
}
sofia_set_flag_locked(tech_pvt, TFLAG_READY); sofia_set_flag_locked(tech_pvt, TFLAG_READY);
...@@ -3417,10 +3445,24 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, sdp_session_t * ...@@ -3417,10 +3445,24 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, sdp_session_t *
} }
if (got_udptl && m->m_type == sdp_media_image && m->m_port) { if (got_udptl && m->m_type == sdp_media_image && m->m_port) {
switch_t38_options_t *t38_options = switch_core_session_alloc(tech_pvt->session, sizeof(switch_t38_options_t)); switch_t38_options_t *t38_options = switch_channel_get_private(tech_pvt->channel, "t38_options");
if (!t38_options) {
t38_options = switch_core_session_alloc(tech_pvt->session, sizeof(switch_t38_options_t));
}
t38_options->port = m->m_port;
if (m->m_connections) {
t38_options->ip = switch_core_session_strdup(tech_pvt->session, m->m_connections->c_address);
} else if (sdp && sdp->sdp_connection) {
t38_options->ip = switch_core_session_strdup(tech_pvt->session, sdp->sdp_connection->c_address);
}
for (attr = m->m_attributes; attr; attr = attr->a_next) { for (attr = m->m_attributes; attr; attr = attr->a_next) {
if (!strcasecmp(attr->a_name, "T38MaxBitRate") && attr->a_value) { if (!strcasecmp(attr->a_name, "T38FaxVersion") && attr->a_value) {
t38_options->T38FaxVersion = (uint16_t) atoi(attr->a_value);
} else if (!strcasecmp(attr->a_name, "T38MaxBitRate") && attr->a_value) {
t38_options->T38MaxBitRate = (uint32_t) atoi(attr->a_value); t38_options->T38MaxBitRate = (uint32_t) atoi(attr->a_value);
} else if (!strcasecmp(attr->a_name, "T38FaxFillBitRemoval")) { } else if (!strcasecmp(attr->a_name, "T38FaxFillBitRemoval")) {
t38_options->T38FaxFillBitRemoval = SWITCH_TRUE; t38_options->T38FaxFillBitRemoval = SWITCH_TRUE;
...@@ -3440,13 +3482,13 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, sdp_session_t * ...@@ -3440,13 +3482,13 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, sdp_session_t *
t38_options->T38VendorInfo = switch_core_session_strdup(tech_pvt->session, attr->a_value); t38_options->T38VendorInfo = switch_core_session_strdup(tech_pvt->session, attr->a_value);
} }
} }
switch_channel_set_variable(tech_pvt->channel, "has_t38", "true"); switch_channel_set_variable(tech_pvt->channel, "has_t38", "true");
switch_channel_set_private(tech_pvt->channel, "t38_options", t38_options); switch_channel_set_private(tech_pvt->channel, "t38_options", t38_options);
switch_channel_set_app_flag(tech_pvt->channel, CF_APP_T38);
//switch_channel_set_flag(tech_pvt->channel, CF_PROXY_MEDIA); /* do nothing here, mod_fax will trigger a response (if it's listening =/)*/
//switch_rtp_set_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_PROXY_MEDIA); match = 1;
goto done;
} else if (m->m_type == sdp_media_audio && m->m_port && !got_audio) { } else if (m->m_type == sdp_media_audio && m->m_port && !got_audio) {
sdp_rtpmap_t *map; sdp_rtpmap_t *map;
for (attr = m->m_attributes; attr; attr = attr->a_next) { for (attr = m->m_attributes; attr; attr = attr->a_next) {
......
...@@ -556,6 +556,7 @@ static const char *message_names[] = { ...@@ -556,6 +556,7 @@ static const char *message_names[] = {
"APPLICATION_EXEC", "APPLICATION_EXEC",
"APPLICATION_EXEC_COMPLETE", "APPLICATION_EXEC_COMPLETE",
"PHONE_EVENT", "PHONE_EVENT",
"T38_DESCRIPTION"
"INVALID" "INVALID"
}; };
......
...@@ -1025,6 +1025,33 @@ SWITCH_DECLARE(switch_port_t) switch_rtp_get_remote_port(switch_rtp_t *rtp_sessi ...@@ -1025,6 +1025,33 @@ SWITCH_DECLARE(switch_port_t) switch_rtp_get_remote_port(switch_rtp_t *rtp_sessi
} }
SWITCH_DECLARE(switch_status_t) switch_rtp_udptl_mode(switch_rtp_t *rtp_session)
{
READ_INC(rtp_session);
WRITE_INC(rtp_session);
if (rtp_session->timer.timer_interface) {
switch_core_timer_destroy(&rtp_session->timer);
memset(&rtp_session->timer, 0, sizeof(rtp_session->timer));
}
switch_set_flag_locked(rtp_session, SWITCH_RTP_FLAG_UDPTL);
switch_set_flag_locked(rtp_session, SWITCH_RTP_FLAG_PROXY_MEDIA);
switch_socket_opt_set(rtp_session->sock_input, SWITCH_SO_NONBLOCK, FALSE);
switch_clear_flag(rtp_session, SWITCH_RTP_FLAG_USE_TIMER);
switch_clear_flag(rtp_session, SWITCH_RTP_FLAG_NOBLOCK);
WRITE_DEC(rtp_session);
READ_DEC(rtp_session);
switch_set_flag_locked(rtp_session, SWITCH_RTP_FLAG_FLUSH);
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(switch_status_t) switch_rtp_set_remote_address(switch_rtp_t *rtp_session, const char *host, switch_port_t port, switch_port_t remote_rtcp_port, SWITCH_DECLARE(switch_status_t) switch_rtp_set_remote_address(switch_rtp_t *rtp_session, const char *host, switch_port_t port, switch_port_t remote_rtcp_port,
switch_bool_t change_adv_addr, const char **err) switch_bool_t change_adv_addr, const char **err)
{ {
...@@ -1227,7 +1254,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_change_interval(switch_rtp_t *rtp_ses ...@@ -1227,7 +1254,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_change_interval(switch_rtp_t *rtp_ses
rtp_session->timer_name, ms_per_packet / 1000, rtp_session->timer_name, ms_per_packet / 1000,
samples_per_interval, rtp_session->pool)) == SWITCH_STATUS_SUCCESS) { samples_per_interval, rtp_session->pool)) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
"RE-Starting timer [%s] %d bytes per %dms\n", rtp_session->timer_name, samples_per_interval, ms_per_packet); "RE-Starting timer [%s] %d bytes per %dms\n", rtp_session->timer_name, samples_per_interval, ms_per_packet / 1000);
} else { } else {
memset(&rtp_session->timer, 0, sizeof(rtp_session->timer)); memset(&rtp_session->timer, 0, sizeof(rtp_session->timer));
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
...@@ -2451,9 +2478,14 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ ...@@ -2451,9 +2478,14 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
} }
} }
if (bytes && switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PROXY_MEDIA)) { if (bytes && (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PROXY_MEDIA) || switch_test_flag(rtp_session, SWITCH_RTP_FLAG_UDPTL))) {
/* Fast PASS! */ /* Fast PASS! */
*flags |= SFF_PROXY_PACKET; *flags |= SFF_PROXY_PACKET;
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_UDPTL)) {
*flags |= SFF_UDPTL_PACKET;
}
ret = (int) bytes; ret = (int) bytes;
goto end; goto end;
} }
...@@ -3475,12 +3507,12 @@ SWITCH_DECLARE(int) switch_rtp_write_frame(switch_rtp_t *rtp_session, switch_fra ...@@ -3475,12 +3507,12 @@ SWITCH_DECLARE(int) switch_rtp_write_frame(switch_rtp_t *rtp_session, switch_fra
return -1; return -1;
} }
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PROXY_MEDIA)) { if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PROXY_MEDIA) || switch_test_flag(rtp_session, SWITCH_RTP_FLAG_UDPTL)) {
switch_size_t bytes; switch_size_t bytes;
char bufa[30]; char bufa[30];
const char *tx_host; const char *tx_host;
/* Fast PASS! */ /* Fast PASS! */
if (!switch_test_flag(frame, SFF_PROXY_PACKET)) { if (!switch_test_flag(frame, SFF_PROXY_PACKET) && !switch_test_flag(frame, SFF_UDPTL_PACKET)) {
return 0; return 0;
} }
bytes = frame->packetlen; bytes = frame->packetlen;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论