Ozeki VoIP SDK - Product Guide
Developers Guide
Flash SIP client
Explanation
Prerequisities
![]() |
Download: | 06_Web2SIP_DesignedGUI.zip |
This article demonstrates a Flash SIP sample application that connects to a console server for SIP communication based on the professional support of Ozeki VoIP SIP SDK. After reading through this page you will be familiar with all the knowledge you need to write a Flash SIP client and connect it to a server application.
Introduction
This sample program demonstrates a one-line Flash SIP
softphone that is created by using the advantageous Ozeki VoIP SIP
SDK. The sample program supports the following
functions: initiating/receiving calls and sending/receiving DTMF signals.
The Flash clients that connect to the server will register in a SIP PBX with a SIP
account that is selected by the server. This SIP PBX is specified on the server
side. After the Flash softphone registered in the SIP PBX, it is possible to
communicate with any device in the SIP network.
The source codes on this page are easy-to-use and transparent that is why they can be used for realizing SIP projects effectively.
How to create the project
This is a client-server application in which the client is a Flash application, the server is a console application written in C#. This way the whole project consists of a server side project created in Visual Studio and a client side project created in Flash Builder 4.5.
Server-side project
- According to the above mentioned the server is created in VS 2010 with the help of
File->New menu. Its name is ChatGatewaySample. .Net Framework 3.5 has been set as
the project’s target framework.
Note: Sometimes it occurs that projects that are set with .Net 3.5 framework are created by default with ’ .NET 3.5 Client Profile’ in VS2010. In this case, it needs to be set back to .NET 3.5 in order to boost the full toolkit.
- In order to use the toolkit of Ozeki VoIP SIP SDK, the VoIPSDK.dll needs to be added to the project references. It makes the project implementation much easier.
Flash client-side project
- The client side is created by using the File->New->Flex project menu item of Flash
builder 4.5 development environment as a web application. It is called FlashSIPClientExample.
- The FlashClientSDK.swc file (that belongs to the SDK and it includes the client side tools) has been added to the Ozeki VoIP SIP SDK path with the Add SWC… button of Project/ Properties / Flex Build Path / Library path tab.
Server implementation
In this example, the server is responsible for keeping connection with the SIP PBX,
setting up/accepting/hanging up calls and transferring media data between the
PBX/SIP device and the Silverlight client. The server also distributes the accounts
that are required for logging into the PBX. Then it also makes the accounts logged
into the PBX for the connected Silverlight clients.
The server is a console application. The SIPGateway class implements the server’s
functionality toward the client. This class will use and extend the basic server
implementation and functionality (client connection handling, data forwarding services,
mechanisms) that is provided by the Ozeki VoIP SIP SDK. It also uses the tools
provided by Ozeki VoIP SIP SDK in order to implement SÍP and VoIP related
functionality easily and quickly. The object of SIPGateway class is
created by the ’Main(string[] args)’ method (that is the entry point of the
application) in the following way (Code 1):
static void Main(string[] args)
{
Console.WriteLine("Remaining days: {0}",LicenseManager.Instance.RemainingDays);
var sipGateway = new SIPGateway();
sipGateway.Start();
Console.ReadLine();
}
Code 1 - The Main method of the server-side application
The ChatGateway derives from the MediaGateway, this way its constructor can be called in two ways: without a parameter and with a MediaGatewayConfig parameter. In the first case, the constructor expects the configuration from the App.Config file of the application, while in the second case, it expects the configuration from the MedaiGatewayConfig type parameter. The App.Config configuration file is demonstrated in Code 2. It includes the follows:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="mediaGateway">
<section name="mediaGatewayConfig" type="Ozeki.MediaGateway.Config.MediaGatewayAppConfig, VoIPSDK"/>
</sectionGroup>
</configSections>
<mediaGateway>
<mediaGatewayConfig>
<providers>
<add type="silverlight" localIPAddress="0.0.0.0" listenedPort="4502" serviceName="SIPGateway"/>
<add type="flash" serviceName="SIPGateway"/>
</providers>
</mediaGatewayConfig>
</mediaGateway>
</configuration>
Code 2 - The App.config file for the server configuration
Basically, it can be seen that a MediaGatewayAppConfig type configuration section (that
belongs to the MediaGateway class) has been added to the configuration file. Then a
Silverlight and Flash provider have been added to the Providers item of this a
MediaGatewayAppConfig type configuration section. By adding these two providers
to the configuration, the server will be available for both Silverlight clients
and Flash clients.
This way the same code will be able to handle both client types. It can
also be seen that the localIPAddress and listenedPort are specified for one of the
providers while they are not specified for the other provider. The reason for this is
that these configurations have default values that allow missing out the configuration
of these variables.
After creating and configuring SIPGateway object, sipGateway.Start(); instruction will
launch the publication of the server’s functionality.
The SIPGateway is responsible for managing client connections and distributing a free
account for the new clients. The SIPGateway also publishes the extended methods of the
MediaGateway such as initiating/rejecting/receiving calls and sending DTMF signals.
The server’s methods are started via MediaGateway.Start(). Then the OnStart method (Code 3) is
invoked which is overridden in the SIPGateway class. Here the necessary initializations are
made. Then the the follows are created: the collection that includes SIPClients, the
object that models the softphone, and the SIPAccountPool that manages SIP accounts
with some specified SIP accounts.
Furthermore, in order to boost the easy-to-handle
two-way communication between the client and the server provided by the Ozeki VoIP SIP
SDK, the stream service of the SDK is requested by calling the
GetService<IStreamService>(); instruction.
public override void OnStart()
{
Console.WriteLine("SIP Gateway started");
sipClients = new Dictionary<IClient, SIPClient>();
softPhone = SoftPhoneFactory.CreateSoftPhone(SoftPhoneFactory.GetLocalIP(), 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.112.100", 5060);
sipAccountPool.AddSIPAcount(sipAccount);
}
streamService = GetService<IStreamService>();
}
Code 3 - The OnStart() method of the server
The softphone (that can be found in the code) is a tool that is provided by the Ozeki VoIP SIP SDK. It represents a fully featured telephone. Due to the flexible licensing of Ozeki SIP SDK, it is even possible to add more telephone lines to the softphone on which calls can be handled simultaneously. This object is created with the SoftPhoneFactory.CreateSoftPhone. In this example, the IP address of Asterisk PBX and the port range used by the PBX are used.
Methods of SIPGateway that manage client connections
OnClientConnect (Code 4) is an overridden method can be found in SIPGateway class. Ozeki VoIP SIP SDK indicates via OnClientConnect method if a client tries to connect.
public override void OnClientConnect(IClient client, object[] parameters)
{
Console.WriteLine("New client connected. Remote address: {0}", client.RemoteAddress);
var sipAccount = sipAccountPool.GetSIPAccount();
if(sipAccount == null)
{
client.InvokeMethod("OnRegistrationStateChanged", RegistrationState.ConnectionLimit);
client.Close();
return;
}
var sipClient = new SIPClient(client, streamService, softPhone, sipAccount);
sipClients.TryAdd(client, sipClient);
sipClient.Register();
}
Code 4 - The method that invokes when a client sends a connection request to the server
As the next step, a SIPClient object of the client is created if there is a free SIP
account in the SIPAccountPool for the client that requested to connect. This way it
will be registered with the selected account into the SIP PBX that has been specified
in the softphone constructor. If the SIPAccountPool has no free SIP account when the
client tries to connect, the client will be notified about this fact and the
connection is closed.
As opposed to this, OnClientDisconnect method (Code 5) is only responsible for removing the
connected client’s reference from the ConcurrentDictionary. Then it resolves the
SIP account that has been used by the given client and unregisters the account
from the SIP PBX.
ublic override void OnClientDisconnect(IClient client)
{
Console.WriteLine("Client disconnected");
lock (sipClients)
{
SIPClient sipClient;
if (sipClients.TryGetValue(client, out sipClient))
{
sipClient.Unregister();
sipAccountPool.AddSIPAcount(sipClient.Account);
sipClients.Remove(client);
}
}
}
Code 5 - This method invokes when a client disconnects from the server
OnSteamPublishStart (Code 6) will indicate if the given client publishes its MediaStreamSender
object. This way it subscribes the MediaDataReceived event of the media stream to
the MediaDataReceived event handler of the SIPClient. It will then forward the incoming
voice data to the right direction.
It has significance in case of setup calls between two Flash clients or two
Silverlight clients: it determines when the server should start to forward media
data from one participating client to the other one.
public override void OnStreamPublishStart(IClient client, IMediaStream mediaStream)
{
Console.WriteLine("Media stream published. Stream name {0}", mediaStream.Name);
lock (sipClients)
{
SIPClient sipClient;
if (sipClients.TryGetValue(client, out sipClient))
sipClient.StreamPublished(mediaStream);
}
}
Code 6 - The OnStreamPublishStrat method of the server application
As opposed to this, OnStreamClose (Code 7) stops data forwarding of the published stream by unsubscribing the previously subscribed event handler.
public override void OnStreamClose(IClient client, IMediaStream mediaStream)
{
Console.WriteLine("Media stream closed.");
lock (sipClients)
{
SIPClient sipClient;
if (sipClients.TryGetValue(client, out sipClient))
sipClient.StreamClosed();
}
}
Code 7 - This code segment stops the media stream sending
The methods described above are parts of the basic services of Ozeki VoIP SIP SDK. They are overridden according to the current implementation in order to provide the appropriate and requested functionality for this task. The further methods such as start Call, HangUp (accept/reject/hang up active call), Accept call, StartDtmf and StopDtmf are not parts of the basic tools of the SDK, they only extend these basic tools. That is why, these methods are invoked on the client side differently from the basic tools (Code 8).
public function invokeOnConnection(methodName:String, ... params):void
Code 8 - The client-side instruction for invoking server-side methods
The client-side functions can invoke server-side methods by using an instruction similar to the one in Code 9. This particular instruction will invoke the proper server-side function in case of a call.
mediaConnection.invokeOnConnection("Call", dialNumber);
Code 9 - This instruction will invoke the Call function on the server's side
The above seen instruction invokes the Call function that is shown in Code 10 and defined in the client-side Flash code.
public void Call(IClient client, string phoneNumber)
{
SIPClient sipClient;
if (sipClients.TryGetValue(client, out sipClient))
sipClient.Call(phoneNumber);
}
Code 10 The Flash code of the Call function that is invoked from server-side
This will basically forward the request to the SIPClient class, and it starts calling the device with the telephone number received in parameter. HangUp, Accept, Reject, StartDtmf, etc. methods are functioning similarly to Call, this way they are not detailed in this example. Their functions can be checked in the attached source code.
The SIPClient class that represent clients on the server-side
A SIPClient object will be created on server-side for each connected client and manages the telephone line status of these clients (Code 11).
public virtual void Register()
{
phoneLine = softPhone.CreatePhoneLine(Account);
phoneLine.PhoneLineStateChanged += PhoneLine_PhoneLineInformationCanged;
softPhone.IncomingCall += SoftPhone_IncomingCall;
softPhone.RegisterPhoneLine(phoneLine);
}
Code 11 - The server-side method for registering a client
The PhoneLine_PhoneLineInformationCanged event is for indicating the status changes of
the phone line. Meanwhile the IncomingCall event of the Softphone is for indicating incoming
calls.
The Unregister() method, as opposed to Register(), unregisters the phone lines and
unsubscribes from the previously subscribed events.
Call(string dialNumber) method (Code 12) will dial the phone number received in parameter via the Call
object provided by Ozeki VoIP SIP SDK. It also subscribes to the events of this
object that are necessary to make the call.
public virtual void Call(string dialNumber)
{
if (phoneLine == null)
{
System.Diagnostics.Debug.Fail("PhoneLine null");
return;
}
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.DtmfReceived += call_DtmfReceived;
call.Start();
}
}
Code 12 - This method performs the dialing process on server-side
The Accept() method is for accepting the request of an incoming call, while HangUp() rejects an incoming call or terminates active calls. The Call_StateChanged event indicates the current status of the call (Busy, Cancelled, Ringing, Incall, Completed, etc.). It is for indicating call status during the call. Here, InCall status is handled. InCall status indicates that the call reaches that call status when sending/receiving media data can be started (Code 13).
protected virtual void Call_StateChanged(object sender, VoIPEventArgs<CallState> e)
{
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 13 - This method is the EventHandler for the state changes of the call
This way two unique stream identifiers are created in InCall status for the client.
One ID is for sending audio data, the other ID is for receiving audio data from the
remote end. This will be indicated for the client via OnInCall. Callstate.Completed
status indicates that the actual call is completed. This way the created streams
are removed from the service and from the call. The method notifies the client about
the change with its last line.
The media data from the client will be received by the MediaDataReceived event handler (Code 14).
It will forward the media data to the Ozeki VoIP SIP SDK via the myMediaSender object.
Note: It needs to be mentioned that the received media data are data encoded by a
compression mechanism. That is why, it needs to be decoded into raw PCM data. It
is necessary because it is possible that the VoIP SDK uses another compression
mechanism during call setup.
public void MediaDataReceived(object sender, GenericEventArgs<IData> e)
{
if (e.Item is AudioData)
{
var audioData = (AudioData) e.Item;
myMediaSender.SendMediaData(codecConverter.Convert(audioData.CodecType, CodecType.PCM, audioData.RawData));
}
}
Code 14 - The MediaDataReceived event handler method
Call_MediaDataReceived event handler (Code 15) forwards the raw PCM media data from the VoIP SDK to the client via its mediaStream object. Then the media data will be compressed into smaller data size with a compression mechanism.
void Call_MediaDataReceived(object sender, VoIPEventArgs<VoIPMediaData> e)
{
if (mediaStream != null)
mediaStream.SendMediaData(new AudioData(CodecType.PCM, e.Item.PCMData));
}
Code 15 - This method forwards the media data to the remote client
A two-way communication is set up between the server and the client. This way the server can also invoke some certain methods of the client. It is similar to the case when the server can call the client’s extended service functions. The difference is that in this case it is made via the InvokeMethod of the IClient object (Code 16).
void OnIncomingCall(string phoneNumber)
{
client.InvokeMethod("OnIncomingCall", phoneNumber);
}
Code 16 - This method invokes the OnIncomingCall client-side function from the server-side code
Where the server indicates to the client that there is an incoming call from the phone number provided in parameter. InvokeMethod is the method declared in Code 17.
public void InvokeMethod(string methoName, params object[] parameters)
Code 17 - This is the definition of the function invocating method
Similarly, the SIPClient also sends the call status changes to the client via OnCallStateChanged and OnCallErrorOccured methods.
Client implementation
The Flash client represents a one-line webphone with the following functionally:
start/receive/hangup calls, send/receive DTMF signals.
The client implements the GUI (graphical user interface) of a simple softphone with a keypad and a display.
The connection with the server is ensured by the client’s SIPClient class. This way
it will be present from the loading of the interface. That is why creating an
object that belongs to this class requires to load the web application (code 18)
protected function init(event:FlexEvent):void
{
...
sipClient = new SIPClient();
sipClient.addEventListener(ConnectionEvent.CONNECTION_STATE_CHANGED, connectionStateChanged);
sipClient.addEventListener(RegistrationEvent.REGISTRATION_STATE_CHANGED, registrationStateChanged);
sipClient.addEventListener(PhoneLineEvent.PHONE_LINE_STATE_CHANGED, phoneLineStateChanged);
sipClient.addEventListener(CallStateEvent.CALL_STATE_CHANGED, callStateChanged);
sipClient.addEventListener(CallErrorEvent.CALL_ERROR_OCCURRED, callErrorOccurred);
sipClient.addEventListener(IncomingCallEvent.INCOMING_CALL, incomingCall);
sipClient.addEventListener(DtmfEvent.DTMF_RECEIVED, callDtmfReceived);
sipClient.connect();
}
Code 18 - The initialization function of the SIP client
It signs up to the events of the SIPClient in order to display the changes of
the server on the interface. Then it connects to the server.
The interactions of the interface will also reach the server’s certain services
via this SIPClient object.
SIPClient
The SIPClient (Code 19) is responsible for ensuring an interface for the client and the server for the two-way client server communication. For easy implementation, the MediaConnection class provided by the client side implementation of the Ozeki MediaGateway SDK has been used. Since the program immediately connects to the server after loading, this object is initialized in the SIPClient’s constructor with the help of the server address’ parameter.
public function SIPClient()
{
mediaConnection = new MediaConnection("localhost/SIPGateway");
mediaConnection.client = this;
mediaConnection.addEventListener(ConnectionEvent.CONNECTION_STATE_CHANGED, connectionStateChanged);
}
Code 19 - Initializing the media connection
Subscription to CONNECTION_STATE_CHANGED event is necessary to get information
about the result of the connection to the server.
In order to allow the server to call the public methods of the SIPClient object,
it needs to be specified for the Client property of the MediaConnection class that
it needs to search the method (that is invited by the server) in this SIPClient
object. (mediaConnection.xlient = this;)
Since the logic for SIP communication is on the server-side, this class is only
responsible for transferring data to the GUI and the server and it also displays
data arriving from the server on the GUI. The media data will be the exception.
Media data is provided by the Microphone class and attached to a MediaStreamSender
object as an input device after the telephone conversation is setup.
Note: It needs to be mentioned that the appropriate audio compression is made by
the Ozeki VoIP SIP SDK so there are no further tasks besides attaching the
media data. The audio data arriving from the server will be played simply by
invoking the Play function on the MediaStreamReceiver object.
The public methods of the SIPClient can be divided into two groups: one of the
group includes the methods that invoke the server side (such as: connect, call,
hangUp, accept, reject, startDtmf, stopDtmf); the other group includes methods
that can be invoked by the server. They are only invoked by the server (such as
OnCallStateChanged, OnInComingCall,OnPhoneLineStateChanged, etc.).
Since the
methods that invoke the server are not parts of the basic methods provided by
the SDK (except for the Connect method), they are invoked
via the invokeOnConnection function of the MediaConnection object that has the following
method definition that is showni in Code 20.
public function invokeOnConnection(methodName:String, ... params):void
Code 20 - The method invocation function on the client-side
For example, the server side Call method of the client is invoked in the following way (Code 21):
public function call(dialNumber:String):void
{
mediaConnection.invokeOnConnection("Call", dialNumber);
}
Code 21 - The invocation of the Call server-side method
The Call server-side method dials the phone number received in dialNumber parameter. The other server-side methods
are also invoked this way and they are similarly simple. That
is why, they are not detailed here.
The functions of the other method group that are invoked only by the server forward
information from the server to the GUI. OnInCall function (Code 22) is an exception. It
indicates the status of the telephone conversation setup when the audio transfer
from the microphone needs to be started, then needs to be forwarded to the server.
It also indicates when the audio (received from the remote end) needs to be played.
public function OnInCall(publishStreamName:String, playStreamName:String):void
{
mediaStreamSender = new MediaStreamSender(mediaConnection);
mediaStreamSender.attachMicrophone(Microphone.getMicrophone());
mediaStreamSender.publish(publishStreamName);
mediaStreamReceiver = new MediaStreamReceiver(mediaConnection);
mediaStreamReceiver.play(playStreamName);
}
Code 22 - The OnInCall client-side function
The mechanism is the following:
- A MediaStreamSender object is created for sending audio data that arrive from the microphone.
- The Microphone object provided by Flash has been attached to this created object.
- In order to make the server play the outgoing media stream to the remote end (with mediaStreamSender.publish(publishStreamName); instruction) it is published with a unique name.
The other client will play this stream via its MediaStreamReceiver object, after
it invoked the Play method on it with the unique ID published by the other client. In
this case both stream IDs are generated by the server, then the server distributes
these generated IDs to the clients as it can be seen in the code section above.
Different mediaStreams are used for calls that follow each other. That is why when a
call is completed, the stream belongs to the given call needs to be closed and resolved.
OnCallStateChanged function (Code 23) investigates the end of the call that will make the resolution
via closeStreams() call.
private function connectionStateChanged(event:ConnectionEvent):void
{
dispatchEvent(event);
}
private function closeStreams():void
{
if(mediaStreamReceiver)
{
mediaStreamReceiver.close();
mediaStreamReceiver = null;
}
if(mediaStreamSender)
{
mediaStreamSender.close();
mediaStreamSender = null;
}
}
Code 23 - Two basic functions for finishing the client-side application programming
If you have any questions or assistance, please contact us at info@voip-sip-sdk.com
You can select a suitable Ozeki VoIP SIP SDK license for building a Flash SIP softphone on Pricing and Licensing page >>>
Operating systems:
Microsoft Windows XP
Microsoft Windows Server 2003
Microsoft Windows Server 2008
Microsoft Windows Vista
Microsoft Windows 7
Developer environment:
Microsoft Visual Studio 2010
Microsoft .Net Framework 3.5 or 4.0
Flash builder 4.5 or other equivalent IDE
Flash player 10 +
Internet connection
Hardware requirements:
1 GHz or faster processor
1 GB RAM (32-bit) +
INTERMEDIATE
VoIP technology walkthrough
Softphone development
Webphone development
Mobile development
Voice recording
GETTING AROUND
Sitemap
Search the manual
API documentation
FAQ
Appendix


