aboutsummaryrefslogtreecommitdiffstats
path: root/channels/chan_sip.c
diff options
context:
space:
mode:
Diffstat (limited to 'channels/chan_sip.c')
-rw-r--r--channels/chan_sip.c113
1 files changed, 87 insertions, 26 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 6e85fa1b9..2b74997b2 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -1138,6 +1138,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 */
@@ -1381,10 +1383,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 */
@@ -1615,6 +1617,7 @@ struct sip_pvt {
int jointnoncodeccapability; /*!< Joint Non codec capability */
int redircodecs; /*!< Redirect codecs */
int maxcallbitrate; /*!< Maximum Call Bitrate for Video Calls */
+ int t38_maxdatagram; /*!< T.38 FaxMaxDatagram override */
struct sip_proxy *outboundproxy; /*!< Outbound proxy for this dialog. Use ref_proxy to set this instead of setting it directly*/
struct t38properties t38; /*!< T38 settings */
struct sockaddr_in udptlredirip; /*!< Where our T.38 UDPTL should be going if not to us */
@@ -1847,6 +1850,7 @@ struct sip_peer {
int inRinging; /*!< Number of calls ringing */
int onHold; /*!< Peer has someone on hold */
int call_limit; /*!< Limit of concurrent calls */
+ int t38_maxdatagram; /*!< T.38 FaxMaxDatagram override */
int busy_level; /*!< Level of active channels where we signal busy */
enum transfermodes allowtransfer; /*! SIP Refer restriction scheme */
struct ast_codec_pref prefs; /*!< codec prefs */
@@ -4919,6 +4923,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);
@@ -6954,6 +6959,7 @@ static struct sip_pvt *sip_alloc(ast_string_field callid, struct sockaddr_in *si
}
ao2_t_ref(p, -1, "failed to create RTP audio session, drop p");
return NULL;
+ p->t38_maxdatagram = global_t38_maxdatagram;
}
ast_rtp_setqos(p->rtp, global_tos_audio, global_cos_audio, "SIP RTP");
ast_rtp_setdtmf(p->rtp, ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833);
@@ -7004,6 +7010,7 @@ static struct sip_pvt *sip_alloc(ast_string_field callid, struct sockaddr_in *si
(ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO))
p->noncodeccapability |= AST_RTP_DTMF;
if (p->udptl) {
+ p->t38_maxdatagram = global_t38_maxdatagram;
set_t38_capabilities(p);
}
ast_string_field_set(p, context, sip_cfg.default_context);
@@ -8377,6 +8384,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);
@@ -13528,6 +13540,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);
}
@@ -14884,6 +14897,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[])
{
@@ -14962,7 +14987,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, " DirectMedia : %s\n", cli_yesno(ast_test_flag(&peer->flags[0], SIP_DIRECT_MEDIA)));
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)));
@@ -15073,6 +15100,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);
@@ -15518,7 +15548,9 @@ static char *sip_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_
ast_cli(a->fd, " Call Events: %s\n", sip_cfg.callevents ? "On" : "Off");
ast_cli(a->fd, " Auth. Failure Events: %s\n", global_authfailureevents ? "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 && !realtimeregs)
ast_cli(a->fd, " SIP realtime: Disabled\n" );
@@ -19493,6 +19525,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
/* 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))) {
+ p->t38_maxdatagram = global_t38_maxdatagram;
set_t38_capabilities(p);
}
@@ -22661,6 +22694,48 @@ 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 if (!strcasecmp(v->name, "t38pt_usertpsource")) {
+ ast_set_flag(&mask[1], SIP_PAGE2_UDPTL_DESTINATION);
+ ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_UDPTL_DESTINATION);
+ } else {
+ res = 0;
+ }
+
+ return res;
+}
+
+/*!
\brief Handle flag-type options common to configuration of devices - peers
\param flags array of two struct ast_flags
\param mask array of two struct ast_flags
@@ -22770,34 +22845,12 @@ static int handle_common_options(struct ast_flags *flags, struct ast_flags *mask
} else if (!strcasecmp(v->name, "faxdetect")) {
ast_set_flag(&mask[1], SIP_PAGE2_FAX_DETECT);
ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_FAX_DETECT);
- } 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);
} else if (!strcasecmp(v->name, "buggymwi")) {
ast_set_flag(&mask[1], SIP_PAGE2_BUGGY_MWI);
ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_BUGGY_MWI);
- } else if (!strcasecmp(v->name, "t38pt_usertpsource")) {
- ast_set_flag(&mask[1], SIP_PAGE2_UDPTL_DESTINATION);
- ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_UDPTL_DESTINATION);
} else if (!strcasecmp(v->name, "constantssrc")) {
ast_set_flag(&mask[1], SIP_PAGE2_CONSTANT_SSRC);
ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_CONSTANT_SSRC);
@@ -23003,6 +23056,7 @@ static void set_peer_defaults(struct sip_peer *peer)
peer->rtpkeepalive = global_rtpkeepalive;
peer->allowtransfer = sip_cfg.allowtransfer;
peer->autoframing = global_autoframing;
+ peer->t38_maxdatagram = global_t38_maxdatagram;
peer->qualifyfreq = global_qualifyfreq;
if (global_callcounter)
peer->call_limit=INT_MAX;
@@ -23161,6 +23215,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;
@@ -23854,6 +23911,7 @@ static int reload_config(enum channelreloadreason reason)
global_timer_b = 64 * DEFAULT_TIMER_T1;
global_t1min = DEFAULT_T1MIN;
global_qualifyfreq = DEFAULT_QUALIFYFREQ;
+ global_t38_maxdatagram = -1;
sip_cfg.matchexterniplocally = DEFAULT_MATCHEXTERNIPLOCALLY;
@@ -23870,6 +23928,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;