Sat Mar 10 01:55:43 2012

Asterisk developer's documentation


res_srtp.c File Reference

Secure RTP (SRTP). More...

#include "asterisk.h"
#include <srtp/srtp.h>
#include "asterisk/lock.h"
#include "asterisk/sched.h"
#include "asterisk/module.h"
#include "asterisk/options.h"
#include "asterisk/rtp_engine.h"
#include "asterisk/astobj2.h"

Go to the source code of this file.

Data Structures

struct  ast_srtp
struct  ast_srtp_policy

Functions

static void __reg_module (void)
static void __unreg_module (void)
static int ast_srtp_add_stream (struct ast_srtp *srtp, struct ast_srtp_policy *policy)
static int ast_srtp_change_source (struct ast_srtp *srtp, unsigned int from_ssrc, unsigned int to_ssrc)
static int ast_srtp_create (struct ast_srtp **srtp, struct ast_rtp_instance *rtp, struct ast_srtp_policy *policy)
static void ast_srtp_destroy (struct ast_srtp *srtp)
static int ast_srtp_get_random (unsigned char *key, size_t len)
static struct ast_srtp_policyast_srtp_policy_alloc (void)
static void ast_srtp_policy_destroy (struct ast_srtp_policy *policy)
static int ast_srtp_policy_set_master_key (struct ast_srtp_policy *policy, const unsigned char *key, size_t key_len, const unsigned char *salt, size_t salt_len)
static void ast_srtp_policy_set_ssrc (struct ast_srtp_policy *policy, unsigned long ssrc, int inbound)
static int ast_srtp_policy_set_suite (struct ast_srtp_policy *policy, enum ast_srtp_suite suite)
static int ast_srtp_protect (struct ast_srtp *srtp, void **buf, int *len, int rtcp)
static void ast_srtp_set_cb (struct ast_srtp *srtp, const struct ast_srtp_cb *cb, void *data)
static int ast_srtp_unprotect (struct ast_srtp *srtp, void *buf, int *len, int rtcp)
static struct ast_srtp_policyfind_policy (struct ast_srtp *srtp, const srtp_policy_t *policy, int flags)
static int load_module (void)
static int policy_cmp_fn (void *obj, void *arg, int flags)
static void policy_destructor (void *obj)
static int policy_hash_fn (const void *obj, const int flags)
static int policy_set_suite (crypto_policy_t *p, enum ast_srtp_suite suite)
static int res_srtp_init (void)
static struct ast_srtpres_srtp_new (void)
static const char * srtp_errstr (int err)
static void srtp_event_cb (srtp_event_data_t *data)
static int unload_module (void)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Secure RTP (SRTP)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND, }
static struct ast_module_infoast_module_info = &__mod_info
static int g_initialized = 0
static struct ast_srtp_policy_res policy_res
static struct ast_srtp_res srtp_res


Detailed Description

Secure RTP (SRTP).

Secure RTP (SRTP) Specified in RFC 3711.

Author:
Mikael Magnusson <mikma@users.sourceforge.net>

Definition in file res_srtp.c.


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 540 of file res_srtp.c.

static void __unreg_module ( void   )  [static]

Definition at line 540 of file res_srtp.c.

static int ast_srtp_add_stream ( struct ast_srtp srtp,
struct ast_srtp_policy policy 
) [static]

Definition at line 462 of file res_srtp.c.

References ao2_t_link, ao2_t_ref, ast_debug, find_policy(), match(), OBJ_POINTER, ast_srtp::policies, ast_srtp::session, and ast_srtp_policy::sp.

Referenced by ast_srtp_change_source().

00463 {
00464    struct ast_srtp_policy *match;
00465 
00466    if ((match = find_policy(srtp, &policy->sp, OBJ_POINTER))) {
00467       ast_debug(3, "Policy already exists, not re-adding\n");
00468       ao2_t_ref(match, -1, "Unreffing already existing policy");
00469       return -1;
00470    }
00471 
00472    if (srtp_add_stream(srtp->session, &policy->sp) != err_status_ok) {
00473       return -1;
00474    }
00475 
00476    ao2_t_link(srtp->policies, policy, "Added additional stream");
00477 
00478    return 0;
00479 }

static int ast_srtp_change_source ( struct ast_srtp srtp,
unsigned int  from_ssrc,
unsigned int  to_ssrc 
) [static]

Definition at line 481 of file res_srtp.c.

References ao2_t_ref, ast_debug, ast_log(), ast_srtp_add_stream(), find_policy(), match(), OBJ_POINTER, OBJ_UNLINK, ast_srtp::session, and status.

00482 {
00483    struct ast_srtp_policy *match;
00484    struct srtp_policy_t sp = {
00485       .ssrc.type = ssrc_specific,
00486       .ssrc.value = from_ssrc,
00487    };
00488    err_status_t status;
00489 
00490    /* If we find a mach, return and unlink it from the container so we
00491     * can change the SSRC (which is part of the hash) and then have
00492     * ast_srtp_add_stream link it back in if all is well */
00493    if ((match = find_policy(srtp, &sp, OBJ_POINTER | OBJ_UNLINK))) {
00494       match->sp.ssrc.value = to_ssrc;
00495       if (ast_srtp_add_stream(srtp, match)) {
00496          ast_log(LOG_WARNING, "Couldn't add stream\n");
00497       } else if ((status = srtp_remove_stream(srtp->session, from_ssrc))) {
00498          ast_debug(3, "Couldn't remove stream (%d)\n", status);
00499       }
00500       ao2_t_ref(match, -1, "Unreffing found policy in change_source");
00501    }
00502 
00503    return 0;
00504 }

static int ast_srtp_create ( struct ast_srtp **  srtp,
struct ast_rtp_instance rtp,
struct ast_srtp_policy policy 
) [static]

Definition at line 428 of file res_srtp.c.

References ao2_t_link, ast_module_ref(), res_srtp_new(), ast_srtp::rtp, ast_srtp::session, and ast_srtp_policy::sp.

00429 {
00430    struct ast_srtp *temp;
00431 
00432    if (!(temp = res_srtp_new())) {
00433       return -1;
00434    }
00435 
00436    if (srtp_create(&temp->session, &policy->sp) != err_status_ok) {
00437       return -1;
00438    }
00439 
00440    ast_module_ref(ast_module_info->self);
00441    temp->rtp = rtp;
00442    *srtp = temp;
00443 
00444    ao2_t_link((*srtp)->policies, policy, "Created initial policy");
00445 
00446    return 0;
00447 }

static void ast_srtp_destroy ( struct ast_srtp srtp  )  [static]

Definition at line 449 of file res_srtp.c.

References ao2_t_callback, ao2_t_ref, ast_free, ast_module_unref(), OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, ast_srtp::policies, and ast_srtp::session.

00450 {
00451    if (srtp->session) {
00452       srtp_dealloc(srtp->session);
00453    }
00454 
00455    ao2_t_callback(srtp->policies, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL, "Unallocate policy");
00456    ao2_t_ref(srtp->policies, -1, "Destroying container");
00457 
00458    ast_free(srtp);
00459    ast_module_unref(ast_module_info->self);
00460 }

static int ast_srtp_get_random ( unsigned char *  key,
size_t  len 
) [static]

Definition at line 302 of file res_srtp.c.

00303 {
00304    return crypto_get_random(key, len) != err_status_ok ? -1: 0;
00305 }

static struct ast_srtp_policy * ast_srtp_policy_alloc ( void   )  [static]

Definition at line 232 of file res_srtp.c.

References ao2_t_alloc, ast_log(), LOG_ERROR, and policy_destructor().

00233 {
00234    struct ast_srtp_policy *tmp;
00235 
00236    if (!(tmp = ao2_t_alloc(sizeof(*tmp), policy_destructor, "Allocating policy"))) {
00237       ast_log(LOG_ERROR, "Unable to allocate memory for srtp_policy\n");
00238    }
00239 
00240    return tmp;
00241 }

static void ast_srtp_policy_destroy ( struct ast_srtp_policy policy  )  [static]

Definition at line 243 of file res_srtp.c.

References ao2_t_ref.

00244 {
00245    ao2_t_ref(policy, -1, "Destroying policy");
00246 }

static int ast_srtp_policy_set_master_key ( struct ast_srtp_policy policy,
const unsigned char *  key,
size_t  key_len,
const unsigned char *  salt,
size_t  salt_len 
) [static]

Definition at line 280 of file res_srtp.c.

References ast_calloc, ast_free, and ast_srtp_policy::sp.

00281 {
00282    size_t size = key_len + salt_len;
00283    unsigned char *master_key;
00284 
00285    if (policy->sp.key) {
00286       ast_free(policy->sp.key);
00287       policy->sp.key = NULL;
00288    }
00289 
00290    if (!(master_key = ast_calloc(1, size))) {
00291       return -1;
00292    }
00293 
00294    memcpy(master_key, key, key_len);
00295    memcpy(master_key + key_len, salt, salt_len);
00296 
00297    policy->sp.key = master_key;
00298 
00299    return 0;
00300 }

static void ast_srtp_policy_set_ssrc ( struct ast_srtp_policy policy,
unsigned long  ssrc,
int  inbound 
) [static]

Definition at line 211 of file res_srtp.c.

References ast_srtp_policy::sp.

00213 {
00214    if (ssrc) {
00215       policy->sp.ssrc.type = ssrc_specific;
00216       policy->sp.ssrc.value = ssrc;
00217    } else {
00218       policy->sp.ssrc.type = inbound ? ssrc_any_inbound : ssrc_any_outbound;
00219    }
00220 }

static int ast_srtp_policy_set_suite ( struct ast_srtp_policy policy,
enum ast_srtp_suite  suite 
) [static]

Definition at line 275 of file res_srtp.c.

References policy_set_suite(), and ast_srtp_policy::sp.

00276 {
00277    return policy_set_suite(&policy->sp.rtp, suite) | policy_set_suite(&policy->sp.rtcp, suite);
00278 }

static int ast_srtp_protect ( struct ast_srtp srtp,
void **  buf,
int *  len,
int  rtcp 
) [static]

Definition at line 406 of file res_srtp.c.

References ast_log(), ast_srtp::buf, ast_srtp::rtcpbuf, ast_srtp::session, and srtp_errstr().

00407 {
00408    int res;
00409    unsigned char *localbuf;
00410 
00411    if ((*len + SRTP_MAX_TRAILER_LEN) > sizeof(srtp->buf)) {
00412       return -1;
00413    }
00414    
00415    localbuf = rtcp ? srtp->rtcpbuf : srtp->buf;
00416 
00417    memcpy(localbuf, *buf, *len);
00418 
00419    if ((res = rtcp ? srtp_protect_rtcp(srtp->session, localbuf, len) : srtp_protect(srtp->session, localbuf, len)) != err_status_ok && res != err_status_replay_fail) {
00420       ast_log(LOG_WARNING, "SRTP protect: %s\n", srtp_errstr(res));
00421       return -1;
00422    }
00423 
00424    *buf = localbuf;
00425    return *len;
00426 }

static void ast_srtp_set_cb ( struct ast_srtp srtp,
const struct ast_srtp_cb cb,
void *  data 
) [static]

Definition at line 307 of file res_srtp.c.

References ast_srtp::cb, and ast_srtp::data.

00308 {
00309    if (!srtp) {
00310       return;
00311    }
00312 
00313    srtp->cb = cb;
00314    srtp->data = data;
00315 }

static int ast_srtp_unprotect ( struct ast_srtp srtp,
void *  buf,
int *  len,
int  rtcp 
) [static]

Definition at line 318 of file res_srtp.c.

References ast_rtp_instance_get_stats(), AST_RTP_INSTANCE_STAT_REMOTE_SSRC, ast_srtp::cb, ast_srtp::data, ast_srtp_cb::no_ctx, ast_rtp_instance_stats::remote_ssrc, ast_srtp::rtp, and ast_srtp::session.

00319 {
00320    int res = 0;
00321    int i;
00322    int retry = 0;
00323    struct ast_rtp_instance_stats stats = {0,};
00324 
00325 tryagain:
00326 
00327    for (i = 0; i < 2; i++) {
00328       res = rtcp ? srtp_unprotect_rtcp(srtp->session, buf, len) : srtp_unprotect(srtp->session, buf, len);
00329       if (res != err_status_no_ctx) {
00330          break;
00331       }
00332 
00333       if (srtp->cb && srtp->cb->no_ctx) {
00334          if (ast_rtp_instance_get_stats(srtp->rtp, &stats, AST_RTP_INSTANCE_STAT_REMOTE_SSRC)) {
00335             break;
00336          }
00337          if (srtp->cb->no_ctx(srtp->rtp, stats.remote_ssrc, srtp->data) < 0) {
00338             break;
00339          }
00340       } else {
00341          break;
00342       }
00343    }
00344 
00345    if (retry == 0  && res == err_status_replay_old) {
00346       ast_log(LOG_WARNING, "SRTP unprotect: %s\n", srtp_errstr(res));
00347 
00348       if (srtp->session) {
00349          struct ast_srtp_policy *policy;
00350          struct ao2_iterator it;
00351          int policies_count;
00352 
00353          // dealloc first
00354          ast_log(LOG_WARNING, "SRTP destroy before re-create\n");
00355          srtp_dealloc(srtp->session);
00356 
00357          // get the count
00358          policies_count = ao2_container_count(srtp->policies);
00359 
00360          // get the first to build up
00361          it = ao2_iterator_init(srtp->policies, 0);
00362          policy = ao2_iterator_next(&it);
00363 
00364          ast_log(LOG_WARNING, "SRTP try to re-create\n");
00365          if (policy) {
00366             if (srtp_create(&srtp->session, &policy->sp) == err_status_ok) {
00367                ast_log(LOG_WARNING, "SRTP re-created with first policy\n");
00368 
00369                // unref first element
00370                ao2_t_ref(policy, -1, "Unreffing first policy for re-creating srtp session");
00371 
00372                // if we have more than one policy, add them afterwards
00373                if (policies_count > 1) {
00374                   ast_log(LOG_WARNING, "Add all the other %d policies\n",
00375                      policies_count - 1);
00376                   while ((policy = ao2_iterator_next(&it))) {
00377                      srtp_add_stream(srtp->session, &policy->sp);
00378                      ao2_t_ref(policy, -1, "Unreffing n-th policy for re-creating srtp session");
00379                   }
00380                }
00381 
00382                retry++;
00383                ao2_iterator_destroy(&it);
00384                goto tryagain;
00385             }
00386             ao2_t_ref(policy, -1, "Unreffing first policy after srtp_create failed");
00387          }
00388          ao2_iterator_destroy(&it);
00389       }
00390    }
00391 
00392    if (res != err_status_ok && res != err_status_replay_fail ) {
00393       if ((srtp->warned >= 10) && !((srtp->warned - 10) % 100)) {
00394          ast_log(LOG_WARNING, "SRTP unprotect: %s %d\n", srtp_errstr(res), srtp->warned);
00395          srtp->warned = 11;
00396       } else {
00397          srtp->warned++;
00398       }
00399       errno = EAGAIN;
00400       return -1;
00401    }
00402 
00403    return *len;
00404 }

static struct ast_srtp_policy* find_policy ( struct ast_srtp srtp,
const srtp_policy_t *  policy,
int  flags 
) [static]

Definition at line 159 of file res_srtp.c.

References ao2_t_find, ast_srtp::policies, and ast_srtp_policy::sp.

Referenced by ast_srtp_add_stream(), and ast_srtp_change_source().

00160 {
00161    struct ast_srtp_policy tmp = {
00162       .sp = {
00163          .ssrc.type = policy->ssrc.type,
00164          .ssrc.value = policy->ssrc.value,
00165       },
00166    };
00167 
00168    return ao2_t_find(srtp->policies, &tmp, flags, "Looking for policy");
00169 }

static int load_module ( void   )  [static]

Definition at line 525 of file res_srtp.c.

References res_srtp_init().

00526 {
00527    return res_srtp_init();
00528 }

static int policy_cmp_fn ( void *  obj,
void *  arg,
int  flags 
) [static]

Definition at line 152 of file res_srtp.c.

References ast_srtp_policy::sp.

Referenced by res_srtp_new().

00153 {
00154    const struct ast_srtp_policy *one = obj, *two = arg;
00155 
00156    return one->sp.ssrc.type == two->sp.ssrc.type && one->sp.ssrc.value == two->sp.ssrc.value;
00157 }

static void policy_destructor ( void *  obj  )  [static]

Definition at line 222 of file res_srtp.c.

References ast_free, and ast_srtp_policy::sp.

Referenced by ast_srtp_policy_alloc().

00223 {
00224    struct ast_srtp_policy *policy = obj;
00225 
00226    if (policy->sp.key) {
00227       ast_free(policy->sp.key);
00228       policy->sp.key = NULL;
00229    }
00230 }

static int policy_hash_fn ( const void *  obj,
const int  flags 
) [static]

Definition at line 145 of file res_srtp.c.

References ast_srtp_policy::sp.

Referenced by res_srtp_new().

00146 {
00147    const struct ast_srtp_policy *policy = obj;
00148 
00149    return policy->sp.ssrc.type == ssrc_specific ? policy->sp.ssrc.value : policy->sp.ssrc.type;
00150 }

static int policy_set_suite ( crypto_policy_t *  p,
enum ast_srtp_suite  suite 
) [static]

Definition at line 248 of file res_srtp.c.

References AST_AES_CM_128_HMAC_SHA1_32, AST_AES_CM_128_HMAC_SHA1_80, ast_log(), and LOG_ERROR.

Referenced by ast_srtp_policy_set_suite().

00249 {
00250    switch (suite) {
00251    case AST_AES_CM_128_HMAC_SHA1_80:
00252       p->cipher_type = AES_128_ICM;
00253       p->cipher_key_len = 30;
00254       p->auth_type = HMAC_SHA1;
00255       p->auth_key_len = 20;
00256       p->auth_tag_len = 10;
00257       p->sec_serv = sec_serv_conf_and_auth;
00258       return 0;
00259 
00260    case AST_AES_CM_128_HMAC_SHA1_32:
00261       p->cipher_type = AES_128_ICM;
00262       p->cipher_key_len = 30;
00263       p->auth_type = HMAC_SHA1;
00264       p->auth_key_len = 20;
00265       p->auth_tag_len = 4;
00266       p->sec_serv = sec_serv_conf_and_auth;
00267       return 0;
00268 
00269    default:
00270       ast_log(LOG_ERROR, "Invalid crypto suite: %d\n", suite);
00271       return -1;
00272    }
00273 }

static int res_srtp_init ( void   )  [static]

Definition at line 506 of file res_srtp.c.

References ast_rtp_engine_register_srtp(), g_initialized, policy_res, srtp_event_cb(), and srtp_res.

Referenced by load_module().

00507 {
00508    if (g_initialized) {
00509       return 0;
00510    }
00511 
00512    if (srtp_init() != err_status_ok) {
00513       return -1;
00514    }
00515 
00516    srtp_install_event_handler(srtp_event_cb);
00517 
00518    return ast_rtp_engine_register_srtp(&srtp_res, &policy_res);
00519 }

static struct ast_srtp* res_srtp_new ( void   )  [static]

Definition at line 171 of file res_srtp.c.

References ao2_t_container_alloc, ast_calloc, ast_free, ast_log(), LOG_ERROR, policy_cmp_fn(), and policy_hash_fn().

Referenced by ast_srtp_create().

00172 {
00173    struct ast_srtp *srtp;
00174 
00175    if (!(srtp = ast_calloc(1, sizeof(*srtp)))) {
00176       ast_log(LOG_ERROR, "Unable to allocate memory for srtp\n");
00177       return NULL;
00178    }
00179 
00180    if (!(srtp->policies = ao2_t_container_alloc(5, policy_hash_fn, policy_cmp_fn, "SRTP policy container"))) {
00181       ast_free(srtp);
00182       return NULL;
00183    }
00184    
00185    srtp->warned = 1;
00186 
00187    return srtp;
00188 }

static const char* srtp_errstr ( int  err  )  [static]

Definition at line 105 of file res_srtp.c.

Referenced by ast_srtp_protect().

00106 {
00107    switch(err) {
00108    case err_status_ok:
00109       return "nothing to report";
00110    case err_status_fail:
00111       return "unspecified failure";
00112    case err_status_bad_param:
00113       return "unsupported parameter";
00114    case err_status_alloc_fail:
00115       return "couldn't allocate memory";
00116    case err_status_dealloc_fail:
00117       return "couldn't deallocate properly";
00118    case err_status_init_fail:
00119       return "couldn't initialize";
00120    case err_status_terminus:
00121       return "can't process as much data as requested";
00122    case err_status_auth_fail:
00123       return "authentication failure";
00124    case err_status_cipher_fail:
00125       return "cipher failure";
00126    case err_status_replay_fail:
00127       return "replay check failed (bad index)";
00128    case err_status_replay_old:
00129       return "replay check failed (index too old)";
00130    case err_status_algo_fail:
00131       return "algorithm failed test routine";
00132    case err_status_no_such_op:
00133       return "unsupported operation";
00134    case err_status_no_ctx:
00135       return "no appropriate context found";
00136    case err_status_cant_check:
00137       return "unable to perform desired validation";
00138    case err_status_key_expired:
00139       return "can't use key any more";
00140    default:
00141       return "unknown";
00142    }
00143 }

static void srtp_event_cb ( srtp_event_data_t *  data  )  [static]

Definition at line 193 of file res_srtp.c.

References ast_debug.

Referenced by res_srtp_init().

00194 {
00195    switch (data->event) {
00196    case event_ssrc_collision:
00197       ast_debug(1, "SSRC collision\n");
00198       break;
00199    case event_key_soft_limit:
00200       ast_debug(1, "event_key_soft_limit\n");
00201       break;
00202    case event_key_hard_limit:
00203       ast_debug(1, "event_key_hard_limit\n");
00204       break;
00205    case event_packet_index_limit:
00206       ast_debug(1, "event_packet_index_limit\n");
00207       break;
00208    }
00209 }

static int unload_module ( void   )  [static]

Definition at line 530 of file res_srtp.c.

References ast_rtp_engine_unregister_srtp().

00531 {
00532    ast_rtp_engine_unregister_srtp();
00533    return 0;
00534 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Secure RTP (SRTP)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND, } [static]

Definition at line 540 of file res_srtp.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 540 of file res_srtp.c.

int g_initialized = 0 [static]

Definition at line 66 of file res_srtp.c.

Referenced by res_srtp_init().

struct ast_srtp_policy_res policy_res [static]

Definition at line 97 of file res_srtp.c.

Referenced by ast_rtp_engine_register_srtp(), and res_srtp_init().

struct ast_srtp_res srtp_res [static]

Definition at line 86 of file res_srtp.c.

Referenced by ast_rtp_engine_register_srtp(), and res_srtp_init().


Generated on Sat Mar 10 01:55:43 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7