Microsoft Lync and Skype for Business have a rich set of .NET APIs which make it easy to extend the platform and integrate it with other applications. This blog helps explain how to use those APIs.

Invisible OCS conference participants

Posted: February 21st, 2010 | Author: | Filed under: OCS Development, UCMA 2.0 | 1 Comment »

invisible Many of you, since encountering OCS 2007 R2 and its trusty sidekick server-side API, UCMA 2.0, have been wondering, “How do I spy on people and secretly record their audio conferences?”

Luckily for you, to complement its delightfully straightforward automation of SIP messaging, UCMA 2.0 has a rich array of covert operations functionality.

That may be a slight exaggeration. What it does provide is a way for server-side applications to perform a “trusted conference join.” A UCMA 2.0 application running as a trusted service which has authenticated with the OCS server by means of a certificate can join a conference invisibly, meaning it does not show up in the roster of conference participants.

Although I was tempted to title this article “Wiretapping in UCMA 2.0,” the trusted conference join feature has many uses. It allows you to create applications that provide services to OCS conferences without causing distracting and tacky-looking bots to appear in the list of participants. Some examples:

  • Recording conversations for auditing, monitoring, or training purposes
  • Conference timekeeping for businesses that bill by the minute
  • Piping music or audio announcements into a conference
  • Silent monitoring of conferences for training purposes
  • Scaring people in a conference by suddenly saying something when they didn’t know you were there

So how do you do it?

First of all, your application needs to be using an application endpoint rather than a user endpoint. User endpoints cannot join conferences as a trusted participant.

When you call the BeginJoin method on the ConferenceSession object to join a conference,you can supply a ConferenceJoinInformation object with the URI of the conference you want to join. This ConferenceJoinInformation object also has a property called IsTrustedJoin. When this property is set to true,your application endpoint will join the conference as a trusted participant.

Let’s say you are joining a conference that has already started, and you have the conference URI stored in a local variable. You would do something like this:

// Create a ConferenceJoinInformation object with the conference URI
ConferenceJoinInformation joinInfo = new ConferenceJoinInformation(    
    new Microsoft.Rtc.Signaling.RealTimeAddress(conferenceUri));

// Make this a trusted join
joinInfo.IsTrustedJoin = true;

// Create a new conversation 
conversation = new Conversation(_applicationEndpoint);

// Use the conversation to join the conference
conversation.ConferenceSession.BeginJoin(joinInfo,    
    result =>    
    {        
        conversation.ConferenceSession.EndJoin(result);    
    },    
    null);

First, you create a new instance of ConferenceJoinInformation, passing in the conference URI. In order for the constructor to like it, you need to turn the string that contains the URI into a RealTimeAddress object.

Next, you set the IsTrustedJoin property to true.

Finally, you create a new conversation and call the BeginJoin method, passing in the join information.

When the asynchronous operation completes, your application will be a participant in the conference, sending and receiving media like any other, but it will be INVISIBLE.

There is one other point I want to call out here before concluding. If you want to have more than one of these invisible participants from the same application (e.g. one to record and one to make animal noises) you can do this, on two conditions: you will need to create a Conversation object for each participant, and you will need to impersonate a fake URI so that the participants have different URIs.

To do this, you use the Impersonate method on the Conversation object, as below:

// Create a new conversation with impersonation
conversation = new Conversation(_applicationEndpoint);
conversation.Impersonate("RandomSounds@____________.com", 
    "tel:+15555551212", "Random Sounds");

The URI you use can be completely fabricated; it doesn’t need to be a real contact.

This technique can be especially handy when combined with a back-to-back user agent (B2BUA) to proxy remote users into a conference invisibly. More on this in a future post if there is interest.

I take no responsibility for any imprudent or illegal things you do with trusted conference participants!