From fcbfc6946655b274751095ea14d375589df45d9b Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Tue, 11 Sep 2012 14:45:57 -0400 Subject: [PATCH] mod_media_gateway now specifies physical channel when opening TDM terminations --- libs/freetdm/mod_freetdm/tdm.c | 4 +- libs/freetdm/src/ftdm_io.c | 96 ++++++++++++++++++++++++++---- libs/freetdm/src/include/freetdm.h | 33 +++++++++- 3 files changed, 118 insertions(+), 15 deletions(-) diff --git a/libs/freetdm/mod_freetdm/tdm.c b/libs/freetdm/mod_freetdm/tdm.c index 0c7657301d..0f8b5814c1 100644 --- a/libs/freetdm/mod_freetdm/tdm.c +++ b/libs/freetdm/mod_freetdm/tdm.c @@ -158,7 +158,7 @@ static ftdm_channel_t *ctdm_get_channel_from_event(switch_event_t *event, ftdm_s return NULL; } - return ftdm_span_get_channel(span, chan_id); + return ftdm_span_get_channel_ph(span, chan_id); } @@ -362,7 +362,7 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi channel = switch_core_session_get_channel(*new_session); - if (ftdm_channel_open(span_id, chan_id, &chan) != FTDM_SUCCESS) { + if (ftdm_channel_open_ph(span_id, chan_id, &chan) != FTDM_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't open span or channel.\n"); goto fail; } diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index b3266e54f4..f80ded35b8 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -1893,7 +1893,7 @@ done: return status; } -static ftdm_status_t _ftdm_channel_open(uint32_t span_id, uint32_t chan_id, ftdm_channel_t **ftdmchan) +static ftdm_status_t _ftdm_channel_open(uint32_t span_id, uint32_t chan_id, ftdm_channel_t **ftdmchan, uint8_t physical) { ftdm_channel_t *check = NULL; ftdm_span_t *span = NULL; @@ -1922,14 +1922,46 @@ static ftdm_status_t _ftdm_channel_open(uint32_t span_id, uint32_t chan_id, ftdm goto done; } - if (chan_id < 1 || chan_id > span->chan_count) { - ftdm_log(FTDM_LOG_ERROR, "Invalid channel %d to open in span %d\n", chan_id, span_id); - goto done; - } + if (physical) { /* Open by physical */ + ftdm_channel_t *fchan = NULL; + ftdm_iterator_t *citer = NULL; + ftdm_iterator_t *curr = NULL; - if (!(check = span->channels[chan_id])) { - ftdm_log(FTDM_LOG_CRIT, "Wow, no channel %d in span %d\n", chan_id, span_id); - goto done; + if (chan_id < 1) { + ftdm_log(FTDM_LOG_ERROR, "Invalid physical channel %d to open in span %d\n", chan_id, span_id); + status = FTDM_FAIL; + goto done; + } + + citer = ftdm_span_get_chan_iterator(span, NULL); + if (!citer) { + status = ENOMEM; + goto done; + } + + for (curr = citer ; curr; curr = ftdm_iterator_next(curr)) { + fchan = ftdm_iterator_current(curr); + if (fchan->physical_chan_id == chan_id) { + check = fchan; + break; + } + } + + ftdm_iterator_free(citer); + if (!check) { + ftdm_log(FTDM_LOG_CRIT, "Wow, no physical channel %d in span %d\n", chan_id, span_id); + goto done; + } + } else { /* Open by logical */ + if (chan_id < 1 || chan_id > span->chan_count) { + ftdm_log(FTDM_LOG_ERROR, "Invalid channel %d to open in span %d\n", chan_id, span_id); + goto done; + } + + if (!(check = span->channels[chan_id])) { + ftdm_log(FTDM_LOG_CRIT, "Wow, no channel %d in span %d\n", chan_id, span_id); + goto done; + } } ftdm_channel_lock(check); @@ -2000,7 +2032,18 @@ done: FT_DECLARE(ftdm_status_t) ftdm_channel_open(uint32_t span_id, uint32_t chan_id, ftdm_channel_t **ftdmchan) { ftdm_status_t status; - status = _ftdm_channel_open(span_id, chan_id, ftdmchan); + status = _ftdm_channel_open(span_id, chan_id, ftdmchan, 0); + if (status == FTDM_SUCCESS) { + ftdm_channel_t *fchan = *ftdmchan; + ftdm_channel_unlock(fchan); + } + return status; +} + +FT_DECLARE(ftdm_status_t) ftdm_channel_open_ph(uint32_t span_id, uint32_t chan_id, ftdm_channel_t **ftdmchan) +{ + ftdm_status_t status; + status = _ftdm_channel_open(span_id, chan_id, ftdmchan, 1); if (status == FTDM_SUCCESS) { ftdm_channel_t *fchan = *ftdmchan; ftdm_channel_unlock(fchan); @@ -2377,6 +2420,39 @@ FT_DECLARE(ftdm_channel_t *) ftdm_span_get_channel(const ftdm_span_t *span, uint return chan; } +FT_DECLARE(ftdm_channel_t *) ftdm_span_get_channel_ph(const ftdm_span_t *span, uint32_t chanid) +{ + ftdm_channel_t *chan = NULL; + ftdm_channel_t *fchan = NULL; + ftdm_iterator_t *citer = NULL; + ftdm_iterator_t *curr = NULL; + + ftdm_mutex_lock(span->mutex); + if (chanid == 0) { + ftdm_mutex_unlock(span->mutex); + return NULL; + } + + citer = ftdm_span_get_chan_iterator(span, NULL); + if (!citer) { + ftdm_mutex_unlock(span->mutex); + return NULL; + } + + for (curr = citer ; curr; curr = ftdm_iterator_next(curr)) { + fchan = ftdm_iterator_current(curr); + if (fchan->physical_chan_id == chanid) { + chan = fchan; + break; + } + } + + ftdm_iterator_free(citer); + + ftdm_mutex_unlock(span->mutex); + return chan; +} + FT_DECLARE(uint32_t) ftdm_span_get_chan_count(const ftdm_span_t *span) { uint32_t count; @@ -2673,7 +2749,7 @@ FT_DECLARE(ftdm_status_t) _ftdm_call_place(const char *file, const char *func, i status = _ftdm_channel_open_by_group(hunting->mode_data.group.group_id, hunting->mode_data.group.direction, caller_data, &fchan); } else if (hunting->mode == FTDM_HUNT_CHAN) { - status = _ftdm_channel_open(hunting->mode_data.chan.span_id, hunting->mode_data.chan.chan_id, &fchan); + status = _ftdm_channel_open(hunting->mode_data.chan.span_id, hunting->mode_data.chan.chan_id, &fchan, 0); } else { ftdm_log(FTDM_LOG_ERROR, "Cannot make outbound call with invalid hunting mode %d\n", hunting->mode); return FTDM_EINVAL; diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index 6f0ac50371..18dfb7605b 100755 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -1370,7 +1370,7 @@ FT_DECLARE(uint32_t) ftdm_group_get_id(const ftdm_group_t *group); * Only use ftdm_channel_close if there is no call (incoming or outgoing) in the channel * * \param span_id The span id the channel belongs to - * \param chan_id Channel id of the channel you want to open + * \param chan_id Logical channel id of the channel you want to open * \param ftdmchan Pointer to store the channel once is open * * \retval FTDM_SUCCESS success (the channel was found and is available) @@ -1378,6 +1378,23 @@ FT_DECLARE(uint32_t) ftdm_group_get_id(const ftdm_group_t *group); */ FT_DECLARE(ftdm_status_t) ftdm_channel_open(uint32_t span_id, uint32_t chan_id, ftdm_channel_t **ftdmchan); +/*! + * \brief Open a channel specifying the span id and physical chan id (required before placing a call on the channel) + * + * \warning Try using ftdm_call_place instead if you plan to place a call after opening the channel + * + * \note You must call ftdm_channel_close() or ftdm_channel_call_hangup() to release the channel afterwards + * Only use ftdm_channel_close if there is no call (incoming or outgoing) in the channel + * + * \param span_id The span id the channel belongs to + * \param chan_id Physical channel id of the channel you want to open + * \param ftdmchan Pointer to store the channel once is open + * + * \retval FTDM_SUCCESS success (the channel was found and is available) + * \retval FTDM_FAIL failure (channel was not found or not available) + */ +FT_DECLARE(ftdm_status_t) ftdm_channel_open_ph(uint32_t span_id, uint32_t chan_id, ftdm_channel_t **ftdmchan); + /*! * \brief Hunts and opens a channel specifying the span id only * @@ -1759,15 +1776,25 @@ FT_DECLARE(ftdm_trunk_type_t) ftdm_span_get_trunk_type(const ftdm_span_t *span); FT_DECLARE(const char *) ftdm_span_get_trunk_type_str(const ftdm_span_t *span); /*! - * \brief Return the channel identified by the provided id + * \brief Return the channel identified by the provided logical id * * \param span The span where the channel belongs - * \param chanid The channel id within the span + * \param chanid The logical channel id within the span * * \return The channel pointer if found, NULL otherwise */ FT_DECLARE(ftdm_channel_t *) ftdm_span_get_channel(const ftdm_span_t *span, uint32_t chanid); +/*! + * \brief Return the channel identified by the provided physical id + * + * \param span The span where the channel belongs + * \param chanid The physical channel id within the span + * + * \return The channel pointer if found, NULL otherwise + */ +FT_DECLARE(ftdm_channel_t *) ftdm_span_get_channel_ph(const ftdm_span_t *span, uint32_t chanid); + /*! \brief Return the channel count number for the given span */ FT_DECLARE(uint32_t) ftdm_span_get_chan_count(const ftdm_span_t *span);