From: Mathieu Rene Date: Fri, 20 Jul 2012 18:33:36 +0000 (-0400) Subject: Pre-fill values for rtp terms (local address + reserved rtp port). Add functions... X-Git-Tag: v1.2.3^2~71^2^2~138 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=dd633cfbfd47f9afcdc0206fdc3a41a8c4024762;p=thirdparty%2Ffreeswitch.git 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. --- diff --git a/src/mod/endpoints/mod_media_gateway/media_gateway.c b/src/mod/endpoints/mod_media_gateway/media_gateway.c index b596cdb819..3a5e7bbb8c 100644 --- a/src/mod/endpoints/mod_media_gateway/media_gateway.c +++ b/src/mod/endpoints/mod_media_gateway/media_gateway.c @@ -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; diff --git a/src/mod/endpoints/mod_media_gateway/mod_media_gateway.h b/src/mod/endpoints/mod_media_gateway/mod_media_gateway.h index 1c9ff91b0d..e62f59bf09 100644 --- a/src/mod/endpoints/mod_media_gateway/mod_media_gateway.h +++ b/src/mod/endpoints/mod_media_gateway/mod_media_gateway.h @@ -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);