Fix a longstanding issue with MFC-R2 configuration that prevented users
authorMoises Silva <moises.silva@gmail.com>
Fri, 12 Jul 2013 22:35:50 +0000 (22:35 +0000)
committerMoises Silva <moises.silva@gmail.com>
Fri, 12 Jul 2013 22:35:50 +0000 (22:35 +0000)
from mixing different variants or general MFC-R2 settings within the same E1 line.

Most users do not have a problem with this since MFC-R2 lines are usually fractional E1s, or
the whole E1 has the same country variant and R2 settings.

In Venezuela however is common to have inbound MFC-R2 and outbound DTMF-R2 within the same E1.

This fix now properly parses the chan_dahdi.conf file to generate a new openr2 context every
time a new channel => section is found and the configuration was changed.

(closes issue ASTERISK-21117)
Reported by: Rafael Angulo
Related Elastix issue: http://bugs.elastix.org/view.php?id=1612
........

Merged revisions 394106 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........

Merged revisions 394173 from http://svn.asterisk.org/svn/asterisk/branches/11

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@394263 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/chan_dahdi.c

index 8cabc79..28fd65f 100644 (file)
@@ -652,14 +652,6 @@ static int cur_defaultdpc = -1;
 #endif /* defined(HAVE_SS7) */
 
 #ifdef HAVE_OPENR2
-struct dahdi_mfcr2 {
-       pthread_t r2master;                    /*!< Thread of master */
-       openr2_context_t *protocol_context;    /*!< OpenR2 context handle */
-       struct dahdi_pvt *pvts[SIG_MFCR2_MAX_CHANNELS];     /*!< Member channel pvt structs */
-       int numchans;                          /*!< Number of channels in this R2 block */
-       int monitored_count;                   /*!< Number of channels being monitored */
-};
-
 struct dahdi_mfcr2_conf {
        openr2_variant_t variant;
        int mfback_timeout;
@@ -694,6 +686,15 @@ struct dahdi_mfcr2_conf {
        openr2_calling_party_category_t category;
 };
 
+/* MFC-R2 pseudo-link structure */
+struct dahdi_mfcr2 {
+       pthread_t r2master;                    /*!< Thread of master */
+       openr2_context_t *protocol_context;    /*!< OpenR2 context handle */
+       struct dahdi_pvt *pvts[SIG_MFCR2_MAX_CHANNELS];     /*!< Member channel pvt structs */
+       int numchans;                          /*!< Number of channels in this R2 block */
+       struct dahdi_mfcr2_conf conf;         /*!< Configuration used to setup this pseudo-link */
+};
+
 /* malloc'd array of malloc'd r2links */
 static struct dahdi_mfcr2 **r2links;
 /* how many r2links have been malloc'd */
@@ -12588,14 +12589,20 @@ static void dahdi_r2_destroy_links(void)
        r2links_count = 0;
 }
 
-#define R2_LINK_CAPACITY 10
-static struct dahdi_mfcr2 *dahdi_r2_get_link(void)
+/* This is an artificial convenient capacity, to keep at most a full E1 of channels in a single thread */
+#define R2_LINK_CAPACITY 30
+static struct dahdi_mfcr2 *dahdi_r2_get_link(const struct dahdi_chan_conf *conf)
 {
        struct dahdi_mfcr2 *new_r2link = NULL;
        struct dahdi_mfcr2 **new_r2links = NULL;
-       /* this function is called just when starting up and no monitor threads have been launched,
-          no need to lock monitored_count member */
-       if (!r2links_count || (r2links[r2links_count - 1]->monitored_count == R2_LINK_CAPACITY)) {
+
+       /* Only create a new R2 link if 
+          1. This is the first link requested
+          2. Configuration changed 
+          3. We got more channels than supported per link */
+       if (!r2links_count ||
+           memcmp(&conf->mfcr2, &r2links[r2links_count - 1]->conf, sizeof(conf->mfcr2)) ||
+          (r2links[r2links_count - 1]->numchans == R2_LINK_CAPACITY)) {
                new_r2link = ast_calloc(1, sizeof(**r2links));
                if (!new_r2link) {
                        ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
@@ -12667,7 +12674,8 @@ static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_
                        ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
                }
        }
-       r2_link->monitored_count = 0;
+       /* Save the configuration used to setup this link */
+       memcpy(&r2_link->conf, conf, sizeof(r2_link->conf));
        return 0;
 }
 #endif
@@ -12898,7 +12906,7 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
 #ifdef HAVE_OPENR2
                        if (chan_sig == SIG_MFCR2) {
                                struct dahdi_mfcr2 *r2_link;
-                               r2_link = dahdi_r2_get_link();
+                               r2_link = dahdi_r2_get_link(conf);
                                if (!r2_link) {
                                        ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
                                        destroy_dahdi_pvt(tmp);
@@ -12940,7 +12948,6 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
                                tmp->mfcr2call = 0;
                                tmp->mfcr2_dnis_index = 0;
                                tmp->mfcr2_ani_index = 0;
-                               r2_link->monitored_count++;
                        }
 #endif
 #ifdef HAVE_PRI