Yesterday we finally got into some UCMA coding – allowing our client to sign in to the OCS server.  Today we will provide the functionality to sign out of the server.  In our current implementation, clicking the start button changes the button to ‘stop’ but the button is still disabled.

 

Before we can get started on our daily dose of UCMA, we will need to make some changes to our UI.  In our main form, we need to add a method to stop our manager.

 

/// <summary>

/// Stops running our manager

/// </summary>

/// <param name="stateInfo"></param>

private void StopManager(object stateInfo)

{

    if (null != _manager)

    {

        _manager.Terminate();

    }

}

 

Of course, the Terminate method does not exist yet.  We will create that method shortly, but first let’s finish with the UI details.  In the event handler for clicking the start button, we need to do the appropriate action depending on whether the we are starting or stopping the manager.  Change the code to the following.

 

private void btnStart_Click(object sender, EventArgs e)

{

    if (btnStart.Text.Equals("Start", StringComparison.CurrentCultureIgnoreCase))

    {

        btnOptions.Enabled = false;

        btnStart.Enabled = false;

        btnStart.Text = "Stop";

        ThreadPool.QueueUserWorkItem(new WaitCallback(StartManager), this.Handle);

    }

    else

    {

        btnOptions.Enabled = true;

        btnStart.Text = "Start";

        ThreadPool.QueueUserWorkItem(new WaitCallback(StopManager), this.Handle);

    }

}

 

Now we can switch to our manager and add the code to sign out.  The Terminate method is quite simple (for now).

 

/// <summary>

/// Terminates the current endpoint

/// </summary>

public void Terminate()

{

    _endPoint.BeginTerminate(new AsyncCallback(TerminateCallback), _endPoint);

}

 

As with all asynchronous methods, we need to implement a callback.

 

/// <summary>

/// Callback method for terminating the endpoint

/// </summary>

/// <param name="asyncResult"></param>

private void TerminateCallback(IAsyncResult asyncResult)

{

    SipEndpoint endPoint = asyncResult.AsyncState as SipEndpoint;

 

    try

    {

        endPoint.EndTerminate(asyncResult);

        if (null != Completed)

        {

            Completed(this, new CompletedEventArgs(CompletionStatus.Success,

                                                "Terminated the endpoint successfully."));

        }

    }

    catch (RealTimeException e)

    {

        Error("An exception occurred when terminating the endpoint.\n{0}", e.ToString());

        return;

    }

}

 

Here we call EndTerminate on the endpoint and then call the Completed event on the main form.  When this event occurs, the main form will change the stop button to start so a new session can begin.  To conserve resources, let’s have our manager implement IDisposable.

 

public class IDKStudioClientManager : IDisposable

 

In our implementation of the Dispose method, we will destroy the resource manager if it is still around.  The following is the implementation for Dispose.

 

public void Dispose()

{

    if (_connectionManager != null)

    {

        _connectionManager.Dispose();

    }

}

 

Finally, since we create a new manager object when the user clicks the start button, let’s dispose of the old manager when the Completed event occurs in the main form.  Add the following lines in the Completed event handler after we display the message box.

 

_manager.Dispose();

_manager = null;

 

We now need to make some UI changes to reenable our start button after we have registered with the server.  First, we will need to add a new event to the manager.

 

/// <summary>

/// Occurs when initialization has completed

/// </summary>

public event EventHandler Started;

 

Now we need to modify the Register callback method to send this event if registration was successful.  Change the RegisterCallback method to the following.

 

/// <summary>

/// Called when the endpoint has finished registering

/// </summary>

/// <param name="asyncResult"></param>

private void RegisterCallback(IAsyncResult asyncResult)

{

    SipEndpoint endPoint = asyncResult.AsyncState as SipEndpoint;

    SipResponseData response;

 

    try

    {

        response = endPoint.EndRegister(asyncResult);

        RecordProgress("Registered the endpoint successfully.");

 

        if (null != Started)

        {

            Started(this, EventArgs.Empty);

        }

    }

    catch (RealTimeException e)

    {

        Error("An exception occurred when registering the endpoint.\n{0}", e.ToString());

        return;

    }

}

 

Now we need to hook up this event in the main form.  Add the following line with the other event handler hookups in StartManager.

 

_manager.Started += new EventHandler(_manager_Started);

 

The following is the code for our event handler.

 

void _manager_Started(object sender, EventArgs e)

{

    Invoke(new EnableButtonDelegate(EnableButton), btnStart, "Stop");

    Invoke(new EnableButtonDelegate(EnableButton), btnOptions, btnOptions.Text);

}

 

We can now successfully sign in to the OCS server and sign out.  Tomorrow we will start to look at what a signaling session is and the building blocks for communications.