diff --git a/pri.c b/pri.c index d5ac4c5..5ff84fd 100644 --- a/pri.c +++ b/pri.c @@ -1646,11 +1646,43 @@ int pri_set_crv(struct pri *pri, q931_call *call, int crv, int callmode) void pri_enslave(struct pri *master, struct pri *slave) { - if (master && slave) { - slave->callpool = &master->localpool; - slave->nfas = 1; - master->nfas = 1; + if (!master || !slave) { + return; } + + if (slave->master) { + struct pri *swp; + + /* The slave already has a master */ + if (master->master || master->slave) { + /* The new master has a master or it already has slaves. */ + return; + } + + /* Swap master and slave. */ + swp = master; + master = slave; + slave = master; + } + + /* + * To have some support for dynamic interfaces, the master NFAS + * D channel control structure will always exist even if it is + * abandoned/deleted by the upper layer. The master/slave + * pointers ensure that the correct master will be used. + */ + + master = PRI_NFAS_MASTER(master); + master->nfas = 1; + slave->nfas = 1; + slave->callpool = &master->localpool; + + /* Link the slave to the master on the end of the master's list. */ + slave->master = master; + slave->slave = NULL; + for (; master->slave; master = master->slave) { + } + master->slave = slave; } struct pri_sr *pri_sr_new(void) diff --git a/pri_internal.h b/pri_internal.h index 74abc58..8235092 100644 --- a/pri_internal.h +++ b/pri_internal.h @@ -76,6 +76,10 @@ struct pri { void *userdata; /*! Accumulated pri_message() line. (Valid in master record only) */ struct pri_msg_line *msg_line; + /*! NFAS master/primary channel if appropriate */ + struct pri *master; + /*! Next NFAS slaved D channel if appropriate */ + struct pri *slave; struct { /*! Dynamically allocated array of timers that can grow as needed. */ struct pri_sched *timer; @@ -951,6 +955,21 @@ int pri_cc_event(struct pri *ctrl, q931_call *call, struct pri_cc_record *cc_rec int q931_cc_timeout(struct pri *ctrl, struct pri_cc_record *cc_record, enum CC_EVENTS event); void q931_cc_indirect(struct pri *ctrl, struct pri_cc_record *cc_record, void (*func)(struct pri *ctrl, q931_call *call, struct pri_cc_record *cc_record)); +/*! + * \brief Get the NFAS master PRI control structure. + * + * \param ctrl D channel controller. + * + * \return NFAS master PRI control structure. + */ +static inline struct pri *PRI_NFAS_MASTER(struct pri *ctrl) +{ + while (ctrl->master) { + ctrl = ctrl->master; + } + return ctrl; +} + /*! * \brief Determine if layer 2 is in BRI NT PTMP mode. *