Overview
IP telephony is the ground-breaking consequence of the convergence between
telecommunications and computer networks. Telephony services can now
be enriched with a host of new functionalities provided by IP network
servers that provide resources such as databases, e-mail facilities
and Web services. This enrichment critically relies on the development
of new services that take advantage of these features. However,
developing enriched, real-size services is quite a challenge
considering the requirements that must be fulfilled by the service
developers. First, developers must have an extensive knowledge on network
protocols and distributed systems. Also, they must be familiar with
often large and complex platform APIs, targeting in-breath and
in-depth access to the platform (e.g., JAIN). Lastly, they must fully
understand the signaling protocol (e.g., SIP) to develop services that
do not compromise the processing of the calls, nor the platform.
To overcome this challenge, we propose SPL, a high-level DSL for
specifying robust Internet telephony services. SPL reconciles
programmability and reliability of telephony services, and offers
high-level constructs that abstract over intricacies of the underlying
protocols and software layers. SPL makes it possible for owners of
telephony platforms to deploy third-party services without
compromising safety and security. This openness is essential to have a
community of service developers that addresses such a wide spectrum of
new functionalities.
Detailed description
The SPL project has two main contributions:
SIP Virtual Machine The analysis of the SIP protocol
is the starting point of the SPL design. The level of abstraction of
the protocol was raised to match the needs of service
development. This process resulted in a domain-specific virtual
machine, named the SIP VM. This virtual machine is centered around
the notion of a session, consisting of a set of events and a state,
which structures the development of telephony services.
Session Processing Language. The SIP virtual machine,
combined with common programming patterns found in telephony services,
forms the main ingredient in the design of SPL. The syntax of an SPL
service reflects the SIP VM session structure. Each kind of session
is represented by a block containing the declarations of the
variables and handlers associated with the session.
SPL semantics have been formally defined, enabling critical properties
services to be guaranteed and capturing expertise on the operational
behavior of a service.
For instance, when a positive response is received (i.e., a 2xx
response code), no additional forwarding of the request is allowed and
the response should be returned as the result of the SPL handler. This
restriction prevents a service from forwarding a call to someone other
than the party who accepted it. We have defined an formal static
analysis that ensures that this restriction is satisfied for any
program written in SPL.
Another example is how requests and responses are handled by SPL.
In SIP, for every request, a response is provided. SPL guarantees this
property by design. Indeed, every request handler (except ACK handler)
must return a response. This design prevents the telephony system from
an inconsistent state.
The compiler parses services and performs the previously mentioned
safety verifications. Then, SPL is interpreted by the SIP application
server. The interpretation is performed by the SLEE (Service Logic
Execution Environment). It is the topmost layer of our application
server. Intermediate layers provide abstractions from the JAIN
SIP
API
to the SLEE as illustrated by Figure 1. The abstractions consists of
events, which are interpreted requests or platform operations, and
sessions, which reflect the SIP philosophy.
Figure 1. Application server architecture
SPL has three main abstractions: sessions, handlers and branches
Sessions
The structure of an SPL service reflects the SIP VM session structure.
Each kind of session is represented by a block containing the declarations
of the variables and handlers associated with the session. Sessions are
organized into a hierarchy, with a service session at the root, the
registration sessions created within the service session as its children,
and dialog and subscription sessions at the leaves. A session at any level
has access to all of the variables of its ancestor sessions.
As an example, Figure 2 shows the SPL service sec_calls, that
implements a counter service. This service maintains a counter of the
calls that have been forwarded to a secretary, whenever the SIP user
associated with the service is unable to take the call. The counter
is set to 0 when the user registers, incremented when a call is
forwarded to the secretary, and logged when the user unregisters.
Handlers
For each event generated by the SIP VM, an SPL service may define a
handler to describe how the service should react to the event. In the
case of verbatim and refined events, the handler processes a complete
SIP transaction from the request to the final response.
Platform events do not
correspond to a SIP request. Therefore, the handler for such an event
only performs non-signaling operations.
A handler may
be designated as either
incoming or
outgoing to
provide a specific behavior for messages received or emitted by the
user associated with the service, respectively. By default, a handler
treats both incoming and outgoing requests.
The
INVITE handler in Figure 2 (lines
17-24) illustrates SPL transaction processing for incoming
INVITE requests. In this example, the forward
operation (line 18) is used initially to forward an incoming call to
the original recipient. This operation yields control to the SIP VM,
which resumes the handler when a response is received. This response
is then stored in the variable
r and checked in line 19.
SPL offers domain-specific abstractions and operations for such
processing of SIP responses: Comparing a response to
/SUCCESS
checks whether the response code of the response is in the range
2xx, while comparing a response to
/ERROR checks
whether the response code of the response is greater than
300. In the example, if the call was not accepted, the
original request is redirected to the secretary (line 21) and the new
response is returned to the caller. If the call was accepted, the
success response that was stored in
r is returned directly (line 23).
As a component of a SIP application server, the SIP VM may receive requests
at any time. To simplify SPL programming, the SIP VM never invokes a
handler during the execution of another handler. Instead, events are queued
by the SIP VM until the handler being executed yields control to the SIP
VM, either due to a
forward or a
return operation. At
this point, the SIP VM sends the request or response, respectively, out on
the network and treats other pending requests. In the case of a
forward, when a response arrives, the SIP VM resumes the handler
containing the
forward operation. The execution of a handler is thus
atomic between two yield points,
i.e., two signaling operations.
1 service sec_calls {
2 localvoid log (int);
3
4 registration {
5 int cnt;
6
7 response outgoing REGISTER() {
8 cnt = 0;
9 return forward;
10 }
11
12 void unregister() {
13 log (cnt);
14 }
15
16 dialog {
17 response incoming INVITE() {
18 response r = forward;
19 if (r != /SUCCESS) {
20 cnt++;
21 return forward 'sip:secretary@example.com';
22 } else
23 return r;
24 }
25 }
26 }
27 }
Figure 2. Answered call counter example
Branches
The SIP protocol imposes a coarse-grained flow of control within each kind
of session. For example, in a dialog, control may flow from
INVITE to
ACK and to
BYE. To enhance expressiveness, SPL allows the
programmer to refine the control-flow specification via a
branch
mechanism that passes control information from one handler to the next.
This abstraction permits,
e.g., classifying a session as either
personal or professional, and then introducing a logical
personal or professional
sub-thread across
the remaining handler invocations of the session. As shown in
Figure 3, the classification is done by adding the
name of the branch to the return from the current handler (
e.g., line
12) and the threads are implemented in each handler using the
branch
construct (
e.g. lines 22-25).
1 service waiting_queue {
2 [...]
3 registration {
4 [...]
5 dialog {
6 [...]
7 response incoming INVITE() {
8 response resp = forward;
9 if (TO == 'sip:secretary@enseirb.fr') {
10 [...]
11 // Session tagged as "secretary"
12 return resp branch secretary;
13 } else {
14 [...]
15 // Session tagged as "private"
16 return resp branch private;
17 }
18 [...]
19 }
20 [...]
21 response incoming ACK() {
22 branch secretary {
23 // Specific treatment for secretary session
24 [...]
25 }
26 branch private {...}
27 [...]
28 }
29 [...]
30 }
Figure 3. Inter-handler control flow
The branch construct is not only convenient for the programmer, it
also increases the amount of information that is available to static
verifications of SPL programs. Specifically, as the branch mechanism
is a built-in language construct, it enables inter-handler control
flow information to be determined accurately, before execution
time. If this mechanism were not available, the programmer could
simulate the same behavior using flags stored in the session state and
conditionals in each handler testing the flag values. In this case,
however, the control-flow information represented by the branches
would not in general be apparent to the verifications associated with
SPL, which would result in a less precise analysis.
Use cases
To demonstrate the usability of SPL, we have developed a queuing
service of our department secretary. Its goal is to automatically
handle incoming call for the telecommunication department. Calls are
redirected to the secretary when she is available. If for some reason,
she could not answer, the call is placed in a waiting queue. As soon
as the secretary becomes available and could take new call, the oldest
call in the queue is transfered from the queue to the secretary.
The queuing service example is available
here.
Future work
Related Phoenix projects
Publications
Publications (papers, presentations and Bibtex references) about SPL are available
here
Participants
Nicolas Palix
Laurent Burgy
Fabien Latry
Laurent Réveillère
Charles Consel
Julia Lawall
Tools
OCaml (OCamlLex and OCamlYacc)
Java with JAIN SIP API and NIST Reference Implementation