All pastes #1208872 Raw Edit

clueless

public text v1 · immutable
#1208872 ·published 2008-09-23 01:31 UTC
rendered paste body
Index: channels/chan_sip.c===================================================================--- channels/chan_sip.c	(.../branches/1.4)	(revision 143963)+++ channels/chan_sip.c	(.../team/seanbright/issue5014-1.4)	(revision 143963)@@ -875,6 +875,13 @@         REFER_NOAUTH                   /*!< We had no auth for REFER */ }; +/*! \brief struct to store off exten and contact for tech independent pickup.+ */+struct pickup_target {+	char *exten;+	char *context;+};+ static const struct c_referstatusstring { 	enum referstatus status; 	char *text;@@ -1355,6 +1362,7 @@ static int sip_refer_allocate(struct sip_pvt *p); static void ast_quiet_chan(struct ast_channel *chan); static int attempt_transfer(struct sip_dual *transferer, struct sip_dual *target);+static int do_magic_pickup(struct ast_channel *channel, const char *exten, const char *context);  /*--- Device monitoring and Device/extension state handling */ static int cb_extensionstate(char *context, char* exten, int state, void *data);@@ -7382,11 +7390,25 @@ 		break; 	case DIALOG_INFO_XML: /* SNOM subscribes in this format */ 		ast_build_string(&t, &maxbytes, "<?xml version=\"1.0\"?>\n");-		ast_build_string(&t, &maxbytes, "<dialog-info xmlns=\"urn:ietf:params:xml:ns:dialog-info\" version=\"%d\" state=\"%s\" entity=\"%s\">\n", p->dialogver++, full ? "full":"partial", mto);-		if ((state & AST_EXTENSION_RINGING) && global_notifyringing)-			ast_build_string(&t, &maxbytes, "<dialog id=\"%s\" direction=\"recipient\">\n", p->exten);-		else+		ast_build_string(&t, &maxbytes, "<dialog-info xmlns=\"urn:ietf:params:xml:ns:dialog-info\" version=\"%d\" state=\"%s\" entity=\"%s\">\n", p->dialogver++, full ? "full" : "partial", mto);+		if ((state & AST_EXTENSION_RINGING) && global_notifyringing) {+			/* We create a fake call-id which the phone will send back in an INVITE+			   Replaces header which we can grab and do some magic with. */+			ast_build_string(&t, &maxbytes, "<dialog id=\"%s\" call-id=\"pickup-%s\" direction=\"recipient\">\n", p->exten, p->callid);+			ast_build_string(&t, &maxbytes, "<remote>\n");+			/* Note that the identity and target elements for the local participant are currently+			   (and may forever be) incorrect since we have no reliable way to get at that information+			   at the moment.  Luckily the phone seems to still live happily without it being correct */+			ast_build_string(&t, &maxbytes, "<identity>%s</identity>\n", mto);+			ast_build_string(&t, &maxbytes, "<target uri=\"%s\"/>\n", mto);+			ast_build_string(&t, &maxbytes, "</remote>\n");+			ast_build_string(&t, &maxbytes, "<local>\n");+			ast_build_string(&t, &maxbytes, "<identity>%s</identity>\n", mto);+			ast_build_string(&t, &maxbytes, "<target uri=\"%s\"/>\n", mto);+			ast_build_string(&t, &maxbytes, "</local>\n");+		} else { 			ast_build_string(&t, &maxbytes, "<dialog id=\"%s\">\n", p->exten);+		} 		ast_build_string(&t, &maxbytes, "<state>%s</state>\n", statestring); 		if (state == AST_EXTENSION_ONHOLD) { 			ast_build_string(&t, &maxbytes, "<local>\n<target uri=\"%s\">\n"@@ -14074,7 +14096,37 @@ 	return sip_uri_params_cmp(params1, params2); } +static int do_magic_pickup(struct ast_channel *channel, const char *extension, const char *context)+{+	char *argument = NULL;+	int length;+	struct ast_app *pickup = pbx_findapp("Pickup"); +	if (!pickup) {+		ast_log(LOG_ERROR, "Unable to perform pickup: Application 'Pickup' not loaded (app_directed_pickup.so).\n");+		return -1;+	}++	/* Enough room for 'extension', 'context', and '@' (and \0) */+	length = strlen(extension) + strlen(context) + 2;++	if (!(argument = ast_malloc(length))) {+		ast_log(LOG_ERROR, "Failed to allocate memory for pickup extension.\n");+		return -1;+	}++	snprintf(argument, length, "%s@%s", extension, context);++	/* There is no point in capturing the return value since pickup_exec+	   doesn't return anything meaningful unless the passed data is an empty+	   string (which in our case it will not be) */+	pbx_exec(channel, pickup, argument);++	ast_free(argument);++	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@@ -14091,6 +14143,7 @@ 	unsigned int required_profile = 0; 	struct ast_channel *c = NULL;		/* New channel */ 	int reinvite = 0;+	struct pickup_target *pickup = NULL;  	/* Find out what they support */ 	if (!p->sipoptions) {@@ -14227,10 +14280,35 @@ 			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) {+		/* Try to find the call that we are replacing.+		   If we have a Replaces header, we need to cancel that call if we succeed with this call.+		   First we cheat a little and look for a magic call-id from phones that support+		   dialog-info+xml so we can do technology independent pickup... */+		if (strncmp(replace_id, "pickup-", 7) == 0) {+			struct sip_pvt *subscription = NULL;+			replace_id += 7; /* Worst case we are looking at \0 */++			if ((subscription = get_sip_pvt_byid_locked(replace_id, NULL, NULL)) == NULL) {+				ast_log(LOG_NOTICE, "Unable to find subscription with call-id: %s\n", replace_id);+				transmit_response_reliable(p, "481 Call Leg Does Not Exist (Replaces)", req);+				error = 1;+			} else {+				if (!(pickup = ast_calloc(1, sizeof(*pickup)))) {+					ast_log(LOG_ERROR, "Memory allocation failed.\n");+					error = 1;+				} else {+					ast_log(LOG_NOTICE, "Trying to pick up %s@%s\n", subscription->exten, subscription->context);+					pickup->exten   = ast_strdup(subscription->exten);+					pickup->context = ast_strdup(subscription->context);+					ast_mutex_unlock(&subscription->lock);+					if (subscription->owner) {+						ast_channel_unlock(subscription->owner);+					}+				}+			}+		}++		if (!error && !pickup && (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_reliable(p, "481 Call Leg Does Not Exist (Replaces)", req); 			error = 1;@@ -14249,7 +14327,7 @@ 			error = 1; 		} -		if (!error && !p->refer->refer_call->owner) {+		if (!error && !pickup && !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 */@@ -14257,7 +14335,7 @@ 			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 ) {+		if (!error && !pickup && 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_reliable(p, "603 Declined (Replaces)", req); 			error = 1;@@ -14447,10 +14525,27 @@ 		p->lastinvite = seqno;  	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 (pickup) {+			append_history(p, "Xfer", "INVITE/Replace received");++			/* Let the caller know we're giving it a shot */+			transmit_response(p, "100 Trying", req);+			ast_setstate(c, AST_STATE_RING);++			/* Do the pickup itself */+			do_magic_pickup(c, pickup->exten, pickup->context);++			/* Do a bit of cleanup */+			ast_free(pickup->exten);+			ast_free(pickup->context);+			ast_free(pickup);+			return 0;+		} else {+			/* 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);+		} 	}  Property changes on: .___________________________________________________________________Added: automerge   + *Added: svnmerge-integrated   + /branches/1.4:1-143955Added: automerge-email   + sean.bright+$branch@gmail.com