Pre-fill values for rtp terms (local address + reserved rtp port). Add functions to pick rtp term ids, add a memory pool in the termination struct.

This commit is contained in:
Mathieu Rene 2012-07-20 14:33:36 -04:00
parent d6d1365053
commit dd633cfbfd
2 changed files with 104 additions and 0 deletions

View File

@ -145,16 +145,40 @@ done:
mg_termination_t *megaco_choose_termination(megaco_profile_t *profile, const char *prefix)
{
mg_termination_type_t termtype;
switch_memory_pool_t *pool;
mg_termination_t *term = NULL;
char name[100];
int term_id;
/* Check the termination type by prefix */
if (strncasecmp(prefix, profile->rtp_termination_id_prefix, strlen(profile->rtp_termination_id_prefix)) == 0) {
termtype = MG_TERM_RTP;
term_id = mg_rtp_request_id(profile);
switch_snprintf(name, sizeof name, "%s/%d", profile->rtp_termination_id_prefix, term_id);
} else {
/* TODO Math: look through TDM channels */
return NULL;
}
switch_core_new_memory_pool(&pool);
term = switch_core_alloc(pool, sizeof *term);
term->pool = pool;
term->type = termtype;
if (termtype == MG_TERM_RTP) {
/* Fill in local address and reserve an rtp port */
term->u.rtp.local_addr = profile->my_ipaddr;
term->u.rtp.local_port = switch_rtp_request_port(term->u.rtp.local_addr);
term->u.rtp.codec = megaco_codec_str(profile->default_codec);
term->u.rtp.term_id = term_id;
term->name = switch_core_strdup(term->pool, name);
} else if (termtype == MG_TERM_TDM) {
/* XXX initialize tdm-specific fields */
}
switch_core_hash_insert_wrlock(profile->terminations, term->name, term, profile->terminations_rwlock);
return term;
}
mg_termination_t *megaco_find_termination(megaco_profile_t *profile, const char *name)
@ -177,7 +201,12 @@ void megaco_termination_destroy(mg_termination_t *term)
term->uuid = NULL;
}
if (term->type == MG_TERM_RTP && term->u.rtp.local_port != 0) {
switch_rtp_release_port(term->u.rtp.local_addr, term->u.rtp.local_port);
}
switch_core_hash_delete_wrlock(term->profile->terminations, term->name, term->profile->terminations_rwlock);
switch_core_destroy_memory_pool(&term->pool);
}
switch_status_t megaco_context_add_termination(mg_context_t *ctx, mg_termination_t *term)
@ -210,6 +239,8 @@ switch_status_t megaco_context_add_termination(mg_context_t *ctx, mg_termination
switch_ivr_uuid_bridge(ctx->terminations[0]->uuid, ctx->terminations[1]->uuid);
}
return SWITCH_STATUS_SUCCESS;
}
@ -226,6 +257,8 @@ switch_status_t megaco_context_sub_termination(mg_context_t *ctx, mg_termination
}
megaco_termination_destroy(term);
return SWITCH_STATUS_SUCCESS;
}
@ -343,6 +376,27 @@ void megaco_release_context(mg_context_t *ctx)
switch_thread_rwlock_unlock(profile->contexts_rwlock);
}
uint32_t mg_rtp_request_id(megaco_profile_t *profile)
{
if (profile->rtpid_next >= MG_MAX_RTPID || profile->rtpid_next == 0) {
profile->rtpid_next = 1;
}
for (; profile->rtpid_next < MG_MAX_RTPID; profile->rtpid_next++) {
if ((profile->rtpid_bitmap[profile->rtpid_next % 8] & (1 << (profile->rtpid_next / 8))) == 0) {
profile->rtpid_bitmap[profile->rtpid_next % 8] |= 1 << (profile->rtpid_next / 8);
return profile->rtpid_next;
}
}
return 0;
}
void mg_rtp_release_id(megaco_profile_t *profile, uint32_t id)
{
profile->rtpid_bitmap[id % 8] &= ~(1 << (id / 8));
}
switch_status_t megaco_profile_start(const char *profilename)
{
switch_memory_pool_t *pool;

View File

@ -40,6 +40,9 @@ typedef enum {
MEGACO_CODEC_G729,
MEGACO_CODEC_G723_1,
MEGACO_CODEC_ILBC,
/* Nothing below this line */
MEGACO_CODEC_INVALID = 0xFFFFFFFF
} megaco_codec_t;
typedef struct mg_peer_profile_s{
@ -81,6 +84,7 @@ typedef struct mg_context_s mg_context_t;
#define kCHAN_ID "chan"
typedef struct mg_termination_s {
switch_memory_pool_t *pool;
mg_termination_type_t type;
const char *name; /*!< Megaco Name */
const char *uuid; /*!< UUID of the associated FS channel, or NULL if it's not activated */
@ -102,6 +106,7 @@ typedef struct mg_termination_s {
int rfc2833_pt; /*!< If the stream is using rfc2833 for dtmf events, this has to be set to its negotiated payload type */
int rate; /*!< Sampling rate */
const char *codec; /*!< Codec to use, using the freeswitch nomenclature. This could be "PCMU" for G711.U, "PCMA" for G711.A, or "G729" for g729 */
int term_id;
} rtp;
struct {
@ -122,6 +127,7 @@ struct mg_context_s {
#define MG_CONTEXT_MODULO 16
#define MG_MAX_CONTEXTS 32768
#define MG_MAX_RTPID 32768
struct megaco_profile_s {
@ -148,10 +154,47 @@ struct megaco_profile_s {
uint8_t contexts_bitmap[MG_MAX_CONTEXTS/8]; /* Availability matrix, enough bits for a 32768 bitmap */
mg_context_t *contexts[MG_CONTEXT_MODULO];
uint8_t rtpid_bitmap[MG_MAX_CONTEXTS/8];
uint32_t rtpid_next;
switch_hash_t *terminations;
switch_thread_rwlock_t *terminations_rwlock;
};
static inline const char *megaco_codec_str(megaco_codec_t codec)
{
switch (codec) {
case MEGACO_CODEC_PCMU:
return "PCMU";
case MEGACO_CODEC_PCMA:
return "PCMA";
case MEGACO_CODEC_G729:
return "G729";
case MEGACO_CODEC_G723_1:
return "G723"; /* XXX double check this */
case MEGACO_CODEC_ILBC:
return "ILBC";
case MEGACO_CODEC_INVALID:
default:
return NULL;
}
}
static inline megaco_codec_t megaco_codec_parse(const char *codec) {
if (!strcasecmp(codec, "PCMU")) {
return MEGACO_CODEC_PCMU;
} else if (!strcasecmp(codec, "PCMA")) {
return MEGACO_CODEC_PCMA;
} else if (!strcasecmp(codec, "G729")) {
return MEGACO_CODEC_G729;
} else if (!strcasecmp(codec, "G723")) {
return MEGACO_CODEC_G723_1;
} else if (!strcasecmp(codec, "ILBC")) {
return MEGACO_CODEC_ILBC;
} else {
return MEGACO_CODEC_INVALID;
}
}
megaco_profile_t *megaco_profile_locate(const char *name);
mg_peer_profile_t *megaco_peer_profile_locate(const char *name);
@ -160,10 +203,17 @@ void megaco_profile_release(megaco_profile_t *profile);
switch_status_t megaco_profile_start(const char *profilename);
switch_status_t megaco_profile_destroy(megaco_profile_t **profile);
uint32_t mg_rtp_request_id(megaco_profile_t *profile);
void mg_rtp_release_id(megaco_profile_t *profile, uint32_t id);
mg_context_t *megaco_get_context(megaco_profile_t *profile, uint32_t context_id);
mg_context_t *megaco_choose_context(megaco_profile_t *profile);
void megaco_release_context(mg_context_t *ctx);
mg_termination_t *megaco_choose_termination(megaco_profile_t *profile, const char *prefix);
mg_termination_t *megaco_find_termination(megaco_profile_t *profile, const char *name);
void megaco_termination_destroy(mg_termination_t *term);
megaco_profile_t* megaco_get_profile_by_suId(SuId suId);
mg_context_t *megaco_find_context_by_suid(SuId suId, uint32_t context_id);