aboutsummaryrefslogtreecommitdiffstats
path: root/channels
diff options
context:
space:
mode:
authorkpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b>2009-10-05 19:49:05 +0000
committerkpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b>2009-10-05 19:49:05 +0000
commita95870bdebdce6b672ff5bce92d9d3914c7858b0 (patch)
tree5b55f43932a191fbfbee19ecb64f17f5638b56a4 /channels
parent241599784788ad7228ef7ad459242d67eabcb22f (diff)
Recorded merge of revisions 222110 via svnmerge from
https://origsvn.digium.com/svn/asterisk/trunk ........ r222110 | kpfleming | 2009-10-05 14:45:00 -0500 (Mon, 05 Oct 2009) | 25 lines Allow non-compliant T.38 endpoints to be supportable via configuration option. Many T.38 endpoints incorrectly send the maximum IFP frame size they can accept as the T38FaxMaxDatagram value in their SDP, when in fact this value is supposed to be the maximum UDPTL payload size (datagram size) they can accept. If the value they supply is small enough (a commonly supplied value is '72'), T.38 UDPTL transmissions will likely fail completely because the UDPTL packets will not have enough room for a primary IFP frame and the redundancy used for error correction. If this occurs, the Asterisk UDPTL stack will emit log messages warning that data loss may occur, and that the value may need to be overridden. This patch extends the 't38pt_udptl' configuration option in sip.conf to allow the administrator to override the value supplied by the remote endpoint and supply a value that allows T.38 FAX transmissions to be successful with that endpoint. In addition, in any SIP call where the override takes effect, a debug message will be printed to that effect. This patch also removes the T38FaxMaxDatagram configuration option from udptl.conf.sample, since it has not actually had any effect for a number of releases. In addition, this patch cleans up the T.38 documentation in sip.conf.sample (which incorrectly documented that T.38 support was passthrough only). (issue #15586) Reported by: globalnetinc ........ git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.6.0@222111 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels')
-rw-r--r--channels/chan_sip.c121
1 files changed, 96 insertions, 25 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 9122d4425..5a42d9d11 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -756,6 +756,8 @@ static int regobjs = 0; /*!< Registry objects */
/* }@ */
static struct ast_flags global_flags[2] = {{0}}; /*!< global SIP_ flags */
+static int global_t38_maxdatagram; /*!< global T.38 FaxMaxDatagram override */
+
static char used_context[AST_MAX_CONTEXT]; /*!< name of automatically created context for unloading */
@@ -988,10 +990,10 @@ struct sip_auth {
#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: T.38 Fax Support */
+#define SIP_PAGE2_T38SUPPORT (3 << 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_T38SUPPORT_UDPTL_REDUNDANCY (3 << 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 */
@@ -1220,7 +1222,8 @@ struct sip_pvt {
int noncodeccapability; /*!< DTMF RFC2833 telephony-event */
int jointnoncodeccapability; /*!< Joint Non codec capability */
int redircodecs; /*!< Redirect codecs */
- int maxcallbitrate; /*!< Maximum Call Bitrate for Video Calls */
+ int maxcallbitrate; /*!< Maximum Call Bitrate for Video Calls */
+ int t38_maxdatagram; /*!< T.38 FaxMaxDatagram override */
struct sip_proxy *outboundproxy; /*!< Outbound proxy for this dialog */
struct t38properties t38; /*!< T38 settings */
struct sockaddr_in udptlredirip; /*!< Where our T.38 UDPTL should be going if not to us */
@@ -1419,6 +1422,7 @@ struct sip_user {
int capability; /*!< Codec capability */
int inUse; /*!< Number of calls in use */
int call_limit; /*!< Limit of concurrent calls */
+ int t38_maxdatagram; /*!< T.38 FaxMaxDatagram override */
enum transfermodes allowtransfer; /*! SIP Refer restriction scheme */
struct ast_ha *ha; /*!< ACL setting */
struct ast_variable *chanvars; /*!< Variables to set for channel created by user */
@@ -1470,6 +1474,7 @@ struct sip_peer {
int onHold; /*!< Peer has someone on hold */
int call_limit; /*!< Limit of concurrent calls */
int busy_level; /*!< Level of active channels where we signal busy */
+ int t38_maxdatagram; /*!< T.38 FaxMaxDatagram override */
enum transfermodes allowtransfer; /*! SIP Refer restriction scheme */
char vmexten[AST_MAX_EXTENSION]; /*!< Dialplan extension for MWI notify message*/
char language[MAX_LANGUAGE]; /*!< Default language for prompts */
@@ -4291,6 +4296,7 @@ static int create_addr_from_peer(struct sip_pvt *dialog, struct sip_peer *peer)
/* t38pt_udptl was enabled in the peer and not in [general] */
dialog->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, bindaddr.sin_addr);
}
+ dialog->t38_maxdatagram = peer->t38_maxdatagram;
set_t38_capabilities(dialog);
} else if (dialog->udptl) {
ast_udptl_destroy(dialog->udptl);
@@ -6243,8 +6249,10 @@ static struct sip_pvt *sip_alloc(ast_string_field callid, struct sockaddr_in *si
p->vrtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
if (ast_test_flag(&p->flags[1], SIP_PAGE2_TEXTSUPPORT))
p->trtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
- if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT))
+ if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT)) {
p->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, bindaddr.sin_addr);
+ p->t38_maxdatagram = global_t38_maxdatagram;
+ }
if (!p->rtp|| (ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT) && !p->vrtp)
|| (ast_test_flag(&p->flags[1], SIP_PAGE2_TEXTSUPPORT) && !p->trtp)) {
ast_log(LOG_WARNING, "Unable to create RTP audio %s%ssession: %s\n",
@@ -7399,6 +7407,11 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
ast_debug(3, "FaxVersion: %d\n", x);
p->t38.their_parms.version = x;
} else if ((sscanf(a, "T38FaxMaxDatagram:%30d", &x) == 1) || (sscanf(a, "T38MaxDatagram:%30d", &x) == 1)) {
+ /* override the supplied value if the configuration requests it */
+ if (p->t38_maxdatagram > x) {
+ ast_debug(1, "Overriding T38FaxMaxDatagram '%d' with '%d'\n", x, p->t38_maxdatagram);
+ x = p->t38_maxdatagram;
+ }
found = 1;
ast_debug(3, "FaxMaxDatagram: %d\n", x);
ast_udptl_set_far_max_datagram(p->udptl, x);
@@ -12223,6 +12236,9 @@ static enum check_auth_result check_user_ok(struct sip_pvt *p, char *of,
ast_rtp_destroy(p->trtp);
p->trtp = NULL;
}
+ if (p->udptl) {
+ p->t38_maxdatagram = user->t38_maxdatagram;
+ }
}
unref_user(user);
return res;
@@ -12267,6 +12283,7 @@ static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of,
ast_copy_flags(&p->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY);
if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) && p->udptl) {
+ p->t38_maxdatagram = peer->t38_maxdatagram;
set_t38_capabilities(p);
}
@@ -12357,6 +12374,9 @@ static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of,
ast_rtp_destroy(p->trtp);
p->trtp = NULL;
}
+ if (p->udptl) {
+ p->t38_maxdatagram = peer->t38_maxdatagram;
+ }
if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) ||
(ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO))
p->noncodeccapability |= AST_RTP_DTMF;
@@ -13439,6 +13459,18 @@ static void peer_mailboxes_to_str(struct ast_str **mailbox_str, struct sip_peer
}
}
+static struct _map_x_s faxecmodes[] = {
+ { SIP_PAGE2_T38SUPPORT_UDPTL, "None"},
+ { SIP_PAGE2_T38SUPPORT_UDPTL_FEC, "FEC"},
+ { SIP_PAGE2_T38SUPPORT_UDPTL_REDUNDANCY, "Redundancy"},
+ { -1, NULL},
+};
+
+static const char *faxec2str(int faxec)
+{
+ return map_x_s(faxecmodes, faxec, "Unknown");
+}
+
/*! \brief Show one peer in detail (main function) */
static char *_sip_show_peer(int type, int fd, struct mansession *s, const struct message *m, int argc, const char *argv[])
{
@@ -13515,7 +13547,9 @@ static char *_sip_show_peer(int type, int fd, struct mansession *s, const struct
ast_cli(fd, " Insecure : %s\n", insecure2str(ast_test_flag(&peer->flags[0], SIP_INSECURE)));
ast_cli(fd, " Nat : %s\n", nat2str(ast_test_flag(&peer->flags[0], SIP_NAT)));
ast_cli(fd, " ACL : %s\n", cli_yesno(peer->ha != NULL));
- ast_cli(fd, " T38 pt UDPTL : %s\n", cli_yesno(ast_test_flag(&peer->flags[1], SIP_PAGE2_T38SUPPORT)));
+ ast_cli(fd, " T.38 support : %s\n", cli_yesno(ast_test_flag(&peer->flags[1], SIP_PAGE2_T38SUPPORT)));
+ ast_cli(fd, " T.38 EC mode : %s\n", faxec2str(ast_test_flag(&peer->flags[1], SIP_PAGE2_T38SUPPORT)));
+ ast_cli(fd, " T.38 MaxDtgrm: %d\n", peer->t38_maxdatagram);
ast_cli(fd, " CanReinvite : %s\n", cli_yesno(ast_test_flag(&peer->flags[0], SIP_CAN_REINVITE)));
ast_cli(fd, " PromiscRedir : %s\n", cli_yesno(ast_test_flag(&peer->flags[0], SIP_PROMISCREDIR)));
ast_cli(fd, " User=Phone : %s\n", cli_yesno(ast_test_flag(&peer->flags[0], SIP_USEREQPHONE)));
@@ -13622,6 +13656,9 @@ static char *_sip_show_peer(int type, int fd, struct mansession *s, const struct
astman_append(s, "SIP-UserPhone: %s\r\n", (ast_test_flag(&peer->flags[0], SIP_USEREQPHONE)?"Y":"N"));
astman_append(s, "SIP-VideoSupport: %s\r\n", (ast_test_flag(&peer->flags[1], SIP_PAGE2_VIDEOSUPPORT)?"Y":"N"));
astman_append(s, "SIP-TextSupport: %s\r\n", (ast_test_flag(&peer->flags[1], SIP_PAGE2_TEXTSUPPORT)?"Y":"N"));
+ astman_append(s, "SIP-T.38Support: %s\r\n", (ast_test_flag(&peer->flags[1], SIP_PAGE2_T38SUPPORT)?"Y":"N"));
+ astman_append(s, "SIP-T.38EC: %s\r\n", faxec2str(ast_test_flag(&peer->flags[1], SIP_PAGE2_T38SUPPORT)));
+ astman_append(s, "SIP-T.38MaxDtgrm: %d\r\n", peer->t38_maxdatagram);
astman_append(s, "SIP-Sess-Timers: %s\r\n", stmode2str(peer->stimer.st_mode_oper));
astman_append(s, "SIP-Sess-Refresh: %s\r\n", strefresher2str(peer->stimer.st_ref));
astman_append(s, "SIP-Sess-Expires: %d\r\n", peer->stimer.st_max_se);
@@ -13901,7 +13938,9 @@ static char *sip_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_
ast_cli(a->fd, " Record SIP history: %s\n", recordhistory ? "On" : "Off");
ast_cli(a->fd, " Call Events: %s\n", global_callevents ? "On" : "Off");
- ast_cli(a->fd, " T38 fax pt UDPTL: %s\n", cli_yesno(ast_test_flag(&global_flags[1], SIP_PAGE2_T38SUPPORT)));
+ ast_cli(a->fd, " T.38 support: %s\n", cli_yesno(ast_test_flag(&global_flags[1], SIP_PAGE2_T38SUPPORT)));
+ ast_cli(a->fd, " T.38 EC mode: %s\n", faxec2str(ast_test_flag(&global_flags[1], SIP_PAGE2_T38SUPPORT)));
+ ast_cli(a->fd, " T.38 MaxDtgrm: %d\n", global_t38_maxdatagram);
if (!realtimepeers && !realtimeusers && !realtimeregs)
ast_cli(a->fd, " SIP realtime: Disabled\n" );
@@ -20733,6 +20772,45 @@ static void set_insecure_flags (struct ast_flags *flags, const char *value, int
}
/*!
+ \brief Handle T.38 configuration options common to users and peers
+ \returns non-zero if any config options were handled, zero otherwise
+*/
+static int handle_t38_options(struct ast_flags *flags, struct ast_flags *mask, struct ast_variable *v,
+ int *maxdatagram)
+{
+ int res = 1;
+
+ if (!strcasecmp(v->name, "t38pt_udptl")) {
+ char *buf = ast_strdupa(v->value);
+ char *word, *next = buf;
+
+ ast_set_flag(&mask[1], SIP_PAGE2_T38SUPPORT);
+
+ while ((word = strsep(&next, ","))) {
+ if (ast_true(word) || !strcasecmp(word, "fec")) {
+ ast_clear_flag(&flags[1], SIP_PAGE2_T38SUPPORT);
+ ast_set_flag(&flags[1], SIP_PAGE2_T38SUPPORT_UDPTL_FEC);
+ } else if (!strcasecmp(word, "redundancy")) {
+ ast_clear_flag(&flags[1], SIP_PAGE2_T38SUPPORT);
+ ast_set_flag(&flags[1], SIP_PAGE2_T38SUPPORT_UDPTL_REDUNDANCY);
+ } else if (!strcasecmp(word, "none")) {
+ ast_clear_flag(&flags[1], SIP_PAGE2_T38SUPPORT);
+ ast_set_flag(&flags[1], SIP_PAGE2_T38SUPPORT_UDPTL);
+ } else if (!strncasecmp(word, "maxdatagram=", 12)) {
+ if (sscanf(&word[12], "%30d", maxdatagram) != 1) {
+ ast_log(LOG_WARNING, "Invalid maxdatagram '%s' at line %d of %s\n", v->value, v->lineno, config);
+ *maxdatagram = global_t38_maxdatagram;
+ }
+ }
+ }
+ } else {
+ res = 0;
+ }
+
+ return res;
+}
+
+/*!
\brief Handle flag-type options common to configuration of devices - users and peers
\param flags array of two struct ast_flags
\param mask array of two struct ast_flags
@@ -20834,25 +20912,6 @@ static int handle_common_options(struct ast_flags *flags, struct ast_flags *mask
} else if (!strcasecmp(v->name, "ignoresdpversion")) {
ast_set_flag(&mask[1], SIP_PAGE2_IGNORESDPVERSION);
ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_IGNORESDPVERSION);
- } else if (!strcasecmp(v->name, "t38pt_udptl")) {
- char buf[16], *word, *next = buf;
-
- ast_set_flag(&mask[1], SIP_PAGE2_T38SUPPORT);
-
- ast_copy_string(buf, v->value, sizeof(buf));
-
- while ((word = strsep(&next, ","))) {
- if (ast_true(word) || !strcasecmp(word, "fec")) {
- ast_clear_flag(&flags[1], SIP_PAGE2_T38SUPPORT);
- ast_set_flag(&flags[1], SIP_PAGE2_T38SUPPORT_UDPTL_FEC);
- } else if (!strcasecmp(word, "redundancy")) {
- ast_clear_flag(&flags[1], SIP_PAGE2_T38SUPPORT);
- ast_set_flag(&flags[1], SIP_PAGE2_T38SUPPORT_UDPTL_REDUNDANCY);
- } else if (!strcasecmp(word, "none")) {
- ast_clear_flag(&flags[1], SIP_PAGE2_T38SUPPORT);
- ast_set_flag(&flags[1], SIP_PAGE2_T38SUPPORT_UDPTL);
- }
- }
} else if (!strcasecmp(v->name, "rfc2833compensate")) {
ast_set_flag(&mask[1], SIP_PAGE2_RFC2833_COMPENSATE);
ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_RFC2833_COMPENSATE);
@@ -21062,6 +21121,7 @@ static struct sip_user *build_user(const char *name, struct ast_variable *v, str
user->allowtransfer = global_allowtransfer;
user->maxcallbitrate = default_maxcallbitrate;
user->autoframing = global_autoframing;
+ user->t38_maxdatagram = global_t38_maxdatagram;
if (global_callcounter)
user->call_limit=999;
user->prefs = default_prefs;
@@ -21079,6 +21139,9 @@ static struct sip_user *build_user(const char *name, struct ast_variable *v, str
for (; v || ((v = alt) && !(alt=NULL)); v = v->next) {
if (handle_common_options(&userflags[0], &mask[0], v))
continue;
+ if (handle_t38_options(&userflags[0], &mask[0], v, &user->t38_maxdatagram)) {
+ continue;
+ }
if (!strcasecmp(v->name, "context")) {
ast_copy_string(user->context, v->value, sizeof(user->context));
} else if (!strcasecmp(v->name, "subscribecontext")) {
@@ -21240,6 +21303,7 @@ static void set_peer_defaults(struct sip_peer *peer)
peer->stimer.st_max_se = global_max_se;
peer->timer_t1 = global_t1;
peer->timer_b = global_timer_b;
+ peer->t38_maxdatagram = global_t38_maxdatagram;
clear_peer_mailboxes(peer);
}
@@ -21364,6 +21428,9 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
if (handle_common_options(&peerflags[0], &mask[0], v)) {
continue;
}
+ if (handle_t38_options(&peerflags[0], &mask[0], v, &peer->t38_maxdatagram)) {
+ continue;
+ }
if (!strcasecmp(v->name, "transport") && !ast_strlen_zero(v->value)) {
char *val = ast_strdupa(v->value);
char *trans;
@@ -22061,6 +22128,7 @@ static int reload_config(enum channelreloadreason reason)
global_timer_b = 64 * SIP_TIMER_T1;
global_t1min = DEFAULT_T1MIN;
global_qualifyfreq = DEFAULT_QUALIFYFREQ;
+ global_t38_maxdatagram = -1;
global_matchexterniplocally = FALSE;
@@ -22075,6 +22143,9 @@ static int reload_config(enum channelreloadreason reason)
for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
if (handle_common_options(&global_flags[0], &dummy[0], v))
continue;
+ if (handle_t38_options(&global_flags[0], &dummy[0], v, &global_t38_maxdatagram)) {
+ continue;
+ }
/* handle jb conf */
if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
continue;