UCMA 2.0 - Part 1.4 Signing in and signing out

It’s about time that we began writing some code and getting into the details of the API. To start out, I will cover the signaling part of UCMA. Those of you who read my previous blog series on UCMA will find the next several posts very familiar.

For some of you, learning the signaling APIs in UCMA will not be very useful because you will use the collaboration layer that abstracts this. However, I still feel that the signaling layer is the best way to understand SIP and prepare oneself for what the collaboration API does for you.

Today, we will begin our Powershell project and create a simple commandlet that signs in and then signs out. I will not go over the majority of the Powershell specific code here, but the following are the steps to install and run the task.

1) Download and install Powershell.

2) Find the location of InstallUtil.exe on your machine – Get-ChildItem –Recurse –path ${env:systemroot} –Include installutil.exe

3) Using the location found from the previous step, run installutil UCMAPowershell.dll

4) Add-pssnapin UCMAPSSnapIn

Each SnapIn is run in its own process, so you can attach to the process in order to debug.

For our first iteration, we will create a simple commandlet that will just sign in and sign out. In subsequent posts, we will modify this commandlet to send a message. For now, the commandlet will have the following parameters.

User – the SIP Uri of the user to log in as

ServerName – the name of the server to use

Retrieving the certificate

I should note that this first commandlet will be much simpler than the subsequent ones we will create. For instance, it is possible to determine a default server name to use without requiring it on the command line. When we start discussing the collaboration API, we will do this.

In order to perform TLS communications, we will need a certificate. For now, let’s just pick the first available certificate. This should work on your machine, but there is a chance that it will not. Later on we will change this logic to be smarter about choosing a certificate.

Here’s the code for retrieving the first available certificate.

public static CertificateEntry GetCertificate()

{

// Load the certificates

X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);

store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);

      // Make sure we have certificates

      if (store.Certificates.Count < 1)

      {

          return null;

      }

      // Pick a certificate

      foreach (X509Certificate2 certificate in store.Certificates)

      {

          // TODO: improve this

          CertificateEntry entry = new CertificateEntry(certificate);

          return entry;

      }

      return null;

  }

Creating a connection manager

We will put the sign in and sign out logic in the BeginProcessing and EndProcessing methods. The primary reason for this is it allows us to send multiple messages without having to sign in and out each time. The ProcessRecord override will contain the code to send the actual message.

The first thing we will need to do is create a connection manager. To start, we will need to create an instance of SipEndpoint. Conveniently named, this class encapsulates a SIP endpoint. A SIP endpoint is the basis for all SIP communications. It is both the “from” and the “to” when it comes to communicating.

So, in order to sign in to OCS we must first create an instance of the SipEndpoint class. The SipEndpoint class derives from the abstract RealTimeEndpoint class. There are two classes of interest to us that derive from RealTimeEndpoint. Both of these classes allow you to send out of dialog messages or establish and receive long sessions.

·         SipEndpoint – can be constructed off any connection manager that derives from RealTimeConnectionManager (server or client)

·         SipPeerToPeerEndpoint –can only be constructed off connection managers that derive from RealTimeServerConnectionManager (RealTimeServerTlsConnectionManager or a RealTimeServerTcpConnectionManager)

 

For our purposes right now, we will use the SipEndpoint class. We will likely use SipPeerToPeerEndpoint in the future. In order to create a SipEndpoint instance, though, we will need to create a RealTimeConnectionManager.

 

RealTimeConnectionManager provides the connection manager features we need for our end points. It contains the logic that allows us to send messages. RealTimeConnectionManager by itself can only send messages. It does not contain logic for listening for them. Since we will likely want to receive messages in the future, we will use the RealTimeServerConnectionManager class. This class allows us to receive messages as well, though we will do that in a future post.

 

RealTimeServerConnectionManager, which derives itself from RealTimeConnectionManager, has two descendents – RealTimeServerTcpConnectionManager and RealTimeServerTlsConnectionManager. Tls is the better way to go here because it is encrypted. Many parts of OCS will not work with TCP communications. Therefore TCP will not be covered in this blog series.

 

So once we have a RealTimeConnectionManager instance, we can create our SipEndpoint instance. Once we have this, we need to register our SIP endpoint. Registering in UCMA is basically the same as signing in in most other environments.

Before we get into the details of creating our SipEndpoint, let’s look at the constructor. There are three available constructors for SipEndpoint but the one we will use here is defined as follows.

 

public SipEndpoint (

        string uri,

        SipAuthenticationProtocols allowedAuthenticationProtocols,

        SipTransportType transportType,

        string serverName,

        int serverPort,

        bool allowNoAuthentication,

        RealTimeConnectionManager connectionManager,

        string endpointId

)

 

To create our SipEndpoint we must supply the information in the following table.

 

Argument

Description

uri

This is the SIP URI of our endpoint. It typically has the form of sip:name@domain.com

allowedAuthenticationProtocols

You can use none, Kerberos, or Ntlm here. You will probably want to play with this some, but I will use Ntlm here.

transportType

This is Tcp or Tls as previously described

serverName

This is the name of the OCS server we will register with

serverPort

This is the port on the server we will use. The default port for Tls it is 5061.

allowNoAuthentication

Use this setting if the server does not authenticate communications from our client. This must be true if you use None for allowedAuthenticationProtocols. In almost all cases, you will pass false here.

connectionManager

This is the connection manager that we must create.

endPointId

If you want to use a specific endpoint Id (also called epid) you can specify it here. In this case I will pass null.

 

The following is how we start the BeginProcessing method.

// Get a certificate

CertificateEntry certificate = GetCertificate();

if (null == certificate)

{

return;

}

// Create the connection manager

_connectionManager = (RealTimeServerConnectionManager)new RealTimeServerTlsConnectionManager(

certificate.IssuerName,

ertificate.SerialNumber);

WriteVerbose("Created connection manager");

// Create the endpoint

_endPoint = new SipEndpoint(

_user,

      SipAuthenticationProtocols.Ntlm,

      SipTransportType.Tls,

      _serverName,

      5061,

      false,

      _connectionManager,

      null);

_endPoint.CredentialCache.Add(

SipEndpoint.DefaultRtcRealm,

      CredentialCache.DefaultNetworkCredentials);

WriteVerbose("Created endpoint");

After retrieving our certificate, we use it to create our connection manager. We then use the connection manager to create our endpoint. Finally, we update the endpoint with the currently running credentials in order to enable to endpoint to sign in.

The final thing we need to do is actually sign in. In UCMA-speak, this is called “registering”.

// Register the endpoint

SipResponseData response = _endPoint.EndRegister(_endPoint.BeginRegister(null, null));

WriteVerbose("Registered endpoint");

I did a big “no-no” here by performing the registration in a synchronous operation. Later on we will create a commandlet that only uses the synchronous methods when we get to the collaboration API, but for now we will use this method. In some respects this lends itself better to the Powershell approach as Powershell runs with more of a synchronous model. One should never do this when creating server (or client) products. Even in Powershell, this breaks down a bit when sending a number of messages.

To sign out, or unregister, add the following code to EndProcessing.

if (null != _endPoint)

{

_endPoint.EndUnregister(_endPoint.BeginUnregister(null, null));

      WriteVerbose("Unregistered endpoint");

}

When you run this code, you’ll see a number of logging messages but otherwise not much will happen. Make sure to run this with –Verbose or you’ll see even less. In the actual project’s files I have added an Xml help file that will allow you to use the help commands within Powershell.

So far our Powershell commandlet doesn’t do very much. That will change over the next few blogs, starting with creating a signaling session in the next blog.

UCMABlog.zip