int laststate; /*!< SUBSCRIBE: Last known extension state */
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
Used in peerpoke, mwi subscriptions */
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) {
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())) {
return;
}
- ast_dsp_set_features(p->dsp, DSP_FEATURE_DIGIT_DETECT);
+ ast_dsp_set_features(p->dsp, features);
if (global_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) {
ast_dsp_free(p->dsp);
ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name);
if (*cp) {
- enable_digit_detect(p);
+ enable_dsp_detect(p);
} else {
- disable_digit_detect(p);
+ disable_dsp_detect(p);
}
res = 0;
}
append_history(p, needcancel ? "Cancel" : "Hangup", "Cause %s", p->owner ? ast_cause2str(p->hangupcause) : "Unknown");
/* Disconnect */
- disable_digit_detect(p);
+ disable_dsp_detect(p);
p->owner = NULL;
ast->tech_pvt = dialog_unref(ast->tech_pvt, "unref ast->tech_pvt");
else
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) ||
(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)) {
- enable_digit_detect(i);
+ enable_dsp_detect(i);
}
} else if (ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) {
if (i->rtp) {
if (f && p->dsp) {
f = ast_dsp_process(p->owner, p->dsp, f);
if (f && f->frametype == AST_FRAME_DTMF) {
- if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) && f->subclass.integer == 'f') {
- ast_debug(1, "Fax CNG detected on %s\n", ast->name);
+ if (f->subclass.integer == 'f') {
+ if (option_debug)
+ ast_log(LOG_DEBUG, "Fax CNG detected on %s\n", ast->name);
*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 {
ast_debug(1, "* Detected inband DTMF '%c'\n", f->subclass.integer);
}
fr = sip_rtp_read(ast, p, &faxdetected);
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 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_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);
- change_t38_state(p, T38_LOCAL_REINVITE);
- transmit_reinvite_with_sdp(p, TRUE, FALSE);
- }
- } else if (!ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) {
- ast_debug(3, "Deferring reinvite on SIP (%s) - it will be re-negotiated for T.38\n", ast->name);
- ast_set_flag(&p->flags[0], SIP_NEEDREINVITE);
- }
- }
+ /* If we detect a CNG tone and fax detection is enabled then send us off to the fax extension */
+ if (faxdetected && ast_test_flag(&p->flags[1], SIP_PAGE2_FAX_DETECT)) {
+ ast_channel_lock(ast);
+ if (strcmp(ast->exten, "fax")) {
+ const char *target_context = S_OR(ast->macrocontext, ast->context);
+ ast_channel_unlock(ast);
+ if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
+ ast_verbose(VERBOSE_PREFIX_2 "Redirecting '%s' to fax extension\n", ast->name);
+ pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
+ if (ast_async_goto(ast, target_context, "fax", 1)) {
+ ast_log(LOG_NOTICE, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
+ }
+ 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 */
if (fr && fr->frametype == AST_FRAME_VOICE && p->invitestate != INV_EARLY_MEDIA && ast->_state != AST_STATE_UP) {
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) ||
(ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) {
- enable_digit_detect(p);
+ enable_dsp_detect(p);
} else {
- disable_digit_detect(p);
+ disable_dsp_detect(p);
}
sip_pvt_unlock(p);
ast_channel_unlock(chan);