Regardless of the language you use to develop
your VOIP application, there are a few software design considerations
you must be aware of in order to achieve the best possible behavior and
performance from the VOIP Media Engine
The information discussed here applies equally to native code application
development (C, C++, pascal, etc) and managed .NET code application development
(Vb.NET, C#.NET, etc).
Application software communicates with the media engine using the published
media engine API. There are no restrictions when using this API from normal
application GUI threads or application worker threads.
The media engine communicates with the VOIP application software using
a single "main callback handler". The media engine calls this
application specified callback procedure anytime the media engine has
event information for the application. Because the media engine is fully
multi-threaded, the media engine thread context used to execute the application's
callback handler will vary depending on what events are being sent to
the VOIP application.
Note:
Most high performance VOIP applications will want to use the callback event mechanism in order to get the best possible performance and maximum call handling capability from the media engine. However, the media engine can be used in a polling mode where no callback handler is specified when the media engine is started. In this case, the application must use media engine API status procedures to poll the state of phone lines and other operations in order to determine proper application activity.
Figure 1
below shows the recommended threading layout of a VOIP application that
will use the event callback mechanism. The VOIP application can have any
number of threads in its process space (i.e. the GUI thread and any number
of worker threads). Media engine API procedures can be called from whatever
application thread your design requires in order to initiate specific
media engine activities (like performing SIP registrations or making calls).
Figure 1: Basic Media Engine Callback Model
When the application needs to perform a telephony operation (like initiating
an outgoing phone call), it can do so using whatever thread of execution
makes the most sense for the application. The application thread need
only call the appropriate media engine API procedure from the application
thread.
When the media engine sends events to the application, it will execute
the application's callback
handler. To allow the telephony engine to perform its tasks as smoothly
and as quickly as possible, it is recommended that the event notifications
received by your callback be put into a FIFO queue. Your application should
then have one of its own worker threads process the FIFO event data as
required.
IMPORTANT:
The event callback is non-reentrant. In other words, the media engine has serialized access to your callback event handler procedure. Your VOIP application must not call any media engine API procedures in the event handler that will in turn generate further events. Any API procedure that can generate additional events cannot be called in the "main event handler" when processing the current event. If you do, your application will deadlock. For example: Calling any of the following API procedures directly from within the callback handler will most likely result in your application deadlocking: MakeCall(), MakeCallUri(), TerminateCall(), GoOffHook(), AbortIncomingCall(), BusyOutLine(), HoldLine(), ConferenceLine(), TransferLine(), TransferLineUri(), EnableSipRegisterServer() or DiableSipRegisterServer().
Figure 1
above shows how the media engine communicates with your application
code. When the media engine has event information for your application,
it executes your callback handler (i.e. the "main callback handler").
The primary goal of all application code executed in the callback handler
is speed. Only perform the bare minimum of application associated tasks
in the callback handler. If you adhere to this rule, you will experience
the best possible performance from the media engine.
There are three classes of media engine events: PHONE_LINE_NOTIFICATION, GLOBAL_NOTIFICATION and IMMEDIATE_NOTIFICATION events.
IMMEDIATE_NOTIFICATION event must be fully processed in the callback event
handler. When receiving these immediate events, the media engine is asking
your application for information or assistance regarding some operation
that is taking place. The type of application you are developing will
determine if you have to handle any of the immediate events. All media
engine APIs that are required for processing immediate events are designed
to be called from within the callback handler procedure and will not deadlock
your application.
PHONE_LINE_NOTIFICATION and GLOBAL_NOTIFICATION events should be "briefly
processed" in the callback handler. When we say "briefly processed",
we mean your VOIP application should perform as little processing of the
event in the callback handler as possible. The preferred method to process
these two classes of events are to gather the event data and any other
status information for the event (using status related APIs like GetIncomingCallInfo(), GetOutgoingCallInfo()
or GetActiveCallInfo())
and queue the event data to an application supplied event FIFO. This is
shown in Figure 1.
Your VOIP application code should have a dedicated worker thread (ApplicationEventWorkerThread())
that does nothing until it detects that there is event data in the event
FIFO. Once your ApplicationEventWorkerThread() executes, it can process
the event data as required and call any of the needed media engine APIs
without risking deadlock situations.