Course 1 / Lecture 1

How to develop a softphone in C#

How to register to a PBX using SIP Account?

Here you can learn how to add reference to Ozeki VoIP SIP SDK, in Visual Studio, and how to create a console application softphone, which is able to register to a PBX, specified by the user's input.

From this tutorial example you can learn the followings:

  • How to add reference to Ozeki VoIP SIP SDK, in Visual Studio
  • How to create a console application softphone, which is able to:
  • Register to a PBX, specified by the user's input

Related: VoIP SIP Regsitration. If also you wish to build VoIP softphone on Android, you might also be interested in a similar document, the SIP account registration in Ozeki VoIP SDK for Android

How to build your solution

If you want to create your own application to reproduce this solution, You have to create a new console application in Visual Studio.

How to add reference to Ozeki VoIP SIP SDK

You would like to use the tools, provided by the Ozeki VoIP SIP SDK, You have to add a reference to it in the Solution Explorer. To do this, You need to locate the "References" folder in your Solution Explorer, and:

  • Right click on the References folder
  • Choose "Add Reference." option

add reference
Figure 1 - Right click on the "References" folder, than choose the "Add Reference..." option

  • Select the "Browse" tab
  • Click the "Browse" button
  • If You've installed the Ozeki VoIP SIP SDK to the default installation directory, You can find the needed ozeki.dll file at the path similar to this: C:\Program Files (x86)\Ozeki\VoIP SIP SDK\SDK\.NET4
  • Select the .dll file, and click the "ADD" button

broese the dll file
Figure 2 - Under the Reference Manager's Browse tab, we need to browse for the "ozeki.dll" file at the installation path.

If You followed these steps, You can find a new line at the end of the References folder: "VoIPSDK". This line indicates, that You can use the tools, provided by the SDK.

Source code of the example, written in C#

To separate the softphone from the user interface - from the console, this time -, the best idea is to use two separate classes in this example:

  • Softphone.cs:
  • The softphone's implementation goes here, all of it's events, methods, functions, variables.

  • Program.cs:
  • Our class with the Main() method, this class controls the console window, interacts with the user, by using a softphone object.

Source code analysis

To understand the source code, the softphone's functions and their usage, we need to discuss the details. In the "using section" we need to add some extra lines, like:

using Ozeki.VoIP;
using Ozeki.VoIP.SDK;

Without these lines we would have to use the namespace information as a label for all tools of the SDK.

What is Softphone.cs used for?

This class is used to introduce how to declare, define and initialize a softphone, how to handle some of the Ozeki VoIP SIP SDK's events and how to use some of that's functions. In other words, we would like to create a "telephone software", which has the same functions (or much more), as an ordinary mobile (or any other) phone. In the Program.cs class we will use this class to create a new softphone, so we can use the functions, we can listen to the events placed here.

What objects does the softphone class use?

We need to create a softphone and a phone line object from the ISoftPhone and the IPhoneLine interfaces:

ISoftPhone softphone;   // softphone object
IPhoneLine phoneLine;   // phoneline object

In a constructor, we also initialize this softphone with default parameters.

softphone = SoftPhoneFactory.CreateSoftPhone(5000, 10000);

We need to set the port range, indicated by the first two parameters as the minimum port's and the maximum port's number, this is the port's interval. If we have any firewall rule which restricts the usable ports, we can set the usable port range here, which will be used during the calls. These are sample ports only in the example, but a softphone with these parameters can be used in the most of the cases. Please note that, if You are handling conference calls, or handling a lot of lines simultaneously, You will need a wide port range.

How to register to a PBX?

To be able to communicate, we need to register our softphone to a PBX. To do this, the example uses the Register method. We need to create a phone line for this registration, which needs a SIP account and a NAT Traversal method.

SIP account:

At the SIP account's creation we can set (usually, we have to set) the followings:

  • RegistrationRequired: is the registration required or not? This field needs to be set to "true", if we would like to receive incoming calls.
  • DisplayName: a name to be displayed at the called client.
  • UserName: if an other client dials this name (number), we are getting called.
  • AuthenticationId: an identifier to the PBX, like a login name.
  • RegisterPassword: the password to register to the PBX. Works in pair with the authentication ID.
  • DomainHost: a domain name, an IP address, for example.
  • DomainPort: Port number.

The last two values are defining the PBX to try to register to.

var account = SIPAccount(registrationRequired, displayName, userName, 
authenticationId, registerPassword, domainHost, domainPort);

We will get the values for these parameters from the user, in the Program.cs file.

How to set up a PhoneLine object?

To communicate (and to register to the PBX) we need to create a phone line. We've already created the necessary SIP account so with this we can do the creation:

phoneLine = softphone.CreatePhoneLine(account);

When the application is running, the phone line's state can change. To follow these changes, we need to listen to this change event:

phoneLine.RegistrationStateChanged += phoneLine_PhoneLineStateChanged;

When the phone line has been created, we have to call the RegisterPhoneLine() method to register the phone line to the softphone. If the registration is set to required, this method will also send the SIP REGISTER command. We just need to use the following line:

softphone.RegisterPhoneLine(phoneLine);

What events are should be handled by the softphone?

In this example, we are using only one; the phone line's event. The phone line can be in several states, for example:

  • Error: occurs, when registration is needed, but couldn't be made. The phone is unable to communicate through the PBX or other error occurs.
  • NotRegistered: when not registered to the PBX, or already unregistered
  • NoRegNeeded: there is no communication with the server, until the first (made) call. If we've set any invalid information at the SIP account's creation, we can't even make that call. Since our softphone is not registered to the server, we can't receive any calls, even with valid SIP account.
  • RegistrationSucceeded: occurs, when registration is needed, and succeeded. The phone is able to receive and make calls.

There are more states as well, but we will use only this four in this example. The using of these sates will be introduced at the Program.cs chapter.

What is Program.cs used for?

This class will introduce the usage of a softphone object, handles the console events, interacts with the user, and uses the opportunities provided by the Softphone class. In this example, the softphone can only register to a PBX by the values given by the user.

First of all, we must create a softphone object.

static Softphone mySoftphone;

We are handling everything with separated methods. These methods are communicating with each other, and making the source code more understandable and reusable.

How to initialize the softphone?

The first step is to initialize the softphone, we have just created. To do this, we need to call an initializer method with the following lines:

mySoftphone = new Softphone();
mySoftphone.PhoneLineStateChanged += mySoftphone_PhoneLineStateChanged;

Call this method in the Main() method. Now, there is a new softphone available to use, and it's already following the phone line's states. We will see how to handle the states below, after we are done with the welcoming and the registration process.

How to show a greeting message?

In a few lines we are introducing the application to the user. It's preferred to tell about the available functions to use. After our softphone has been initialized, call this method to introduce the application in the Main() method.

How to create SIP account by the user's input and register to a PBX

As we could see at the Softphone class, we need a SIP account to be set to be available to use the softphone for communication. We are asking the user to enter valid values to create a SIP account and to try to register to a PBX. This procedure is done with simple commands, like:

Console.WriteLine();
Console.ReadLine();

In the example's source code You can find a Read() method. With the usage of that method we can set if the asked information must be enter by the user (so, we need to ask for it again and again), or we can set a default parameter instead of that.

You can create your own procedure to get the necessary values from the user. The example shows only a sample way to do it. When the user set up the account, this method starts the registration process. The result of the registration will change the phone line's state, so the next steps will be handled in that chapter. We should call this method in the Main() method, after the greetings.

How to handle the phone line states?

We are subscribed to get notified if the phone line's state has been changed. At the mySoftphone_PhoneLineStateChanged method we can set what to do for each state, if we would like to. In this example we are handling four states: If the registration was unsuccessful, we are asking for user inputs (we are calling the correct method for that purpose), again. States for this case:

RegState.Error

or

RegState.NotRegistered

The "RegistrationFailed" state occurs, when the registration is simply unsuccessful, for example, if the user set up invalid SIP account to register. The "RegistrationTimedOut" state occurs, if the registration request takes too long (for example: in this case, we can programmatically command to try again until it succeeds, or we can ask for a new SIP account creation.)

If the registration has succeeded or there is no need for registration, we are notifying the user about it. Please note that, if there is no need for registration, but we could not reach the PBX (or we could, but with invalid SIP account), we won't notice that until we make our first call. The states to use:

RegState.RegistrationSucceeded
RegState.NoRegNeeded

In the next examples, we will work with our softphone if the registration was successful, but in this example, it's enough to notify the user about the succeeded connection.

What is BlockExit() used for?

You can see a method, called BlockExit() in this Program.cs file. This method's function is to don't let the application to exit, so we can register (or in later examples; make or receive calls) while we would like to. You can write other solutions to solve this, but You won't need anything like this if You are working with Windows Form applications.

Summary

After reading this documentation and studying the source code, we must be familiar about how to add reference to the Ozeki VoIP SIP SDK, how to create a Softphone class which provides a softphone object to the user with the input setups. We have a console window which is interacting with the user and handling our softphone with the provided opportunities.

The next example will introduce how to:

  • Handle the call's events
  • Accept a call
  • Make a call

There are a lot of more available media handlers, not just only microphones and speakers. To learn more about them, you can continue your learning at the next chapter:

You can also learn how to send Instant Messages, by continuing to develop the "SIP Registration" example:

Related Pages

More information