|
|
|
@ -18816,6 +18816,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
|
|
|
|
|
int gotdest;
|
|
|
|
|
const char *p_replaces;
|
|
|
|
|
char *replace_id = NULL;
|
|
|
|
|
int refer_locked = 0;
|
|
|
|
|
const char *required;
|
|
|
|
|
unsigned int required_profile = 0;
|
|
|
|
|
struct ast_channel *c = NULL; /* New channel */
|
|
|
|
@ -18856,7 +18857,8 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
|
|
|
|
|
p->invitestate = INV_COMPLETED;
|
|
|
|
|
if (!p->lastinvite)
|
|
|
|
|
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
|
|
|
|
|
return -1;
|
|
|
|
|
res = -1;
|
|
|
|
|
goto request_invite_cleanup;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -18883,7 +18885,8 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
|
|
|
|
|
transmit_response(p, "482 Loop Detected", req);
|
|
|
|
|
p->invitestate = INV_COMPLETED;
|
|
|
|
|
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
|
|
|
|
|
return 0;
|
|
|
|
|
res = 0;
|
|
|
|
|
goto request_invite_cleanup;
|
|
|
|
|
} else {
|
|
|
|
|
/*! This is a spiral. What we need to do is to just change the outgoing INVITE
|
|
|
|
|
* so that it now routes to the new Request URI. Since we created the INVITE ourselves
|
|
|
|
@ -18909,7 +18912,8 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
|
|
|
|
|
*/
|
|
|
|
|
ast_string_field_set(p->owner, call_forward, peerorhost);
|
|
|
|
|
ast_queue_control(p->owner, AST_CONTROL_BUSY);
|
|
|
|
|
return 0;
|
|
|
|
|
res = 0;
|
|
|
|
|
goto request_invite_cleanup;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -18947,7 +18951,8 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
|
|
|
|
|
transmit_response_reliable(p, "491 Request Pending", req);
|
|
|
|
|
ast_debug(1, "Got INVITE on call where we already have pending INVITE, deferring that - %s\n", p->callid);
|
|
|
|
|
/* Don't destroy dialog here */
|
|
|
|
|
return 0;
|
|
|
|
|
res = 0;
|
|
|
|
|
goto request_invite_cleanup;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -18964,7 +18969,8 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
|
|
|
|
|
ast_debug(3, "INVITE w Replaces on existing call? Refusing action. [%s]\n", p->callid);
|
|
|
|
|
transmit_response_reliable(p, "400 Bad request", req); /* The best way to not not accept the transfer */
|
|
|
|
|
/* Do not destroy existing call */
|
|
|
|
|
return -1;
|
|
|
|
|
res = -1;
|
|
|
|
|
goto request_invite_cleanup;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sipdebug)
|
|
|
|
@ -18977,7 +18983,8 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
|
|
|
|
|
append_history(p, "Xfer", "INVITE/Replace Failed. Out of memory.");
|
|
|
|
|
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
|
|
|
|
|
p->invitestate = INV_COMPLETED;
|
|
|
|
|
return -1;
|
|
|
|
|
res = -1;
|
|
|
|
|
goto request_invite_cleanup;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Todo: (When we find phones that support this)
|
|
|
|
@ -19040,6 +19047,8 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
|
|
|
|
|
ast_log(LOG_NOTICE, "Supervised transfer attempted to replace non-existent call id (%s)!\n", replace_id);
|
|
|
|
|
transmit_response_reliable(p, "481 Call Leg Does Not Exist (Replaces)", req);
|
|
|
|
|
error = 1;
|
|
|
|
|
} else {
|
|
|
|
|
refer_locked = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The matched call is the call from the transferer to Asterisk .
|
|
|
|
@ -19077,8 +19086,10 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
|
|
|
|
|
ast_channel_unlock(p->refer->refer_call->owner);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
refer_locked = 0;
|
|
|
|
|
p->invitestate = INV_COMPLETED;
|
|
|
|
|
return -1;
|
|
|
|
|
res = -1;
|
|
|
|
|
goto request_invite_cleanup;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -19121,7 +19132,8 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
|
|
|
|
|
transmit_response_reliable(p, "488 Not acceptable here", req);
|
|
|
|
|
if (!p->lastinvite)
|
|
|
|
|
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
|
|
|
|
|
return -1;
|
|
|
|
|
res = -1;
|
|
|
|
|
goto request_invite_cleanup;
|
|
|
|
|
}
|
|
|
|
|
ast_queue_control(p->owner, AST_CONTROL_SRCUPDATE);
|
|
|
|
|
} else {
|
|
|
|
@ -19142,7 +19154,8 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
|
|
|
|
|
res = check_user(p, req, SIP_INVITE, e, XMIT_RELIABLE, sin);
|
|
|
|
|
if (res == AUTH_CHALLENGE_SENT) {
|
|
|
|
|
p->invitestate = INV_COMPLETED; /* Needs to restart in another INVITE transaction */
|
|
|
|
|
return 0;
|
|
|
|
|
res = 0;
|
|
|
|
|
goto request_invite_cleanup;
|
|
|
|
|
}
|
|
|
|
|
if (res < 0) { /* Something failed in authentication */
|
|
|
|
|
if (res == AUTH_FAKE_AUTH) {
|
|
|
|
@ -19155,7 +19168,8 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
|
|
|
|
|
p->invitestate = INV_COMPLETED;
|
|
|
|
|
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
|
|
|
|
|
ast_string_field_set(p, theirtag, NULL);
|
|
|
|
|
return 0;
|
|
|
|
|
res = 0;
|
|
|
|
|
goto request_invite_cleanup;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If T38 is needed but not present, then make it magically appear */
|
|
|
|
@ -19172,7 +19186,8 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
|
|
|
|
|
p->invitestate = INV_COMPLETED;
|
|
|
|
|
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
|
|
|
|
|
ast_debug(1, "No compatible codecs for this SIP call.\n");
|
|
|
|
|
return -1;
|
|
|
|
|
res = -1;
|
|
|
|
|
goto request_invite_cleanup;
|
|
|
|
|
}
|
|
|
|
|
if (p->rtp) {
|
|
|
|
|
ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_CONSTANT_SSRC, ast_test_flag(&p->flags[1], SIP_PAGE2_CONSTANT_SSRC));
|
|
|
|
@ -19205,7 +19220,8 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
|
|
|
|
|
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
|
|
|
|
|
p->invitestate = INV_COMPLETED;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
res = 0;
|
|
|
|
|
goto request_invite_cleanup;
|
|
|
|
|
}
|
|
|
|
|
gotdest = get_destination(p, NULL); /* Get destination right away */
|
|
|
|
|
change_redirecting_information(p, req, &redirecting, FALSE); /*Will return immediately if no Diversion header is present */
|
|
|
|
@ -19232,7 +19248,8 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
|
|
|
|
|
p->invitestate = INV_COMPLETED;
|
|
|
|
|
update_call_counter(p, DEC_CALL_LIMIT);
|
|
|
|
|
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
|
|
|
|
|
return 0;
|
|
|
|
|
res = 0;
|
|
|
|
|
goto request_invite_cleanup;
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
/* If no extension was specified, use the s one */
|
|
|
|
@ -19292,7 +19309,8 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
|
|
|
|
|
if (!p->lastinvite) {
|
|
|
|
|
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
|
|
|
|
|
}
|
|
|
|
|
return -1;
|
|
|
|
|
res = -1;
|
|
|
|
|
goto request_invite_cleanup;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -19306,7 +19324,8 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
|
|
|
|
|
if (!p->lastinvite) {
|
|
|
|
|
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
|
|
|
|
|
}
|
|
|
|
|
return -1;
|
|
|
|
|
res = -1;
|
|
|
|
|
goto request_invite_cleanup;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -19320,7 +19339,8 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
|
|
|
|
|
if (!p->lastinvite) {
|
|
|
|
|
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
|
|
|
|
|
}
|
|
|
|
|
return -1;
|
|
|
|
|
res = -1;
|
|
|
|
|
goto request_invite_cleanup;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p->stimer->st_active_peer_ua = TRUE;
|
|
|
|
@ -19350,7 +19370,8 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
|
|
|
|
|
if (!p->lastinvite) {
|
|
|
|
|
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
|
|
|
|
|
}
|
|
|
|
|
return -1;
|
|
|
|
|
res = -1;
|
|
|
|
|
goto request_invite_cleanup;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
@ -19429,12 +19450,15 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
|
|
|
|
|
ast_hangup(c);
|
|
|
|
|
sip_pvt_lock(p); /* pvt is expected to remain locked on return, so re-lock it */
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
res = 0;
|
|
|
|
|
goto request_invite_cleanup;
|
|
|
|
|
} else {
|
|
|
|
|
/* Go and take over the target call */
|
|
|
|
|
if (sipdebug)
|
|
|
|
|
ast_debug(4, "Sending this call to the invite/replcaes handler %s\n", p->callid);
|
|
|
|
|
return handle_invite_replaces(p, req, debug, seqno, sin, nounlock);
|
|
|
|
|
res = handle_invite_replaces(p, req, debug, seqno, sin, nounlock);
|
|
|
|
|
refer_locked = 0;
|
|
|
|
|
goto request_invite_cleanup;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -19558,6 +19582,16 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
|
|
|
|
|
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
request_invite_cleanup:
|
|
|
|
|
|
|
|
|
|
if (refer_locked && p->refer && p->refer->refer_call) {
|
|
|
|
|
sip_pvt_unlock(p->refer->refer_call);
|
|
|
|
|
if (p->refer->refer_call->owner) {
|
|
|
|
|
ast_channel_unlock(p->refer->refer_call->owner);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|