From b77d873929a3eea43189cff59253e41da08c95f4 Mon Sep 17 00:00:00 2001 From: irroot Date: Mon, 16 May 2011 14:56:53 +0000 Subject: [PATCH] When a error in T.38 negotiation happens or its rejected on a channel the state of the channel reverts to unknown this should be rejected. this is important for negotiating T.38 gateway see #13405 This patch adds a option T38_REJECTED that behaves as T38_DISABLED except it reports state rejected. Trivial Change to res_fax to honnor UNAVAILABLE and REJECTED states. (closes issue #18889) Reported by: irroot Tested by: irroot, darkbasic, mnicholson Review: https://reviewboard.asterisk.org/r/1115 git-svn-id: http://svn.digium.com/svn/asterisk/trunk@319087 f38db490-d61c-443f-a65b-d21fe96a405b --- CHANGES | 1 + channels/chan_sip.c | 18 +++++++++++------- channels/sip/include/sip.h | 3 ++- res/res_fax.c | 9 +++++++-- 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/CHANGES b/CHANGES index c7aebe183..205a64041 100644 --- a/CHANGES +++ b/CHANGES @@ -199,6 +199,7 @@ SIP Changes res_stun_monitor module support in chan_sip. * Addition of the 'auth_options_requests' option for turning on and off authentication for OPTIONS requests in chan_sip. + * Add T38 support for REJECTED state where T.38 Negotiation is explicitly rejected. IAX2 Changes diff --git a/channels/chan_sip.c b/channels/chan_sip.c index fa525a5d2..0adb24bf9 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -4301,6 +4301,9 @@ static int sip_queryoption(struct ast_channel *chan, int option, void *data, int case T38_ENABLED: state = T38_STATE_NEGOTIATED; break; + case T38_REJECTED: + state = T38_STATE_REJECTED; + break; default: state = T38_STATE_UNKNOWN; } @@ -4961,6 +4964,7 @@ static void change_t38_state(struct sip_pvt *p, int state) parameters.request_response = AST_T38_NEGOTIATED; ast_udptl_set_tag(p->udptl, "SIP/%s", p->username); break; + case T38_REJECTED: case T38_DISABLED: if (old == T38_ENABLED) { parameters.request_response = AST_T38_TERMINATED; @@ -6528,11 +6532,11 @@ static int interpret_t38_parameters(struct sip_pvt *p, const struct ast_control_ case AST_T38_REQUEST_NEGOTIATE: /* Request T38 */ /* Negotiation can not take place without a valid max_ifp value. */ if (!parameters->max_ifp) { - change_t38_state(p, T38_DISABLED); if (p->t38.state == T38_PEER_REINVITE) { AST_SCHED_DEL_UNREF(sched, p->t38id, dialog_unref(p, "when you delete the t38id sched, you should dec the refcount for the stored dialog ptr")); transmit_response_reliable(p, "488 Not acceptable here", &p->initreq); } + change_t38_state(p, T38_REJECTED); break; } else if (p->t38.state == T38_PEER_REINVITE) { AST_SCHED_DEL_UNREF(sched, p->t38id, dialog_unref(p, "when you delete the t38id sched, you should dec the refcount for the stored dialog ptr")); @@ -6570,7 +6574,7 @@ static int interpret_t38_parameters(struct sip_pvt *p, const struct ast_control_ case AST_T38_REQUEST_TERMINATE: /* Shutdown T38 */ if (p->t38.state == T38_PEER_REINVITE) { AST_SCHED_DEL_UNREF(sched, p->t38id, dialog_unref(p, "when you delete the t38id sched, you should dec the refcount for the stored dialog ptr")); - change_t38_state(p, T38_DISABLED); + change_t38_state(p, T38_REJECTED); transmit_response_reliable(p, "488 Not acceptable here", &p->initreq); } else if (p->t38.state == T38_ENABLED) transmit_reinvite_with_sdp(p, FALSE, FALSE); @@ -9141,7 +9145,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action } } - if ((portno == -1) && (p->t38.state != T38_DISABLED)) { + if ((portno == -1) && (p->t38.state != T38_DISABLED) && (p->t38.state != T38_REJECTED)) { ast_debug(3, "Have T.38 but no audio, accepting offer anyway\n"); res = 0; goto process_sdp_cleanup; @@ -19081,7 +19085,7 @@ static int function_sipchaninfo_read(struct ast_channel *chan, const char *cmd, } else if (!strcasecmp(data, "peername")) { ast_copy_string(buf, p->peername, len); } else if (!strcasecmp(data, "t38passthrough")) { - if (p->t38.state == T38_DISABLED) { + if ((p->t38.state == T38_DISABLED) || (p->t38.state == T38_REJECTED)) { ast_copy_string(buf, "0", len); } else { /* T38 is offered or enabled in this call */ ast_copy_string(buf, "1", len); @@ -19852,7 +19856,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest case 606: /* Not Acceptable */ xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); if (p->udptl && p->t38.state == T38_LOCAL_REINVITE) { - change_t38_state(p, T38_DISABLED); + change_t38_state(p, T38_REJECTED); /* Try to reset RTP timers */ //ast_rtp_set_rtptimers_onhold(p->rtp); @@ -21573,7 +21577,7 @@ static int sip_t38_abort(const void *data) * want to abort the negotiation process */ if (p->t38id != -1) { - change_t38_state(p, T38_DISABLED); + change_t38_state(p, T38_REJECTED); transmit_response_reliable(p, "488 Not acceptable here", &p->initreq); p->t38id = -1; dialog_unref(p, "unref the dialog ptr from sip_t38_abort, because it held a dialog ptr"); @@ -22449,7 +22453,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int } else if (p->t38.state == T38_ENABLED) { ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); transmit_response_with_t38_sdp(p, "200 OK", req, (reinvite ? XMIT_RELIABLE : (req->ignore ? XMIT_UNRELIABLE : XMIT_CRITICAL))); - } else if (p->t38.state == T38_DISABLED) { + } else if ((p->t38.state == T38_DISABLED) || (p->t38.state == T38_REJECTED)) { /* If this is not a re-invite or something to ignore - it's critical */ if (p->srtp && !ast_test_flag(p->srtp, SRTP_CRYPTO_OFFER_OK)) { ast_log(LOG_WARNING, "Target does not support required crypto\n"); diff --git a/channels/sip/include/sip.h b/channels/sip/include/sip.h index 4c2d34264..b856a7f3e 100644 --- a/channels/sip/include/sip.h +++ b/channels/sip/include/sip.h @@ -594,7 +594,8 @@ enum t38state { T38_DISABLED = 0, /*!< Not enabled */ T38_LOCAL_REINVITE, /*!< Offered from local - REINVITE */ T38_PEER_REINVITE, /*!< Offered from peer - REINVITE */ - T38_ENABLED /*!< Negotiated (enabled) */ + T38_ENABLED, /*!< Negotiated (enabled) */ + T38_REJECTED /*!< Refused */ }; /*! \brief Parameters to know status of transfer */ diff --git a/res/res_fax.c b/res/res_fax.c index 4126cef5c..e323fba65 100644 --- a/res/res_fax.c +++ b/res/res_fax.c @@ -991,6 +991,7 @@ static int set_fax_t38_caps(struct ast_channel *chan, struct ast_fax_session_det case T38_STATE_UNKNOWN: details->caps |= AST_FAX_TECH_T38; break; + case T38_STATE_REJECTED: case T38_STATE_UNAVAILABLE: details->caps |= AST_FAX_TECH_AUDIO; break; @@ -1510,6 +1511,7 @@ static int receivefax_exec(struct ast_channel *chan, const char *data) ); struct ast_flags opts = { 0, }; struct manager_event_info info; + enum ast_t38_state t38state; /* initialize output channel variables */ pbx_builtin_setvar_helper(chan, "FAXSTATUS", "FAILED"); @@ -1631,7 +1633,8 @@ static int receivefax_exec(struct ast_channel *chan, const char *data) details->option.statusevents = AST_FAX_OPTFLAG_TRUE; } - if ((ast_channel_get_t38_state(chan) == T38_STATE_UNAVAILABLE) || + t38state = ast_channel_get_t38_state(chan); + if ((t38state == T38_STATE_UNAVAILABLE) || (t38state == T38_STATE_REJECTED) || ast_test_flag(&opts, OPT_ALLOWAUDIO) || ast_test_flag(&opts, OPT_FORCE_AUDIO)) { details->option.allow_audio = AST_FAX_OPTFLAG_TRUE; @@ -1972,6 +1975,7 @@ static int sendfax_exec(struct ast_channel *chan, const char *data) ); struct ast_flags opts = { 0, }; struct manager_event_info info; + enum ast_t38_state t38state; /* initialize output channel variables */ pbx_builtin_setvar_helper(chan, "FAXSTATUS", "FAILED"); @@ -2112,7 +2116,8 @@ static int sendfax_exec(struct ast_channel *chan, const char *data) details->option.statusevents = AST_FAX_OPTFLAG_TRUE; } - if ((ast_channel_get_t38_state(chan) == T38_STATE_UNAVAILABLE) || + t38state = ast_channel_get_t38_state(chan); + if ((t38state == T38_STATE_UNAVAILABLE) || (t38state == T38_STATE_REJECTED) || ast_test_flag(&opts, OPT_ALLOWAUDIO) || ast_test_flag(&opts, OPT_FORCE_AUDIO)) { details->option.allow_audio = AST_FAX_OPTFLAG_TRUE;