Call replacement extension method for UCMA

Recently I did some experimenting with call replacement, and I came up with a set of extension methods that you can use to try out the INVITE with Replaces technique. To start, I should probably explain what it does. There is a BeginReplace extension method for AudioVideoCall, which allows you to take over the spot in a two-party call that belongs to your application. Note that this is different from a supervised transfer. In a supervised transfer, you send a REFER message to the remote endpoint telling IT to do an INVITE with Replaces. With this method, on the other hand, your application itself is sending the new INVITE and taking over one end of the call. You can use it more or less like this:

[csharp] try { newCall.BeginReplace(oldCall, callEstablishOptions, ar => { try { newCall.EndReplace(ar); } catch (RealTimeException ex) { Console.WriteLine(ex); } }, null); } catch (InvalidOperationException ex) { Console.WriteLine(ex); } [/csharp]

When you call BeginReplace, the call should be in the Idle state: i.e., not yet established. The second parameter (for AudioVideoCallEstablishOptions) can be null.

Here is the code for the extension methods (BeginReplace and EndReplace):

[csharp] public static class ExtensionMethods { public static IAsyncResult BeginReplace(this AudioVideoCall newCall,AudioVideoCall replacedCall,AudioVideoCallEstablishOptions options, AsyncCallback asyncCallback, object state) { string replacedCallKey = string.Format("{0};from-tag={1};to-tag={2}", replacedCall.CallId, replacedCall.LocalTag, replacedCall.RemoteTag);

AudioVideoCallEstablishOptions newCallOptions = options;

if (newCallOptions == null) { newCallOptions = new AudioVideoCallEstablishOptions(); }

newCallOptions.Headers.Add( new SignalingHeader("Replaces", replacedCallKey));

return newCall.BeginEstablish(replacedCall.RemoteEndpoint.Uri, newCallOptions, asyncCallback, state); }

public static CallMessageData EndReplace(this AudioVideoCall call, IAsyncResult result) { return call.EndEstablish(result); } } [/csharp]