Isabelle Puaut
email: isabelle.puaut@irisa.fr

Mickaël Dardaillon
email: mickael.dardaillon@irisa.fr

Christoph Cullmann
email: cullmann@absint.com

Gernot Gebhard
email: gebhard@absint.com

Steven Derrien
email: steven.derrien@irisa.fr

Fine-Grain Iterative Compilation for WCET Estimation

Keywords: 2012 ACM Subject Classification Computer systems organization → Real-time systems, Computer systems organization → Embedded systems Worst-Case Execution Time Estimation, Compiler optimizations, Iterative Compilation, Flow fact extraction, Outlining Digital Object Identifier 10.4230/OASIcs.WCET.2018.9

Compiler optimizations, although reducing the execution times of programs, raise issues in static WCET estimation techniques and tools. Flow facts, such as loop bounds, may not be automatically found by static WCET analysis tools after aggressive code optimizations. In this paper, we explore the use of iterative compilation (WCET-directed program optimization to explore the optimization space), with the objective to (i) allow flow facts to be automatically found and (ii) select optimizations that result in the lowest WCET estimates. We also explore to which extent code outlining helps, by allowing the selection of different optimization options for different code snippets of the application.

Introduction

Real-time systems play an important role in our daily life. In hard real-time systems, computing correct results is not the only requirement. Results must be also produced within pre-determined timing constraints, typically deadlines. To obtain strong guarantees on the system temporal behavior, designers must compute upper bounds of the Worst-Case Execution Times (WCET) of the tasks composing the system, in order to finally guarantee that they meet their deadlines. Standard static WCET estimation techniques [START_REF] Wilhelm | The worst-case execution-time problem -overview of methods and survey of tools[END_REF] compute such bounds from static analysis of the machine code. Their goal is to obtain a safe and accurate estimation of a task execution time on a given hardware platform. The safety criterion ensures that the WCET holds for any possible execution of the task on the target platform, whereas accuracy avoids resource over-provisioning. WCET analysis is confronted with the challenges of extracting knowledge of the execution flow of an application from its machine code. In particular, loop bounds are mandatory to estimate WCETs. Extraction of flow information can be performed automatically by static WCET analysis tools, or guided by the designer through flow facts (loop bounds, unfeasible paths) expressed using source-level annotations.

Compiler optimizations are well known to significantly improve the (average-case) performance of programs, but raise issues regarding WCET estimation. On the one hand, automatic detection of loop bounds may not be feasible anymore because the generated code is more complex and less amenable to static analysis. On the other hand, manual annotations may not be valid anymore after the code optimizations (loops may have been unrolled, re-rolled, split, fused, or may simply have disappeared from the code).

To safely benefit from compiler optimizations, in this paper, we explore the use of iterative compilation (exploration of the optimization space) to minimize WCETs instead of averagecase in the original use of iterative compilation [START_REF] Cooper | ACME: adaptive compilation made efficient[END_REF][START_REF] Agakov | Using machine learning to focus iterative optimization[END_REF][START_REF] Chen | Deconstructing iterative optimization[END_REF]. More precisely, our contributions are the following:

We propose and evaluate coarse-grain (application-level) WCET-oriented optimization exploration strategies. Each of the two proposed strategies selects a sequence of optimization passes that (i) allows static WCET analysis tools to automatically detect loop bounds (i.e. disregards optimizations making the WCET estimation fail because it is unable to detect some loop bounds without the use of annotations); (ii) results in the lowest estimated WCET. Two strategies are proposed, the former based on random selection of optimization sequences and the latter using a genetic algorithm. We detail and provide preliminary experimental data on a fine-grain (code snippet-level) WCET-oriented optimization exploration strategy, that allows different optimization per code snippet. Interesting code snippets (for the scope of this paper, loops) are outlined, to allow different optimization sequences within a same function. This enables selective application of optimizations: code snippets for which static WCET estimation tools can detect loop bounds with optimizations can be aggressively optimized, whereas the remaining parts can be left un-optimized and later fed with source-level flow fact annotations [START_REF] Lefeuvre | Using polyhedral techniques to tighten wcet estimates of optimized code: a case study with array contraction[END_REF]. Experiments were conducted using the LLVM [START_REF] Lattner | LLVM: A compilation framework for lifelong program analysis and transformation[END_REF] compilation framework, that allows fine control over optimization passes, and aiT [1], the industry standard for static WCET analysis. The target architecture is the Leon3 core, used to build a predictable multi-core architecture in the framework of the Argo H2020 project 1 . The rest of this paper is organized as follows. We first introduce in Section 2 the background on compilation optimization and static WCET estimation. Section 3 presents the coarse-grain and fine-grain strategies to explore the optimization space in order to both enable automatic flow fact derivation and minimize WCET estimates. Section 4 then describes the experimental setup used to evaluate their quality. Section 5 is devoted to an extensive experimental evaluation of the impact of optimizations on WCET estimates, with and without the proposed techniques. We conclude in Section 6.

Background & Related Work

Turning on compiler optimizations impacts static WCET estimation from two respects. First, automatic detection of flow information, in particular loop bounds that are mandatory for WCET estimation, may not be feasible anymore because the transformed code is more complex and less amenable to static analysis. Second, manual source-level annotations may not be valid anymore after the code transformations, in particular the ones deeply modifying loops (loop unrolling, re-rolling, fusion, splitting, among others).

To address these issues, one solution would be to use some feedback provided by the compiler [START_REF] Bernat | Compiler support for WCET analysis: a wish list[END_REF] to identify which optimizations were applied, in which ordering and with which parameter, and to transform manually-provided source-level flow information accordingly. However, the level of feedback provided by state-of-the-art compilers is still very limited. Another approach is to instrument the compiler such that it transforms source-level flow information jointly with code transformations, as done by several authors within gcc [START_REF] Kirner | Transforming flow information during code optimization for timing analysis[END_REF], LLVM [START_REF] Li | Traceability of flow information: Reconciling compiler optimizations and wcet estimation[END_REF][START_REF] Li | Tracing flow information for tighter WCET estimation: Application to vectorization[END_REF] or WCC [START_REF] Lokuciejewski | Approximating pareto optimal compiler optimization sequences -a trade-off between wcet, ACET and code size[END_REF]. This however imposes to stick to a given compiler version, or to maintain the flow-fact co-transformation framework along compiler versions. This is the approach followed by the WCC compiler infrastructure [START_REF] Falk | Reconciling compilation and timing analysis[END_REF], containing WCET-oriented optimization and flow fact traceability features. Although a compiler designed specifically for WCET has many benefits, it lacks many optimizations available in standard compilation toolchains such as gcc/LLVM.

In this paper, we experiment a completely different approach based on the principles of iterative compilation, which is a now mature technology in compilers for optimizing (average-case) performance [START_REF] Cooper | ACME: adaptive compilation made efficient[END_REF][START_REF] Agakov | Using machine learning to focus iterative optimization[END_REF]. The benefits of our approach are twofold. First, we rely on standard industrial strength compiler toolchain to benefit from their large number of available optimizations. Second, we consider the compiler as a black box and adapt the optimization sequences to the code under study to minimize the WCET. Our metrics for evaluating the quality of optimization sequences differ from standard iterative compilation: WCET is optimized instead of average-case performance, and optimizations sequences may be regarded as invalid if static WCET estimation fails at determining loop bounds. One of the hardest challenge in iterative compilation is dealing with the sensitivity of execution performance to input data. Interestingly, this issue does not manifest in our case, because WCET estimation is by definition insensitive to input data, making our approach even more relevant.

Proposed WCET-directed Optimization Strategies

Our approaches combine two techniques, with the variation of the optimized code granularity presented in Section 3.1, and the iterative strategies to explore the resulting optimization space in Section 3.2.

W C E T

Optimization Granularity

The intuitive way to optimize an application is to compile all its functions with the same optimization options. We refer to this approach as coarse-grain optimization in the rest of the paper. However, a single problem in a part of the application code, due to the application of an optimization, can forbid the use of that optimization on the whole application. To circumvent this difficulty, we propose to use different optimizations sequences on different parts of the code. In order to isolate a block of code to apply different optimizations we use outlining [START_REF] Liao | Effective sourceto-source outlining to support whole program empirical optimization[END_REF]. With this technique, the code snippet to isolate is replaced by a call to a new function that implement the same functionality. All variables used by the code snippet are passed as parameters to the generated function. The naive way to pass arguments is to pass everything by reference, which may significantly increase the average and the worst case execution time. Using liveness [START_REF] Cooper | Engineering a compiler[END_REF] properties of the used variables, we can filter which variable needs to be passed by reference or value. In our implementation all arrays are passed by reference; scalars are passed by reference if they are live-out, and by value otherwise; pointers which may be modified are similarly passed by reference.

In this work we systematically outline all outer loops, using to the GeCoS source-to-source code transformation framework [START_REF] Floc'h | Gecos: A framework for prototyping custom hardware design flows[END_REF]. Different optimizations sequences are generated, for the original functions, and also for each new function generated by loop outlining. We refer to this approach as fine-grain optimization in the rest of the paper.

Iterative Optimization Space Exploration Strategies

We designed two strategies to explore the optimization space:

Random exploration. For this strategy, for each experiment the number of optimization passes to be applied is selected randomly. The sequence of passes to be applied is then constructed, each optimization in the sequence being selected randomly, with no attention paid to duplicated optimization passes. This random selection of optimizations is repeated a fixed number of times. Genetic exploration. A population is set-up, each individual representing a sequence of optimization passes to be applied. Individuals in the population are selected for breeding. At every generation, there is a probability of mutation of individuals (here change of one pass in the optimization sequence, selected randomly). Then, the population is doubled in size by randomly selecting N pairs of individuals for breeding. Each pair gives birth to two children by crossover. Figure 1 gives an example of crossover. A rank in the optimization sequence is selected randomly and the sequences of optimizations are swapped. Similarly to random exploration, to keep the implementation simple, no attention is paid to duplicated passes in an optimizations sequence. The optimizations sequences for the initial individuals are selected randomly (using the same techniques as in the random exploration strategy). At each generation, the N best individuals (optimizations sequences for which aiT succeeds in estimating loop bounds, keeping the N lower WCET values) are kept.

Experimental Setup

This section presents our experimental setup. We first briefly discuss our choice of input benchmarks. We then describe the compiler and WCET tools used in our experiments, before detailing the parameters of our optimization space search strategies.

Corpus of Codes

Experiments were conducted on two image processing data benchmarks (Harris and PIPS, see description in Table 1) from the Mälardalen WCET benchmark suite 2 and from the PolyBench/C benchmark suite 3 . We restricted our study to the benchmarks analyzable by aiT with no additional information when compiled without optimization (-O0). This excludes the benchmarks that call library functions (libmath, libc) that need manual flow annotations. The complete list of benchmarks is given in Table 1 with a small description of each benchmark.

Compiler and WCET Estimation Tools

Programs are compiled using LLVM [START_REF] Lattner | LLVM: A compilation framework for lifelong program analysis and transformation[END_REF], version 4.0.0, targeting the Leon3 architecture (Sparc instruction set). Programs are first compiled into LLVM bitcode using the clang frontend, before using the opt LLVM optimizer to selectively apply optimization passes and then generating a Leon3 executable. opt takes as parameters an ordered list of optimization passes. opt automatically applies any analysis passes required when turning on a given optimization. The order of application of optimizations is respected unless there are dependencies between passes, in which case opt reorders the passes to respect the dependencies. At this stage of our work, we assume the combination of optimization passes to be correct. This will need to be verified for certification concerns, and is considered outside the scope of the paper. Programs WCETs are estimated using aiT, the industry standard for static WCET analysis, version 17.04, for the Leon3 target [1], configured with no cache. No flow annotations are given to aiT, resulting in situations where the tool is not able to derive them automatically on the optimized code. The virtual unrolling factor of aiT used by its value analysis is set to 2.

Detection of loop bounds in aiT uses an interprocedural data-flow based analysis operating at assembly level. The analysis first searches for loop counters (registers or memory cells with known value when entering the loop). Potential loop counters are further examined by a data-flow analysis to derive loop invariants (expressions indicating how the loop counter is modified at each iteration). More details can be found in [START_REF] Cullmann | Data-Flow Based Detection of Loop Bounds[END_REF].

Parameters of Optimization Exploration Strategies

To provide a fair comparison, the same number of optimization sequences were experimented on each benchmark. For random exploration, 1000 random optimizations sequences were generated. By default, our genetic exploration generated optimizations sequences from 10 generations of 100 individuals each (same number of distinct optimization sequences as random exploration). 15% of individuals are mutated at each generation.

In the coarse-grain case, all files are compiled using the same optimizations sequence, while fine-grain optimization uses different sequences for each file. Regarding the extension of the genetic exploration strategy to fine-grain, the implemented mutation operator mutates all files (with a different mutation per file). Similarly, we chose to apply the crossover operation to all files when breeding two individuals.

Experimental Evaluation

In this section, we look at the impact of standard optimizations levels on the WCET estimates, and then evaluate our coarse-grain and fine-grain optimization selection strategies.

Impact of Optimizations on the Ability to Derive Flow Information

LLVM comes with four optimization levels -O0 (no optimization applied) to -O3 (highly optimized code). Figure 2 gives for all optimizations levels beyond -O0 (-O1, -O2, -O3 ) the ratio WCET -Oi / WCET -O0 expressed in percentage (the lower the better). No bar for a given optimization level means that aiT was not able to detect loop bounds automatically.

The results show that in most situations, turning on optimizations results in lower WCET estimates than when compiling with option -O0 (ratio WCET -Oi / WCET -O0 lower than 100 %). However, in some cases (benchmarks qurt and sqrt and des) optimized codes result in larger WCETs than non-optimized ones. For some benchmarks (harris, pips, trmm, lu, ludcmp, nussinov), aiT was not able to extract loop bounds when optimizations are turned on (depicted as red bars below the x-axis in the figure). Finally and surprisingly, for benchmark trmm aiT was not able to detect loop bounds at -O1 and -O2 but was able to estimate loop bounds at -O3. One can also note that the levels of optimization (from -O1 to -O3) have similar impact on estimated WCETs.

To detect which individual optimizations make automatic for loop bounds detection fail, we activated each optimization pass individually and estimated the resulting WCET using aiT. Experimental results are presented in Figure 3, that gives for each optimization WCET optim / WCET -O0 , when optimization pass optim is activated on benchmark pips. Results show that optimization passes, even if only one of them is activated at a time, can significantly lower estimated WCETs, but may also have a negative impact. For example in benchmark pips, pass -jump-threading 4 makes aiT unable to estimate loop bounds; optimization pass -loop-rotate (classical loop rotation) reduces the estimate WCET of 15% and optimization pass -simplifycfg (dead code elimination and basic block merging) augments it of 7%.

Note that this experiment does not allow us to identify optimization passes that made aiT systematically fail to identify loop bounds. This is because activating an optimization pass does not imply that the optimization is actually triggered (e.g. pre-conditions are not always met). Passes -gvn, -jmp-threading, -instcombine, -licm -mem2reg, -sroa, -lowerswitch when activated made estimation of loop bounds fail for some programs. Pass -jmp-threading was the most harmful (aiT was unable to estimate a WCET on 20 benchmarks out of 46 when this optimization turned on).

We performed an in-depth analysis of the code generated by LLVM on a very small code snippet (simple loop initializing an array), with optimization -jmp-threading turned on, to identify why loop bound estimation fails on the generated code. It turns out that LLVM duplicates the loop induction variable: the first variable is used to index the array, whereas the second one is used in the loop exit test; the first variable is incremented, and then copied into the second one. The initial loop bound analysis of aiT was not able to demonstrate that the two induction variables were actually a single one and were equal at all times. The issue was fixed in aiT to correctly detect the loop bound when such a code is generated. Understanding why the optimization passes other than -jmp-threading generate hard-to-analyze code is left for future work.

Evaluation of Coarse-Grain Optimization Selection Strategies

Figure 4 presents the experimental results for all benchmarks. The first important remark on the experimental results is that for all benchmarks aiT was able to derive loop bounds automatically, even in the situations where some optimization levels made it impossible before (benchmarks harris, pips, trmm, lu, ludcmp, nussinov). On all benchmarks, exploring the optimization space using random exploration resulted in WCET estimates lower than the best WCET possible with -O1, -O2 and -O3.

WCET / WCET_O0

Coarse/WCET_O0 fine10steps/WCET_O0 fine20steps/WCET_O0

Figure 5

Fine grain exploration of optimization space.

Evaluation of Fine-Grain Optimization Selection Strategies

Due to time constraints, experiments of the proposed fine-grain optimization strategies were conducted on the image processing benchmarks harris, pips and the Mälardalen benchmarks only. We further restricted the benchmarks to the ones containing loops, and avoided those containing a single loop that covers the entire code. Results are given in Figure 5, showing three values for each benchmark: WCET coarse /WCET -O0 , WCET f ine10steps /WCET -O0 (10 generations) and WCET f ine20steps /WCET -O0 (20 generations instead of the default value of 10).

The first results obtained are encouraging (improvement of 37 % of the WCET estimates on average). On 6 out of the 9 benchmarks analyzed (all but the 3 ones at the right of the figure), the fine-grain genetic exploration outperforms the coarse-grain exploration. Moreover, for all benchmarks except one, having 20 generations instead of 10 significantly improves WCETs, at the cost of an analysis time twice longer. This result is expected, since the optimization space to be explored is much larger than for the coarse-grain strategy. We believe there is room left for improvements, by tuning the parameters of the genetic algorithm to better deal with the very large optimization space to be explored, or avoid the cost of outlining when not beneficial to the WCET.

Conclusion

Compiler optimizations are known to add challenges when estimating the WCET of applications. Hence it is quite common to disable them when dealing with critical systems. In this paper, we proposed an iterative compilation workflow to reconcile timing critical applications with compiler optimizations. Our methods, based on optimization space exploration, show a significant tightening of the estimated WCETs. Our first exploration of fine-grain application of optimizations demonstrated opportunities to further reduce WCET estimates (improvement of 37 % of the WCET estimates on average). Future work is still needed to take full benefit of fine-grain exploration of optimizations. A first direction is to better explore the very large optimization space, for example by concentrating the optimization effort of regions having the most impact on worst-case performance. Another direction is to develop techniques to better select the code snippets to be outlined: outlining has a cost (extra function call and parameter passing) that has to be avoided when outlining is not beneficial to the WCET. Symmetrically, we still need to explore which code sequences would benefit from being outlined and not optimized, such that manual source-level annotations can be given when more beneficial to WCET estimates than compiler optimizations and automatic flow fact extraction.

Figure 1

 1 Figure 1 Crossover operation in genetic exploration.

Figure 2

 2 Figure 2 Ability to derive WCETs at -O1, -O2 and -O3.

Figure 3

 3 Figure 3 Impact of independent optimization passes on estimated WCET (application PIPS).

Figure 4

 4 Figure 4Coarse grain exploration of optimization space.

2 0 1 8 9:6 Fine-Grain Iterative Compilation for WCET Estimation Table 1

  Corpus of programs.

							9:7
					WCET_O1/WCET_O0	WCET_O2/WCET_O0 (%)	WCET_O3/WCET_O0 (%)
	120%
	110%
	100%
	90%	Harris		Classical Harris corner detection algorithm.
	80%	PIPS			Industrial use case from the ARGO project [8]. Image processing pipeline for
	70%				post-processing raw data from a polarized image sensor.
	60%	cnt			Counts non-negative numbers in a matrix
	50%	cover			Program for testing many paths.
	40%	crc			Cyclic redundancy check computation on 40 bytes of data.
	h a r r is	des duff p i p s	c n t	c o v e r	DES and Triple-DES encryption/decryption algorithm. Using "Duff's device" from the Jargon file to copy 43 bytes array. c r c d e s d u f f e x p in t f d c t f ir jf d c t i n t lc d n u m lu d c m p m a t m u l t n s n s ic h n e u q u r t s t a t e m s q r t a t e	u d
		expint		Series expansion for computing an exponential integral function.
		fdct			Fast Discrete Cosine Transform.
	90%	fir			Finite impulse response filter (signal processing algorithm) over a 700 items
	80% 85%				long sample.
	75%	jfdctint		Discrete-cosine transformation on a 8x8 pixel block.
	70%	lcdnum		Read ten values, output half to LCD.
	60% 65%	ludcmp		LU decomposition algorithm.
	55%	matmult		Matrix multiplication of two 20x20 matrices.
	50%	ns			Search in a multi-dimensional array.
	40% 45%	nsichneu		Simulate an extended Petri Net.
		qurt			Root computation of quadratic equations.
		sqrt			Square root function implemented by Taylor series.
		statemate	Automatically generated code.
		ud			Calculation of matrices.
		covariance	Co-variance computation.
		2mm			2 Matrix multiplications.
		3mm			3 Matrix multiplications.
		atax			Matrix transpose and vector multiplication.
		bicg			BiCG sub kernel of BiCGStab linear solver.
		doitgen		Multi-resolution analysis kernel (MADNESS).
		mvt			Matrix vector product and transpose.
		gemm		Matrix multiply.
		gemver		Vector multiplication and matrix addition.
		gesummv		Scalar, vector and matrix multiplication.
		symm		Symmetric matrix-multiply.
		syr2k			Symmetric rank-2k operations.
		syrk			Symmetric rank-k operations.
		trmm			Triangular matrix-multiply.
		durbin		Algorithm for solving Yule-Walker equations.
		lu			LU decomposition without pivoting.
		ludcmp		Solving a system of linear equations using LU decomposition followed by
					forward and backward substitutions.
		trisolv		Triangular solver.
		floyd-warshall Finds the shortest path in a graph.
		nussinov		Algorithm for predicting RNA folding using dynamic programming.
		adi			Alternating Direction Implicit solver.
		fdtd-2d		2-D finite different time domain kernel.
		heat-3d		Solving of heat equation over 3D space.
		jacobi-1D	1-D Jacobi stencil computation.
		jacobi-2D	2-D Jacobi stencil computation.
		seidel-2D		2-D Seidel stencil computation.

2 http://www.mrtc.mdh.se/projects/wcet/benchmarks.html 3 http://web.cse.ohio-state.edu/~pouchet.2/software/polybench/ W C E T

The work presented in this paper is part of ARGO (http://www.argo-project.eu/), funded by the European Commission under Horizon

Research and Innovation Action, Grant Agreement Number 688131.

This pass looks at blocks that have multiple predecessors and multiple successors. If one or more of the predecessors of the block can be proven to always cause a jump to one of the successors, it forwards the edge from the predecessor to the successor by duplicating the contents of this block.

This work was funded by European Union's Horizon 2020 research and innovation program under grant agreement No 688131, project Argo. The authors would like to warmly thank Benjamin


Gilles Vanwormhoudt
email: vanwormhoudt@telecom-lille1.eu

Areski Flissi
email: areski.flissi@lifl.fr

Ciaoserverrole Ciaosipport

Ciaoroleevent Ciaoevent Ciaosessionevent

Ciaosession Partcreator Ciaorolecreator

CIAO: A Component Model and its OSGi Framework for Dynamically Adaptable Telephony Applications

Keywords: D.2.8 [Software Engineering]: Software Architecturedomain-specific architectures, adaptable architectures Component model, telephony, sessions, dynamism, SIP, OSGi

In recent years, thanks to new IP protocols like SIP, telephony applications and services have evolved to offer and combine a variety of communication forms including presence status, instant messaging and videoconference. As a result, advanced telephony applications now consist of distributed entities that are involved into multiple heterogeneous, stateful and long-running interactions (sessions). This evolution complicated significantly applications development and calls for more effective solutions. In this paper, we explore the adoption of components for addressing this issue, focusing specifically on the management and coordination of the numerous and various sessions occurring in such applications. The paper presents CIAO, a domain-specific and hierarchical component model for SIP applications. CIAO combines three kinds of component that are Actor, Session-Part and Role and manage them dynamically in accordance with real SIP sessions. By using these features, we are able to break the complexity of SIP entities and provide flexibility for their development. CIAO is implemented above OSGi to experiment the building of concrete SIP applications and enable their dynamic adaptation.

INTRODUCTION

Stimulated by the ubiquity of IP networks and the existence of new protocols like SIP (Session Initiation Protocol), telephony services have endorsed significant changes in recent years. They are now able to offer and combine a variety of communication forms including presence status, instant messaging and videoconference while managing other concerns like mobility, localization, security, etc. This situation changes and complicates significantly the development of telephony applications that mainly consist of distributed entities involved into multiple heterogeneous, stateful and long-running interactions (sessions). Designing such applications not only requires programming expertise but it also requires familiarity with the handling of complex sessions and interactions. Owning to the specific skills required for these applications, the development process becomes expensive in terms of time and resources, calling for more effective solutions. Regarding this problem, a component-based approach to develop telephony applications becomes an attractive feature as it promises several advantages in terms of design flexibility and evolution [START_REF] Bond | Experience with component-based development of a telecommunication service[END_REF]. For the flexibility in design, components can help to decompose the complex behaviour required for sessions management into prepackaged and reusable units that can be further assembled for specific applications. For evolution, recent component models designed to deal with dynamic changes like OSGi [START_REF]Osgi service platform core specification[END_REF], can help to accommodate new features or change behaviours after the deployment stage.

Main existing works on component-based development for SIP applications are [START_REF]SIP Servlet 1.1 Specification[END_REF][START_REF] Jcp | JAIN SLEE API Specification[END_REF]11] and mainly target server-side entities. In all these works, the multiplicity and dynamicity of sessions occurring in advanced telephony applications are not or poorly addressed by means of components. Not only this causes difficulties when the base of sessions to manage and coordinate is various and complex, it also hampers the modularity and adaptability of SIP applications relatively to sessions.

In this paper, we propose CIAO (Component for sIp Ap-plicatiOns), a domain-specific component model for developing any kind of SIP entities, either client, server or both. This component model is hierarchical and relies on three specific component types that are Actor, SessionPart and Role. Actor components are top level components that represent distributed SIP entities. They contain SessionPart components that provide actor behaviour related to particular kinds of session. SessionParts are themselves container for Role components which encapsulate one of the behaviour played by an actor when it participates to a particular session. Besides these specific components, the model is characterized by powerful mechanisms for components interaction and coordination and by a management of components which is dynamic and maps real SIP sessions. According to this management, SessionParts and Roles created for an Actor depend automatically on the session it participates in at runtime. Advantages provided by this model are to achieve a better modularization between session-dependent parts of entities, to simplify the reasoning regarding sessions dynamicity and to improve the capacities for constructing SIP entities from reusable components.

In addition to this model, we also describe an implementation of the CIAO model as component framework over the OSGi platform. This implementation leverages the capacity of OSGi components for software adaptation. The resulting framework allows to adapt components of SIP entities at runtime with minimal interruptions. This feature are illustrated and discussed through characteristic examples of adaptation.

The rest of the paper is organized as follows. Section 2 gives background on SIP and the issues underlying the development of advanced SIP applications. It is followed by the description of CIAO component model in section 3. The implementation of CIAO components over OSGi is presented in section 4. Section 5 reports experiments, notably on dynamic adaptations. Section 6 comments on related works prior to conclude in section 7.

BACKGROUND ON SIP AND ISSUES

SIP is an application-layered signaling protocol standardized by the IETF that supports applications ranging from simple VoIP routing or instant messaging to sophisticated multimedia sessions involving multiple parties with presence management. For these applications, SIP provides a rich range of communication forms. Communications can be stateless for simple messages exchange, session-based to exchange messages over a period of time or event-based to propagate information like state-change of an entity. One main benefit of SIP is that it enables mixing all its communication forms in order to design advanced telephony applications.

Figure 1 shows the architecture of an advanced telephony application based on SIP to provide presence-based redirection 1 of invitation to a dialog combining voice and text. The architecture is composed of three SIP entities having distinct capacities and interacting in multiple ways. In the scenario depicted by this figure, Alice updates its status because she leaves its office for a meeting [START_REF] Akolkar | Reusable dialog component framework for rapid voice application development[END_REF][START_REF] Meddahi | Telephonie SIP : Concepts, usages et programmation en Java[END_REF]. Then, Bob calls Alice during her meeting and he receives a BUSY response [START_REF] Bond | An open architecture for next-generation telecommunication services[END_REF][START_REF] Bond | Experience with component-based development of a telecommunication service[END_REF]. When Alice becomes available [START_REF] Jcp | JAIN SLEE API Specification[END_REF][START_REF] Jcp | JAIN SIP API Specification[END_REF], a new invitation from Bob results in a redirect response including Alice's address to initiate a dialog [START_REF]SIP Servlet 1.1 Specification[END_REF][START_REF] Palix | A stepwise approach to developing languages for SIP telephony service creation[END_REF]. Thanks to the returned address, Bob can directly contact Alice to establish a successful dialog (9 to 18).

As illustrated by the previous example, lots of message exchanges between the involved SIP entities may be required to achieve the intended functionality. This profusion of messages complicates significantly the development of SIP entities. In [START_REF] Vanwormhoudt | Session-based role programming for the design of advanced telephony applications[END_REF], we identified three typical sources of complexity:

1) Complex messages flow within a session : Within a session, SIP entities exchange and handle SIP messages at each end. Several difficulties must be faced when handling these messages:

-Messages can be received at any time from the network. As a result, SIP entities must be prepared to react to any 1 In SIP, redirection consists in directing the client to contact an alternate address. received messages, including while others are processed; -Interpretation of messages in the flow is generally statedependent (see OK messages in the example). This requires the entities maintain a session state according to the exchanged messages for distinguishing between these interpretations;

-Messages flow of a session may contain and interleave messages that are related to distinct concerns as illustrated by colored groups of messages in the lower part of Figure 1.

-Message flow can be inverted during the session (see BYE for example). This implies that entities must be able to provide behaviours for handling session flow in both directions and to act both as requestor and responder.

Because of these difficulties, the behaviour of entities handling some parts of the session flow like the previous one is usually not easy to design.

2) Multi-branches session : A SIP session is not always restricted to a peer-to-peer conversation. There are some classical calling or presence scenarios which involve more than two peers in the same session. In these scenarios, one or several SIP entities generally act as facilitator between several participants to the session. For such entities, this entails to handle more that one conversation within the same session and to coordinate all the conversations in order to serve the communication partners properly. In our example, we initially assume a redirect behaviour for the server but we can easily imagine changing this behaviour to a proxylike one in order to extend the status of a user according to its participation in an existing dialog2 . Compared to the previous behaviour, adopting this change requires that the server manages and coordinates two communication paths within a session : one to the callee and one to the caller, switching back and forth being a client and a server at the same time. When a SIP entity is involved in more than one conversation within a session, the complexity for describing its behaviour is inherently increased.

3) Multi-sessions management : The need to handle multiple sessions is another situation that makes the development of SIP applications and their entities complicated. Two cases may be distinguished for multi-sessions management. The first case is the one where the sessions managed by a SIP entity have the same type and typically occur concurrently. We generally encounter this case when designing SIP servers. In our example, the redirect server is an illustration of this case as it must be able to manage calling session coming from multiple requestors. Here, the difficulty is that multiple session states must be maintained separately and concurrently. The second case is the one where each session has a different type. This case can be found particularly in the development of rich user agents and rich servers. In our example, Alice's user agent illustrates this case as it must be able to manage several sessions related to registration, incoming invitation and status modification. For this case, an additional difficulty besides maintaining multiple states is that each session may require the handling of distinct set of messages resulting in a significant amount of messages to handle. Note that a combination of the two cases may sometimes be required for the design of a SIP entity as it is illustrated by the redirect server. For SIP entities, supporting multiple sessions makes their design more complicated because they must include characteristics for many states and behaviours.

As we can see, SIP applications have specific issues related to sessions management that make their development complex and lead to intricate structure of behaviour for involved SIP entities. Therefore, an adequate component model targeting these applications and their entities should provide abstractions to solve all these issues. In the next section, we present CIAO, a component model that includes appropriate abstractions for that purpose.

CIAO COMPONENT MODEL

CIAO only deals with the part of applications that is related to SIP but it is sufficiently general to address the needs of any SIP entity, that is client, server or both. For other parts of applications like UI or database, we assume that they are addressed by more classical components. CIAO components can be assembled and interact with these components to form a complete application.

Kinds of component

CIAO has three kinds of component which are Actor, Ses-sionPart and Role. The first two are composite components while the last one is atomic. In our model, a composite encapsulates subcomponents as well as the logic for controlling them. An atomic component encapsulates computation logic. Each kind of component has a specific purpose in the model :

-Actors are composite components at the top-level. These components are so called because they represent SIP entities from the network view. They directly exchange SIP messages with other entities in the network. Actors are typically involved into one or several SIP sessions that may have the same nature or being different and exist concurrently. To handle these sessions, Actors encapsulate subcomponents which are SessionParts. Actors are also responsible of routing SIP messages from and to its SessionParts and coordinating them.

-SessionParts are composite components encapsulated by actors. These components aim to provide the behaviour of actors related to a specific session type. A SessionPart en- -Role are components at the lower level. These components are atomic and provides one of the actor behaviour involved in a session. This behaviour consists in handling incoming and outgoing SIP messages while realizing the relevant logic.

In CIAO, the Role kind introduced above is further refined in three sub-kinds to specify their capacities in terms of received and sent messages and help the analysis and correlation of communicating roles inside and between actors : -Client role represents an asymmetric role type that sends requests and receives related responses.

-Server role represents an asymmetric role that receives request and sends related responses.

-ClientServer role represents a symmetric role that sends and receives both requests and responses.

Figure 2 shows a concrete Actor corresponding to Proxy entities and illustrates the hierarchical structure of such components. This Actor is composed of two SessionParts, one dedicated to sessions for user address registering, the other to sessions for user calling. These two SessionParts include themselves Roles for providing the respective behaviour. In the Registering SessionPart, the Registrar role provides the behaviour for registering/unregistered user agent address. In the Calling SessionPart, the CallHandler role handles the communication with the calling user agent and the Call-Forwarder role handles the communication with registered called user agents. Timer and SipAddressStore are not CIAO components but are functional ones. They are included in the Proxy architecture to provide both timing and usage address storage functionalities. The first one is needed to record the time period of each user address registration, so is contained in Registering SessionPart. The second one allows to store user address during registration and retrieve them during calling, so is contained in the Proxy Actor to be shared by its two SessionParts.

Using CIAO, SIP architectures that generally involve several SIP entities, can be built from a set of related actors 3 3 To preserve the interoperability with existing SIP systems, CIAO does not enforce that all entities in such architecture be necessarily based on CIAO. Indeed, Actors can interop- where each actor communicates with other actors within sessions, playing dual and consistent roles. Figure 3 illustrates such an architecture and show capacities of the model. In this architecture, related actors A1 and A2 participate to a SIP session S1. Within this session, actor A1 plays a single role R1 and communicates with A2 that plays dual roles R2 and R2'. Figure 3 also shows a second SIP session S2 independent from S1 that involves actors A3 and A4 but also A1, already engaged in S1. For this session, we may observe that actor A1 plays a role R1' distinct from R1 played in S1. Actor A3 plays two distinct roles to communicate with A1 and A4 actors.

The combined use of Actor, SessionPart and Role components proposed by our model allows to deal with the issues identified above. The first issue can be managed by defining multiple roles for a particular session (e.g. A2), each dealing with one session concern. The capacity for an actor to play multiple roles for distinct communication path (e.g. A3) of a session may be exploited to solve the second issue. Concerning the last issue, the solution is provided by the ability of an actor to participate in multiple sessions with separate roles (e.g. A2 and A4).

Component instanciation and life-cycle

Whereas some models treat component as configured instances, CIAO differentiates between component types and instances. The principle is that all CIAO components are type-level component and these components are instantiated at runtime to form the architecture of concrete Actors. For an actor, its architecture is always a tree of component instances where they can be multiple instances from a given inner component type. Figure 4 gives an example showing the instance tree of a Proxy actor currently engaged in two calling SIP sessions (represented by SessionParts with Call-Id @345 and Call-Id @127) and one registering SIP session (represented by SessionPart with Call-Id @56).

One key feature of CIAO is that the inner architecture of an actor is not fixed at instantiation-time but changes dynamically during its lifetime. Changes performed to an actor architecture aim to reflect its participation to real SIP sessions and provide all the states and behaviours required for these sessions. These changes are as follows: each time an actor is involved in a new SIP session, a corresponding SessionPart is created and added to the actor architecture. Conversely, each time a SIP session is terminated, the corresponding SessionPart and its roles are removed from the actor architecture.

The instantiation of SessionPart can be done explicitly on erate transparently with existing SIP entities.

demand by means of a new-like construct or occurs implicitly on the basis of received request. For a receiving request, the decision to create a SessionPart instance depends if there already exists a session part matching the session identifier (Call-Id header) included in the request. If none exists, some rules attached to the Actor for SessionParts are evaluated to create a matching instance. A SessionPart may be instantiated more than once per actor. This corresponds to the situation where an actor participates to several sessions of the same type during its lifetime. At the level of SessionPart, similar changes are performed for the inner roles. These changes consist in adding and removing roles to advance the actor state and behaviour inside the SIP session. Like session part instantiation, the creation of roles attached to a session can be done in two ways: either explicitly by means of a new-like construct or implicitly on the basis of a received request. In the latter case, rules attached to the SessionPart are evaluated to determine if a corresponding role must be created.

SessionPart and Role components have explicit states that are automatically setup during their lifecycle. SessionPart can be in one of the following session-related states: Idle (initial state), Bound (after binding with real session), Started, Ended, Unbound (terminal state). For a Role, there are three states, namely: Idle, Active, Invalid. All these states are accessible through a common interface provided by components so that they can be used to realize the actor behaviour.

Component interaction

CIAO components have features to interact with other components both at functional and SIP levels.

Functional Ports

For functional interactions, components may have functional ports which are access points to component functionality with a set of operations. In CIAO, functional ports can be of two kinds: provided and required. A provided functional port corresponds to a functionality provided by the component whereas a required functional port corresponds to a functionality required by the component. Interaction between components is only possible if required functional ports are bound to provided ports. Connection between ports can be dynamically set and unset at runtime. By means of functional ports, a component can interact with other components to use or provide its functionality. For example, a Role (resp. SessionPart) component can use the functionality of its owning SessionPart (resp. Actor) to access a shared state or activate a common behaviour. Conversely, a composite like an Actor (resp. SessionPart) may consume functionality provided by its inner Session-Parts (resp. Roles).

SIP Ports

For SIP interactions, CIAO introduces SIP ports and SIP messages routing among the hierarchy of components. SIP ports are bidirectional access points to the SIP network for components. They are used for sending and receiving SIP messages. Actor and SessionPart may have several SIP ports but roles only have a single one (see Figure 2). A SIP port is created dynamically each time a communication path is established for a role, that is an initial SIP request is sent to or received from the network. There are three kinds of SIP port in relation to the kinds of role defined in section 3.1 :

-Client SIP Port enables sending of SIP requests and receipt of SIP responses -Server SIP Port enables receipt of SIP requests and sending of SIP responses -Client/Server SIP Port enables both sending and receipt of SIP requests and responses.

In CIAO, the source and destination of SIP messages exchanged with the network are always Roles. More precisely, SIP messages are routed from and to the network following a unique path in the Actor's component hierarchy. This path starts from the root Actor to the appropriate role if the message is a received message. Conversely, the path starts from the emitting role to the root Actor if the message is sent. Along the path, the message is delivered to components through their SIP ports. This enables components to adapt the routing and eventually to perform computations in relation with the delivered messages.

When a component receives a message via one of its SIP ports, it is responsible of selecting the next component along the path and passing the message to this component. A routing component may use various strategies to make this selection. Currently, we use default strategies for sent and received messages. For sent messages, the strategy consists simply in selecting the outer component. According to this strategy, a message sent from a Role is submitted to its containing SessionPart then to the containing Actor and finally to the network. For received messages, the strategy for selecting the right component depends on the type of the message and the session it belongs. With this strategy, a message received from the network is first delivered to the root Actor. Then, the message is forwarded by the Actor to the SessionPart matching the message session identifier and type, eventually a new one if none matches. After that, the process continues with the selection of a matching role. This selection is done by the SessionPart on the basis of the message type and optionally some current state using its rules. At last, the message is forwarded to the selected Role so that it can realize the relevant logic. This is achieved by triggering one of its message handlers. Message handlers are special operations provided by Role to handle an incoming SIP request or response. These operations have a specific signature that matches the type of particular SIP message.

Figure 4 illustrates the receipt of an INVITE initial request by a Proxy Actor and its routing through the corresponding SessionPart up to the CallHandler role. This routing terminates by executing the onInvite() request handler provided by the role. The response emitted by the role is 301 Moved Permanently indicating that the user is not available through the given SIP address but via another address provided in the response. As we can observe, its routing follows the converse way, through the same SIP Ports.

Component coordination

In some scenarios, the roles that an actor plays during a session or the multiple sessions it is involved in require coordination within the actor itself. Generally, this is due to the fact that some actions provided by some entities depend on actions provided by other ones. To fulfill these coordination needs, our component model offers two coordination mechanisms, one dedicated to SessionParts and one targeting Roles. These two mechanisms are grounded on the same principle : a composite instance provides the coordinating behaviour for its inner component instances. These princi- ple aims to provide two benefits. Firstly, it permits to avoid explicit coupling between subcomponents for coordination purposes, improving therefore their reuse. Secondly, it permits to locate the coordinating behaviour in one place, facilitating its understanding and maintenance. In the following, we detail these two mechanisms which are both event-based.

SessionPart Coordination

The need to coordinate the behaviour of an actor across several sessions can be illustrated using the case of third-party call entities which are controllers setting up and managing a phone call between two or more other parties 4 . Figure 5 illustrates the basic idea behind third-party call entities using an example which only connects two users in a call. We can see that the server is represented by an actor which is involved into two calling sessions with user-agent actors. For these sessions, coordinating behaviour are required from the previous actor. The second calling session must be started only when the initial one has been acknowledged. It consists for the third-party entity in sending a second INVITE after the first INVITE was confirmed by a 200 OK. Furthermore, when the second session is confirmed, the two sessions must be acknowledged by sending a ACK message to each user agent.

Within an Actor, the behaviour for coordinating its Ses-sionPart is defined by means of callback operations related to specific SessionPart events. These coordinating callback operations are attached to the Actor component and they are automatically triggered at runtime each time the corresponding event related to a SessionPart occurs. The struc- 1: Kind of session events and their corresponding operations ture of coordinating operations is similar to normal operations. Like an operation, it owns a body containing the set of coordinating actions and has provided parameters.

Table 1 gives the set of events dedicated to sessions coordination within an actor. They are related to the life-cycle of a session as well as its state from the actor point of view. For each event, this table also indicates the corresponding operations and provided parameters.

For this set of events, it is important to precise that only events related to session life-cycle are triggered automatically (creation, deletion). Those related to session state (started, ended) must be triggered explicitly by the developer. The reason why such event needs to be handled explicitly comes from the fact that determining the start or the end of a session is generally application-specific. Using the previous facilities, the behaviour for coordinating the two sessions as described can be done by defining an onStartSession operation for the Third-Party call Actor and by using provided session parameters to distinguish between second INVITE sending case and acknowledgments case.

Role Coordination

To illustrate the need of roles coordination, let us consider the case of a forking operation handled by SIP proxies. In a proxy, this operation occurs when it receives an invitation for a user which has registered more than one user agent. In that case, the proxy relays the invitation to all registered user agents by creating separate branches. When one registered user agent accepts the invitation, other invitations must be cancelled. Using CIAO, the behaviour for a forking operation may be achieved by coordinating CallHandler and CallForward roles attached to the running CallingSession SessionPart as illustrated in Figure 6. To achieve the forking operation, coordinating actions are required to create new CallHandler on the receipt of a request by the Call-Handler and to activate or deactivate them depending on which user agent is the first to respond.

To deal with situations like the previous one, our component model includes a mechanism dedicated to the coordination of roles within a session. This mechanism follows the same design principles than the one designed for coordinating SessionParts of an Actor : the SessionPart acts as the coordinator of its role and relies on special operations to define the coordinating behaviour in term of actions.

Table 2 presents the set of role events that may captured in a SessionPart through the definition of coordinating operations. These events can be subdivided in two groups: one concerns the life-cycle of a role during a session while the other deals with message handling performed by a particular role.

All these operations allow to have a fine and complete control over the role events related to a session. Thanks to

CIAO ABOVE OSGI

To experiment our component model for the development of real applications and validate its benefits, the proposed components and mechanisms must be implemented concretely. To this end, we have developed an implementation of CIAO on top of the OSGi component framework. The choice of OSGi were driven by the need to exploit its capacities for dynamic adaptation of applications.

Mapping CIAO components to Declarative Services

We use Declarative Services as a basis for implementing all the kinds of component included in CIAO. Declarative Services (DS) is a part of the R4 OSGi [START_REF]Osgi service platform core specification[END_REF] specification that extends the service component model provided by OSGi Bundles. This extension offers a declarative model (based on XML descriptor) for managing multiple components within each OSGi bundle and for automatically managing the component lifecycle in response to bound services coming and going. In our implementation, each CIAO component of an application is implemented as a DS component and functional ports provided by CIAO components are specified as By default, Declarative Services automatically creates instance of component when their service dependencies declared statically inside its descriptor are satisfied. This default behaviour is not well-suited to the dynamic nature of the CIAO component model. In CIAO, components, mainly internal ones, need to be created dynamically depending on SIP messages flow. Furthermore, multiple instances of a CIAO component may also be needed when handling multiple sessions at the same time. Owing to these specific needs, it was necessary to elaborate a specific management of component instances over DS.

To solve the previous problem, we rely on the Factory Component facility provided by DS and specific helper components added to the set of DS components derived from CIAO ones. A factory component is a DS component that can be used by other DS components to create and dispose instances of particular DS components. Such factory component are implicitly created if required. They are also automatically registered and can be referenced by other DS component to manufacture component instances. In our case, we declare a distinct factory component for each CIAO component included in an application.

In addition to factory components, we also introduce a correlated helper service component (called Creator) for each SessionPart and Role. The role of Creator components is to provide the logic for determining if a component instance have to be created for the handling of a particular SIP message. These helper components make directly use of the corresponding factory. They are also declared to provide a service that is referenced by the outer component and some properties for determining the appropriate component to instantiate on specific messages.

Figure 7 shows the architecture of DS components corresponding to a Proxy actor currently engaged in one registering session and two calling sessions. In this figure, components that are declared statically in descriptor files have underlined names. Others are instantiated dynamically for matching the sessions and supporting the intended behaviour. Dependencies that are automatically managed by the DS runtime are represented with dotted line. As we can observe, Actor and SessionPart components maintain a set of references to Creator components so that they can collaborate with them for instance creation during messages routing.

The code in Figure 8 gives several descriptors used in the example. They correspond to the declarations of a Proxy Actor, the CallingSessionPart component with its factory and the corresponding Creator component. The previous architectural principles enables to benefit from the capacities of Declarative Services for all CIAO components. First, the modularity provided by DS allows to decompose an actor into multiple ways for their deployment in a running OSGi platform. For instance, it is possible to have a bundle containing an actor and all its inner components or having separate bundles for each SessionPart used by an actor. Secondly, thanks to the DS capacities for dynamic updates of components, all CIAO components can be installed, updated and started with minimal disruption to the running SIP entity. See section 5.2 for example of SessionPart and Role added dynamically.

Runtime and annotation frameworks

To enable the development and execution of SIP applications in accordance with our component model, we have implemented a runtime framework which is build above OSGi and JAIN-SIP frameworks. This framework defines a set of classes that provides certain core data structures and functionalities for managing the execution of CIAO components. Figure 9 shows the main classes of this framework.

Some CIAO runtime classes extend themselves the standardized JAIN-SIP API. To build an application, developers have to write Actor, SessionPart, Role, and Creator components by specializing respective classes and write XML descriptors as described previously.

Using CIAO implementation constitutes an improvement for the development of SIP applications but specializing the framework still requires deep knowledge of underlying programming rules. To simplify and speed up the coding task, we provide a Java annotations framework too. In our case, A class with the @actor annotation will inherit from the CiaoActor class of the framework, whereas a class annotated with @sessionPart will inherit from CiaoSessionPart class. The three subkinds of role provided by the model are declined in corresponding annotations for classes: @client-Role, @serverRole, @clientserverRole.

An actor declares its sessions part with @useSession-Part(type, method, condition) annotation on its class. The mandatory type attribute determines the SessionPart class that has to be imported and activated. The mandatory method attribute provides the type of SIP request method (e.g. INVITE message) that triggers the activation of the Ses-sionPart. The optional condition attribute is a string that refers to the name of a boolean method that describes some particular conditions for the activation of the SessionPart. The principle is similar for declaring roles of a SessionPart, thanks to @useRole annotations, except that it is used with a SessionPart class. Figure 10 gives an example of annotated code corresponding to some CIAO components used in the definition of PresenceEnableUserAgent actor.

EXPERIMENTATION

In this section, we report some experiments about the building of SIP entities using CIAO, their adaptation relatively to sessions and a capitalization of these experiments for providing a first set of reusable components.

Developed SIP entities

In order to validate the generality of our CIAO component model and the relevance of its structuring, we have developed four SIP entities 5 that target distinct SIP areas (telephony, presence) and map to classical categories of SIP agents (end-point, intermediary entity, client and/or server). In the following, we list these entities and indicate the issue(s) it was necessary to solve for each:

-SipPhone : The development of this entity required to manage two independent session types, one dedicated to call management and one dedicated to user address registration. Other addressed issues were mainly related to the complexity of flow during a call as it relies on state-dependent, asynchronous and inverted exchange of messages.

-Proxy : Through the development of this entity, we addressed the issue of handling multiple sessions of two distinct 5 Three of these entities are detailled in the first coauthor book on SIP Telephony in Java [ types (recording, calling) at the same time with the particular issue that the calling session is multi-branches and have a quite complex flow. For managing this issue, we used the mechanism for coordinating roles of a session as described in section 3.4.

-Third-party Call Server : In terms of issues, the design of this entity required the ability to initiate and manage as many calling sessions as parties as well as the ability to orchestrate all these sessions.

-Presence Server : Like a proxy, a presence server is an intermediary entity that accepts, stores and distributes SIP presence information from a source entity to subscribing entities. This kind of entity needs to manage several sets of sessions at the same time with the difficulty that the sessions in a set have distinct types (publish and subscribe-notify), map to distinct participants and need to be coordinated.

The following table presents the structuring of developed entities, so Actor components. For each Actor, we give its SessionPart components and its Role components 6 . For instance, the row for Proxy Server actor can be interpreted as follow: this actor has two CallingSessionSvr and Regis-terSessionSvr SessionParts and play one CallHandler server role and one CallForwarder client role for the former and one RegisterAcceptor server role for the latter.

These experiments confirmed the generality of our proposal and the relevance of its structuring. They also highlighted that the model offer several advantages. First, it raises the level of abstraction as the developer can think about the behaviour of its actor at a higher level thanks to SessionPart and Role. Second, the encapsulation of behaviour and state into multiple SessionPart and Role components with delimited scope contributes to increase the modularity of actors, making the maintenance and evolution of SIP entities easier. Third, automatic selection of Session-Parts and Roles as well as automatic messages routing to roles allow to reduce the coding effort since number of controls and extra-state to ensure execution of the appropriate behaviour is minimized. Finally, our approach gives the ability to capture some recurrent behaviours into reusable components (see section 5.3).

Adaptation case studies

In addition to experiment CIAO for the development of SIP entities, we also tested the capacities offered by our implementation over OSGI for adapting SIP applications after their deployment, including at runtime. In our case, we tested the following adaptations using scenarios applied to the developed SIP entities:

-Role addition to SessionPart : This was tested by extending SipPhone Actor with a new functionality to exchange instant text message during a call. To get this extension, we added a MessageHandler client/server role to its CallingSessionPartClt so that MESSAGE requests and their responses can be exchanged during the session.

-Role replacement in SessionPart : This was tested by modifying the SipPhone so that it can handle redirected calls in addition to direct calls. For that purpose, we replaced the initial Caller role of CallingSessionPartClt with a richer Caller role.

-Addition of SessionPart to Actor : This was tested by adding the functionality of presence publishing and subscribing to ProxyServer Actor in order to get enhanced proxy. For this adaptation, we simply added the two SessionParts defined for the presence server (PresencePublishSessionSrv and PresenceSubscribeSessionSrv ) to the deployed proxy. This required to change the target Actor in the descriptor of these components.

-Replacement of SessionPart to Actor : This was tested by changing the basic registration functionality of SipPhone and Proxy actors to secured registration with authentication. To apply these changes, we replaced each registering SessionPart contained in these entities with new ones encapsulating roles capable of handling flow with authentication SIP messages.

All the previous adaptations have been achieved by packaging required components (CIAO components and the related Creator components) in OSGI bundles with the appropriate descriptors and by deploying the bundles in an OSGI platform hosting the application to adapt. Thanks to the use of Declarative Services, CIAO components currently instantiated in the application are automatically notified of the installation of Creator components and can link to them. However, in case of replacement, such components must not be used immediately to create instance as they may be running sessions relying on replaced components. In this work, the replacement takes place when all related sessions are terminated. This strategy is intended to ensure a proper state and behaviour for these sessions until they finish. In particular, we exploit the states from the life-cycle of component (see section 3.2) to determine the correct moment of replacement. After replacement, bundles containing replaced components can be removed from the platform.

During these adaptation experiments, we meet some limitations related to the coordination of components. Indeed, when adding or replacing a subcomponent, it may be necessary to replace the composite if the adaptation also impacts its coordination behaviour. Currently, there is no way to adapt or extend the coordination behaviour of a composite without changing the composite itself. This limitation will be addressed in future works.

Towards a set of reusable components

During the development of targeted applications, we were able to identify and define a first set of reusable Role and SessionPart in the area of calling, location and presence management. We can cite Caller, Callee, RegAcceptor as examples of roles that we were able to reuse in more than one application. PresencePublishRequest, PresenceNotifier and PresenceSubscriptionRecorder roles are not specifically tied to the Presence server application and therefore have the potential to be reused in other presence-enabled applications. SessionParts are also reusable. For example, redirect servers can easily reuse the SessionPart for registering in Proxy (RegisterSessionSrv ) since they need the same functionality. This set of components is a first step and as the number and types of applications developed with our approach will grow, we expect that more reusable Roles and SessionParts will be discovered and that finally a rich base of telephony-related components will be available. The existence of such base should improve significantly the quality of telephony applications but also accelerate their development. It is one of our perspective to construct such a base.

RELATED WORKS

Over the years, several approaches for simplifying the development of SIP applications have been proposed. Most of these approaches are not component-based and can be subdivided in two main categories which are : 1) domain-specific language (DSL) like LESS [START_REF] Wu | Handling feature interactions in the Language for End System Services[END_REF] or SPL [START_REF] Palix | A stepwise approach to developing languages for SIP telephony service creation[END_REF] to program specific kind of SIP entities by means of high-level concepts hiding the intricacies of SIP; 2) generic APIs or frameworks like JAIN-SIP [START_REF] Jcp | JAIN SIP API Specification[END_REF] or PJSIP [START_REF] Prijono | PJSIP -Open Source SIP Stack[END_REF] which enables the programming of unrestricted SIP applications but have limited support for breaking the complexity of involved behaviours. Compared to these approaches, CIAO raises the level of abstraction in a direction similar to DSL but without sacrificing the generality. In addition, CIAO allows to increase the modularity of SIP entities making their maintenance and their evolution easier than with API or frameworks Besides the previous approaches, we also found a few component-based approaches for developing SIP-based applications. Compared to our work, all these approaches only focus on server-side component while CIAO offers a component model for developing both client and server entities. Another important difference with CIAO is that these approaches do not correlate components with the multiple sessions to manage but with features included in the application instead. This difference has some consequences on how components are organized and managed at runtime by respective approaches. Lastly, none of these approaches supports adaptation at the level of components like in our implementation of CIAO above OSGI. Hereafter, we present these approaches and discuss more specific differences with CIAO.

SIP Servlet [START_REF]SIP Servlet 1.1 Specification[END_REF] is a JAIN 7 specification of component and container for building SIP convergent applications similar to HTTP Servlet. SIP Applications are essentially composed of SIP Servlets which are Java components performing answering incoming request but also proxying them or creating new ones. Applications are hosted by a container which handles low-level functionalities and provides a set of high-level services to managed servlets. Compared to CIAO, SIP Servlet is not a hierarchical and dynamic component model. Its components are monolithic and are only instantiated once during the application life-cycle. Interaction between components for routing and handling messages from one or several sessions is possible but it must be done explicitly and is more restricted than in CIAO.

SLEE [START_REF] Jcp | JAIN SLEE API Specification[END_REF] is another JAIN specification for developing communication services based on SIP and others protocols occurring in the area of telephony. This specification defines both a model of high-level component for designing these services and a standardized environment for hosting and executing them. The atomic element defined by SLEE is the Service Building Block, a software component written in Java that send and receive events and perform computation on the receipts of subscribed event and its current state. A service is typically composed of a tree of SBBs. The SLEE environment instantiates such SBB tree when relevant events from the network are triggered and delegates the events to interested SBB instances. As we can observe, SLEE is also a hierarchical and dynamic component model like CIAO. However, the hierarchy of instantiated components is dedicated to a single session while several sessions are dynamically reflected in a CIAO hierarchy. As a result, interactions between sessions are more difficult to manage with the SLEE approach.

ECharts for SIP Servlet [11] is a state-based language that provides component-like entities (called Machines) translated into SIP Servlets. Such entities encapsulate state and logic for handling SIP signaling and have connectable ports to interact with SIP and non-SIP environments. Applications are specified by a top-level Machine that can contain nested machines. Machines are instantiated in response to initial request and the instances interact for handling subsequent messages. Compared to other models, ECharts is very close to SLEE in the sense that it instantiates a complete hierarchy of components for one session and therefore can be compared similarly with CIAO.

More generally, outside the previous works, the use of components for developing telecommunications applications have not been explored a lot. In this area, we may cite the work on DFC [START_REF] Bond | An open architecture for next-generation telecommunication services[END_REF] which has inspired the previous SIP- 7 JAIN is an industrial initiative to standardize the development of telecommunication systems in Java. based component approaches. The work described in [START_REF] Akolkar | Reusable dialog component framework for rapid voice application development[END_REF] also adopts components but specifically targets the development of voice-based applications accessible to web browsers.

CONCLUSION

To tackle some issues arising from the design of advanced telephony applications based on SIP, we have proposed an component-based approach that enables involved entities to be constructed as actors playing roles in multiple sessions. Proposed approach have been experimented to develop various SIP entities with an increase in modularity and adaptability relatively to sessions.

In future works, we plan to optimize the instantiation process by recycling component instances instead of deleting them when a session is terminated. We also plan to identify recurrent coordination patterns between components (such as pipe-and-filter, delegation, forking patterns) and provide these patterns as reusable behaviour for components. Facilitating adaptation of components regarding coordination is also a perspective of this work. A last perspective is to study the typing rules underlying our components, particularly those relative to SIP Ports, in order to enable rigorous checking of components assembly.

Figure 1 :

 1 Figure 1: Example of Presence-based Redirection

Figure 3 :

 3 Figure 3: Illustration of Actors, SessionParts and Roles

Figure 4 :Figure 5 :

 45 Figure 4: SIP Message routing among components

Figure 7 :

 7 Figure 7: Architecture of the Proxy implemented with DS Components

Figure 8 :

 8 Figure 8: Example of descriptors for a Proxy Actor

Figure 9 :

 9 Figure 9: Main classes of CIAO Runtime Framework

Figure 10 :

 10 Figure 10: Example of annotated code for components of presence-enabled UserAgent

Table 2 :

 2 Kind of role events and coordinating operations such control, many scenario for coordinating roles, including the one discussed previously for proxy servers may be managed seamlessly. For this scenario, the expected behaviour can be achieved by defining two coordinating operations in the CallingSession SessionPart: an onRequestReceived operation to detect INVITE request handled by the CallHandler role and relay such request using appropriate CallForwarder roles ; an onResponseReceived operation to cancel unconfirmed branch of CallForwarder roles.

						ua2: UserAgent
						<<actor>>
						r: Callee
						<<Role>>
					2.INVITE	ua3: UserAgent
	ua1: UserAgent			pxy1: Proxy		<<actor>>
	<<actor>>			<<actor>>	5.OK
						r: Callee
	r: Caller	1.INVITE	r: CallHandler	3.INVITE	<<Role>>
	<<Role>>	8.OK		<<Role>>
			f1: CallForwarder
				<<Role>>
			f2: CallForwarder	6.CANCEL	ua4: UserAgent
				<<Role>>		<<actor>>
			f3: CallForwarder <<Role>>	4.INVITE 7.CANCEL	r: Callee <<Role>>
	SessionPart				CallingSession
	Figure 6: Forking as example of roles coordination
	Role event		Coordinating op-	Provided Parameters
			eration
	Role creation		onCreatedRole	New role reference
	Role deletion		onDeletedRole	Deleted role reference
	Role binding		onBoundRole	Bound role
	Request reception	onRequest-	Role reference, Request ref-
	by a role		Received	erence
	Response reception	onResponse-	Role reference, Response ref-
	by a role		Received	erence
	Request sending by	onRequestSent	Role reference, Request ref-
	a role				erence
	Response sending	onResponse-	Role reference, Response ref-
	by a role		Received	erence

2 ]

 2 @clientserverRole // Declaration of role class public class Callee { public void onInvite (Request req, ServerTransaction tx) { ... } public void onACK (Request req, ServerTransaction tx) { ... } public void sendBye () {...} Example of annotations use to code the presence server example

	...
	}
	@sessionPart // Declaration of session part
	@useRole(type=Callee.class,method="INVITE")
	@useRole(type=Caller.class)
	public class CallingSessionPartUA { public void onRequestReceive(Role r, Request req) { if (r.hasType(Callee.class) && isINVITE(req)) { from = req.fromHeader().getAddress();
		actor.getCallerHistory().put(from);
	}	} ...
	@actor // Declaration of actor class
	@useSessionPart(type=RegisteringSessionPartPUA.class)
	@useSessionPart(type=PublishingSessionPartPUA.class)
	@useSessionPart(type=CallingSessionPartPUA.class,method="INVITE",
	condition="isUserAvailable))
	public class PresenceEnabledUA implements ICallControl,
	IPresenceControl, ICallHistoryMngt { String contactName;
		List<SipAddress> callerHistory;
	public void clearHistory() {...} public void addHistory(SipAddress adr) {...} public void initiateCall(String sipAddress) {...} public void endCall() {...} public boolean isUserAvailable() { ... } public void onStartedSession(SessionPart session){
		getRole(PublishSession,PresencePublisher).
	...	setNewState(State.unavailable); }
	}
		Code 3.

Proxy behaviour in SIP consists in relaying each request and response between user agents of a session.

Third party call entities are often used for operator services, click-to-dial and conferencing services.

The table also indicates if the actors participate to one or several sessions at the same time (written respectively[START_REF] Akolkar | Reusable dialog component framework for rapid voice application development[END_REF] or [*] after the session type name).