Index: channels/chan_sip.c =================================================================== --- channels/chan_sip.c (Revision 3538) +++ channels/chan_sip.c (Arbeitskopie) @@ -513,6 +513,7 @@ #define DEFAULT_QUALIFY FALSE #define DEFAULT_T1MIN 100 /*!< 100 MS for minimal roundtrip time */ #define DEFAULT_MAX_CALL_BITRATE (384) /*!< Max bitrate for video */ +#define DEFAULT_T38_FALLBACK_CODEC "ulaw" #ifndef DEFAULT_USERAGENT #define DEFAULT_USERAGENT "Asterisk PBX" /*!< Default Useragent: header unless re-defined in sip.conf */ #endif @@ -563,6 +564,7 @@ static char global_realm[MAXHOSTNAMELEN]; /*!< Default realm */ static char global_regcontext[AST_MAX_CONTEXT]; /*!< Context for auto-extensions */ static char global_useragent[AST_MAX_EXTENSION]; /*!< Useragent for the SIP channel */ +static char global_t38_fallback_codec[AST_MAX_EXTENSION]; /*!< The codec to use for the T.38 fallback to audio fax */ static int allow_external_domains; /*!< Accept calls to external SIP domains? */ static int global_callevents; /*!< Whether we send manager events or not */ static int global_t1min; /*!< T1 roundtrip time minimum */ @@ -12118,6 +12120,7 @@ int outgoing = ast_test_flag(&p->flags[0], SIP_OUTGOING); int res = 0; int xmitres = 0; + int fmt; int reinvite = (p->owner && p->owner->_state == AST_STATE_UP); struct ast_channel *bridgepeer = NULL; @@ -12367,25 +12370,31 @@ } break; case 488: /* Not acceptable here */ + case 606: /* Not Acceptable */ xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); if (reinvite && p->udptl) { - /* If this is a T.38 call, we should go back to - audio. If this is an audio call - something went - terribly wrong since we don't renegotiate codecs, - only IP/port . - */ + + /* Trigger a reinvite back to audio */ + fmt = ast_getformatbyname(global_t38_fallback_codec); + p->jointcapability &= fmt; + p->capability &= fmt; + transmit_reinvite_with_sdp(p); + + if (p->owner && (p->owner->_state == AST_STATE_UP) && (bridgepeer = ast_bridged_channel(p->owner))) { /* if this is a re-invite */ + struct sip_pvt *bridgepvt = NULL; + if (bridgepeer->tech == &sip_tech || bridgepeer->tech == &sip_tech_info) { + bridgepvt = (struct sip_pvt*)(bridgepeer->tech_pvt); + if (bridgepvt->udptl) { + sip_handle_t38_reinvite(bridgepeer, p, 0); + } + } + } + + p->t38.state = T38_DISABLED; /* Try to reset RTP timers */ ast_rtp_set_rtptimers_onhold(p->rtp); - ast_log(LOG_ERROR, "Got error on T.38 re-invite. Bad configuration. Peer needs to have T.38 disabled.\n"); - - /*! \bug Is there any way we can go back to the audio call on both - sides here? - */ - /* While figuring that out, hangup the call */ - if (p->owner && !ast_test_flag(req, SIP_PKT_IGNORE)) - ast_queue_control(p->owner, AST_CONTROL_CONGESTION); - ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); + } else if (p->udptl && p->t38.state == T38_LOCAL_DIRECT) { /* We tried to send T.38 out in an initial INVITE and the remote side rejected it, right now we can't fall back to audio so totally abort. @@ -12895,6 +12904,7 @@ handle_response_invite(p, resp, rest, req, seqno); break; case 488: /* Not acceptable here - codec error */ + case 606: /* Not Acceptable */ if (sipmethod == SIP_INVITE) handle_response_invite(p, resp, rest, req, seqno); break; @@ -16290,6 +16300,8 @@ ast_set_flag(&mask[1], SIP_PAGE2_T38SUPPORT_TCP); ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_T38SUPPORT_TCP); #endif + } else if (!strcasecmp(v->name, "t38_fallback_codec")) { + ast_copy_string(global_t38_fallback_codec, v->value, sizeof(global_t38_fallback_codec)); } 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); @@ -16987,6 +16999,7 @@ global_alwaysauthreject = 0; global_allowsubscribe = FALSE; ast_copy_string(global_useragent, DEFAULT_USERAGENT, sizeof(global_useragent)); + ast_copy_string(global_t38_fallback_codec, DEFAULT_T38_FALLBACK_CODEC, sizeof(global_t38_fallback_codec)); ast_copy_string(default_notifymime, DEFAULT_NOTIFYMIME, sizeof(default_notifymime)); if (ast_strlen_zero(ast_config_AST_SYSTEM_NAME)) ast_copy_string(global_realm, DEFAULT_REALM, sizeof(global_realm)); @@ -17588,7 +17601,7 @@ p->lastrtprx = p->lastrtptx = time(NULL); ast_mutex_unlock(&p->lock); return 0; - } else { /* If we are handling sending 200 OK to the other side of the bridge */ + } else if (pvt->t38.state != T38_DISABLED) { /* If we are handling sending 200 OK to the other side of the bridge */ if (ast_test_flag(&p->flags[0], SIP_CAN_REINVITE) && ast_test_flag(&pvt->flags[0], SIP_CAN_REINVITE)) { ast_udptl_get_peer(pvt->udptl, &p->udptlredirip); flag = 1; @@ -17611,6 +17624,20 @@ p->lastrtprx = p->lastrtptx = time(NULL); ast_mutex_unlock(&p->lock); return 0; + } else if (pvt->t38.state == T38_DISABLED) { /* The other side can not talk T.38 with us. We tell it to the the originating T.38 party with a 488 */ + p->t38.state = T38_DISABLED; + if (option_debug > 1) { + ast_log(LOG_DEBUG, "T38 changed state to %d on channel %s\n", pvt->t38.state, pvt->owner ? pvt->owner->name : ""); + ast_log(LOG_DEBUG, "T38 changed state to %d on channel %s\n", p->t38.state, chan ? chan->name : ""); + } + transmit_response_reliable(p, "488 Not acceptable here", &p->initreq); + p->lastrtprx = p->lastrtptx = time(NULL); + ast_mutex_unlock(&p->lock); + return 0; + } else { + ast_log(LOG_ERROR, "Something went wrong with T.38. State is:%d on channel %s and %d on channel %s\n", pvt->t38.state, pvt->owner ? pvt->owner->name : "", p->t38.state, chan ? chan->name : ""); + ast_mutex_unlock(&p->lock); + return 0; } }