info@voip-sip-sdk.com Tel: +36 1 371 0150

How to build a Flash SIP softphone for web to SIP calls

Explanation

Prerequisities

Download: 03_Softphone_Web2SIP_calls.zip

This article is a detailed guide for building a Flash SIP softphone solution using Ozeki VoIP SDK. After reading this manual you will be able to write your own fully featured Flash softphone application and webphone server and as Ozeki VoIP SIP SDK provides you all the background support you will also find it an easy task to do.

Introduction

Ozeki VoIP SIP SDK provides you all the background support for building a Flash webphone. And more than that, as you can not only write a simple click-to-call webphone but can also implement a fully featured softphone that can be embedded in your web site.


Figure 1 - Flash softphone solution with Ozeki VoIP SIP SDK

From now on, if you put an Ozeki VoIP SIP SDK supported softphone in your web site, your customers can call you, or some other numbers you allow for that matter, only by using this embedded application.

Ozeki provides support for both server- and client-side webphone programming, and as for the client-side it supports both Silverlight and Flash technologies. And even more, as you can use the same server for both client types.

This guide will show you how you can write a fully featured Flash softphone that can be embedded in your web page and how you can build an Ozeki VoIP SIP SDK supported C# console server application that is capable of handling the connection of both Flash and Silverlight clients.

The sample program that is introduced in this guide is written in C# (as for the server-side) and Adobe Flash (as for the client-side) and uses the background support of Ozeki VoIP SIP SDK. If you want to follow the guide properly and want to build a similar solution, you will need to have Ozeki VoIP SIP SDK that is the part of the Ozeki VoIP SIP SDK downloaded and installed on your computer.

The server-side application of this example is written in C# language. You will need to have Visual Studio 2010 to run this server properly.

The basic changes in the server functionality

As in the case of the Silverlight solution the webphone server needs to make some basic changes to be able to establish a SIP connection. It may be good if you read through the pages about softphone technology in order to see the fundament of this new server.

The basic softphone programming guide can be found on Ozeki VoIP SIP Softphone page. It is strongly recommended to become familiar with the basic terms of softphones if you want to create a Flash softphone solution. These guides will refer to softphone tools and settings as they were familiar to you.

If you want to know more about webphone technology, you can check the following pages:

The MyClient class should be partly rewritten for the softphone support

As you surely know the MyClient class in the previous click-to-call example programs was only a storage class that had an IClient object and a name field defined in it. In this case, the MyClient class will represent a more complex function as it will store the whole SIP support and background for the webphone clients.

In order to be able to use the object names without labeling them with the namespaces, you will need to use some new using lines in you code like in Code 1.

Of course, you can only use these tools and namespaces if you have registered your Ozeki VoIP SIP SDK to your server project on the Solution Explorer panel.

using Ozeki.Common;
using Ozeki.Media;
using Ozeki.Media.MediaHandlers;
using Ozeki.MediaGateway;
using Ozeki.MediaGateway.Data;
using Ozeki.MediaGateway.Service;
using Ozeki.Network;
using Ozeki.Network.Nat;
using Ozeki.VoIP;
using Ozeki.VoIP.Media;
using Ozeki.VoIP.SDK;

Code 1 - The using lines ensures the use of the objects without namespace labeling

Code 2 shows the tools you will use when having a webphone client. You can see a lot of tools that can be familiar from the softphone examples. There is a need for example for a phone line or a softphone object and you will need to handle SIP accounts as well.

IClient client;
ISoftPhone softPhone;
IPhoneLine phoneLine;
IPhoneCall call;
IStreamService streamService;
IMediaStream mediaStream;
string publishStreamName;
string playStreamName;
MediaConnector mediaConnector;
MyMediaSender myMediaSender;
PhoneCallAudioSender phoneCallMediaSender;
CodecConverter codecConverter;

Code 2 - SIP initialization in MyClient class

When creating a new client, the program initializes the basic tools for the connection. At this time the server itself will handle the available SIP account for the clients and it will give and get back them in case of a client connection or disconnection.

This solution of the SIP account handling allows you to limit the number of the clients that can be connected to the server at the same time. If there is no available SIP account the server will reject the connection request of the clients.

The constructor of the MyClient class initializes the basic tools and sets the field values according to the parameters (Code 3).

public MyClient(IClient client, IStreamService streamService, ISoftPhone softPhone, SIPAccount account)
{
    mediaConnector = new MediaConnector();
    myMediaSender = new MyMediaSender();
    phoneCallMediaSender = new PhoneCallAudioSender();
    codecConverter = CodecConverter.Instance;

    mediaConnector.Connect(myMediaSender, phoneCallMediaSender);

    this.streamService = streamService;
    this.softPhone = softPhone;
    this.client = client;

    Account = account;
}

Code 3 - MyClient class constructor

As this solution will be a fully featured softphone application you have to handle the registration to the softphone PBX. This function will also be written in the MyClient class. (Code 4).

The phoneLine is created with the SIP account the client gets from the server and it must be registered to the state change event. The softphone object also has to be registered to the incoming call event in order to be able to notice an incoming call. The last step is to register the phone line to the softphone. This establishes the PXB registration.

The only difference between this registration and the registration of an ordinary softphone is that in this case the SIP account is provided by the server.

{
    phoneLine = softPhone.CreatePhoneLine(Account);

    phoneLine.PhoneLineStateChanged += PhoneLine_PhoneLineInformationCanged;
    softPhone.IncomingCall += SoftPhone_IncomingCall;


    softPhone.RegisterPhoneLine(phoneLine);

}

Code 4 - The softphone registration to a SIP PBX is the same as for an ordinary softphone

The EventHandler methods for the incoming calls and the change of the call state will be slightly different from the previously written softphone methods. In case of this webphone solution, there is a server that will handle the connection and communication between the clients.

Code 5 shows the EventHandler for the incoming calls. It ensures that the right phone line is used with a conditional instruction.

if (e.Item.PhoneLine == phoneLine)
{
call = e.Item;
call.CallErrorOccured += Call_ErrorOccured;
call.CallStateChanged += Call_StateChanged;
call.MediaDataReceived += Call_MediaDataReceived;

OnCallRequest(call.DialInfo);
}

Code 5 - In case of an incoming call you will register to some events of the call

The call state change event is one of the most important events to notice. This informs both the server and the client about a change in the call state (Code 6).

This method has two sections. The first part is a multiple choice instruction that decides about the type of the change and starts the proper activities.

The publishStreamName is the name that the client publishes and the playStreamName is the one that the server will publish. These publishing calls have to be made in case of an incoming call.

This method also calls the OnInCall method that invokes the OnInCall method of the client-side application. This method makes the client run the proper activities in case of an incoming call.

When one of the clients hung up the phone, the method will detach the phoneCallMediaSender from the call, remove the streamService object from the mediaStream and free the call object. This case is identified with the CallState.Completed value.

The second part of the EventHandler is only made up one instruction that informs the remote client about the change in the call state. This method call will invoke the proper method of the remote client.

switch (e.Item)
{
case CallState.InCall:
    phoneCallMediaSender.AttachToCall(call);
    publishStreamName = Guid.NewGuid().ToString();
    playStreamName = Guid.NewGuid().ToString();

    mediaStream = streamService.CreateStream(playStreamName);
    timeStamp = 1000;
    OnInCall(publishStreamName, playStreamName);
    break;

case CallState.Completed:
    phoneCallMediaSender.Detach(call);

    streamService.RemoveStream(mediaStream);
    call = null;
    break;
}
OnCallStateChanged(e.Item);

Code 6 - The call state change event has to be noticed by the server and both connected clients

The MyClient class implements the methods that invoke the client-side methods according to the messages from the other clients. The client-side application has to have the proper methods that can be invoked in case of these method calls.

The server can invoke the client-side method by giving the method's name as the first parameter of the invoke call and then it has to set all the parameters the client-side method needs (Code 7).

client.InvokeMethod("ClientMethodName", [method parameter(s)]);

Code 7 - The server can invoke the client's proper method with this instruction

The MyClient class also contains the basic methods for handling the call. These are the well-known softphone methods and they can be implemented similar to the ones you did in case of the softphone application.

Code 8 shows the main functionality of the Call method that is for starting a call towards a remote client. Starting a call needs the same registration to the possible call events as in case of an ordinary softphone.

if ((phoneLine.RegisteredInfo == PhoneLineState.RegistrationSucceded || phoneLine.RegisteredInfo == PhoneLineState.NoRegNeeded) && call == null)
{
call = softPhone.CreateCallObject(phoneLine, dialNumber);

call.CallErrorOccured += Call_ErrorOccured;
call.CallStateChanged += Call_StateChanged;
call.MediaDataReceived += Call_MediaDataReceived;
call.Start();
}

Code 8 - Starting a call is similar to the softphone method

The MyClient class used a SIP account in several cased and it was mentioned that the server itself gives a SIP account to each clients. For this purpose you will need to define a new class.

The server stores and handles the available SIP accounts

This server solution has a new class that stores all the available SIP accounts. These accounts are given to the connected clients from the server. If there is no available SIP account, the server rejects the connection request with the message that notifies the client about the loss of SIP accounts.

The server uses the SIPAccountPool class for storing the available SIP accounts. You can put all the usable accounts to this pool and the server will get one for the connected clients. When a client diconnects, the SIP account will be put back into the pool and can be given to another client that will connect later.

The SIP AccountPool class only has the GetSIPAccount and the AddSIPAcount methods. The GetSIPAccount method will provide a SIP account to the connected client. It gets one account from the Queue object and returns with it. The account will be dequeued from the pool.

The AddSIPAcount method will add a SIP account to the pool Queue object. This method is called when the server fills up the pool when it starts and it is also called when a client disconnects and gives back the SIP account it got from the server.

The SIPGateway class will implement main server functionality

The SIPGateway class implements the main server functionality in this project. This class looks similar to the one that was defined in case of the click-to-call webphone solution but it has some differences for the softphone functionalities.

This webphone server will need the properties of a softphone and a SIPAccountPool that will store the SIP accounts the server can give to the clients. When the server starts and the OnStart method is called the softphone is initialized and the usable SIP accounts will be set (Code 9).

This server application will generate 18 different SIP accounts that can be registered to the PBX. Note that you have to set your own proper SIP accounts you got from your PBX provider in order to have your webphone work.

Note that you need to set your PBX IP and port information in order to have your webphone work. If you do not know these data, please ask for them from your PBX provider.

Console.WriteLine("SIP Gateway started");

MyClients = new Dictionary<IClient, MyClient>();
softPhone = SoftPhoneFactory.CreateSoftPhone("192.168.113.6", 5060, 5800, 5060);

sipAccountPool = new SIPAccountPool();

for (int i = 80; i < 99; i++)
{
var name = "oz8" + i;
var sipAccount = new SIPAccount(true, name, name, name, name, "192.168.115.1", 5060);

sipAccountPool.AddSIPAcount(sipAccount);
}

streamService = GetService<IStreamService>();

Code 9 - This method runs in case of the server start

In case of a client connect request is received the sever calls OnClientConnect method (Code 10). The client gets a SIP account from the server or if there are no available SIP accounts the client's OnRegistrationStateChanged method will be invoked with the parameter "Connection limit" that means that the server actually rejected the connection request.

If there is at least one available SIP account the client is initialized and put in the register Dictionary of the server.

Console.WriteLine("New client connected. Remote address: {0}", client.RemoteAddress);

var sipAccount = sipAccountPool.GetSIPAccount();

if (sipAccount == null)
{
client.InvokeMethod("OnRegistrationStateChanged", "Connection limit");
client.Close();
return;
}

var MyClient = new MyClient(client, streamService, softPhone, sipAccount);
MyClients.Add(client, MyClient);

MyClient.Register();

Code 10 - When a client connects to the server it gets a SIP account to use

When a client disconnects the server gets back the SIP account ant puts it back to the pool of available SIP accounts.

The server has to implement the basic EventHandler methods that are related to the call. These methods are similar to the ones you used for the click-to-call webphone.

The server configuration xml file has to contain information about the supported client types. If you put the lines in Code 11 into the App.config file of the server, your server will be able to receive connection requests from both Sivlerlight and Flash clients.

Note that you need to set your server information in the configuration file (server name, IP and listening port) in order to have a properly working webphone server.

<providers>
     <add type="silverlight" localIPAddress="0.0.0.0" listenedPort="4502" serviceName="SIPGateway"/>
     <add type="flash" listenedPort="1937" serviceName="SIPGateway"/>
</providers>

Code 11 - The server configuration file needs to contain these lines for defining the supported clients

After having all these methods, you can start implementing the client-side application in Flash.

How to build a Flash softphone client using Ozeki VoIP SIP SDK

The client-side solution of this sample webphone program is written in Flash. You will need Adobe Flash builder and Flex 4.5.1 if you want to build this client application.

This client also uses the background support of the Ozeki VoIP SIP SDK that provides a .swc file for the Flash clients. You will also have to have this .swc file and you will have it registered to your Flash Builder project.

As this client-side application is a fully featured softphone, it is easier to start a new project in Flash Builder that modifying one of the former webphone clients. After setting Flex 4.5.1 and Ozeki VoIP SIP SDK during the project creation process you can start to build the GUI of the softphone.

A fully featured softphone needs a display with some notification and a dialing label and a standard telephone keypad. The keypad needs to have a Call and a Call stop button that will have the same functionality as in case of the click-to-call webphone.

The numeric keypad is also essential for a softphone GUI. It has to contain the numeric buttons form 0 to 9 and the usual '*' and '#' buttons.

You can build this GUI on the Design panel by using your mouse and setting some properties of the elements on the Properties panel. After you customized your GUI it should look similar to the one shown in Figure 2.


Figure 2 - The GUI of a Flash softphone

If your GUI is ready, you can start the programming stage. The functionality of the client will be similar to an ordinary softphone, only you will need to use Flash syntax and some webphone functions too.

First of all, you will need to define the basic variables that will be essential for the softphone functionality. These are the sender and receiver object, the connection itself and, of course, the microphone (Code 12).

If you want to use the VoIP SIP provided object like connection or mediaSender, mediaReceiver without namespace labeling, you will need to import the mediaGateway namespace in your program too.

private var connection:MediaConnection;
private var streamSender:MediaStreamSender;
private var streamReceiver:MediaStreamReceiver;
private var microphone:Microphone;
private var callProcess:Boolean;

Code 12 - The essential variables have to be declared

The establishment of the connection is the same as in case of a normal softphone. The MediaConnection constructor needs the essential data about the server (IP, name, listening port) and the connection can be established. You also need to attach the client to the connection and sign up to the state change event (Code 13).

Note that you have to set your own server data here in order to be able to connect your client to the server. This information needs to be the same that you specified in the server configuration file.

connection = new MediaConnection("localhost:1937/SIPGateway");
connection.client=this;
connection.addEventListener(ConnectionEvent.CONNECTION_STATE_CHANGED,connecionStateChanged);
connection.connect();

Code 13 - The connection establishment is very similar to the ordinary softphone method

You will need to write the EventHandler functions for the buttons. As for the numeric keypad (including the * and # buttons) you can use a single EventHandler as they are only used for dialing. The function only needs to append the proper number to the dial number label on the display.

The call button has the functionalities of starting and accepting a call. When you press the button, the phone state will decide which activity should be performed. Code 14 shows the EventHandler function for the Call button. In both cases it calls the same function that will be establish the connection the only differences are in the notifications that will appear on the display and the setting of the actual phone state.

switch (phoneState)
{
        case PhoneState.INRINGING:
                connection.invokeOnConnection("Accept");
                setPhoneState(PhoneState.INCALL);
                break;
        case PhoneState.READY:
                connection.invokeOnConnection("Call", lblDial.text);
                lblInfo.text = "Outgoing call progress.";
                setPhoneState(PhoneState.OUTRINGING);
                break;
}

Code 14 - The EventHandler for the onclick event of the Call button

The Call stop button ends all reject a call according to the phone state. The EventHandler for this button can be seen in Code 15. This method also uses a multiple choice (switch) instruction for the decision about the proper activity.

switch (phoneState)
{
        case PhoneState.INRINGING:
                connection.invokeOnConnection("Reject");
                setPhoneState(PhoneState.READY);
                break;
        case PhoneState.OUTRINGING:
        case PhoneState.INCALL:
                lblInfo.text = "Call stop, ready to call.";
                connection.invokeOnConnection("HangUp");
                setPhoneState(PhoneState.READY);
                break;
}
lblDial.text = "";

Code 15 - The EventHandler function for the Stop call button

The client-side application needs to implement the methods that will be invoked from the server-side according to the remote client's activity. These are the functions those names start with "On".

Code 16 contains an example of the server-side invoked functions, namely the OnInCall function that runs in case of a call. This method is for sending audio data to the remote client and for receiving and playing the audio stream that comes from it.

The function attaches the microphone to the streamSender and publishes the client's name. The streamReceiver is also created and it starts to play the incoming audio stream.

streamSender = new MediaStreamSender(connection);
streamSender.attachMicrophone(Microphone.getMicrophone());
streamSender.publish(publisStreamName);

streamReceiver = new MediaStreamReceiver(connection);
streamReceiver.play(playStreamName);

Code 16 - The OnInCall function that is invoked from server-side in case of a call

The other invoking functions work the same way. If you check the code in the example program, you will see that all the functions implement a same activity as the softphone and webphone applications you used before. You will need exactly the same methods in this case.

After you have all the EventHandler and invoking functions implemented, you can start your server and clients and you will be able to use your webphone right away. Do not forget to check that you have set the right data for the server and the PBX in order to have a proper working webphone solution.

This article gave you a detailed guide for programming a Flash softphone solution that can be connected to your webphone server. If you followed the guide carefully and you set have the right server data, you now have a fully operational softphone solution with the background support of Ozeki VoIP SIP SDK on both server- and client-side.

If you have read this guide and became familiar with all terms related to a Flash softphone, you can explore more extraordinary features of the Ozeki VoIP SIP SDK and you will surely found the best solution for all your communication related wishes.

If you have any questions or need assistance, please contact us at info@voip-sip-sdk.com

You can select a suitable Ozeki VoIP SIP SDK license for your project on licensing page

Related Pages

Operating system: Windows 10 Windows 8, Windows 7, Vista, 200x, XP
System memory: 512 MB+
Free disk space: 100 MB+
Development environment: Visual Studio 2012, Visual Studio 2010, Visual Studio 2008, Visual Studio 2005, Adobe Flash Builder 4.5
Programming language: C#.NET, Adobe Flash
Supported .NET framework: .NET Framework 4.5, .NET Framework 4.0, .NET Framework 3.5 SP1
Software development kit: OZEKI VoIP SIP SDK(Download)
VoIP connection: 1 SIP account

Ozeki Cookie Policy
Ozeki Informatics Ltd uses cookies to provide you the best experience on this website. The further use of the website will be considered as an agreement to the use of cookies. For more information read this website.

Cookies are enabled You are browsing the optimized version of this website. For more information read this website.