Skip to content
Snippets Groups Projects
chan_sip.c 586 KiB
Newer Older
  • Learn to ignore specific revisions
  • 	transferee = d->chan1;
    	transferer = d->chan2;
    
    	if (!transferee || !transferer) {
    		ast_log(LOG_ERROR, "Missing channels for parking! Transferer %s Transferee %s\n", transferer ? "<available>" : "<missing>", transferee ? "<available>" : "<missing>" );
    
    	if (option_debug > 3) 
    		ast_log(LOG_DEBUG, "SIP Park: Transferer channel %s, Transferee %s\n", transferer->name, transferee->name);
    
    
    	ast_channel_lock(transferee);
    	if (ast_do_masquerade(transferee)) {
    		ast_log(LOG_WARNING, "Masquerade failed.\n");
    		transmit_response(transferer->tech_pvt, "503 Internal error", &req);
    		ast_channel_unlock(transferee);
    		return NULL;
    	} 
    	ast_channel_unlock(transferee);
    
    	res = ast_park_call(transferee, transferer, 0, &ext);
    
    
    #ifdef WHEN_WE_KNOW_THAT_THE_CLIENT_SUPPORTS_MESSAGE
    	if (!res) {
    		transmit_message_with_text(transferer->tech_pvt, "Unable to park call.\n");
    	} else {
    		/* Then tell the transferer what happened */
    		sprintf(buf, "Call parked on extension '%d'", ext);
    		transmit_message_with_text(transferer->tech_pvt, buf);
    	}
    #endif
    
    	/* Any way back to the current call??? */
    
    	/* Transmit response to the REFER request */
    
    	transmit_response(transferer->tech_pvt, "202 Accepted", &req);
    	if (!res)	{
    		/* Transfer succeeded */
    
    		append_history(transferer->tech_pvt, "SIPpark","Parked call on %d", ext);
    
    		transmit_notify_with_sipfrag(transferer->tech_pvt, d->seqno, "200 OK", TRUE);
    
    		transferer->hangupcause = AST_CAUSE_NORMAL_CLEARING;
    		ast_hangup(transferer); /* This will cause a BYE */
    		if (option_debug)
    			ast_log(LOG_DEBUG, "SIP Call parked on extension '%d'\n", ext);
    	} else {
    
    		transmit_notify_with_sipfrag(transferer->tech_pvt, d->seqno, "503 Service Unavailable", TRUE);
    
    		append_history(transferer->tech_pvt, "SIPpark","Parking failed\n");
    
    		if (option_debug)
    			ast_log(LOG_DEBUG, "SIP Call parked failed \n");
    		/* Do not hangup call */
    	}
    
    /*! \brief Park a call using the subsystem in res_features.c 
    	This is executed in a separate thread
    */
    
    static int sip_park(struct ast_channel *chan1, struct ast_channel *chan2, struct sip_request *req, int seqno)
    
    	struct ast_channel *transferee, *transferer;
    		/* Chan2m: The transferer, chan1m: The transferee */
    
    
    	transferee = ast_channel_alloc(0);
    	transferer = ast_channel_alloc(0);
    	if ((!transferer) || (!transferee)) {
    		if (transferee) {
    			transferee->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
    			ast_hangup(transferee);
    
    		if (transferer) {
    			transferer->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
    			ast_hangup(transferer);
    
    	ast_string_field_build(transferee, name,  "Parking/%s", chan1->name);
    
    
    	/* Make formats okay */
    
    	transferee->readformat = chan1->readformat;
    	transferee->writeformat = chan1->writeformat;
    
    
    	/* Prepare for taking over the channel */
    
    	ast_channel_masquerade(transferee, chan1);
    
    
    	/* Setup the extensions and such */
    
    	ast_copy_string(transferee->context, chan1->context, sizeof(transferee->context));
    	ast_copy_string(transferee->exten, chan1->exten, sizeof(transferee->exten));
    	transferee->priority = chan1->priority;
    
    		
    	/* We make a clone of the peer channel too, so we can play
    	   back the announcement */
    
    	ast_string_field_build(transferer, name, "SIPPeer/%s", chan2->name);
    
    
    	/* Make formats okay */
    
    	transferer->readformat = chan2->readformat;
    	transferer->writeformat = chan2->writeformat;
    
    
    	/* Prepare for taking over the channel */
    
    	ast_channel_masquerade(transferer, chan2);
    
    
    	/* Setup the extensions and such */
    
    	ast_copy_string(transferer->context, chan2->context, sizeof(transferer->context));
    	ast_copy_string(transferer->exten, chan2->exten, sizeof(transferer->exten));
    	transferer->priority = chan2->priority;
    
    	ast_channel_lock(transferer);
    	if (ast_do_masquerade(transferer)) {
    
    		ast_log(LOG_WARNING, "Masquerade failed :(\n");
    
    		ast_channel_unlock(transferer);
    		transferer->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
    		ast_hangup(transferer);
    
    	ast_channel_unlock(transferer);
    
    	if (!transferer || !transferee) {
    		if (!transferer)
    			ast_log(LOG_DEBUG, "No transferer channel, giving up parking\n");
    		if (!transferee)
    			ast_log(LOG_DEBUG, "No transferee channel, giving up parking\n");
    		return -1;
    	}
    
    	if ((d = ast_calloc(1, sizeof(*d)))) {
    
    		/* Save original request for followup */
    		copy_request(&d->req, req);
    
    		d->chan1 = transferee;	/* Transferee */
    		d->chan2 = transferer;	/* Transferer */
    		d->seqno = seqno;
    
    		if (ast_pthread_create(&th, NULL, sip_park_thread, d) < 0) {
    			/* Could not start thread */
    
    			free(d);	/* We don't need it anymore. If thread is created, d will be free'd
    					   by sip_park_thread() */
    
    /*! \brief Turn off generator data 
    	XXX Does this function belong in the SIP channel?
    */
    
    static void ast_quiet_chan(struct ast_channel *chan) 
    {
    	if (chan && chan->_state == AST_STATE_UP) {
    		if (chan->generatordata)
    
    			ast_deactivate_generator(chan);
    	}
    }
    
    /*! \brief Attempt transfer of SIP call 
    	This fix for attended transfers on a local PBX */
    static int attempt_transfer(struct sip_dual *transferer, struct sip_dual *target)
    
    	struct ast_channel *peera = NULL,	
    
    		*peerc = NULL,
    		*peerd = NULL;
    
    
    	/* We will try to connect the transferee with the target and hangup
       	all channels to the transferer */	
    	if (option_debug > 3) {
    		ast_log(LOG_DEBUG, "Sip transfer:--------------------\n");
    		if (transferer->chan1)
    			ast_log(LOG_DEBUG, "-- Transferer to PBX channel: %s State %s\n", transferer->chan1->name, ast_state2str(transferer->chan1->_state));
    		else
    			ast_log(LOG_DEBUG, "-- No transferer first channel - odd??? \n");
    		if (target->chan1)
    			ast_log(LOG_DEBUG, "-- Transferer to PBX second channel (target): %s State %s\n", target->chan1->name, ast_state2str(target->chan1->_state));
    		else
    			ast_log(LOG_DEBUG, "-- No target first channel ---\n");
    		if (transferer->chan2)
    			ast_log(LOG_DEBUG, "-- Bridged call to transferee: %s State %s\n", transferer->chan2->name, ast_state2str(transferer->chan2->_state));
    		else
    			ast_log(LOG_DEBUG, "-- No bridged call to transferee\n");
    		if (target->chan2)
    			ast_log(LOG_DEBUG, "-- Bridged call to transfer target: %s State %s\n", target->chan2 ? target->chan2->name : "<none>", target->chan2 ? ast_state2str(target->chan2->_state) : "(none)");
    		else
    			ast_log(LOG_DEBUG, "-- No target second channel ---\n");
    		ast_log(LOG_DEBUG, "-- END Sip transfer:--------------------\n");
    	}
    	if (transferer->chan2) {			/* We have a bridge on the transferer's channel */
    		peera = transferer->chan1;	/* Transferer - PBX -> transferee channel * the one we hangup */
    		peerb = target->chan1;		/* Transferer - PBX -> target channel - This will get lost in masq */
    		peerc = transferer->chan2;	/* Asterisk to Transferee */
    		peerd = target->chan2;		/* Asterisk to Target */
    		if (option_debug > 2)
    			ast_log(LOG_DEBUG, "SIP transfer: Four channels to handle\n");
    	} else if (target->chan2) {	/* Transferer has no bridge (IVR), but transferee */
    		peera = target->chan1;		/* Transferer to PBX -> target channel */
    		peerb = transferer->chan1;	/* Transferer to IVR*/
    		peerc = target->chan2;		/* Asterisk to Target */
    		peerd = transferer->chan2;	/* Nothing */
    		if (option_debug > 2)
    			ast_log(LOG_DEBUG, "SIP transfer: Three channels to handle\n");
    
    	if (peera && peerb && peerc && (peerb != peerc)) {
    
    		ast_quiet_chan(peera);		/* Stop generators */
    		ast_quiet_chan(peerb);	
    
    		ast_quiet_chan(peerc);
    
    		/* Fix CDRs so they're attached to the remaining channel */
    		if (peera->cdr && peerb->cdr)
    
    			peerb->cdr = ast_cdr_append(peerb->cdr, peera->cdr);
    
    			peerb->cdr = peera->cdr;
    		peera->cdr = NULL;
    
    
    			peerb->cdr = ast_cdr_append(peerb->cdr, peerc->cdr);
    
    			peerb->cdr = peerc->cdr;
    		peerc->cdr = NULL;
    
    	
    		if (option_debug > 3)
    			ast_log(LOG_DEBUG, "SIP transfer: trying to masquerade %s into %s\n", peerc->name, peerb->name);
    
    		if (ast_channel_masquerade(peerb, peerc)) {
    			ast_log(LOG_WARNING, "Failed to masquerade %s into %s\n", peerb->name, peerc->name);
    
    		} else
    			ast_log(LOG_DEBUG, "SIP transfer: Succeeded to masquerade channels.\n");
    
    		ast_log(LOG_NOTICE, "SIP Transfer attempted with no appropriate bridged calls to transfer\n");
    		if (transferer->chan1)
    			ast_softhangup_nolock(transferer->chan1, AST_SOFTHANGUP_DEV);
    		if (target->chan1)
    			ast_softhangup_nolock(target->chan1, AST_SOFTHANGUP_DEV);
    
    /*! \brief Get tag from packet 
     *
     * \return Returns the pointer to the provided tag buffer,
     *         or NULL if the tag was not found.
     */
    
    static const char *gettag(const struct sip_request *req, const char *header, char *tagbuf, int tagbufsize)
    
    
    	if (!tagbuf)
    		return NULL;
    	tagbuf[0] = '\0'; 	/* reset the buffer */
    	thetag = get_header(req, header);
    	thetag = strcasestr(thetag, ";tag=");
    	if (thetag) {
    		thetag += 5;
    		ast_copy_string(tagbuf, thetag, tagbufsize);
    
    		return strsep(&tagbuf, ";");
    
    /*! \brief Handle incoming notifications */
    
    static int handle_request_notify(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, int seqno, char *e)
    
    {
    	/* This is mostly a skeleton for future improvements */
    	/* Mostly created to return proper answers on notifications on outbound REFER's */
    	int res = 0;
    
    	const char *event = get_header(req, "Event");
    
    	if( (sep = strchr(event, ';')) ) {	/* XXX bug here - overwriting string ? */
    
    	}
    	
    	if (option_debug > 1 && sipdebug)
    		ast_log(LOG_DEBUG, "Got NOTIFY Event: %s\n", event);
    
    	if (strcmp(event, "refer")) {
    		/* We don't understand this event. */
    		/* Here's room to implement incoming voicemail notifications :-) */
    		transmit_response(p, "489 Bad event", req);
    		if (!p->lastinvite) 
    			ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);	
    		return -1;
    	} else {
    
    		/* Save nesting depth for now, since there might be other events we will
    			support in the future */
    
    		/* Handle REFER notifications */
    
    		char buf[1024];
    		char *cmd, *code;
    		int respcode;
    		int success = TRUE;
    
    		/* EventID for each transfer... EventID is basically the REFER cseq 
    
    		 We are getting notifications on a call that we transfered
    		 We should hangup when we are getting a 200 OK in a sipfrag
    		 Check if we have an owner of this event */
    		
    		/* Check the content type */
    		if (strncasecmp(get_header(req, "Content-Type"), "message/sipfrag", strlen("message/sipfrag"))) {
    			/* We need a sipfrag */
    			transmit_response(p, "400 Bad request", req);
    			ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);	
    			return -1;
    		}
    
    		/* Get the text of the attachment */
    		if (get_msg_text(buf, sizeof(buf), req)) {
    			ast_log(LOG_WARNING, "Unable to retrieve attachment from NOTIFY %s\n", p->callid);
    			transmit_response(p, "400 Bad request", req);
    			ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);	
    			return -1;
    		}
    
    		/*
    		From the RFC...
    		A minimal, but complete, implementation can respond with a single
       		NOTIFY containing either the body:
          			SIP/2.0 100 Trying
    		
       		if the subscription is pending, the body:
          			SIP/2.0 200 OK
       		if the reference was successful, the body:
          			SIP/2.0 503 Service Unavailable
       		if the reference failed, or the body:
          			SIP/2.0 603 Declined
    
       		if the REFER request was accepted before approval to follow the
       		reference could be obtained and that approval was subsequently denied
       		(see Section 2.4.7).
    		
    		If there are several REFERs in the same dialog, we need to
    		match the ID of the event header...
    		*/
    		if (option_debug > 2)
    			ast_log(LOG_DEBUG, "* SIP Transfer NOTIFY Attachment: \n---%s\n---\n", buf);
    
    		cmd = ast_skip_blanks(buf);
    
    		code = cmd;
    		/* We are at SIP/2.0 */
    		while(*code && (*code > 32)) {	/* Search white space */
    			code++;
    		}
    
    		*code++ = '\0';
    		code = ast_skip_blanks(code);
    
    		sep = code;
    		sep++;
    		while(*sep && (*sep > 32)) {	/* Search white space */
    			sep++;
    		}
    
    		*sep++ = '\0';			/* Response string */
    
    		respcode = atoi(code);
    		switch (respcode) {
    		case 100:	/* Trying: */
    			/* Don't do anything yet */
    			break;
    		case 183:	/* Ringing: */
    			/* Don't do anything yet */
    			break;
    		case 200:	/* OK: The new call is up, hangup this call */
    			/* Hangup the call that we are replacing */
    			break;
    		case 301: /* Moved permenantly */
    		case 302: /* Moved temporarily */
    			/* Do we get the header in the packet in this case? */
    			success = FALSE;
    			break;
    		case 503:	/* Service Unavailable: The new call failed */
    				/* Cancel transfer, continue the call */
    			success = FALSE;
    			break;
    		case 603:	/* Declined: Not accepted */
    				/* Cancel transfer, continue the current call */
    			success = FALSE;
    			break;
    		}
    		if (!success) {
    			ast_log(LOG_NOTICE, "Transfer failed. Sorry. Nothing further to do with this call\n");
    		}
    		
    		/* Confirm that we received this packet */
    		transmit_response(p, "200 OK", req);
    		return res;
    	};
    }
    
    
    /*! \brief Handle incoming OPTIONS request */
    
    static int handle_request_options(struct sip_pvt *p, struct sip_request *req)
    
    {
    	int res;
    
    	res = get_destination(p, req);
    	build_contact(p);
    	/* XXX Should we authenticate OPTIONS? XXX */
    	if (ast_strlen_zero(p->context))
    
    		ast_string_field_set(p, context, default_context);
    
    	if (res < 0)
    		transmit_response_with_allow(p, "404 Not Found", req, 0);
    	else 
    		transmit_response_with_allow(p, "200 OK", req, 0);
    	/* Destroy if this OPTIONS was the opening request, but not if
    	   it's in the middle of a normal call flow. */
    	if (!p->lastinvite)
    
    		ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);	
    
    /*! \brief Handle the transfer part of INVITE with a replaces: header, 
        meaning a target pickup or an attended transfer */
    static int handle_invite_replaces(struct sip_pvt *p, struct sip_request *req, int debug, int ignore, int seqno, struct sockaddr_in *sin)
    {
    	struct ast_frame *f;
    	int earlyreplace = 0;
    	int oneleggedreplace = 0;		/* Call with no bridge, propably IVR or voice message */
    	struct ast_channel *c = p->owner;	/* Our incoming call */
    	struct ast_channel *replacecall = p->refer->refer_call->owner;	/* The channel we're about to take over */
    	struct ast_channel *targetcall;		/* The bridge to the take-over target */
    
    	/* Check if we're in ring state */
    	if (replacecall->_state == AST_STATE_RING)
    		earlyreplace = 1;
    
    	/* Check if we have a bridge */
    	if (!(targetcall = ast_bridged_channel(replacecall))) {
    		/* We have no bridge */
    		if (!earlyreplace) {
    			if (option_debug > 1)
    
    				ast_log(LOG_DEBUG, "	Attended transfer attempted to replace call with no bridge (maybe ringing). Channel %s!\n", replacecall->name);
    
    			oneleggedreplace = 1;
    		}
    	} 
    	if (option_debug > 3 && targetcall && targetcall->_state == AST_STATE_RINGING)
    			ast_log(LOG_DEBUG, "SIP transfer: Target channel is in ringing state\n");
    
    	if (option_debug > 3) {
    		if (targetcall) 
    			ast_log(LOG_DEBUG, "SIP transfer: Invite Replace incoming channel should bridge to channel %s while hanging up channel %s\n", targetcall->name, replacecall->name); 
    		else
    			ast_log(LOG_DEBUG, "SIP transfer: Invite Replace incoming channel should replace and hang up channel %s (one call leg)\n", replacecall->name); 
    	}
    
    	if (ignore) {
    		ast_log(LOG_NOTICE, "Ignoring this INVITE with replaces in a stupid way.\n");
    		/* We should answer something here. If we are here, the
    			call we are replacing exists, so an accepted 
    			can't harm */
    		transmit_response_with_sdp(p, "200 OK", req, 1);
    		/* Do something more clever here */
    		ast_channel_unlock(c);
    		ast_mutex_unlock(&p->refer->refer_call->lock);
    		return 1;
    	} 
    	if (!c) {
    		/* What to do if no channel ??? */
    		ast_log(LOG_ERROR, "Unable to create new channel.  Invite/replace failed.\n");
    		transmit_response_with_sdp(p, "503 Service Unavailable", req, 1);
    		append_history(p, "Xfer", "INVITE/Replace Failed. No new channel.");
    		ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);	
    		ast_mutex_unlock(&p->refer->refer_call->lock);
    		return 1;
    	}
    	append_history(p, "Xfer", "INVITE/Replace received");
    	/* We have three channels to play with
    		channel c: New incoming call
    		targetcall: Call from PBX to target
    		p->refer->refer_call: SIP pvt dialog from transferer to pbx.
    		replacecall: The owner of the previous
    		We need to masq C into refer_call to connect to 
    		targetcall;
    		If we are talking to internal audio stream, target call is null.
    	*/
    
    	/* Fake call progress */
    	transmit_response(p, "100 Trying", req);
    	ast_setstate(c, AST_STATE_RING);
    
    	/* Masquerade the new call into the referred call to connect to target call 
    	   Targetcall is not touched by the masq */
    
    	/* Answer the incoming call and set channel to UP state */
    	transmit_response_with_sdp(p, "200 OK", req, 1);
    	ast_setstate(c, AST_STATE_UP);
    	
    	/* Stop music on hold and other generators */
    	ast_quiet_chan(replacecall);
    
    	if (option_debug > 3)
    		ast_log(LOG_DEBUG, "Invite/Replaces: preparing to masquerade %s into %s\n", c->name, replacecall->name);
    	/* Unlock clone, but not original (replacecall) */
    	ast_channel_unlock(c);
    
    	/* Unlock PVT */
    	ast_mutex_unlock(&p->refer->refer_call->lock);
    
    	/* Make sure that the masq does not free our PVT for the old call */
    	ast_set_flag(&p->refer->refer_call->flags[0], SIP_DEFER_BYE_ON_TRANSFER);	/* Delay hangup */
    		
    	/* Prepare the masquerade - if this does not happen, we will be gone */
    	if(ast_channel_masquerade(replacecall, c))
    		ast_log(LOG_ERROR, "Failed to masquerade C into Replacecall\n");
    	else if (option_debug > 3)
    		ast_log(LOG_DEBUG, "Invite/Replaces: Going to masquerade %s into %s\n", c->name, replacecall->name);
    
    	/* The masquerade will happen as soon as someone reads a frame from the channel */
    
    	/* C should now be in place of replacecall */
    	/* ast_read needs to lock channel */
    	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;
    			if (option_debug > 3)
    				ast_log(LOG_DEBUG, "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;
    		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;
    			if (option_debug > 2)
    				ast_log(LOG_DEBUG, "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);
    	}
    	ast_mutex_unlock(&p->refer->refer_call->lock);
    
    	ast_setstate(c, AST_STATE_DOWN);
    	if (option_debug > 3) {
    		struct ast_channel *test;
    		ast_log(LOG_DEBUG, "After transfer:----------------------------\n");
    		ast_log(LOG_DEBUG, " -- C:        %s State %s\n", c->name, ast_state2str(c->_state));
    		if (replacecall)
    			ast_log(LOG_DEBUG, " -- replacecall:        %s State %s\n", replacecall->name, ast_state2str(replacecall->_state));
    		if (p->owner) {
    			ast_log(LOG_DEBUG, " -- P->owner: %s State %s\n", p->owner->name, ast_state2str(p->owner->_state));
    			test = ast_bridged_channel(p->owner);
    			if (test)
    				ast_log(LOG_DEBUG, " -- Call bridged to P->owner: %s State %s\n", test->name, ast_state2str(test->_state));
    			else
    				ast_log(LOG_DEBUG, " -- No call bridged to C->owner \n");
    		} else 
    			ast_log(LOG_DEBUG, " -- No channel yet \n");
    		ast_log(LOG_DEBUG, "End After transfer:----------------------------\n");
    	}
    
    	ast_channel_unlock(p->owner);	/* Unlock new owner */
    	ast_mutex_unlock(&p->lock);	/* Unlock SIP structure */
    
    	/* The call should be down with no ast_channel, so hang it up */
    	c->tech_pvt = NULL;
    	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)
    
    	const char *p_replaces;
    	char *replace_id = NULL;
    
    	struct ast_channel *c = NULL;		/* New channel */
    
    
    	/* Find out what they support */
    	if (!p->sipoptions) {
    
    		const char *supported = get_header(req, "Supported");
    
    		if (supported)
    			parse_sip_options(p, supported);
    	}
    
    
    	/* Find out what they require */
    
    Olle Johansson's avatar
    Olle Johansson committed
    	required = get_header(req, "Require");
    
    	if (required && !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);
    
    				ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);	
    
    	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);
    		/* We do NOT destroy p here, so that our response will be accepted */
    		return 0;
    	}
    
    	if (!ast_test_flag(req, SIP_PKT_IGNORE) && p->pendinginvite) {
    
    		/* We already have a pending invite. Sorry. You are on hold. */
    		transmit_response(p, "491 Request Pending", req);
    
    			ast_log(LOG_DEBUG, "Got INVITE on call where we already have pending INVITE, deferring that - %s\n", p->callid);
    		return 0;
    	}
    
    
    	if ((p_replaces = get_header(req, "Replaces")) && !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) {
    			if (option_debug > 2)
    				ast_log(LOG_DEBUG, "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 && option_debug > 2)
    			ast_log(LOG_DEBUG, "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.");
    			ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
    			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 && option_debug > 3) 
    			ast_log(LOG_DEBUG,"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 = NULL;
    			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_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.");
    			ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
    			ast_mutex_unlock(&p->lock);
    			if (p->refer->refer_call) {
    				ast_mutex_unlock(&p->refer->refer_call->lock);
    				ast_channel_unlock(p->refer->refer_call->owner);
    			}
    			return -1;
    		}
    	}
    
    
    	/* Check if this is an INVITE that sets up a new dialog or
    	   a re-invite in an existing dialog */
    
    
    	if (!ast_test_flag(req, SIP_PKT_IGNORE)) {
    
    		sip_cancel_destroy(p);
    		/* This also counts as a pending invite */
    		p->pendinginvite = seqno;
    		check_via(p, req);
    
    
    		if (!p->owner) {	/* Not a re-invite */
    			/* Use this as the basis */
    			copy_request(&p->initreq, req);
    			if (debug)
    				ast_verbose("Using INVITE request as basis request - %s\n", p->callid);
    
    Olle Johansson's avatar
    Olle Johansson committed
    			append_history(p, "Invite", "New call: %s", p->callid);
    
    		} else {	/* Re-invite on existing call */
    
    			/* Handle SDP here if we already have an owner */
    
    				if (process_sdp(p, req)) {
    					transmit_response(p, "488 Not acceptable here", req);
    
    						ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);	
    
    			} else {
    				p->jointcapability = p->capability;
    				ast_log(LOG_DEBUG, "Hm....  No sdp for the moment\n");
    			}
    
    			if (recordhistory) /* 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 && !ast_test_flag(req, SIP_PKT_IGNORE) && !p->owner) {
    		/* This is a new invite */
    
    		/* Handle authentication if this is our first invite */
    
    		res = check_user(p, req, SIP_INVITE, e, XMIT_RELIABLE, sin);
    
    			return 0; 
    		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);
      			}
    
    			ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
    
    			ast_string_field_free(p, theirtag);
    
    
    		/* We have a succesful authentication, process the SDP portion if there is one */
    
    				transmit_response_reliable(p, "488 Not acceptable here", req);
    
    				ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);	
    
    				if (option_debug)
    					ast_log(LOG_DEBUG, "No compatible codecs for this SIP call.\n");
    
    		} else {	/* No SDP in invite, call control session */
    
    			p->jointcapability = p->capability;
    
    			if (option_debug > 1)
    				ast_log(LOG_DEBUG, "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 */
    
    		if (option_debug)
    			ast_log(LOG_DEBUG, "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);
    
    				ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);	
    
    		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_INFO);
    
    		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_set_flag(&p->flags[0], SIP_NEEDDESTROY);		
    
    		} 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);
    
    		if (option_debug > 1 && sipdebug) {
    
    			if (!ast_test_flag(req, SIP_PKT_IGNORE))
    
    				ast_log(LOG_DEBUG, "Got a SIP re-invite for call %s\n", p->callid);
    			else
    				ast_log(LOG_DEBUG, "Got a SIP re-transmit of INVITE for call %s\n", p->callid);
    		}
    
    	if (!ast_test_flag(req, SIP_PKT_IGNORE) && p)
    
    
    	if (replace_id) { 	/* Attended transfer or call pickup - we're the target */
    		/* Go and take over the target call */
    		if (sipdebug && option_debug > 3)
    			ast_log(LOG_DEBUG, "Sending this call to the invite/replcaes handler %s\n", p->callid);
    		return handle_invite_replaces(p, req, debug, ast_test_flag(req, SIP_PKT_IGNORE), 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:
    
    			if (option_debug > 1)
    				ast_log(LOG_DEBUG, "%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");
    
    					if (ast_test_flag(req, SIP_PKT_IGNORE))
    
    						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");
    
    					if (ast_test_flag(req, SIP_PKT_IGNORE))
    
    						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_mutex_unlock(&c->lock);
    					ast_mutex_unlock(&p->lock);
    
    					ast_hangup(c);
    					ast_mutex_lock(&p->lock);
    					c = NULL;
    				}
    
    			} 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);
    
    					if (ast_test_flag(req, SIP_PKT_IGNORE))
    
    						transmit_response(p, "503 Unavailable", req);	/* OEJ - Right answer? */
    
    						transmit_response_reliable(p, "503 Unavailable", req);
    
    					ast_set_flag(&p->flags[0], SIP_ALREADYGONE);	
    
    					/* Unlock locks so ast_hangup can do its magic */
    					ast_mutex_unlock(&p->lock);
    
    					c->hangupcause = AST_CAUSE_CALL_REJECTED;
    
    				} else {
    					ast_mutex_unlock(&p->lock);
    					ast_setstate(c, AST_STATE_DOWN);
    
    					c->hangupcause = AST_CAUSE_NORMAL_CLEARING;
    
    				ast_hangup(c);
    				ast_mutex_lock(&p->lock);
    				c = NULL;
    
    			}
    			break;
    		case AST_STATE_RING:
    			transmit_response(p, "100 Trying", req);
    			break;
    		case AST_STATE_RINGING:
    			transmit_response(p, "180 Ringing", req);
    			break;
    		case AST_STATE_UP:
    
    				ast_log(LOG_DEBUG, "%s: This call is UP.... \n", c->name);
    
    
    			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 (!strcasecmp(bridgepeer->tech->type, "SIP")) { /* If we are bridged to SIP channel */
    						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");
    								ast_mutex_lock(&bridgepvt->lock);
    								bridgepvt->t38.state = T38_DISABLED;
    								ast_mutex_unlock(&bridgepvt->lock);
    								if (option_debug > 1)
    									ast_log(LOG_DEBUG,"T38 state changed to %d on channel %s\n", bridgepvt->t38.state, bridgepeer->name);
    								if (ast_test_flag(req, SIP_PKT_IGNORE))
    									transmit_response(p, "488 Not acceptable here", req);
    								else
    									transmit_response_reliable(p, "488 Not acceptable here", req);
    								ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
    							}
    						}
    					} else {
    						/* Other side is not a SIP channel */
    						if (ast_test_flag(req, SIP_PKT_IGNORE))
    							transmit_response(p, "488 Not acceptable here", req);
    						else
    							transmit_response_reliable(p, "488 Not acceptable here", req);
    						p->t38.state = T38_DISABLED;
    						if (option_debug > 1)
    							ast_log(LOG_DEBUG,"T38 state changed to %d on channel %s\n", p->t38.state, p->owner ? p->owner->name : "<none>");
    						ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
    					}
    				} else {
    					/* we are not bridged in a call */
    					transmit_response_with_t38_sdp(p, "200 OK", req, XMIT_CRITICAL);
    					p->t38.state = T38_ENABLED;