We finally have all the pieces ready to get our client and server communicating.  Yesterday we allowed our client and server to agree on communicating through the SIP MESSAGE message so the next step is to get our client to send a message and get our server to receive one.  Let’s start with our client.  On our client, the method we are interested in is BeginSendMessage on the SignalingSession class.  This takes the following parameters.

                messageType – For our purposes this is Message but as you can see from the enumeration you can use the same method to send INFO and other types of messages

                contentType – for our purposes this will be text/plain as agreed upon in the media negotiations

                body – the body of the message

 

Also note that there is an overload that allows you to specify custom headers.  We will talk more about custom headers in a later post.  The last two parameters should be familiar to you from the other asynchronous methods we have called.  Let’s add a method to our client to send a message.  Add the following method in IDKStudioClientManager.cs.

 

private void SendMessage(string message)

{

    RecordProgress("Sending the message {0}", message);

    _session.BeginSendMessage(MessageType.Message,

                             new ContentType("text/plain"),

                             Encoding.UTF8.GetBytes(message),

                             SendMessageCallback,

                             _session);

}

 

This should be simple enough.  Note that we have to convert our message to bytes.  As not all messages contain text, we must send the message in binary form.  Our callback method may look like a lot of code, but it’s not much different from callbacks we already have.

 

private void SendMessageCallback(IAsyncResult ar)

{

    SignalingSession session = ar.AsyncState as SignalingSession;

    SipResponseData response = null;

 

    try

    {

        response = session.EndSendMessage(ar);

        RecordProgress("Message sent successfully");

    }

    catch (FailureResponseException e)

    {

        if (e.ResponseData != null)

        {

            Error("The Notification could not be received by {0}; the MESSAGE was rejected with error code {1}.",

                         Settings.OurServerName,

                         e.ResponseData.ResponseCode);

        }

        else

        {

            Error("The Notification could not be received by {0}; the MESSAGE was rejected",

                  Settings.OurServerName);

        }

        return;

    }

    catch (OperationTimeoutException)

    {

        Error("The Notification could not be received by {0}; the MESSAGE request timed out.",

              Settings.OurServerName);

        return;

    }

    catch (RealTimeException e)

    {

        Error("The Notification could not be received by {0}; Message: {1}.",

                     Settings.OurServerName,

                     e.Message);

        return;

    }

}

 

If we receive a failure response, it is possible the server may have indicated exactly why the message failed with a response.  If we have a response, we display the response code returned.  Otherwise, we just assume the message failed.  For the client, all we need to do now is call SendMessage.  Add a call to SendMessage in ParticipateCallback after we have called EndParticipate.

 

response = session.EndParticipate(ar);

RecordProgress("Session setup successful");

SendMessage("hello world!");

 

It would probably be more useful to add a feature to the client where the user can type in the text that is sent, but that is more of a UI project than a UCMA project at this point.  The goal of this series is to introduce the UCMA API and so for simplicity sake many things will be hard coded.  Let’s get our server to accept the message.  In order to receive a message, we need to handle the MessageReceived event on the SignalingSession.  Add the following line at the end of the constructor in IDKStudioSession.cs of the server.

 

_session.MessageReceived += new EventHandler<MessageReceivedEventArgs>(_session_MessageReceived);

 

The following is our MessageReceived event handler, which simply checks that the message type is MESSAGE and that plain text was sent and not binary.  We then send the text to the UI.

 

void _session_MessageReceived(object sender, MessageReceivedEventArgs e)

{

    if (e.MessageType == MessageType.Message && e.HasTextBody)

    {

        RecordProgress(e.TextBody);

    }

}

 

Congratulations!  You now have a Hello World application in UCMA!  Now that wasn’t so hard, was it?  In reality though, our app already does quite a bit.

-          Both the client and the server sign in

-          The client successfully establishes a dialog with the server

-          The client and server agree on the media protocol

-          Our server can support multiple clients at the same time

-          The client and server can detect when the other has closed the session

-          The client can send a message to the server, which is received

 

You now have mastered some of the basics of UCMA.  Next I will begin covering other interesting aspects of the API.