Skip to content
Snippets Groups Projects
chan_sip.c 699 KiB
Newer Older
  • Learn to ignore specific revisions
  • 	ast_channel_unlock(c);
    	
    	if (earlyreplace || oneleggedreplace ) {
    		/* Force the masq to happen */
    		if ((f = ast_read(replacecall))) {	/* Force the masq to happen */
    			ast_frfree(f);
    			f = NULL;
    
    			ast_debug(4, "Invite/Replace:  Could successfully read frame from RING channel!\n");
    
    		} else {
    			ast_log(LOG_WARNING, "Invite/Replace:  Could not read frame from RING channel \n");
    		}
    		c->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
    
    		if (!oneleggedreplace)
    			ast_channel_unlock(replacecall);
    
    	} else {	/* Bridged call, UP channel */
    		if ((f = ast_read(replacecall))) {	/* Force the masq to happen */
    			/* Masq ok */
    			ast_frfree(f);
    			f = NULL;
    
    			ast_debug(3, "Invite/Replace:  Could successfully read frame from channel! Masq done.\n");
    
    		} else {
    			ast_log(LOG_WARNING, "Invite/Replace:  Could not read frame from channel. Transfer failed\n");
    		}
    		ast_channel_unlock(replacecall);
    	}
    
    	sip_pvt_unlock(p->refer->refer_call);
    
    	ast_debug(4, "After transfer:----------------------------\n");
    	ast_debug(4, " -- C:        %s State %s\n", c->name, ast_state2str(c->_state));
    	if (replacecall)
    		ast_debug(4, " -- replacecall:        %s State %s\n", replacecall->name, ast_state2str(replacecall->_state));
    	if (p->owner) {
    		ast_debug(4, " -- P->owner: %s State %s\n", p->owner->name, ast_state2str(p->owner->_state));
    		test = ast_bridged_channel(p->owner);
    		if (test)
    			ast_debug(4, " -- Call bridged to P->owner: %s State %s\n", test->name, ast_state2str(test->_state));
    		else
    			ast_debug(4, " -- No call bridged to C->owner \n");
    	} else 
    		ast_debug(4, " -- No channel yet \n");
    	ast_debug(4, "End After transfer:----------------------------\n");
    
    
    	ast_channel_unlock(p->owner);	/* Unlock new owner */
    
    	if (!oneleggedreplace)
    		sip_pvt_unlock(p);	/* Unlock SIP structure */
    
    
    	/* The call should be down with no ast_channel, so hang it up */
    
    	c->tech_pvt = dialog_unref(c->tech_pvt);
    
    	ast_hangup(c);
    	return 0;
    }
    
    
    /*! \brief Handle incoming INVITE request
    \note 	If the INVITE has a Replaces header, it is part of an
     *	attended transfer. If so, we do not go through the dial
     *	plan but tries to find the active call and masquerade
     *	into it 
     */
    
    static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int debug, int seqno, struct sockaddr_in *sin, int *recount, char *e, int *nounlock)
    
    	const char *p_replaces;
    	char *replace_id = NULL;
    
    	struct ast_channel *c = NULL;		/* New channel */
    
    	int reinvite = 0;
    
    
    	/* Find out what they support */
    	if (!p->sipoptions) {
    
    		const char *supported = get_header(req, "Supported");
    
    		if (!ast_strlen_zero(supported))
    
    
    	/* Find out what they require */
    
    Olle Johansson's avatar
    Olle Johansson committed
    	required = get_header(req, "Require");
    
    	if (!ast_strlen_zero(required)) {
    
    		required_profile = parse_sip_options(NULL, required);
    
    		if (required_profile && required_profile != SIP_OPT_REPLACES) {
    			/* At this point we only support REPLACES */
    			transmit_response_with_unsupported(p, "420 Bad extension (unsupported)", req, required);
    
    			ast_log(LOG_WARNING,"Received SIP INVITE with unsupported required extension: %s\n", required);
    
    			p->invitestate = INV_COMPLETED;
    
    				sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
    
    	if (ast_test_flag(&p->flags[0], SIP_OUTGOING) && p->owner && (p->owner->_state != AST_STATE_UP)) {
    
    		/* This is a call to ourself.  Send ourselves an error code and stop
    
    	   	processing immediately, as SIP really has no good mechanism for
    	   	being able to call yourself */
    		/* If pedantic is on, we need to check the tags. If they're different, this is
    	   	in fact a forked call through a SIP proxy somewhere. */
    
    		transmit_response(p, "482 Loop Detected", req);
    
    		p->invitestate = INV_COMPLETED;
    
    		sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
    
    	if (!req->ignore && p->pendinginvite) {
    
    		/* We already have a pending invite. Sorry. You are on hold. */
    		transmit_response(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 */
    
    	p_replaces = get_header(req, "Replaces");
    	if (!ast_strlen_zero(p_replaces)) {
    
    		/* We have a replaces header */
    		char *ptr;
    		char *fromtag = NULL;
    		char *totag = NULL;
    		char *start, *to;
    		int error = 0;
    
    		if (p->owner) {
    
    			ast_debug(3, "INVITE w Replaces on existing call? Refusing action. [%s]\n", p->callid);
    
    			transmit_response(p, "400 Bad request", req);	/* The best way to not not accept the transfer */
    			/* Do not destroy existing call */
    			return -1;
    		}
    
    
    		if (sipdebug)
    			ast_debug(3, "INVITE part of call transfer. Replaces [%s]\n", p_replaces);
    
    		/* Create a buffer we can manipulate */
    		replace_id = ast_strdupa(p_replaces);
    		ast_uri_decode(replace_id);
    
    		if (!p->refer && !sip_refer_allocate(p)) {
    			transmit_response(p, "500 Server Internal Error", req);
    			append_history(p, "Xfer", "INVITE/Replace Failed. Out of memory.");
    
    			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
    
    			p->invitestate = INV_COMPLETED;
    
    			return -1;
    		}
    
    		/*  Todo: (When we find phones that support this)
    			if the replaces header contains ";early-only"
    			we can only replace the call in early
    			stage, not after it's up.
    
    			If it's not in early mode, 486 Busy.
    		*/
    		
    		/* Skip leading whitespace */
    
    		replace_id = ast_skip_blanks(replace_id);
    
    		start = replace_id;
    		while ( (ptr = strsep(&start, ";")) ) {
    			ptr = ast_skip_blanks(ptr); /* XXX maybe unnecessary ? */
    			if ( (to = strcasestr(ptr, "to-tag=") ) )
    				totag = to + 7;	/* skip the keyword */
    			else if ( (to = strcasestr(ptr, "from-tag=") ) ) {
    				fromtag = to + 9;	/* skip the keyword */
    				fromtag = strsep(&fromtag, "&"); /* trim what ? */
    			}
    		}
    
    		if (sipdebug) 
    			ast_debug(4,"Invite/replaces: Will use Replace-Call-ID : %s Fromtag: %s Totag: %s\n", replace_id, fromtag ? fromtag : "<no from tag>", totag ? totag : "<no to tag>");
    
    
    
    		/* Try to find call that we are replacing 
    			If we have a Replaces  header, we need to cancel that call if we succeed with this call 
    		*/
    		if ((p->refer->refer_call = get_sip_pvt_byid_locked(replace_id, totag, fromtag)) == NULL) {
    			ast_log(LOG_NOTICE, "Supervised transfer attempted to replace non-existent call id (%s)!\n", replace_id);
    			transmit_response(p, "481 Call Leg Does Not Exist (Replaces)", req);
    			error = 1;
    		}
    
    		/* At this point, bot the pvt and the owner of the call to be replaced is locked */
    
    		/* The matched call is the call from the transferer to Asterisk .
    			We want to bridge the bridged part of the call to the 
    			incoming invite, thus taking over the refered call */
    
    		if (p->refer->refer_call == p) {
    			ast_log(LOG_NOTICE, "INVITE with replaces into it's own call id (%s == %s)!\n", replace_id, p->callid);
    
    			p->refer->refer_call = dialog_unref(p->refer->refer_call);
    
    			transmit_response(p, "400 Bad request", req);	/* The best way to not not accept the transfer */
    			error = 1;
    		}
    
    		if (!error && !p->refer->refer_call->owner) {
    			/* Oops, someting wrong anyway, no owner, no call */
    			ast_log(LOG_NOTICE, "Supervised transfer attempted to replace non-existing call id (%s)!\n", replace_id);
    			/* Check for better return code */
    			transmit_response(p, "481 Call Leg Does Not Exist (Replace)", req);
    			error = 1;
    		}
    
    
    		if (!error && p->refer->refer_call->owner->_state != AST_STATE_RINGING && p->refer->refer_call->owner->_state != AST_STATE_RING && p->refer->refer_call->owner->_state != AST_STATE_UP ) {
    
    			ast_log(LOG_NOTICE, "Supervised transfer attempted to replace non-ringing or active call id (%s)!\n", replace_id);
    			transmit_response(p, "603 Declined (Replaces)", req);
    			error = 1;
    		}
    
    		if (error) {	/* Give up this dialog */
    			append_history(p, "Xfer", "INVITE/Replace Failed.");
    
    			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
    
    				sip_pvt_unlock(p->refer->refer_call);
    
    				ast_channel_unlock(p->refer->refer_call->owner);
    			}
    
    			p->invitestate = INV_COMPLETED;
    
    			return -1;
    		}
    	}
    
    
    	/* Check if this is an INVITE that sets up a new dialog or
    	   a re-invite in an existing dialog */
    
    
    Olle Johansson's avatar
    Olle Johansson committed
    		int newcall = (p->initreq.headers ? TRUE : FALSE);
    
    
    		sip_cancel_destroy(p);
    		/* This also counts as a pending invite */
    		p->pendinginvite = seqno;
    		check_via(p, req);
    
    		copy_request(&p->initreq, req);		/* Save this INVITE as the transaction basis */
    
    		if (sipdebug)
    			ast_debug(1, "Initializing initreq for method %s - callid %s\n", sip_methods[req->method].text, p->callid);
    
    		if (!p->owner) {	/* Not a re-invite */
    			if (debug)
    				ast_verbose("Using INVITE request as basis request - %s\n", p->callid);
    
    Olle Johansson's avatar
    Olle Johansson committed
    			if (newcall)
    				append_history(p, "Invite", "New call: %s", p->callid);
    
    		} else {	/* Re-invite on existing call */
    
    			ast_clear_flag(&p->flags[0], SIP_OUTGOING);	/* This is now an inbound dialog */
    
    			/* Handle SDP here if we already have an owner */
    
    				if (process_sdp(p, req)) {
    					transmit_response(p, "488 Not acceptable here", req);
    
    						sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
    
    			} else {
    				p->jointcapability = p->capability;
    
    				ast_debug(1, "Hm....  No sdp for the moment\n");
    
    			if (p->do_history) /* This is a response, note what it was for */
    
    Olle Johansson's avatar
    Olle Johansson committed
    				append_history(p, "ReInv", "Re-invite received");
    
    		ast_verbose("Ignoring this INVITE request\n");
    
    	if (!p->lastinvite && !req->ignore && !p->owner) {
    
    		/* Handle authentication if this is our first invite */
    
    		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 */
    
    		if (res < 0) { /* Something failed in authentication */
    
    			if (res == AUTH_FAKE_AUTH) {
    				ast_log(LOG_NOTICE, "Sending fake auth rejection for user %s\n", get_header(req, "From"));
    				transmit_fake_auth_response(p, req, 1);
    			} else {
    
    				ast_log(LOG_NOTICE, "Failed to authenticate user %s\n", get_header(req, "From"));
    
    				transmit_response_reliable(p, "403 Forbidden", req);
    
    			p->invitestate = INV_COMPLETED;	
    
    			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
    
    			ast_string_field_set(p, theirtag, NULL);
    
    
    		/* We have a succesful authentication, process the SDP portion if there is one */
    
    				transmit_response_reliable(p, "488 Not acceptable here", req);
    
    				p->invitestate = INV_COMPLETED;	
    
    				sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
    
    				ast_debug(1, "No compatible codecs for this SIP call.\n");
    
    		} else {	/* No SDP in invite, call control session */
    
    			p->jointcapability = p->capability;
    
    			ast_debug(2, "No SDP in Invite, third party call control\n");
    
    		/* Queue NULL frame to prod ast_rtp_bridge if appropriate */
    
    		/* This seems redundant ... see !p-owner above */
    
    			ast_queue_frame(p->owner, &ast_null_frame);
    
    		/* Initialize the context if it hasn't been already */
    		if (ast_strlen_zero(p->context))
    
    			ast_string_field_set(p, context, default_context);
    
    		/* Check number of concurrent calls -vs- incoming limit HERE */
    
    		ast_debug(1, "Checking SIP call limits for device %s\n", p->username);
    
    		if ((res = update_call_counter(p, INC_CALL_LIMIT))) {
    
    				ast_log(LOG_NOTICE, "Failed to place call for user %s, too many calls\n", p->username);
    
    				transmit_response_reliable(p, "480 Temporarily Unavailable (Call limit) ", req);
    
    				sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
    
    				p->invitestate = INV_COMPLETED;	
    
    		gotdest = get_destination(p, NULL);	/* Get destination right away */
    		get_rdnis(p, NULL);			/* Get redirect information */
    		extract_uri(p, req);			/* Get the Contact URI */
    		build_contact(p);			/* Build our contact header */
    
    			ast_rtp_setdtmf(p->rtp, ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833);
    
    			ast_rtp_setdtmfcompensate(p->rtp, ast_test_flag(&p->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
    		}
    
    		if (!replace_id && gotdest) {	/* No matching extension found */
    
    			if (gotdest == 1 && ast_test_flag(&p->flags[1], SIP_PAGE2_ALLOWOVERLAP))
    
    Olle Johansson's avatar
    Olle Johansson committed
    				transmit_response_reliable(p, "484 Address Incomplete", req);
    
    Olle Johansson's avatar
    Olle Johansson committed
    				transmit_response_reliable(p, "404 Not Found", req);
    
    				ast_log(LOG_NOTICE, "Call from '%s' to extension"
    
    					" '%s' rejected because extension not found.\n",
    					S_OR(p->username, p->peername), p->exten);
    			}
    
    			p->invitestate = INV_COMPLETED;	
    
    			update_call_counter(p, DEC_CALL_LIMIT);
    
    			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
    
    			return 0;
    
    		} else {
    			/* If no extension was specified, use the s one */
    
    			/* Basically for calling to IP/Host name only */
    
    			if (ast_strlen_zero(p->exten))
    
    				ast_string_field_set(p, exten, "s");
    
    			/* First invitation - create the channel */
    
    			c = sip_new(p, AST_STATE_DOWN, S_OR(p->username, NULL));
    
    			/* Save Record-Route for any later requests we make on this dialogue */
    			build_route(p, req, 0);
    
    			if (c) {
    				/* Pre-lock the call */
    
    				ast_channel_lock(c);
    
    				ast_debug(2, "Got a SIP re-invite for call %s\n", p->callid);
    
    				ast_debug(2, "Got a SIP re-transmit of INVITE for call %s\n", p->callid);
    
    		reinvite = 1;
    
    
    	if (replace_id) { 	/* Attended transfer or call pickup - we're the target */
    		/* 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);
    
    	}
    
    
    	if (c) {	/* We have a call  -either a new call or an old one (RE-INVITE) */
    
    		switch(c->_state) {
    		case AST_STATE_DOWN:
    
    			ast_debug(2, "%s: New call is still down.... Trying... \n", c->name);
    
    			transmit_response(p, "100 Trying", req);
    
    			ast_setstate(c, AST_STATE_RING);
    
    			if (strcmp(p->exten, ast_pickup_ext())) {	/* Call to extension -start pbx on this call */
    
    				case AST_PBX_FAILED:
    					ast_log(LOG_WARNING, "Failed to start PBX :(\n");
    
    						transmit_response(p, "503 Unavailable", req);
    					else
    
    						transmit_response_reliable(p, "503 Unavailable", req);
    
    					break;
    				case AST_PBX_CALL_LIMIT:
    					ast_log(LOG_WARNING, "Failed to start PBX (call limit reached) \n");
    
    						transmit_response(p, "480 Temporarily Unavailable", req);
    					else
    
    						transmit_response_reliable(p, "480 Temporarily Unavailable", req);
    
    					/* Unlock locks so ast_hangup can do its magic */
    
    					ast_channel_unlock(c);
    
    			} else {	/* Pickup call in call group */
    
    				ast_channel_unlock(c);
    
    				if (ast_pickup_call(c)) {
    
    					ast_log(LOG_NOTICE, "Nothing to pick up for %s\n", p->callid);
    
    						transmit_response(p, "503 Unavailable", req);	/* OEJ - Right answer? */
    
    						transmit_response_reliable(p, "503 Unavailable", req);
    
    Olle Johansson's avatar
    Olle Johansson committed
    					sip_alreadygone(p);
    
    					/* Unlock locks so ast_hangup can do its magic */
    
    					c->hangupcause = AST_CAUSE_CALL_REJECTED;
    
    					ast_setstate(c, AST_STATE_DOWN);
    
    					c->hangupcause = AST_CAUSE_NORMAL_CLEARING;
    
    			}
    			break;
    		case AST_STATE_RING:
    			transmit_response(p, "100 Trying", req);
    
    			break;
    		case AST_STATE_RINGING:
    			transmit_response(p, "180 Ringing", req);
    
    			ast_debug(2, "%s: This call is UP.... \n", c->name);
    
    			transmit_response(p, "100 Trying", req);
    
    
    			if (p->t38.state == T38_PEER_REINVITE) {
    				struct ast_channel *bridgepeer = NULL;
    				struct sip_pvt *bridgepvt = NULL;
    				
    				if ((bridgepeer = ast_bridged_channel(p->owner))) {
    					/* We have a bridge, and this is re-invite to switchover to T38 so we send re-invite with T38 SDP, to other side of bridge*/
    					/*! XXX: we should also check here does the other side supports t38 at all !!! XXX */
    
    					if (IS_SIP_TECH(bridgepeer->tech)) {
    
    						bridgepvt = (struct sip_pvt*)bridgepeer->tech_pvt;
    						if (bridgepvt->t38.state == T38_DISABLED) {
    							if (bridgepvt->udptl) { /* If everything is OK with other side's udptl struct */
    								/* Send re-invite to the bridged channel */
    								sip_handle_t38_reinvite(bridgepeer, p, 1);
    							} else { /* Something is wrong with peers udptl struct */
    								ast_log(LOG_WARNING, "Strange... The other side of the bridge don't have udptl struct\n");
    
    								bridgepvt->t38.state = T38_DISABLED;
    
    								sip_pvt_unlock(bridgepvt);
    
    								ast_debug(2,"T38 state changed to %d on channel %s\n", bridgepvt->t38.state, bridgepeer->name);
    
    									transmit_response(p, "488 Not acceptable here", req);
    								else
    									transmit_response_reliable(p, "488 Not acceptable here", req);
    
    						} else {
    							/* The other side is already setup for T.38 most likely so we need to acknowledge this too */
    							transmit_response_with_t38_sdp(p, "200 OK", req, XMIT_CRITICAL);
    							p->t38.state = T38_ENABLED;
    
    							ast_debug(1, "T38 state changed to %d on channel %s\n", p->t38.state, p->owner ? p->owner->name : "<none>");
    
    						}
    					} else {
    						/* Other side is not a SIP channel */
    
    							transmit_response(p, "488 Not acceptable here", req);
    						else
    							transmit_response_reliable(p, "488 Not acceptable here", req);
    						p->t38.state = T38_DISABLED;
    
    						ast_debug(2,"T38 state changed to %d on channel %s\n", p->t38.state, p->owner ? p->owner->name : "<none>");
    
    
    						if (!p->lastinvite) /* Only destroy if this is *not* a re-invite */
    							sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
    
    					}
    				} else {
    					/* we are not bridged in a call */
    					transmit_response_with_t38_sdp(p, "200 OK", req, XMIT_CRITICAL);
    					p->t38.state = T38_ENABLED;
    
    					ast_debug(1,"T38 state changed to %d on channel %s\n", p->t38.state, p->owner ? p->owner->name : "<none>");
    
    				}
    			} else if (p->t38.state == T38_DISABLED) { /* Channel doesn't have T38 offered or enabled */
    
    				/* If we are bridged to a channel that has T38 enabled than this is a case of RTP re-invite after T38 session */
    				/* so handle it here (re-invite other party to RTP) */
    				struct ast_channel *bridgepeer = NULL;
    				struct sip_pvt *bridgepvt = NULL;
    				if ((bridgepeer = ast_bridged_channel(p->owner))) {
    
    					if (IS_SIP_TECH(bridgepeer->tech)) {
    
    						bridgepvt = (struct sip_pvt*)bridgepeer->tech_pvt;
    
    						if (bridgepvt->t38.state == T38_ENABLED) {
    							ast_log(LOG_WARNING, "RTP re-invite after T38 session not handled yet !\n");
    							/* Insted of this we should somehow re-invite the other side of the bridge to RTP */
    
    								transmit_response(p, "488 Not Acceptable Here (unsupported)", req);
    							else
    								transmit_response_reliable(p, "488 Not Acceptable Here (unsupported)", req);
    
    							sendok = FALSE;
    						} 
    						/* No bridged peer with T38 enabled*/
    
    				/* Respond to normal re-invite */
    
    					/* If this is not a re-invite or something to ignore - it's critical */
    
    					transmit_response_with_sdp(p, "200 OK", req, (reinvite || req->ignore) ?  XMIT_UNRELIABLE : XMIT_CRITICAL);
    
    			break;
    		default:
    			ast_log(LOG_WARNING, "Don't know how to handle INVITE in state %d\n", c->_state);
    			transmit_response(p, "100 Trying", req);
    
    		if (p && (p->autokillid == -1)) {
    
    			const char *msg;
    
    			if (!p->jointcapability)
    				msg = "488 Not Acceptable Here (codec error)";
    			else {
    
    				ast_log(LOG_NOTICE, "Unable to create/find SIP channel for this INVITE\n");
    
    				msg = "503 Unavailable";
    
    				transmit_response(p, msg, req);
    			else
    				transmit_response_reliable(p, msg, req);
    
    			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
    
    /*! \brief  Find all call legs and bridge transferee with target 
     *	called from handle_request_refer */
    
    static int local_attended_transfer(struct sip_pvt *transferer, struct sip_dual *current, struct sip_request *req, int seqno)
    
    {
    	struct sip_dual target;		/* Chan 1: Call from tranferer to Asterisk */
    					/* Chan 2: Call from Asterisk to target */
    	int res = 0;
    	struct sip_pvt *targetcall_pvt;
    
    	/* Check if the call ID of the replaces header does exist locally */
    	if (!(targetcall_pvt = get_sip_pvt_byid_locked(transferer->refer->replaces_callid, transferer->refer->replaces_callid_totag, 
    		transferer->refer->replaces_callid_fromtag))) {
    		if (transferer->refer->localtransfer) {
    			/* We did not find the refered call. Sorry, can't accept then */
    			transmit_response(transferer, "202 Accepted", req);
    			/* Let's fake a response from someone else in order
    		   	to follow the standard */
    			transmit_notify_with_sipfrag(transferer, seqno, "481 Call leg/transaction does not exist", TRUE);
    			append_history(transferer, "Xfer", "Refer failed");
    			ast_clear_flag(&transferer->flags[0], SIP_GOTREFER);	
    			transferer->refer->status = REFER_FAILED;
    			return -1;
    		}
    		/* Fall through for remote transfers that we did not find locally */
    
    		ast_debug(3, "SIP attended transfer: Not our call - generating INVITE with replaces\n");
    
    		return 0;
    	}
    
    	/* Ok, we can accept this transfer */
    	transmit_response(transferer, "202 Accepted", req);
    	append_history(transferer, "Xfer", "Refer accepted");
    	if (!targetcall_pvt->owner) {	/* No active channel */
    
    		ast_debug(4, "SIP attended transfer: Error: No owner of target call\n");
    
    		/* Cancel transfer */
    
    		transmit_notify_with_sipfrag(transferer, seqno, "503 Service Unavailable", TRUE);
    		append_history(transferer, "Xfer", "Refer failed");
    
    		ast_clear_flag(&transferer->flags[0], SIP_GOTREFER);
    
    		transferer->refer->status = REFER_FAILED;
    
    		sip_pvt_unlock(targetcall_pvt);
    
    		ast_channel_unlock(current->chan1);
    		return -1;
    	}
    
    
    	/* We have a channel, find the bridge */
    	target.chan1 = targetcall_pvt->owner;				/* Transferer to Asterisk */
    	target.chan2 = ast_bridged_channel(targetcall_pvt->owner);	/* Asterisk to target */
    
    	if (!target.chan2 || !(target.chan2->_state == AST_STATE_UP || target.chan2->_state == AST_STATE_RINGING) ) {
    		/* Wrong state of new channel */
    
    		if (target.chan2) 
    			ast_debug(4, "SIP attended transfer: Error: Wrong state of target call: %s\n", ast_state2str(target.chan2->_state));
    		else if (target.chan1->_state != AST_STATE_RING)
    			ast_debug(4, "SIP attended transfer: Error: No target channel\n");
    		else
    			ast_debug(4, "SIP attended transfer: Attempting transfer in ringing state\n");
    
    		if (current->chan2)	/* We have two bridges */
    
    			ast_debug(4, "SIP attended transfer: trying to bridge %s and %s\n", target.chan1->name, current->chan2->name);
    
    		else			/* One bridge, propably transfer of IVR/voicemail etc */
    
    			ast_debug(4, "SIP attended transfer: trying to make %s take over (masq) %s\n", target.chan1->name, current->chan1->name);
    
    	}
    
    	ast_set_flag(&transferer->flags[0], SIP_DEFER_BYE_ON_TRANSFER);	/* Delay hangup */
    
    	/* Perform the transfer */
    
    	manager_event(EVENT_FLAG_CALL, "Transfer", "TransferMethod: SIP\r\nTransferType: Attended\r\nChannel: %s\r\nUniqueid: %s\r\nSIP-Callid: %s\r\nTargetChannel: %s\r\nTargetUniqueid: %s\r\n",
    		transferer->owner->name,
    		transferer->owner->uniqueid,
    		transferer->callid,
    		target.chan1->name,
    		target.chan1->uniqueid);
    
    	res = attempt_transfer(current, &target);
    
    	sip_pvt_unlock(targetcall_pvt);
    
    		transmit_notify_with_sipfrag(transferer, seqno, "486 Busy Here", TRUE);
    
    		append_history(transferer, "Xfer", "Refer failed");
    
    		transferer->refer->status = REFER_FAILED;
    
    		if (targetcall_pvt->owner)
    			ast_channel_unlock(targetcall_pvt->owner);
    		/* Right now, we have to hangup, sorry. Bridge is destroyed */
    
    		if (res != -2)
    			ast_hangup(transferer->owner);
    
    		else
    			ast_clear_flag(&transferer->flags[0], SIP_DEFER_BYE_ON_TRANSFER);
    
    	} else {
    		/* Transfer succeeded! */
    
    		/* Tell transferer that we're done. */
    		transmit_notify_with_sipfrag(transferer, seqno, "200 OK", TRUE);
    		append_history(transferer, "Xfer", "Refer succeeded");
    		transferer->refer->status = REFER_200OK;
    		if (targetcall_pvt->owner) {
    
    			ast_debug(1, "SIP attended transfer: Unlocking channel %s\n", targetcall_pvt->owner->name);
    
    /*! \brief Handle incoming REFER request */
    
    /*! \page SIP_REFER SIP transfer Support (REFER)
    
    	REFER is used for call transfer in SIP. We get a REFER
    	to place a new call with an INVITE somwhere and then
    	keep the transferor up-to-date of the transfer. If the
    	transfer fails, get back on line with the orginal call. 
    
    	- REFER can be sent outside or inside of a dialog.
    	  Asterisk only accepts REFER inside of a dialog.
    
    	- If we get a replaces header, it is an attended transfer
    
    	\par Blind transfers
    	The transferor provides the transferee
    	with the transfer targets contact. The signalling between
    	transferer or transferee should not be cancelled, so the
    	call is recoverable if the transfer target can not be reached 
    	by the transferee.
    
    	In this case, Asterisk receives a TRANSFER from
    	the transferor, thus is the transferee. We should
    	try to set up a call to the contact provided
    	and if that fails, re-connect the current session.
    	If the new call is set up, we issue a hangup.
    	In this scenario, we are following section 5.2
    	in the SIP CC Transfer draft. (Transfer without
    	a GRUU)
    
    	\par Transfer with consultation hold
    	In this case, the transferor
    	talks to the transfer target before the transfer takes place.
    	This is implemented with SIP hold and transfer.
    	Note: The invite From: string could indicate a transfer.
    	(Section 6. Transfer with consultation hold)
    	The transferor places the transferee on hold, starts a call
    	with the transfer target to alert them to the impending
    	transfer, terminates the connection with the target, then
    	proceeds with the transfer (as in Blind transfer above)
    
    	\par Attended transfer
    	The transferor places the transferee
    	on hold, calls the transfer target to alert them,
    	places the target on hold, then proceeds with the transfer
    	using a Replaces header field in the Refer-to header. This
    	will force the transfee to send an Invite to the target,
    	with a replaces header that instructs the target to
    	hangup the call between the transferor and the target.
    	In this case, the Refer/to: uses the AOR address. (The same
    	URI that the transferee used to establish the session with
    	the transfer target (To: ). The Require: replaces header should
    	be in the INVITE to avoid the wrong UA in a forked SIP proxy
    	scenario to answer and have no call to replace with.
    
    	The referred-by header is *NOT* required, but if we get it,
    	can be copied into the INVITE to the transfer target to 
    	inform the target about the transferor
    
    	"Any REFER request has to be appropriately authenticated.".
    	
    	We can't destroy dialogs, since we want the call to continue.
    	
    	*/
    
    static int handle_request_refer(struct sip_pvt *p, struct sip_request *req, int debug, int seqno, int *nounlock)
    
    	struct sip_dual current;	/* Chan1: Call between asterisk and transferer */
    					/* Chan2: Call between asterisk and transferee */
    
    		ast_verbose("Call %s got a SIP call transfer from %s: (REFER)!\n", p->callid, ast_test_flag(&p->flags[0], SIP_OUTGOING) ? "callee" : "caller");
    
    
    	if (!p->owner) {
    		/* This is a REFER outside of an existing SIP dialog */
    		/* We can't handle that, so decline it */
    
    		ast_debug(3, "Call %s: Declined REFER, outside of dialog...\n", p->callid);
    
    		transmit_response(p, "603 Declined (No dialog)", req);
    
    			append_history(p, "Xfer", "Refer failed. Outside of dialog.");
    
    Olle Johansson's avatar
    Olle Johansson committed
    			sip_alreadygone(p);
    
    
    	/* Check if transfer is allowed from this device */
    	if (p->allowtransfer == TRANSFER_CLOSED ) {
    		/* Transfer not allowed, decline */
    		transmit_response(p, "603 Declined (policy)", req);
    		append_history(p, "Xfer", "Refer failed. Allowtransfer == closed.");
    		/* Do not destroy SIP session */
    		return 0;
    	}
    
    
    	if (!req->ignore && ast_test_flag(&p->flags[0], SIP_GOTREFER)) {
    
    		/* Already have a pending REFER */	
    		transmit_response(p, "491 Request pending", req);
    		append_history(p, "Xfer", "Refer failed. Request pending.");
    		return 0;
    	}
    
    	/* Allocate memory for call transfer data */
    	if (!p->refer && !sip_refer_allocate(p)) {
    		transmit_response(p, "500 Internal Server Error", req);
    		append_history(p, "Xfer", "Refer failed. Memory allocation error.");
    		return -3;
    	}
    
    	res = get_refer_info(p, req);	/* Extract headers */
    
    	p->refer->status = REFER_SENT;
    
    	if (res != 0) {
    		switch (res) {
    		case -2:	/* Syntax error */
    			transmit_response(p, "400 Bad Request (Refer-to missing)", req);
    			append_history(p, "Xfer", "Refer failed. Refer-to missing.");
    
    				ast_debug(1, "SIP transfer to black hole can't be handled (no refer-to: )\n");
    
    			break;
    		case -3:
    			transmit_response(p, "603 Declined (Non sip: uri)", req);
    			append_history(p, "Xfer", "Refer failed. Non SIP uri");
    
    				ast_debug(1, "SIP transfer to non-SIP uri denied\n");
    
    			break;
    		default:
    			/* Refer-to extension not found, fake a failed transfer */
    			transmit_response(p, "202 Accepted", req);
    			append_history(p, "Xfer", "Refer failed. Bad extension.");
    			transmit_notify_with_sipfrag(p, seqno, "404 Not found", TRUE);
    			ast_clear_flag(&p->flags[0], SIP_GOTREFER);	
    
    				ast_debug(1, "SIP transfer to bad extension: %s\n", p->refer->refer_to);
    
    	if (ast_strlen_zero(p->context))
    
    		ast_string_field_set(p, context, default_context);
    
    
    	/* If we do not support SIP domains, all transfers are local */
    	if (allow_external_domains && check_sip_domain(p->refer->refer_to_domain, NULL, 0)) {
    		p->refer->localtransfer = 1;
    
    		if (sipdebug)
    			ast_debug(3, "This SIP transfer is local : %s\n", p->refer->refer_to_domain);
    
    	} else if (AST_LIST_EMPTY(&domain_list) || check_sip_domain(p->refer->refer_to_domain, NULL, 0)) {
    		/* This PBX doesn't bother with SIP domains or domain is local, so this transfer is local */
    
    	} else if (sipdebug)
    
    			ast_debug(3, "This SIP transfer is to a remote SIP extension (remote domain %s)\n", p->refer->refer_to_domain);
    
    	
    	/* Is this a repeat of a current request? Ignore it */
    	/* Don't know what else to do right now. */
    
    		return res;
    
    	/* If this is a blind transfer, we have the following
    
    	channels to work with:
    	- chan1, chan2: The current call between transferer and transferee (2 channels)
    	- target_channel: A new call from the transferee to the target (1 channel)
    	We need to stay tuned to what happens in order to be able
    	to bring back the call to the transferer */
    
    
    	/* If this is a attended transfer, we should have all call legs within reach:
    
    	- chan1, chan2: The call between the transferer and transferee (2 channels)
    	- target_channel, targetcall_pvt: The call between the transferer and the target (2 channels)
    
    	We want to bridge chan2 with targetcall_pvt!
    	
    
    	The replaces call id in the refer message points
    	to the call leg between Asterisk and the transferer.
    	So we need to connect the target and the transferee channel
    	and hangup the two other channels silently 
    
    	If the target is non-local, the call ID could be on a remote
    	machine and we need to send an INVITE with replaces to the
    	target. We basically handle this as a blind transfer
    	and let the sip_call function catch that we need replaces
    	header in the INVITE.
    
    	*/
    
    
    	/* Get the transferer's channel */
    	current.chan1 = p->owner;
    
    	/* Find the other part of the bridge (2) - transferee */
    	current.chan2 = ast_bridged_channel(current.chan1);
    	
    
    	if (sipdebug)
    		ast_debug(3, "SIP %s transfer: Transferer channel %s, transferee channel %s\n", p->refer->attendedtransfer ? "attended" : "blind", current.chan1->name, current.chan2 ? current.chan2->name : "<none>");
    
    
    	if (!current.chan2 && !p->refer->attendedtransfer) {
    		/* No bridged channel, propably IVR or echo or similar... */
    		/* Guess we should masquerade or something here */
    		/* Until we figure it out, refuse transfer of such calls */
    
    		if (sipdebug)
    			ast_debug(3,"Refused SIP transfer on non-bridged channel.\n");
    
    		p->refer->status = REFER_FAILED;
    		append_history(p, "Xfer", "Refer failed. Non-bridged channel.");
    		transmit_response(p, "603 Declined", req);
    		return -1;
    	}
    
    
    		if (sipdebug)
    			ast_debug(4, "Got SIP transfer, applying to bridged peer '%s'\n", current.chan2->name);
    
    		ast_queue_control(current.chan1, AST_CONTROL_UNHOLD);
    
    
    	ast_set_flag(&p->flags[0], SIP_GOTREFER);	
    
    	/* Attended transfer: Find all call legs and bridge transferee with target*/
    	if (p->refer->attendedtransfer) {
    		if ((res = local_attended_transfer(p, &current, req, seqno)))
    			return res;	/* We're done with the transfer */
    		/* Fall through for remote transfers that we did not find locally */
    
    		if (sipdebug)
    			ast_debug(4, "SIP attended transfer: Still not our call - generating INVITE with replaces\n");
    
    		/* Fallthrough if we can't find the call leg internally */
    	}
    
    
    	/* Parking a call */
    	if (p->refer->localtransfer && !strcmp(p->refer->refer_to, ast_parking_ext())) {
    		/* Must release c's lock now, because it will not longer be accessible after the transfer! */
    		*nounlock = 1;
    		ast_channel_unlock(current.chan1);
    		copy_request(&current.req, req);
    		ast_clear_flag(&p->flags[0], SIP_GOTREFER);	
    		p->refer->status = REFER_200OK;
    		append_history(p, "Xfer", "REFER to call parking.");
    
    		manager_event(EVENT_FLAG_CALL, "Transfer", "TransferMethod: SIP\r\nTransferType: Blind\r\nChannel: %s\r\nUniqueid: %s\r\nSIP-Callid: %s\r\nTargetChannel: %s\r\nTargetUniqueid: %s\r\nTransferExten: %s\r\nTransfer2Parking: Yes\r\n",
    			current.chan1->name,
    			current.chan1->uniqueid,
    			p->callid,
    			current.chan2->name,
    			current.chan2->uniqueid,
    			p->refer->refer_to);
    
    		if (sipdebug)
    			ast_debug(4, "SIP transfer to parking: trying to park %s. Parked by %s\n", current.chan2->name, current.chan1->name);
    
    		sip_park(current.chan2, current.chan1, req, seqno);
    		return res;
    	} 
    
    	/* Blind transfers and remote attended xfers */
    	transmit_response(p, "202 Accepted", req);
    
    		ast_debug(3, "chan1->name: %s\n", current.chan1->name);
    
    		pbx_builtin_setvar_helper(current.chan1, "BLINDTRANSFER", current.chan2->name);
    	}
    	if (current.chan2) {
    
    		pbx_builtin_setvar_helper(current.chan2, "BLINDTRANSFER", current.chan1->name);
    
    		pbx_builtin_setvar_helper(current.chan2, "SIPDOMAIN", p->refer->refer_to_domain);
    		pbx_builtin_setvar_helper(current.chan2, "SIPTRANSFER", "yes");
    		/* One for the new channel */
    		pbx_builtin_setvar_helper(current.chan2, "_SIPTRANSFER", "yes");
    		/* Attended transfer to remote host, prepare headers for the INVITE */
    
    		if (p->refer->referred_by) 
    			pbx_builtin_setvar_helper(current.chan2, "_SIPTRANSFER_REFERER", p->refer->referred_by);
    
    	/* Generate a Replaces string to be used in the INVITE during attended transfer */
    
    	if (!ast_strlen_zero(p->refer->replaces_callid)) {
    
    		char tempheader[BUFSIZ];
    		snprintf(tempheader, sizeof(tempheader), "%s%s%s%s%s", p->refer->replaces_callid, 
    				p->refer->replaces_callid_totag ? ";to-tag=" : "", 
    				p->refer->replaces_callid_totag, 
    				p->refer->replaces_callid_fromtag ? ";from-tag=" : "",
    				p->refer->replaces_callid_fromtag);
    		if (current.chan2)
    
    			pbx_builtin_setvar_helper(current.chan2, "_SIPTRANSFER_REPLACES", tempheader);
    
    	}
    	/* Must release lock now, because it will not longer
    
    	   be accessible after the transfer! */
    
    	*nounlock = 1;
    	ast_channel_unlock(current.chan1);
    
    	/* Connect the call */
    
    	/* FAKE ringing if not attended transfer */
    	if (!p->refer->attendedtransfer)
    
    		transmit_notify_with_sipfrag(p, seqno, "183 Ringing", FALSE); 
    
    		
    	/* For blind transfer, this will lead to a new call */
    	/* For attended transfer to remote host, this will lead to
    
    	   a new SIP call with a replaces header, if the dial plan allows it 
    	*/
    
    	if (!current.chan2) {
    		/* We have no bridge, so we're talking with Asterisk somehow */
    		/* We need to masquerade this call */
    		/* What to do to fix this situation:
    		   * Set up the new call in a new channel 
    		   * Let the new channel masq into this channel
    		   Please add that code here :-)
    		*/
    		p->refer->status = REFER_FAILED;
    		transmit_notify_with_sipfrag(p, seqno, "503 Service Unavailable (can't handle one-legged xfers)", TRUE);
    		ast_clear_flag(&p->flags[0], SIP_GOTREFER);	
    		append_history(p, "Xfer", "Refer failed (only bridged calls).");
    		return -1;
    	}
    	ast_set_flag(&p->flags[0], SIP_DEFER_BYE_ON_TRANSFER);	/* Delay hangup */
    
    
    	/* For blind transfers, move the call to the new extensions. For attended transfers on multiple
    	   servers - generate an INVITE with Replaces. Either way, let the dial plan decided  */
    	res = ast_async_goto(current.chan2, p->refer->refer_to_context, p->refer->refer_to, 1);
    
    	if (!res) {
    
    		manager_event(EVENT_FLAG_CALL, "Transfer", "TransferMethod: SIP\r\nTransferType: Blind\r\nChannel: %s\r\nUniqueid: %s\r\nSIP-Callid: %s\r\nTargetChannel: %s\r\nTargetUniqueid: %s\r\nTransferExten: %s\r\nTransferContext: %s\r\n",
    			current.chan1->name,
    			current.chan1->uniqueid,
    			p->callid,
    			current.chan2->name,
    			current.chan2->uniqueid,
    			p->refer->refer_to, p->refer->refer_to_context);
    
    		/* Success  - we have a new channel */
    
    		ast_debug(3, "%s transfer succeeded. Telling transferer.\n", p->refer->attendedtransfer? "Attended" : "Blind");
    
    		transmit_notify_with_sipfrag(p, seqno, "200 Ok", TRUE);
    		if (p->refer->localtransfer)
    			p->refer->status = REFER_200OK;
    		if (p->owner)
    			p->owner->hangupcause = AST_CAUSE_NORMAL_CLEARING;