mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-29 15:36:13 +00:00
Timout or error on INFO or MESSAGE transaction causes call to be lost.
When exchanging INFO messages within a call, 4xx error causes the call to be disconnected although RFC 2976 explicitly states that such transactions do not modify the state of the dialog. When exchanging MESSAGE messages within a call, 4xx error causes the call to be disconnected. To provide least surprise, we should not disconnect the call since a MESSAGE is like INFO in this case. (Implied by RFC 3428 Section 2) (closes issue ASTERISK-17901) Reported by: neutrino88 Review: https://reviewboard.asterisk.org/r/1257/ Review: https://reviewboard.asterisk.org/r/1258/ JIRA SWP-3486 git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.8@324481 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -20100,6 +20100,83 @@ static void handle_response_peerpoke(struct sip_pvt *p, int resp, struct sip_req
|
|||||||
ref_peer(peer, "adding poke peer ref"));
|
ref_peer(peer, "adding poke peer ref"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \internal
|
||||||
|
* \brief Handle responses to INFO messages
|
||||||
|
*
|
||||||
|
* \note The INFO method MUST NOT change the state of calls or
|
||||||
|
* related sessions (RFC 2976).
|
||||||
|
*/
|
||||||
|
static void handle_response_info(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno)
|
||||||
|
{
|
||||||
|
int sipmethod = SIP_INFO;
|
||||||
|
|
||||||
|
switch (resp) {
|
||||||
|
case 401: /* Not www-authorized on SIP method */
|
||||||
|
case 407: /* Proxy auth required */
|
||||||
|
ast_log(LOG_WARNING, "Host '%s' requests authentication (%d) for '%s'\n",
|
||||||
|
ast_sockaddr_stringify(&p->sa), resp, sip_methods[sipmethod].text);
|
||||||
|
break;
|
||||||
|
case 405: /* Method not allowed */
|
||||||
|
case 501: /* Not Implemented */
|
||||||
|
mark_method_unallowed(&p->allowed_methods, sipmethod);
|
||||||
|
if (p->relatedpeer) {
|
||||||
|
mark_method_allowed(&p->relatedpeer->disallowed_methods, sipmethod);
|
||||||
|
}
|
||||||
|
ast_log(LOG_WARNING, "Host '%s' does not implement '%s'\n",
|
||||||
|
ast_sockaddr_stringify(&p->sa), sip_methods[sipmethod].text);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (300 <= resp && resp < 700) {
|
||||||
|
ast_verb(3, "Got SIP %s response %d \"%s\" back from host '%s'\n",
|
||||||
|
sip_methods[sipmethod].text, resp, rest, ast_sockaddr_stringify(&p->sa));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \internal
|
||||||
|
* \brief Handle responses to MESSAGE messages
|
||||||
|
*
|
||||||
|
* \note The MESSAGE method should not change the state of calls
|
||||||
|
* or related sessions if associated with a dialog. (Implied by
|
||||||
|
* RFC 3428 Section 2).
|
||||||
|
*/
|
||||||
|
static void handle_response_message(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno)
|
||||||
|
{
|
||||||
|
int sipmethod = SIP_MESSAGE;
|
||||||
|
/* Out-of-dialog MESSAGE currently not supported. */
|
||||||
|
//int in_dialog = ast_test_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
|
||||||
|
|
||||||
|
switch (resp) {
|
||||||
|
case 401: /* Not www-authorized on SIP method */
|
||||||
|
case 407: /* Proxy auth required */
|
||||||
|
ast_log(LOG_WARNING, "Host '%s' requests authentication (%d) for '%s'\n",
|
||||||
|
ast_sockaddr_stringify(&p->sa), resp, sip_methods[sipmethod].text);
|
||||||
|
break;
|
||||||
|
case 405: /* Method not allowed */
|
||||||
|
case 501: /* Not Implemented */
|
||||||
|
mark_method_unallowed(&p->allowed_methods, sipmethod);
|
||||||
|
if (p->relatedpeer) {
|
||||||
|
mark_method_allowed(&p->relatedpeer->disallowed_methods, sipmethod);
|
||||||
|
}
|
||||||
|
ast_log(LOG_WARNING, "Host '%s' does not implement '%s'\n",
|
||||||
|
ast_sockaddr_stringify(&p->sa), sip_methods[sipmethod].text);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (100 <= resp && resp < 200) {
|
||||||
|
/* Must allow provisional responses for out-of-dialog requests. */
|
||||||
|
} else if (200 <= resp && resp < 300) {
|
||||||
|
p->authtries = 0; /* Reset authentication counter */
|
||||||
|
} else if (300 <= resp && resp < 700) {
|
||||||
|
ast_verb(3, "Got SIP %s response %d \"%s\" back from host '%s'\n",
|
||||||
|
sip_methods[sipmethod].text, resp, rest, ast_sockaddr_stringify(&p->sa));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*! \brief Immediately stop RTP, VRTP and UDPTL as applicable */
|
/*! \brief Immediately stop RTP, VRTP and UDPTL as applicable */
|
||||||
static void stop_media_flows(struct sip_pvt *p)
|
static void stop_media_flows(struct sip_pvt *p)
|
||||||
{
|
{
|
||||||
@@ -20220,6 +20297,12 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc
|
|||||||
* we just always call the response handler. Good gravy!
|
* we just always call the response handler. Good gravy!
|
||||||
*/
|
*/
|
||||||
handle_response_publish(p, resp, rest, req, seqno);
|
handle_response_publish(p, resp, rest, req, seqno);
|
||||||
|
} else if (sipmethod == SIP_INFO) {
|
||||||
|
/* More good gravy! */
|
||||||
|
handle_response_info(p, resp, rest, req, seqno);
|
||||||
|
} else if (sipmethod == SIP_MESSAGE) {
|
||||||
|
/* More good gravy! */
|
||||||
|
handle_response_message(p, resp, rest, req, seqno);
|
||||||
} else if (ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
|
} else if (ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
|
||||||
switch(resp) {
|
switch(resp) {
|
||||||
case 100: /* 100 Trying */
|
case 100: /* 100 Trying */
|
||||||
@@ -20233,11 +20316,7 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc
|
|||||||
break;
|
break;
|
||||||
case 200: /* 200 OK */
|
case 200: /* 200 OK */
|
||||||
p->authtries = 0; /* Reset authentication counter */
|
p->authtries = 0; /* Reset authentication counter */
|
||||||
if (sipmethod == SIP_MESSAGE || sipmethod == SIP_INFO) {
|
if (sipmethod == SIP_INVITE) {
|
||||||
/* We successfully transmitted a message
|
|
||||||
or a video update request in INFO */
|
|
||||||
/* Nothing happens here - the message is inside a dialog */
|
|
||||||
} else if (sipmethod == SIP_INVITE) {
|
|
||||||
handle_response_invite(p, resp, rest, req, seqno);
|
handle_response_invite(p, resp, rest, req, seqno);
|
||||||
} else if (sipmethod == SIP_NOTIFY) {
|
} else if (sipmethod == SIP_NOTIFY) {
|
||||||
handle_response_notify(p, resp, rest, req, seqno);
|
handle_response_notify(p, resp, rest, req, seqno);
|
||||||
@@ -20429,14 +20508,13 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* Send hangup */
|
/* Send hangup */
|
||||||
if (owner && sipmethod != SIP_MESSAGE && sipmethod != SIP_INFO && sipmethod != SIP_BYE)
|
if (owner && sipmethod != SIP_BYE)
|
||||||
ast_queue_hangup_with_cause(p->owner, AST_CAUSE_PROTOCOL_ERROR);
|
ast_queue_hangup_with_cause(p->owner, AST_CAUSE_PROTOCOL_ERROR);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* ACK on invite */
|
/* ACK on invite */
|
||||||
if (sipmethod == SIP_INVITE)
|
if (sipmethod == SIP_INVITE)
|
||||||
transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE);
|
transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE);
|
||||||
if (sipmethod != SIP_MESSAGE && sipmethod != SIP_INFO)
|
|
||||||
sip_alreadygone(p);
|
sip_alreadygone(p);
|
||||||
if (!p->owner) {
|
if (!p->owner) {
|
||||||
pvt_set_needdestroy(p, "transaction completed");
|
pvt_set_needdestroy(p, "transaction completed");
|
||||||
@@ -20498,10 +20576,6 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc
|
|||||||
}
|
}
|
||||||
} else if (sipmethod == SIP_BYE) {
|
} else if (sipmethod == SIP_BYE) {
|
||||||
pvt_set_needdestroy(p, "transaction completed");
|
pvt_set_needdestroy(p, "transaction completed");
|
||||||
} else if (sipmethod == SIP_MESSAGE || sipmethod == SIP_INFO) {
|
|
||||||
/* We successfully transmitted a message or
|
|
||||||
a video update request in INFO */
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 401: /* www-auth */
|
case 401: /* www-auth */
|
||||||
|
|||||||
Reference in New Issue
Block a user