[asterisk-commits] kpfleming: branch 1.6.1 r208484 - in /branches/1.6.1: ./ apps/ channels/ incl...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Thu Jul 23 17:22:02 CDT 2009
Author: kpfleming
Date: Thu Jul 23 17:21:57 2009
New Revision: 208484
URL: http://svn.asterisk.org/svn-view/asterisk?view=rev&rev=208484
Log:
Merged revisions 208464 via svnmerge from
https://origsvn.digium.com/svn/asterisk/trunk
........
r208464 | kpfleming | 2009-07-23 16:57:24 -0500 (Thu, 23 Jul 2009) | 46 lines
Rework of T.38 negotiation and UDPTL API to address interoperability problems
Over the past couple of months, a number of issues with Asterisk
negotiating (and successfully completing) T.38 sessions with various
endpoints have been found. This patch attempts to address many of
them, primarily focused around ensuring that the endpoints'
MaxDatagram size is honored, and in addition by ensuring that T.38
session parameter negotiation is performed correctly according to the
ITU T.38 Recommendation.
The major changes here are:
1) T.38 applications in Asterisk (app_fax) only generate/receive IFP
packets, they do not ever work with UDPTL packets. As a result of
this, they cannot be allowed to generate packets that would overflow
the other endpoints' MaxDatagram size after the UDPTL stack adds any
error correction information. With this patch, the application is told
the maximum *IFP* size it can generate, based on a calculation using
the far end MaxDatagram size and the active error correction mode on
the T.38 session. The same is true for sending *our* MaxDatagram size
to the remote endpoint; it is computed from the value that the
application says it can accept (for a single IFP packet) combined with
the active error correction mode.
2) All treatment of T.38 session parameters as 'capabilities' in
chan_sip has been removed; these parameters are not at all like
audio/video stream capabilities. There are strict rules to follow for
computing an answer to a T.38 offer, and chan_sip now follows those
rules, using the desired parameters from the application (or channel)
that wants to accept the T.38 negotiation.
3) chan_sip now stores and forwards ast_control_t38_parameters
structures for tracking 'our' and 'their' T.38 session parameters;
this greatly simplifies negotiation, especially for pass-through
calls.
4) Since T.38 negotiation without specifying parameters or receiving
the final negotiated parameters is not very worthwhile, the
AST_CONTROL_T38 control frame has been removed. A note has been added
to UPGRADE.txt about this removal, since any out-of-tree applications
that use it will no longer function properly until they are upgraded
to use AST_CONTROL_T38_PARAMETERS.
Review: https://reviewboard.asterisk.org/r/310/
........
Modified:
branches/1.6.1/ (props changed)
branches/1.6.1/UPGRADE.txt
branches/1.6.1/apps/app_fax.c
branches/1.6.1/channels/chan_sip.c
branches/1.6.1/include/asterisk/frame.h
branches/1.6.1/include/asterisk/udptl.h
branches/1.6.1/main/channel.c
branches/1.6.1/main/frame.c
branches/1.6.1/main/rtp.c
branches/1.6.1/main/udptl.c
Propchange: branches/1.6.1/
------------------------------------------------------------------------------
Binary property 'trunk-merged' - no diff available.
Modified: branches/1.6.1/UPGRADE.txt
URL: http://svn.asterisk.org/svn-view/asterisk/branches/1.6.1/UPGRADE.txt?view=diff&rev=208484&r1=208483&r2=208484
==============================================================================
--- branches/1.6.1/UPGRADE.txt (original)
+++ branches/1.6.1/UPGRADE.txt Thu Jul 23 17:21:57 2009
@@ -17,6 +17,18 @@
=== UPGRADE-1.6.txt -- Upgrade info for 1.4 to 1.6
===
===========================================================
+
+From 1.6.1.1 to 1.6.1.2:
+
+Beginning with this release, Asterisk's internal methods of
+negotiating T.38 (FAX over IP) sessions changed in
+non-backwards-compatible ways. Any applications that previously used
+AST_CONTROL_T38 control frames will have to be upgraded to use
+AST_CONTROL_T38_PARAMETERS control frames instead; app_fax.c is a good
+example of how to generate and respond to these frames. These changes
+were made to solve significant T.38 interoperability problems between
+Asterisk and various SIP/T.38 endpoints identified by many users of
+Asterisk.
From 1.6.0.1 to 1.6.1:
Modified: branches/1.6.1/apps/app_fax.c
URL: http://svn.asterisk.org/svn-view/asterisk/branches/1.6.1/apps/app_fax.c?view=diff&rev=208484&r1=208483&r2=208484
==============================================================================
--- branches/1.6.1/apps/app_fax.c (original)
+++ branches/1.6.1/apps/app_fax.c Thu Jul 23 17:21:57 2009
@@ -412,11 +412,12 @@
if (fr && fr->frametype == AST_FRAME_DTMF && fr->subclass == 'f') {
struct ast_control_t38_parameters parameters = { .request_response = AST_T38_REQUEST_NEGOTIATE,
.version = 0,
- .max_datagram = 400,
+ .max_ifp = 800,
.rate = AST_T38_RATE_9600,
.rate_management = AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF,
.fill_bit_removal = 1,
.transcoding_mmr = 1,
+ .transcoding_jbig = 1,
};
ast_debug(1, "Fax tone detected. Requesting T38\n");
ast_indicate_data(s->chan, AST_CONTROL_T38_PARAMETERS, ¶meters, sizeof(parameters));
@@ -452,20 +453,18 @@
res = 1;
break;
} else if (parameters->request_response == AST_T38_REQUEST_NEGOTIATE) {
+ struct ast_control_t38_parameters our_parameters = { .request_response = AST_T38_NEGOTIATED,
+ .version = 0,
+ .max_ifp = 800,
+ .rate = AST_T38_RATE_9600,
+ .rate_management = AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF,
+ .fill_bit_removal = 1,
+ .transcoding_mmr = 1,
+ .transcoding_jbig = 1,
+ };
ast_debug(1, "T38 request received, accepting\n");
- if (parameters->version > 0) {
- /* Only T.38 Version 0 is supported at this time */
- parameters->version = 0;
- }
- if (parameters->max_datagram > 400) {
- /* Limit incoming datagram size to our default */
- /* TODO: this need to come from the udptl stack, not be hardcoded */
- parameters->max_datagram = 400;
- }
- /* we only support bit rates up to 9.6kbps */
- parameters->rate = AST_T38_RATE_9600;
/* Complete T38 switchover */
- ast_indicate_data(s->chan, AST_CONTROL_T38_PARAMETERS, parameters, sizeof(*parameters));
+ ast_indicate_data(s->chan, AST_CONTROL_T38_PARAMETERS, &our_parameters, sizeof(our_parameters));
/* Do not break audio loop, wait until channel driver finally acks switchover
with AST_T38_NEGOTIATED */
}
@@ -545,7 +544,7 @@
return -1;
}
- t38_set_max_datagram_size(t38state, s->t38parameters.max_datagram);
+ t38_set_max_datagram_size(t38state, s->t38parameters.max_ifp);
if (s->t38parameters.fill_bit_removal) {
t38_set_fill_bit_removal(t38state, TRUE);
Modified: branches/1.6.1/channels/chan_sip.c
URL: http://svn.asterisk.org/svn-view/asterisk/branches/1.6.1/channels/chan_sip.c?view=diff&rev=208484&r1=208483&r2=208484
==============================================================================
--- branches/1.6.1/channels/chan_sip.c (original)
+++ branches/1.6.1/channels/chan_sip.c Thu Jul 23 17:21:57 2009
@@ -1068,10 +1068,10 @@
#define SIP_PAGE2_SUBSCRIBEMWIONLY (1 << 18) /*!< GP: Only issue MWI notification if subscribed to */
#define SIP_PAGE2_IGNORESDPVERSION (1 << 19) /*!< GDP: Ignore the SDP session version number we receive and treat all sessions as new */
-#define SIP_PAGE2_T38SUPPORT (7 << 20) /*!< GDP: T38 Fax Passthrough Support */
-#define SIP_PAGE2_T38SUPPORT_UDPTL (1 << 20) /*!< GDP: T38 Fax Passthrough Support (no error correction) */
-#define SIP_PAGE2_T38SUPPORT_UDPTL_FEC (2 << 20) /*!< GDP: T38 Fax Passthrough Support (FEC error correction) */
-#define SIP_PAGE2_T38SUPPORT_UDPTL_REDUNDANCY (4 << 20) /*!< GDP: T38 Fax Passthrough Support (redundancy error correction) */
+#define SIP_PAGE2_T38SUPPORT (7 << 20) /*!< GDP: T.38 Fax Support */
+#define SIP_PAGE2_T38SUPPORT_UDPTL (1 << 20) /*!< GDP: T.38 Fax Support (no error correction) */
+#define SIP_PAGE2_T38SUPPORT_UDPTL_FEC (2 << 20) /*!< GDP: T.38 Fax Support (FEC error correction) */
+#define SIP_PAGE2_T38SUPPORT_UDPTL_REDUNDANCY (4 << 20) /*!< GDP: T.38 Fax Support (redundancy error correction) */
#define SIP_PAGE2_CALL_ONHOLD (3 << 23) /*!< D: Call hold states: */
#define SIP_PAGE2_CALL_ONHOLD_ACTIVE (1 << 23) /*!< D: Active hold */
@@ -1091,36 +1091,6 @@
SIP_PAGE2_BUGGY_MWI | SIP_PAGE2_TEXTSUPPORT | \
SIP_PAGE2_UDPTL_DESTINATION | SIP_PAGE2_VIDEOSUPPORT_ALWAYS)
-/*@}*/
-
-/*! \name SIPflagsT38
- T.38 set of flags */
-
-/*@{*/
-#define T38FAX_FILL_BIT_REMOVAL (1 << 0) /*!< Default: 0 (unset)*/
-#define T38FAX_TRANSCODING_MMR (1 << 1) /*!< Default: 0 (unset)*/
-#define T38FAX_TRANSCODING_JBIG (1 << 2) /*!< Default: 0 (unset)*/
-/* Rate management */
-#define T38FAX_RATE_MANAGEMENT_TRANSFERRED_TCF (0 << 3)
-#define T38FAX_RATE_MANAGEMENT_LOCAL_TCF (1 << 3) /*!< Unset for transferredTCF (UDPTL), set for localTCF (TPKT) */
-/* UDP Error correction */
-#define T38FAX_UDP_EC_NONE (0 << 4) /*!< two bits, if unset NO t38UDPEC field in T38 SDP*/
-#define T38FAX_UDP_EC_FEC (1 << 4) /*!< Set for t38UDPFEC */
-#define T38FAX_UDP_EC_REDUNDANCY (2 << 4) /*!< Set for t38UDPRedundancy */
-/* T38 Spec version */
-#define T38FAX_VERSION (3 << 6) /*!< two bits, 2 values so far, up to 4 values max */
-#define T38FAX_VERSION_0 (0 << 6) /*!< Version 0 */
-#define T38FAX_VERSION_1 (1 << 6) /*!< Version 1 */
-/* Maximum Fax Rate */
-#define T38FAX_RATE_2400 (1 << 8) /*!< 2400 bps t38FaxRate */
-#define T38FAX_RATE_4800 (1 << 9) /*!< 4800 bps t38FaxRate */
-#define T38FAX_RATE_7200 (1 << 10) /*!< 7200 bps t38FaxRate */
-#define T38FAX_RATE_9600 (1 << 11) /*!< 9600 bps t38FaxRate */
-#define T38FAX_RATE_12000 (1 << 12) /*!< 12000 bps t38FaxRate */
-#define T38FAX_RATE_14400 (1 << 13) /*!< 14400 bps t38FaxRate */
-
-/*!< This is default: NO MMR and JBIG transcoding, NO fill bit removal, transferredTCF TCF, UDP FEC, Version 0 and 9600 max fax rate */
-static int global_t38_capability = T38FAX_VERSION_0 | T38FAX_RATE_2400 | T38FAX_RATE_4800 | T38FAX_RATE_7200 | T38FAX_RATE_9600;
/*@}*/
/*! \brief debugging state
@@ -1153,11 +1123,9 @@
/*! \brief T.38 channel settings (at some point we need to make this alloc'ed */
struct t38properties {
- struct ast_flags t38support; /*!< Flag for udptl, rtp or tcp support for this session */
- int capability; /*!< Our T38 capability */
- int peercapability; /*!< Peers T38 capability */
- int jointcapability; /*!< Supported T38 capability at both ends */
enum t38state state; /*!< T.38 state */
+ struct ast_control_t38_parameters our_parms;
+ struct ast_control_t38_parameters their_parms;
};
/*! \brief Parameters to know status of transfer */
@@ -3607,7 +3575,7 @@
sip_pvt_lock(p);
/* Now if T38 support is enabled we need to look and see what the current state is to get what we want to report back */
- if (ast_test_flag(&p->t38.t38support, SIP_PAGE2_T38SUPPORT)) {
+ if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT)) {
switch (p->t38.state) {
case T38_LOCAL_REINVITE:
case T38_PEER_REINVITE:
@@ -4339,57 +4307,12 @@
}
}
-/*! \brief Helper function which interprets T.38 capabilities and fills a parameters structure in */
-static void fill_t38_parameters(int capabilities, struct ast_control_t38_parameters *parameters, struct sip_pvt *p)
-{
- if (capabilities & T38FAX_VERSION_0) {
- parameters->version = 0;
- } else if (capabilities & T38FAX_VERSION_1) {
- parameters->version = 1;
- }
-
- if (capabilities & T38FAX_RATE_14400) {
- parameters->rate = AST_T38_RATE_14400;
- } else if (capabilities & T38FAX_RATE_12000) {
- parameters->rate = AST_T38_RATE_12000;
- } else if (capabilities & T38FAX_RATE_9600) {
- parameters->rate = AST_T38_RATE_9600;
- } else if (capabilities & T38FAX_RATE_7200) {
- parameters->rate = AST_T38_RATE_7200;
- } else if (capabilities & T38FAX_RATE_4800) {
- parameters->rate = AST_T38_RATE_4800;
- } else if (capabilities & T38FAX_RATE_2400) {
- parameters->rate = AST_T38_RATE_2400;
- }
-
- if (capabilities & T38FAX_RATE_MANAGEMENT_TRANSFERRED_TCF) {
- parameters->rate_management = AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF;
- } else if (capabilities & T38FAX_RATE_MANAGEMENT_LOCAL_TCF) {
- parameters->rate_management = AST_T38_RATE_MANAGEMENT_LOCAL_TCF;
- }
-
- if (capabilities & T38FAX_FILL_BIT_REMOVAL) {
- parameters->fill_bit_removal = 1;
- }
-
- if (capabilities & T38FAX_TRANSCODING_MMR) {
- parameters->transcoding_mmr = 1;
- }
-
- if (capabilities & T38FAX_TRANSCODING_JBIG) {
- parameters->transcoding_jbig = 1;
- }
-
- parameters->max_datagram = ast_udptl_get_far_max_datagram(p->udptl);
-}
-
/*! \brief Change the T38 state on a SIP dialog */
static void change_t38_state(struct sip_pvt *p, int state)
{
int old = p->t38.state;
struct ast_channel *chan = p->owner;
- enum ast_control_t38 message = 0;
- struct ast_control_t38_parameters parameters = { 0, };
+ struct ast_control_t38_parameters parameters = { .request_response = 0 };
/* Don't bother changing if we are already in the state wanted */
if (old == state)
@@ -4404,39 +4327,34 @@
/* Given the state requested and old state determine what control frame we want to queue up */
if (state == T38_PEER_REINVITE) {
- message = parameters.request_response = AST_T38_REQUEST_NEGOTIATE;
- fill_t38_parameters(p->t38.peercapability, ¶meters, p);
+ parameters = p->t38.their_parms;
+ parameters.max_ifp = ast_udptl_get_far_max_ifp(p->udptl);
+ parameters.request_response = AST_T38_REQUEST_NEGOTIATE;
} else if (state == T38_ENABLED) {
- message = parameters.request_response = AST_T38_NEGOTIATED;
- fill_t38_parameters(p->t38.jointcapability, ¶meters, p);
+ parameters = p->t38.their_parms;
+ parameters.max_ifp = ast_udptl_get_far_max_ifp(p->udptl);
+ parameters.request_response = AST_T38_NEGOTIATED;
} else if (state == T38_DISABLED && old == T38_ENABLED)
- message = parameters.request_response = AST_T38_TERMINATED;
+ parameters.request_response = AST_T38_TERMINATED;
else if (state == T38_DISABLED && old == T38_LOCAL_REINVITE)
- message = parameters.request_response = AST_T38_REFUSED;
+ parameters.request_response = AST_T38_REFUSED;
/* Woot we got a message, create a control frame and send it on! */
if (parameters.request_response)
ast_queue_control_data(chan, AST_CONTROL_T38_PARAMETERS, ¶meters, sizeof(parameters));
- if (message)
- ast_queue_control_data(chan, AST_CONTROL_T38, &message, sizeof(message));
}
/*! \brief Set the global T38 capabilities on a SIP dialog structure */
static void set_t38_capabilities(struct sip_pvt *p)
{
- p->t38.capability = global_t38_capability;
if (p->udptl) {
if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) == SIP_PAGE2_T38SUPPORT_UDPTL_REDUNDANCY) {
ast_udptl_set_error_correction_scheme(p->udptl, UDPTL_ERROR_CORRECTION_REDUNDANCY);
- p->t38.capability |= T38FAX_UDP_EC_REDUNDANCY;
} else if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) == SIP_PAGE2_T38SUPPORT_UDPTL_FEC) {
ast_udptl_set_error_correction_scheme(p->udptl, UDPTL_ERROR_CORRECTION_FEC);
- p->t38.capability |= T38FAX_UDP_EC_FEC;
} else if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) == SIP_PAGE2_T38SUPPORT_UDPTL) {
ast_udptl_set_error_correction_scheme(p->udptl, UDPTL_ERROR_CORRECTION_NONE);
- p->t38.capability |= T38FAX_UDP_EC_NONE;
- }
- p->t38.capability |= T38FAX_RATE_MANAGEMENT_TRANSFERRED_TCF;
+ }
}
}
@@ -4497,9 +4415,7 @@
/* t38pt_udptl was enabled in the peer and not in [general] */
dialog->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, bindaddr.sin_addr);
}
- ast_copy_flags(&dialog->t38.t38support, &peer->flags[1], SIP_PAGE2_T38SUPPORT);
set_t38_capabilities(dialog);
- dialog->t38.jointcapability = dialog->t38.capability;
} else if (dialog->udptl) {
ast_udptl_destroy(dialog->udptl);
dialog->udptl = NULL;
@@ -4788,9 +4704,6 @@
res = -1;
} else {
int xmitres;
-
- p->t38.jointcapability = p->t38.capability;
- ast_debug(2, "Our T38 capability (%d), joint T38 capability (%d)\n", p->t38.capability, p->t38.jointcapability);
xmitres = transmit_invite(p, SIP_INVITE, 1, 2);
if (xmitres == XMIT_ERROR)
@@ -5629,15 +5542,10 @@
we simply forget the frames if we get modem frames before the bridge is up.
Fax will re-transmit.
*/
- if (ast->_state == AST_STATE_UP) {
- if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) && p->t38.state == T38_DISABLED) {
- if (!p->pendinginvite) {
- change_t38_state(p, T38_LOCAL_REINVITE);
- transmit_reinvite_with_sdp(p, TRUE, FALSE);
- }
- } else if (p->udptl && p->t38.state == T38_ENABLED) {
- res = ast_udptl_write(p->udptl, frame);
- }
+ if ((ast->_state == AST_STATE_UP) &&
+ p->udptl &&
+ (p->t38.state == T38_ENABLED)) {
+ res = ast_udptl_write(p->udptl, frame);
}
sip_pvt_unlock(p);
}
@@ -5759,66 +5667,34 @@
}
/*! \brief Helper function which updates T.38 capability information and triggers a reinvite */
-static void interpret_t38_parameters(struct sip_pvt *p, enum ast_control_t38 request_response, const struct ast_control_t38_parameters *parameters)
-{
- if (parameters) {
- if (!parameters->version) {
- p->t38.capability = p->t38.jointcapability |= T38FAX_VERSION_0;
- } else if (parameters->version == 1) {
- p->t38.capability = p->t38.jointcapability |= T38FAX_VERSION_1;
- }
-
- if (parameters->rate == AST_T38_RATE_14400) {
- p->t38.capability = p->t38.jointcapability |= T38FAX_RATE_14400 | T38FAX_RATE_12000 | T38FAX_RATE_9600 | T38FAX_RATE_7200 | T38FAX_RATE_4800 | T38FAX_RATE_2400;
- } else if (parameters->rate == AST_T38_RATE_12000) {
- p->t38.capability = p->t38.jointcapability |= T38FAX_RATE_12000 | T38FAX_RATE_9600 | T38FAX_RATE_7200 | T38FAX_RATE_4800 | T38FAX_RATE_2400;
- } else if (parameters->rate == AST_T38_RATE_9600) {
- p->t38.capability = p->t38.jointcapability |= T38FAX_RATE_9600 | T38FAX_RATE_7200 | T38FAX_RATE_4800 | T38FAX_RATE_2400;
- } else if (parameters->rate == AST_T38_RATE_7200) {
- p->t38.capability = p->t38.jointcapability |= T38FAX_RATE_7200 | T38FAX_RATE_4800 | T38FAX_RATE_2400;
- } else if (parameters->rate == AST_T38_RATE_4800) {
- p->t38.capability = p->t38.jointcapability |= T38FAX_RATE_4800 | T38FAX_RATE_2400;
- } else if (parameters->rate == AST_T38_RATE_2400) {
- p->t38.capability = p->t38.jointcapability |= T38FAX_RATE_2400;
- }
-
- if (parameters->rate_management == AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF) {
- p->t38.capability = p->t38.jointcapability |= T38FAX_RATE_MANAGEMENT_TRANSFERRED_TCF;
- } else if (parameters->rate_management == AST_T38_RATE_MANAGEMENT_LOCAL_TCF) {
- p->t38.capability = p->t38.jointcapability |= T38FAX_RATE_MANAGEMENT_LOCAL_TCF;
- }
-
- if (parameters->fill_bit_removal) {
- p->t38.capability = p->t38.jointcapability |= T38FAX_FILL_BIT_REMOVAL;
- } else {
- p->t38.capability = p->t38.jointcapability &= ~T38FAX_FILL_BIT_REMOVAL;
- }
-
- if (parameters->transcoding_mmr) {
- p->t38.capability = p->t38.jointcapability |= T38FAX_TRANSCODING_MMR;
- } else {
- p->t38.capability = p->t38.jointcapability &= ~T38FAX_TRANSCODING_MMR;
- }
-
- if (parameters->transcoding_jbig) {
- p->t38.capability = p->t38.jointcapability |= T38FAX_TRANSCODING_JBIG;
- } else {
- p->t38.capability = p->t38.jointcapability &= ~T38FAX_TRANSCODING_JBIG;
- }
-
- if (p->udptl && request_response == AST_T38_REQUEST_NEGOTIATE) {
- ast_udptl_set_local_max_datagram(p->udptl, parameters->max_datagram ? parameters->max_datagram : 400);
- }
- }
-
- switch (request_response) {
+static void interpret_t38_parameters(struct sip_pvt *p, const struct ast_control_t38_parameters *parameters)
+{
+ switch (parameters->request_response) {
case AST_T38_NEGOTIATED:
case AST_T38_REQUEST_NEGOTIATE: /* Request T38 */
if (p->t38.state == T38_PEER_REINVITE) {
AST_SCHED_DEL_UNREF(sched, p->t38id, dialog_unref(p, "when you delete the t38id sched, you should dec the refcount for the stored dialog ptr"));
+ p->t38.our_parms = *parameters;
+ /* modify our parameters to conform to the peer's parameters,
+ * based on the rules in the ITU T.38 recommendation
+ */
+ if (!p->t38.their_parms.fill_bit_removal) {
+ p->t38.our_parms.fill_bit_removal = FALSE;
+ }
+ if (!p->t38.their_parms.transcoding_mmr) {
+ p->t38.our_parms.transcoding_mmr = FALSE;
+ }
+ if (!p->t38.their_parms.transcoding_jbig) {
+ p->t38.our_parms.transcoding_jbig = FALSE;
+ }
+ p->t38.our_parms.version = MIN(p->t38.our_parms.version, p->t38.their_parms.version);
+ p->t38.our_parms.rate_management = p->t38.their_parms.rate_management;
+ ast_udptl_set_local_max_ifp(p->udptl, p->t38.our_parms.max_ifp);
change_t38_state(p, T38_ENABLED);
transmit_response_with_t38_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL);
- } else if (ast_test_flag(&p->t38.t38support, SIP_PAGE2_T38SUPPORT) && p->t38.state != T38_ENABLED) {
+ } else if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) && p->t38.state != T38_ENABLED) {
+ p->t38.our_parms = *parameters;
+ ast_udptl_set_local_max_ifp(p->udptl, p->t38.our_parms.max_ifp);
change_t38_state(p, T38_LOCAL_REINVITE);
if (!p->pendinginvite) {
transmit_reinvite_with_sdp(p, TRUE, FALSE);
@@ -5926,19 +5802,12 @@
} else
res = -1;
break;
- case AST_CONTROL_T38: /* T38 control frame */
- if (datalen != sizeof(enum ast_control_t38)) {
- ast_log(LOG_ERROR, "Invalid datalen for AST_CONTROL_T38. Expected %d, got %d\n", (int)sizeof(enum ast_control_t38), (int)datalen);
- } else {
- interpret_t38_parameters(p, *((enum ast_control_t38 *) data), NULL);
- }
- break;
case AST_CONTROL_T38_PARAMETERS:
if (datalen != sizeof(struct ast_control_t38_parameters)) {
- ast_log(LOG_ERROR, "Invalid datalen for AST_CONTROL_T38_PARAMETERS. Expected %d, got %d\n", (int)sizeof(struct ast_control_t38_parameters), (int)datalen);
+ ast_log(LOG_ERROR, "Invalid datalen for AST_CONTROL_T38_PARAMETERS. Expected %d, got %d\n", (int) sizeof(struct ast_control_t38_parameters), (int) datalen);
} else {
const struct ast_control_t38_parameters *parameters = data;
- interpret_t38_parameters(p, parameters->request_response, parameters);
+ interpret_t38_parameters(p, parameters);
}
break;
case AST_CONTROL_SRCUPDATE:
@@ -6348,7 +6217,7 @@
if (f && (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) && p->vad) {
f = ast_dsp_process(p->owner, p->vad, f);
if (f && f->frametype == AST_FRAME_DTMF) {
- if (ast_test_flag(&p->t38.t38support, SIP_PAGE2_T38SUPPORT) && f->subclass == 'f') {
+ if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) && f->subclass == 'f') {
ast_debug(1, "Fax CNG detected on %s\n", ast->name);
*faxdetect = 1;
} else {
@@ -6373,7 +6242,7 @@
/* If we are NOT bridged to another channel, and we have detected fax tone we issue T38 re-invite to a peer */
/* If we are bridged then it is the responsibility of the SIP device to issue T38 re-invite if it detects CNG or fax preamble */
- if (faxdetected && ast_test_flag(&p->t38.t38support, SIP_PAGE2_T38SUPPORT) && (p->t38.state == T38_DISABLED) && !(ast_bridged_channel(ast))) {
+ if (faxdetected && ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) && (p->t38.state == T38_DISABLED) && !(ast_bridged_channel(ast))) {
if (!ast_test_flag(&p->flags[0], SIP_GOTREFER)) {
if (!p->pendinginvite) {
ast_debug(3, "Sending reinvite on SIP (%s) for T.38 negotiation.\n", ast->name);
@@ -6586,9 +6455,7 @@
(ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO))
p->noncodeccapability |= AST_RTP_DTMF;
if (p->udptl) {
- ast_copy_flags(&p->t38.t38support, &p->flags[1], SIP_PAGE2_T38SUPPORT);
set_t38_capabilities(p);
- p->t38.jointcapability = p->t38.capability;
}
ast_string_field_set(p, context, default_context);
ast_string_field_set(p, parkinglot, default_parkinglot);
@@ -7190,7 +7057,6 @@
int vportno = -1; /*!< RTP Video port number */
int tportno = -1; /*!< RTP Text port number */
int udptlportno = -1;
- int peert38capability = 0;
char s[256];
int old = 0;
@@ -7703,6 +7569,7 @@
int found = 0, x;
old = 0;
+ memset(&p->t38.their_parms, 0, sizeof(p->t38.their_parms));
/* Scan trough the a= lines for T38 attributes and set apropriate fileds */
iterator = req->sdp_start;
@@ -7715,110 +7582,92 @@
ast_debug(3, "T38MaxBitRate: %d\n", x);
switch (x) {
case 14400:
- peert38capability |= T38FAX_RATE_14400 | T38FAX_RATE_12000 | T38FAX_RATE_9600 | T38FAX_RATE_7200 | T38FAX_RATE_4800 | T38FAX_RATE_2400;
+ p->t38.their_parms.rate = AST_T38_RATE_14400;
break;
case 12000:
- peert38capability |= T38FAX_RATE_12000 | T38FAX_RATE_9600 | T38FAX_RATE_7200 | T38FAX_RATE_4800 | T38FAX_RATE_2400;
+ p->t38.their_parms.rate = AST_T38_RATE_12000;
break;
case 9600:
- peert38capability |= T38FAX_RATE_9600 | T38FAX_RATE_7200 | T38FAX_RATE_4800 | T38FAX_RATE_2400;
+ p->t38.their_parms.rate = AST_T38_RATE_9600;
break;
case 7200:
- peert38capability |= T38FAX_RATE_7200 | T38FAX_RATE_4800 | T38FAX_RATE_2400;
+ p->t38.their_parms.rate = AST_T38_RATE_7200;
break;
case 4800:
- peert38capability |= T38FAX_RATE_4800 | T38FAX_RATE_2400;
+ p->t38.their_parms.rate = AST_T38_RATE_4800;
break;
case 2400:
- peert38capability |= T38FAX_RATE_2400;
+ p->t38.their_parms.rate = AST_T38_RATE_2400;
break;
}
} else if ((sscanf(a, "T38FaxVersion:%d", &x) == 1)) {
found = 1;
ast_debug(3, "FaxVersion: %d\n", x);
- if (x == 0)
- peert38capability |= T38FAX_VERSION_0;
- else if (x == 1)
- peert38capability |= T38FAX_VERSION_1;
+ p->t38.their_parms.version = x;
} else if ((sscanf(a, "T38FaxMaxDatagram:%d", &x) == 1) || (sscanf(a, "T38MaxDatagram:%d", &x) == 1)) {
found = 1;
ast_debug(3, "FaxMaxDatagram: %d\n", x);
ast_udptl_set_far_max_datagram(p->udptl, x);
- if (!ast_udptl_get_local_max_datagram(p->udptl)) {
- ast_udptl_set_local_max_datagram(p->udptl, x);
- }
} else if ((strncmp(a, "T38FaxFillBitRemoval", 20) == 0)) {
found = 1;
- if(sscanf(a, "T38FaxFillBitRemoval:%d", &x) == 1) {
- ast_debug(3, "FillBitRemoval: %d\n", x);
- if(x == 1)
- peert38capability |= T38FAX_FILL_BIT_REMOVAL;
+ if (sscanf(a, "T38FaxFillBitRemoval:%d", &x) == 1) {
+ ast_debug(3, "FillBitRemoval: %d\n", x);
+ if (x == 1) {
+ p->t38.their_parms.fill_bit_removal = TRUE;
+ }
} else {
- ast_debug(3, "FillBitRemoval\n");
- peert38capability |= T38FAX_FILL_BIT_REMOVAL;
+ ast_debug(3, "FillBitRemoval\n");
+ p->t38.their_parms.fill_bit_removal = TRUE;
}
} else if ((strncmp(a, "T38FaxTranscodingMMR", 20) == 0)) {
found = 1;
- if(sscanf(a, "T38FaxTranscodingMMR:%d", &x) == 1) {
- ast_debug(3, "Transcoding MMR: %d\n", x);
- if(x == 1)
- peert38capability |= T38FAX_TRANSCODING_MMR;
+ if (sscanf(a, "T38FaxTranscodingMMR:%d", &x) == 1) {
+ ast_debug(3, "Transcoding MMR: %d\n", x);
+ if (x == 1) {
+ p->t38.their_parms.transcoding_mmr = TRUE;
+ }
} else {
- ast_debug(3, "Transcoding MMR\n");
- peert38capability |= T38FAX_TRANSCODING_MMR;
+ ast_debug(3, "Transcoding MMR\n");
+ p->t38.their_parms.transcoding_mmr = TRUE;
}
} else if ((strncmp(a, "T38FaxTranscodingJBIG", 21) == 0)) {
found = 1;
- if(sscanf(a, "T38FaxTranscodingJBIG:%d", &x) == 1) {
- ast_debug(3, "Transcoding JBIG: %d\n", x);
- if(x == 1)
- peert38capability |= T38FAX_TRANSCODING_JBIG;
+ if (sscanf(a, "T38FaxTranscodingJBIG:%d", &x) == 1) {
+ ast_debug(3, "Transcoding JBIG: %d\n", x);
+ if (x == 1) {
+ p->t38.their_parms.transcoding_jbig = TRUE;
+ }
} else {
- ast_debug(3, "Transcoding JBIG\n");
- peert38capability |= T38FAX_TRANSCODING_JBIG;
+ ast_debug(3, "Transcoding JBIG\n");
+ p->t38.their_parms.transcoding_jbig = TRUE;
}
} else if ((sscanf(a, "T38FaxRateManagement:%255s", s) == 1)) {
found = 1;
ast_debug(3, "RateManagement: %s\n", s);
if (!strcasecmp(s, "localTCF"))
- peert38capability |= T38FAX_RATE_MANAGEMENT_LOCAL_TCF;
+ p->t38.their_parms.rate_management = AST_T38_RATE_MANAGEMENT_LOCAL_TCF;
else if (!strcasecmp(s, "transferredTCF"))
- peert38capability |= T38FAX_RATE_MANAGEMENT_TRANSFERRED_TCF;
+ p->t38.their_parms.rate_management = AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF;
} else if ((sscanf(a, "T38FaxUdpEC:%255s", s) == 1)) {
found = 1;
ast_debug(3, "UDP EC: %s\n", s);
if (!strcasecmp(s, "t38UDPRedundancy")) {
- peert38capability |= T38FAX_UDP_EC_REDUNDANCY;
ast_udptl_set_error_correction_scheme(p->udptl, UDPTL_ERROR_CORRECTION_REDUNDANCY);
} else if (!strcasecmp(s, "t38UDPFEC")) {
- peert38capability |= T38FAX_UDP_EC_FEC;
ast_udptl_set_error_correction_scheme(p->udptl, UDPTL_ERROR_CORRECTION_FEC);
} else {
- peert38capability |= T38FAX_UDP_EC_NONE;
ast_udptl_set_error_correction_scheme(p->udptl, UDPTL_ERROR_CORRECTION_NONE);
}
}
}
- if (found) { /* Some cisco equipment returns nothing beside c= and m= lines in 200 OK T38 SDP */
- p->t38.peercapability = peert38capability;
- p->t38.jointcapability = (peert38capability & 255); /* Put everything beside supported speeds settings */
- peert38capability &= (T38FAX_RATE_14400 | T38FAX_RATE_12000 | T38FAX_RATE_9600 | T38FAX_RATE_7200 | T38FAX_RATE_4800 | T38FAX_RATE_2400);
- p->t38.jointcapability |= (peert38capability & p->t38.capability); /* Put the lower of our's and peer's speed */
- }
- if (debug)
- ast_debug(1, "Our T38 capability = (%d), peer T38 capability (%d), joint T38 capability (%d)\n",
- p->t38.capability,
- p->t38.peercapability,
- p->t38.jointcapability);
/* Remote party offers T38, we need to update state */
- if (t38action == SDP_T38_ACCEPT) {
- if (p->t38.state == T38_LOCAL_REINVITE)
- change_t38_state(p, T38_ENABLED);
- } else if (t38action == SDP_T38_INITIATE) {
- if (p->owner && p->lastinvite) {
- change_t38_state(p, T38_PEER_REINVITE); /* T38 Offered in re-invite from remote party */
- }
+ if ((t38action == SDP_T38_ACCEPT) &&
+ (p->t38.state == T38_LOCAL_REINVITE)) {
+ change_t38_state(p, T38_ENABLED);
+ } else if ((t38action == SDP_T38_INITIATE) &&
+ p->owner && p->lastinvite) {
+ change_t38_state(p, T38_PEER_REINVITE); /* T38 Offered in re-invite from remote party */
}
} else {
change_t38_state(p, T38_DISABLED);
@@ -7852,7 +7701,7 @@
}
if (!newjointcapability) {
/* If T.38 was not negotiated either, totally bail out... */
- if (!p->t38.jointcapability || !udptlportno) {
+ if ((p->t38.state == T38_DISABLED) || !udptlportno) {
ast_log(LOG_NOTICE, "No compatible codecs, not accepting this offer!\n");
/* Do NOT Change current setting */
return -1;
@@ -8872,30 +8721,22 @@
/*! \brief Get Max T.38 Transmission rate from T38 capabilities */
-static int t38_get_rate(int t38cap)
-{
- int maxrate = (t38cap & (T38FAX_RATE_14400 | T38FAX_RATE_12000 | T38FAX_RATE_9600 | T38FAX_RATE_7200 | T38FAX_RATE_4800 | T38FAX_RATE_2400));
-
- if (maxrate & T38FAX_RATE_14400) {
- ast_debug(2, "T38MaxBitRate 14400 found\n");
+static unsigned int t38_get_rate(enum ast_control_t38_rate rate)
+{
+ switch (rate) {
+ case AST_T38_RATE_2400:
+ return 2400;
+ case AST_T38_RATE_4800:
+ return 4800;
+ case AST_T38_RATE_7200:
+ return 7200;
+ case AST_T38_RATE_9600:
+ return 9600;
+ case AST_T38_RATE_12000:
+ return 12000;
+ case AST_T38_RATE_14400:
return 14400;
- } else if (maxrate & T38FAX_RATE_12000) {
- ast_debug(2, "T38MaxBitRate 12000 found\n");
- return 12000;
- } else if (maxrate & T38FAX_RATE_9600) {
- ast_debug(2, "T38MaxBitRate 9600 found\n");
- return 9600;
- } else if (maxrate & T38FAX_RATE_7200) {
- ast_debug(2, "T38MaxBitRate 7200 found\n");
- return 7200;
- } else if (maxrate & T38FAX_RATE_4800) {
- ast_debug(2, "T38MaxBitRate 4800 found\n");
- return 4800;
- } else if (maxrate & T38FAX_RATE_2400) {
- ast_debug(2, "T38MaxBitRate 2400 found\n");
- return 2400;
- } else {
- ast_debug(2, "Strange, T38MaxBitRate NOT found in peers T38 SDP.\n");
+ default:
return 0;
}
}
@@ -9220,35 +9061,38 @@
/* We break with the "recommendation" and send our IP, in order that our
peer doesn't have to ast_gethostbyname() us */
- if (debug) {
- ast_debug(1, "Our T38 capability (%d), peer T38 capability (%d), joint capability (%d)\n",
- p->t38.capability,
- p->t38.peercapability,
- p->t38.jointcapability);
- }
-
ast_str_append(&m_modem, 0, "m=image %d udptl t38\r\n", ntohs(udptldest.sin_port));
- if ((p->t38.jointcapability & T38FAX_VERSION) == T38FAX_VERSION_0)
- ast_str_append(&a_modem, 0, "a=T38FaxVersion:0\r\n");
- if ((p->t38.jointcapability & T38FAX_VERSION) == T38FAX_VERSION_1)
- ast_str_append(&a_modem, 0, "a=T38FaxVersion:1\r\n");
- if ((x = t38_get_rate(p->t38.jointcapability)))
- ast_str_append(&a_modem, 0, "a=T38MaxBitRate:%d\r\n", x);
- if ((p->t38.jointcapability & T38FAX_FILL_BIT_REMOVAL) == T38FAX_FILL_BIT_REMOVAL)
+ ast_str_append(&a_modem, 0, "a=T38Faxversion:%d\r\n", p->t38.our_parms.version);
+ ast_str_append(&a_modem, 0, "a=T38MaxBitRate:%d\r\n", t38_get_rate(p->t38.our_parms.rate));
+ if (p->t38.our_parms.fill_bit_removal) {
ast_str_append(&a_modem, 0, "a=T38FaxFillBitRemoval\r\n");
- if ((p->t38.jointcapability & T38FAX_TRANSCODING_MMR) == T38FAX_TRANSCODING_MMR)
+ }
+ if (p->t38.our_parms.transcoding_mmr) {
ast_str_append(&a_modem, 0, "a=T38FaxTranscodingMMR\r\n");
- if ((p->t38.jointcapability & T38FAX_TRANSCODING_JBIG) == T38FAX_TRANSCODING_JBIG)
+ }
+ if (p->t38.our_parms.transcoding_jbig) {
ast_str_append(&a_modem, 0, "a=T38FaxTranscodingJBIG\r\n");
- ast_str_append(&a_modem, 0, "a=T38FaxRateManagement:%s\r\n", (p->t38.jointcapability & T38FAX_RATE_MANAGEMENT_LOCAL_TCF) ? "localTCF" : "transferredTCF");
- x = ast_udptl_get_local_max_datagram(p->udptl);
- ast_str_append(&a_modem, 0, "a=T38FaxMaxBuffer:%d\r\n", x);
- ast_str_append(&a_modem, 0, "a=T38FaxMaxDatagram:%d\r\n", x);
- if (p->t38.jointcapability & T38FAX_UDP_EC_REDUNDANCY)
+ }
+ switch (p->t38.our_parms.rate_management) {
+ case AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF:
+ ast_str_append(&a_modem, 0, "a=T38FaxRateManagement:transferredTCF\r\n");
+ break;
+ case AST_T38_RATE_MANAGEMENT_LOCAL_TCF:
+ ast_str_append(&a_modem, 0, "a=T38FaxRateManagement:localTCF\r\n");
+ break;
+ }
+ ast_str_append(&a_modem, 0, "a=T38FaxMaxDatagram:%d\r\n", ast_udptl_get_local_max_datagram(p->udptl));
+ switch (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT)) {
+ case SIP_PAGE2_T38SUPPORT_UDPTL:
+ break;
+ case SIP_PAGE2_T38SUPPORT_UDPTL_FEC:
+ ast_str_append(&a_modem, 0, "a=T38FaxUdpEC:t38UDPFEC\r\n");
+ break;
+ case SIP_PAGE2_T38SUPPORT_UDPTL_REDUNDANCY:
ast_str_append(&a_modem, 0, "a=T38FaxUdpEC:t38UDPRedundancy\r\n");
- else if (p->t38.jointcapability & T38FAX_UDP_EC_FEC)
- ast_str_append(&a_modem, 0, "a=T38FaxUdpEC:t38UDPFEC\r\n");
+ break;
+ }
}
if (m_audio->len - m_audio->used < 2 || m_video->len - m_video->used < 2 ||
@@ -9334,7 +9178,6 @@
}
respprep(&resp, p, msg, req);
if (p->udptl) {
- ast_udptl_offered_from_local(p->udptl, 0);
add_sdp(&resp, p, 0, 0, 1);
} else
ast_log(LOG_ERROR, "Can't add SDP to response, since we have no UDPTL session allocated. Call-ID %s\n", p->callid);
@@ -9879,7 +9722,6 @@
if (sdp) {
memset(p->offered_media, 0, sizeof(p->offered_media));
if (p->udptl && p->t38.state == T38_LOCAL_REINVITE) {
- ast_udptl_offered_from_local(p->udptl, 1);
ast_debug(1, "T38 is in state %d on channel %s\n", p->t38.state, p->owner ? p->owner->name : "<none>");
add_sdp(&req, p, FALSE, FALSE, TRUE);
} else if (p->rtp)
@@ -12742,7 +12584,6 @@
if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) && p->udptl) {
set_t38_capabilities(p);
- p->t38.jointcapability = p->t38.capability;
}
/* Copy SIP extensions profile to peer */
@@ -12843,8 +12684,6 @@
else
p->noncodeccapability &= ~AST_RTP_DTMF;
p->jointnoncodeccapability = p->noncodeccapability;
- if (p->t38.peercapability)
- p->t38.jointcapability &= p->t38.peercapability;
}
unref_peer(peer, "check_peer_ok: unref_peer: tossing temp ptr to peer from find_peer");
return res;
@@ -18620,9 +18459,6 @@
/* If T38 is needed but not present, then make it magically appear */
if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) && !p->udptl && (p->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, bindaddr.sin_addr))) {
set_t38_capabilities(p);
- p->t38.jointcapability = p->t38.capability;
- set_t38_capabilities(p);
- p->t38.jointcapability = p->t38.capability;
}
/* We have a succesful authentication, process the SDP portion if there is one */
Modified: branches/1.6.1/include/asterisk/frame.h
URL: http://svn.asterisk.org/svn-view/asterisk/branches/1.6.1/include/asterisk/frame.h?view=diff&rev=208484&r1=208483&r2=208484
==============================================================================
--- branches/1.6.1/include/asterisk/frame.h (original)
+++ branches/1.6.1/include/asterisk/frame.h Thu Jul 23 17:21:57 2009
@@ -315,7 +315,7 @@
AST_CONTROL_HOLD = 16, /*!< Indicate call is placed on hold */
AST_CONTROL_UNHOLD = 17, /*!< Indicate call is left from hold */
AST_CONTROL_VIDUPDATE = 18, /*!< Indicate video frame update */
- AST_CONTROL_T38 = 19, /*!< T38 state change request/notification */
+ _XXX_AST_CONTROL_T38 = 19, /*!< T38 state change request/notification \deprecated This is no longer supported. Use AST_CONTROL_T38_PARAMETERS instead. */
AST_CONTROL_SRCUPDATE = 20, /*!< Indicate source of media has changed */
AST_CONTROL_T38_PARAMETERS = 24, /*!< T38 state change request/notification with parameters */
};
@@ -343,14 +343,14 @@
};
struct ast_control_t38_parameters {
- enum ast_control_t38 request_response; /*!< Request or response of the T38 control frame */
- unsigned int version; /*!< Supported T.38 version */
- unsigned int max_datagram; /*!< Maximum datagram size supported */
- enum ast_control_t38_rate rate; /*!< Maximum fax rate supported */
- enum ast_control_t38_rate_management rate_management; /*!< Rate management setting */
- unsigned int fill_bit_removal:1; /*!< Set if fill bit removal should be used */
- unsigned int transcoding_mmr:1; /*!< Set if MMR transcoding should be used */
- unsigned int transcoding_jbig:1; /*!< Set if JBIG transcoding should be used */
+ enum ast_control_t38 request_response; /*!< Request or response of the T38 control frame */
+ unsigned int version; /*!< Supported T.38 version */
+ unsigned int max_ifp; /*!< Maximum IFP size supported */
+ enum ast_control_t38_rate rate; /*!< Maximum fax rate supported */
+ enum ast_control_t38_rate_management rate_management; /*!< Rate management setting */
+ unsigned int fill_bit_removal:1; /*!< Set if fill bit removal can be used */
+ unsigned int transcoding_mmr:1; /*!< Set if MMR transcoding can be used */
+ unsigned int transcoding_jbig:1; /*!< Set if JBIG transcoding can be used */
};
#define AST_SMOOTHER_FLAG_G729 (1 << 0)
Modified: branches/1.6.1/include/asterisk/udptl.h
[... 698 lines stripped ...]
More information about the asterisk-commits
mailing list