Skip to content
Snippets Groups Projects
Commit 60e10aba authored by Joshua Colp's avatar Joshua Colp
Browse files

Change fax detection in chan_sip so it behaves as one would expect.

Internally the way T.38 is negotiated has changed and the option no longer
reflects a behavior that is valid. It will now look for a CNG tone on
received calls and if present send the call to the 'fax' extension. It is
then up to the application or channel to request the switch over to T.38.


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@230881 65c4cc65-6c06-0410-ace0-fbb531ad65f3
parent fe1ebc8d
Branches
Tags
No related merge requests found
...@@ -1828,7 +1828,7 @@ struct sip_pvt { ...@@ -1828,7 +1828,7 @@ struct sip_pvt {
int laststate; /*!< SUBSCRIBE: Last known extension state */ int laststate; /*!< SUBSCRIBE: Last known extension state */
int dialogver; /*!< SUBSCRIBE: Version for subscription dialog-info */ int dialogver; /*!< SUBSCRIBE: Version for subscription dialog-info */
   
struct ast_dsp *dsp; /*!< Inband DTMF Detection dsp */ struct ast_dsp *dsp; /*!< Inband DTMF or Fax CNG tone Detection dsp */
   
struct sip_peer *relatedpeer; /*!< If this dialog is related to a peer, which one struct sip_peer *relatedpeer; /*!< If this dialog is related to a peer, which one
Used in peerpoke, mwi subscriptions */ Used in peerpoke, mwi subscriptions */
...@@ -4442,23 +4442,40 @@ static int send_request(struct sip_pvt *p, struct sip_request *req, enum xmittyp ...@@ -4442,23 +4442,40 @@ static int send_request(struct sip_pvt *p, struct sip_request *req, enum xmittyp
return res; return res;
} }
   
static void enable_digit_detect(struct sip_pvt *p) static void enable_dsp_detect(struct sip_pvt *p)
{ {
int features = 0;
if (p->dsp) { if (p->dsp) {
return; return;
} }
   
if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) ||
(ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) {
if (!p->rtp || ast_rtp_instance_dtmf_mode_set(p->rtp, AST_RTP_DTMF_MODE_INBAND)) {
features |= DSP_FEATURE_DIGIT_DETECT;
}
}
if (ast_test_flag(&p->flags[1], SIP_PAGE2_FAX_DETECT)) {
features |= DSP_FEATURE_FAX_DETECT;
}
if (!features) {
return;
}
if (!(p->dsp = ast_dsp_new())) { if (!(p->dsp = ast_dsp_new())) {
return; return;
} }
   
ast_dsp_set_features(p->dsp, DSP_FEATURE_DIGIT_DETECT); ast_dsp_set_features(p->dsp, features);
if (global_relaxdtmf) { if (global_relaxdtmf) {
ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | DSP_DIGITMODE_RELAXDTMF); ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | DSP_DIGITMODE_RELAXDTMF);
} }
} }
   
static void disable_digit_detect(struct sip_pvt *p) static void disable_dsp_detect(struct sip_pvt *p)
{ {
if (p->dsp) { if (p->dsp) {
ast_dsp_free(p->dsp); ast_dsp_free(p->dsp);
...@@ -4489,9 +4506,9 @@ static int sip_setoption(struct ast_channel *chan, int option, void *data, int d ...@@ -4489,9 +4506,9 @@ static int sip_setoption(struct ast_channel *chan, int option, void *data, int d
   
ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name); ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name);
if (*cp) { if (*cp) {
enable_digit_detect(p); enable_dsp_detect(p);
} else { } else {
disable_digit_detect(p); disable_dsp_detect(p);
} }
res = 0; res = 0;
} }
...@@ -6329,7 +6346,7 @@ static int sip_hangup(struct ast_channel *ast) ...@@ -6329,7 +6346,7 @@ static int sip_hangup(struct ast_channel *ast)
append_history(p, needcancel ? "Cancel" : "Hangup", "Cause %s", p->owner ? ast_cause2str(p->hangupcause) : "Unknown"); append_history(p, needcancel ? "Cancel" : "Hangup", "Cause %s", p->owner ? ast_cause2str(p->hangupcause) : "Unknown");
   
/* Disconnect */ /* Disconnect */
disable_digit_detect(p); disable_dsp_detect(p);
   
p->owner = NULL; p->owner = NULL;
ast->tech_pvt = dialog_unref(ast->tech_pvt, "unref ast->tech_pvt"); ast->tech_pvt = dialog_unref(ast->tech_pvt, "unref ast->tech_pvt");
...@@ -6996,10 +7013,12 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit ...@@ -6996,10 +7013,12 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit
else else
ast_debug(3, "This channel will not be able to handle video.\n"); ast_debug(3, "This channel will not be able to handle video.\n");
   
enable_dsp_detect(i);
if ((ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) || if ((ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) ||
(ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) { (ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) {
if (!i->rtp || ast_rtp_instance_dtmf_mode_set(i->rtp, AST_RTP_DTMF_MODE_INBAND)) { if (!i->rtp || ast_rtp_instance_dtmf_mode_set(i->rtp, AST_RTP_DTMF_MODE_INBAND)) {
enable_digit_detect(i); enable_dsp_detect(i);
} }
} else if (ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) { } else if (ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) {
if (i->rtp) { if (i->rtp) {
...@@ -7321,9 +7340,17 @@ static struct ast_frame *sip_rtp_read(struct ast_channel *ast, struct sip_pvt *p ...@@ -7321,9 +7340,17 @@ static struct ast_frame *sip_rtp_read(struct ast_channel *ast, struct sip_pvt *p
if (f && p->dsp) { if (f && p->dsp) {
f = ast_dsp_process(p->owner, p->dsp, f); f = ast_dsp_process(p->owner, p->dsp, f);
if (f && f->frametype == AST_FRAME_DTMF) { if (f && f->frametype == AST_FRAME_DTMF) {
if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) && f->subclass.integer == 'f') { if (f->subclass.integer == 'f') {
ast_debug(1, "Fax CNG detected on %s\n", ast->name); if (option_debug)
ast_log(LOG_DEBUG, "Fax CNG detected on %s\n", ast->name);
*faxdetect = 1; *faxdetect = 1;
/* If we only needed this DSP for fax detection purposes we can just drop it now */
if (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) {
ast_dsp_set_features(p->dsp, DSP_FEATURE_DIGIT_DETECT);
} else {
ast_dsp_free(p->dsp);
p->dsp = NULL;
}
} else { } else {
ast_debug(1, "* Detected inband DTMF '%c'\n", f->subclass.integer); ast_debug(1, "* Detected inband DTMF '%c'\n", f->subclass.integer);
} }
...@@ -7344,20 +7371,26 @@ static struct ast_frame *sip_read(struct ast_channel *ast) ...@@ -7344,20 +7371,26 @@ static struct ast_frame *sip_read(struct ast_channel *ast)
fr = sip_rtp_read(ast, p, &faxdetected); fr = sip_rtp_read(ast, p, &faxdetected);
p->lastrtprx = time(NULL); p->lastrtprx = time(NULL);
   
/* If we are NOT bridged to another channel, and we have detected fax tone we issue T38 re-invite to a peer */ /* If we detect a CNG tone and fax detection is enabled then send us off to the fax extension */
/* 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->flags[1], SIP_PAGE2_FAX_DETECT)) {
if (faxdetected && ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) && (p->t38.state == T38_DISABLED) && !(ast_bridged_channel(ast))) { ast_channel_lock(ast);
if (!ast_test_flag(&p->flags[0], SIP_GOTREFER)) { if (strcmp(ast->exten, "fax")) {
if (!p->pendinginvite) { const char *target_context = S_OR(ast->macrocontext, ast->context);
ast_debug(3, "Sending reinvite on SIP (%s) for T.38 negotiation.\n", ast->name); ast_channel_unlock(ast);
change_t38_state(p, T38_LOCAL_REINVITE); if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
transmit_reinvite_with_sdp(p, TRUE, FALSE); ast_verbose(VERBOSE_PREFIX_2 "Redirecting '%s' to fax extension\n", ast->name);
} pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
} else if (!ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) { if (ast_async_goto(ast, target_context, "fax", 1)) {
ast_debug(3, "Deferring reinvite on SIP (%s) - it will be re-negotiated for T.38\n", ast->name); ast_log(LOG_NOTICE, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
ast_set_flag(&p->flags[0], SIP_NEEDREINVITE); }
} fr = &ast_null_frame;
} } else {
ast_log(LOG_NOTICE, "Fax detected but no fax extension\n");
}
} else {
ast_channel_unlock(ast);
}
}
   
/* Only allow audio through if they sent progress with SDP, or if the channel is actually answered */ /* Only allow audio through if they sent progress with SDP, or if the channel is actually answered */
if (fr && fr->frametype == AST_FRAME_VOICE && p->invitestate != INV_EARLY_MEDIA && ast->_state != AST_STATE_UP) { if (fr && fr->frametype == AST_FRAME_VOICE && p->invitestate != INV_EARLY_MEDIA && ast->_state != AST_STATE_UP) {
...@@ -26521,9 +26554,9 @@ static int sip_dtmfmode(struct ast_channel *chan, const char *data) ...@@ -26521,9 +26554,9 @@ static int sip_dtmfmode(struct ast_channel *chan, const char *data)
ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_DTMF, ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833); ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_DTMF, ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833);
if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) || if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) ||
(ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) { (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) {
enable_digit_detect(p); enable_dsp_detect(p);
} else { } else {
disable_digit_detect(p); disable_dsp_detect(p);
} }
sip_pvt_unlock(p); sip_pvt_unlock(p);
ast_channel_unlock(chan); ast_channel_unlock(chan);
......
...@@ -552,7 +552,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls ...@@ -552,7 +552,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls
; ; send 400 byte T.38 FAX packets to it. ; ; send 400 byte T.38 FAX packets to it.
; ;
; FAX detection will cause the SIP channel to jump to the 'fax' extension (if it exists) ; FAX detection will cause the SIP channel to jump to the 'fax' extension (if it exists)
; after T.38 is successfully negotiated. ; when a CNG tone is detected on an incoming call.
; ;
; faxdetect = yes ; Default false ; faxdetect = yes ; Default false
; ;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment