In a previous article, we learned how to get presence using UCMA. In this article, we'll learn how to start a conversation and send messages using UCMA.

The code for the entire program is located near the end of the article.

The process for starting a conversation is incredibly easy:

  1. Have the UserEndpoint create a Conversation
  2. Create a new InstantMessagingCall
  3. Establish the new IM call

The code:

public class ConnectionService 
{
    public ConversationCreateConversation()
    {
        return new Conversation(_endpoint);
    }
}

public class ConversationService
{
    private ConnectionService _connectionService;
    private Conversation _currentConversation;
    private InstantMessagingCall _currentIMCall;

    public ConversationService(ConnectionService connectionService)
    {
        _connectionService = connectionService;
    }

    public IAsyncResult StartConversationWith(string contactSipUri)
    {
        _currentConversation = _connectionService.CreateConversation();
        _currentIMCall = new InstantMessagingCall( _currentConversation);

        return _currentIMCall.BeginEstablish(
            contactSipUri,
            new ToastMessage("New conversation"), 
            new CallEstablishOptions(),
            EstablishCompleted, 
            null);
    }

    private void EstablishCompleted(IAsyncResult result)
    {
        _currentIMCall.EndEstablish(result);
    }
}

Ending a conversation is similarly simple:

public class ConversationService
{
    public IAsyncResult EndConversation()
    {
        return _currentConversation.BeginTerminate(TerminateCompleted, null);
    }

    private void TerminateCompleted(IAsyncResult result)
    {
        _currentConversation.EndTerminate(result);
    }
}

The remaining task is to send messages:

public class ConversationService
{
    public IAsyncResult SendMessage(string message)
    {
        return _currentIMCall.Flow.BeginSendMessage(message, SendMessageCompleted, null);
    }

    private void SendMessageCompleted(IAsyncResult result)
    {
        _currentIMCall.Flow.EndSendMessage(result);
    }
}

Here is the whole console application in one place:

using System;
using System.Net;
using Microsoft.Rtc.Signaling;
using Microsoft.Rtc.Collaboration;

namespace OCS_IM
{
    public static class Program
    {
        public static void Main(string[] args)
        {
            var connection = new ConnectionService();

            connection.Start().AsyncWaitHandle.WaitOne();

            connection.InitEndpoint(
                "sip:you@domain", 
                "ocs-server-name")
                .AsyncWaitHandle.WaitOne();

            var conversation = new ConversationService(connection);

            conversation.StartConversationWith("sip:contact@domain")
                .AsyncWaitHandle.WaitOne();

            conversation.SendMessage("A message");

            Console.WriteLine("Press any key to end program.");
            Console.ReadLine();

            conversation.EndConversation().AsyncWaitHandle.WaitOne();
            connection.Stop().AsyncWaitHandle.WaitOne();

            Console.ReadLine();
        }
    }

    public class ConversationService
    {
        private ConnectionService _connectionService;
        private Conversation _currentConversation;
        private InstantMessagingCall _currentIMCall;

        public ConversationService(ConnectionService connectionService)
        {
            _connectionService = connectionService;
        }

        public IAsyncResult StartConversationWith(string contactSipUri)
        {
            _currentConversation = _connectionService.CreateConversation();
            _currentIMCall = new InstantMessagingCall(_currentConversation);

            return _currentIMCall.BeginEstablish(
                contactSipUri,
                new ToastMessage("New conversation"),
                new CallEstablishOptions(),
                EstablishCompleted,
                null);
        }

        private void EstablishCompleted(IAsyncResult result)
        {
            _currentIMCall.EndEstablish(result);
        }

        public IAsyncResult SendMessage(string message)
        {
            return _currentIMCall.Flow.BeginSendMessage(
                message, SendMessageCompleted, null);
        }

        private void SendMessageCompleted(IAsyncResult result)
        {
            _currentIMCall.Flow.EndSendMessage(result);
        }

        public IAsyncResult EndConversation()
        {
            return _currentConversation.BeginTerminate(
                TerminateCompleted, null);
        }

        private void TerminateCompleted(IAsyncResult result)
        {
            _currentConversation.EndTerminate(result);
        }
    }

    public class ConnectionService
    {
        private CollaborationPlatform _platform;
        private UserEndpoint _endpoint;

        public IAsyncResult Start()
        {
            var settings = new ClientPlatformSettings("OCS_IM", SipTransportType.Tls);

            _platform = new CollaborationPlatform(settings);

            return _platform.BeginStartup(StartupCompleted, null);
        }

        private void StartupCompleted(IAsyncResult result)
        {
            _platform.EndStartup(result);
        }

        public IAsyncResult InitEndpoint(string currentUserSipUri, string ocsServerName)
        {
            var settings = new UserEndpointSettings(currentUserSipUri, ocsServerName);

            _endpoint = new UserEndpoint(_platform, settings);
            _endpoint.Credential = CredentialCache.DefaultNetworkCredentials;

            return _endpoint.BeginEstablish(EstablishCompleted, null);
        }

        private void EstablishCompleted(IAsyncResult result)
        {
            _endpoint.EndEstablish(result);
        }

        public Conversation CreateConversation()
        {
            return new Conversation(_endpoint);
        }

        public IAsyncResult Stop()
        {
            return _endpoint.BeginTerminate(TerminateCompleted, null);
        }

        private void TerminateCompleted(IAsyncResult result)
        {
            _endpoint.EndTerminate(result);
            _platform.BeginShutdown(ShutdownCompleted, null);
        }

        private void ShutdownCompleted(IAsyncResult result)
        {
            _platform.EndShutdown(result);
        }
    }
}