]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
Pre-fill values for rtp terms (local address + reserved rtp port). Add functions...
authorMathieu Rene <mrene@avgs.ca>
Fri, 20 Jul 2012 18:33:36 +0000 (14:33 -0400)
committerMathieu Rene <mrene@avgs.ca>
Fri, 20 Jul 2012 18:33:36 +0000 (14:33 -0400)
src/mod/endpoints/mod_media_gateway/media_gateway.c
src/mod/endpoints/mod_media_gateway/mod_media_gateway.h

index b596cdb81913eaab9d65473e36c9106905d702b8..3a5e7bbb8cc8b2cf686c485e38f61bbff24cbcd5 100644 (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;
index 1c9ff91b0de85eba9b0e14acd2393289aef623e6..e62f59bf09e5ce7a004e0f538d638e0f76a9226b 100644 (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);