diff options
Diffstat (limited to 'channels')
-rw-r--r-- | channels/chan_sip.c | 121 |
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; |