提交 74a01d23 authored 作者: Moises Silva's avatar Moises Silva

freetdm: Added FTDM_SIGEVENT_DIALING

         Added hunting scheme to support new ftdm_call_place API
         Make ftdm_channel_call_answer use ftdm_channel_call_indicate with FTDM_CHANNEL_INDICATE_ANSWER
         Updated doxygen docs in freetdm.h
上级 2cfd09c3
APIs that result in an event when the API returns FTDM_SUCCESS
ftdm_channel_call_answer()
ftdm_channel_call_indicate()
FTDM_SIGEVENT_INDICATION_COMPLETED
*note that FTDM_SIGEVENT_INDICATION_COMPLETED has associated data to indicate the result of the indication
*note this event is only delivered on non-blocking channels
ftdm_call_place
FTDM_SIGEVENT_DIALING
ftdm_channel_call_hangup
FTDM_SIGEVENT_RELEASED
...@@ -1073,6 +1073,64 @@ static const char* channel_get_variable(switch_core_session_t *session, switch_e ...@@ -1073,6 +1073,64 @@ static const char* channel_get_variable(switch_core_session_t *session, switch_e
return NULL; return NULL;
} }
typedef struct {
switch_event_t *var_event;
switch_core_session_t *new_session;
private_t *tech_pvt;
switch_caller_profile_t *caller_profile;
} hunt_data_t;
static ftdm_status_t on_channel_found(ftdm_channel_t *fchan, ftdm_caller_data_t *caller_data)
{
uint32_t span_id, chan_id;
const char *var;
char *sess_uuid;
char name[128];
ftdm_status_t status;
hunt_data_t *hdata = caller_data->priv;
switch_channel_t *channel = switch_core_session_get_channel(hdata->new_session);
if ((var = switch_event_get_header(hdata->var_event, "freetdm_pre_buffer_size"))) {
int tmp = atoi(var);
if (tmp > -1) {
ftdm_channel_command(fchan, FTDM_COMMAND_SET_PRE_BUFFER_SIZE, &tmp);
}
}
span_id = ftdm_channel_get_span_id(fchan);
chan_id = ftdm_channel_get_id(fchan);
tech_init(hdata->tech_pvt, hdata->new_session, fchan);
hdata->tech_pvt->caller_profile = hdata->caller_profile;
snprintf(name, sizeof(name), "FreeTDM/%u:%u/%s", span_id, chan_id, caller_data->dnis.digits);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Connect outbound channel %s\n", name);
switch_channel_set_name(channel, name);
switch_channel_set_variable(channel, "freetdm_span_name", ftdm_channel_get_span_name(fchan));
switch_channel_set_variable_printf(channel, "freetdm_span_number", "%d", span_id);
switch_channel_set_variable_printf(channel, "freetdm_chan_number", "%d", chan_id);
switch_channel_set_state(channel, CS_INIT);
sess_uuid = switch_core_session_get_uuid(hdata->new_session);
status = ftdm_channel_add_token(fchan, sess_uuid, ftdm_channel_get_token_count(fchan));
switch_assert(status == FTDM_SUCCESS);
if (SPAN_CONFIG[span_id].limit_calls) {
char spanresource[512];
snprintf(spanresource, sizeof(spanresource), "span_%s_%s", ftdm_channel_get_span_name(fchan),
caller_data->dnis.digits);
ftdm_log(FTDM_LOG_DEBUG, "Adding rate limit resource on channel %d:%d (%s/%s/%d/%d)\n",
span_id, chan_id, FREETDM_LIMIT_REALM,
spanresource, SPAN_CONFIG[span_id].limit_calls, SPAN_CONFIG[span_id].limit_seconds);
if (switch_limit_incr("hash", hdata->new_session, FREETDM_LIMIT_REALM, spanresource,
SPAN_CONFIG[span_id].limit_calls, SPAN_CONFIG[span_id].limit_seconds) != SWITCH_STATUS_SUCCESS) {
return FTDM_BREAK;
}
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Attached session %s to channel %d:%d\n", sess_uuid, span_id, chan_id);
return FTDM_SUCCESS;
}
/* Make sure when you have 2 sessions in the same scope that you pass the appropriate one to the routines /* Make sure when you have 2 sessions in the same scope that you pass the appropriate one to the routines
that allocate memory or you will have 1 channel with memory allocated from another channel's pool! that allocate memory or you will have 1 channel with memory allocated from another channel's pool!
*/ */
...@@ -1081,13 +1139,11 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi ...@@ -1081,13 +1139,11 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_core_session_t **new_session, switch_memory_pool_t **pool,
switch_originate_flag_t flags, switch_call_cause_t *cancel_cause) switch_originate_flag_t flags, switch_call_cause_t *cancel_cause)
{ {
hunt_data_t hunt_data;
const char *dest = NULL; const char *dest = NULL;
char *data = NULL; char *data = NULL;
int span_id = -1, group_id = -1, chan_id = 0; int span_id = -1, group_id = -1, chan_id = 0;
ftdm_channel_t *ftdmchan = NULL;
switch_call_cause_t cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; switch_call_cause_t cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
char name[128];
ftdm_status_t status; ftdm_status_t status;
int direction = FTDM_TOP_DOWN; int direction = FTDM_TOP_DOWN;
ftdm_caller_data_t caller_data = {{ 0 }}; ftdm_caller_data_t caller_data = {{ 0 }};
...@@ -1097,6 +1153,7 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi ...@@ -1097,6 +1153,7 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
int argc = 0; int argc = 0;
const char *var; const char *var;
const char *dest_num = NULL, *callerid_num = NULL; const char *dest_num = NULL, *callerid_num = NULL;
ftdm_hunting_scheme_t hunting;
if (!outbound_profile) { if (!outbound_profile) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing caller profile\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing caller profile\n");
...@@ -1309,31 +1366,22 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi ...@@ -1309,31 +1366,22 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
ftdm_set_string(caller_data.cid_name, outbound_profile->caller_id_name); ftdm_set_string(caller_data.cid_name, outbound_profile->caller_id_name);
ftdm_set_string(caller_data.cid_num.digits, switch_str_nil(outbound_profile->caller_id_number)); ftdm_set_string(caller_data.cid_num.digits, switch_str_nil(outbound_profile->caller_id_number));
memset(&hunting, 0, sizeof(hunting));
if (group_id >= 0) { if (group_id >= 0) {
status = ftdm_channel_open_by_group(group_id, direction, &caller_data, &ftdmchan); hunting.mode = FTDM_HUNT_GROUP;
hunting.mode_data.group.group_id = group_id;
hunting.mode_data.group.direction = direction;
} else if (chan_id) { } else if (chan_id) {
status = ftdm_channel_open(span_id, chan_id, &ftdmchan); hunting.mode = FTDM_HUNT_CHAN;
hunting.mode_data.chan.span_id = span_id;
hunting.mode_data.chan.chan_id = chan_id;
} else { } else {
status = ftdm_channel_open_by_span(span_id, direction, &caller_data, &ftdmchan); hunting.mode = FTDM_HUNT_SPAN;
hunting.mode_data.span.span_id = span_id;
hunting.mode_data.span.direction = direction;
} }
if (status != FTDM_SUCCESS) {
if (caller_data.hangup_cause == SWITCH_CAUSE_NONE) {
caller_data.hangup_cause = SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION;
}
return caller_data.hangup_cause;
}
if ((var = switch_event_get_header(var_event, "freetdm_pre_buffer_size"))) {
int tmp = atoi(var);
if (tmp > -1) {
ftdm_channel_command(ftdmchan, FTDM_COMMAND_SET_PRE_BUFFER_SIZE, &tmp);
}
}
span_id = ftdm_channel_get_span_id(ftdmchan);
chan_id = ftdm_channel_get_id(ftdmchan);
for (h = var_event->headers; h; h = h->next) { for (h = var_event->headers; h; h = h->next) {
if (!strncasecmp(h->name, FREETDM_VAR_PREFIX, FREETDM_VAR_PREFIX_LEN)) { if (!strncasecmp(h->name, FREETDM_VAR_PREFIX, FREETDM_VAR_PREFIX_LEN)) {
char *v = h->name + FREETDM_VAR_PREFIX_LEN; char *v = h->name + FREETDM_VAR_PREFIX_LEN;
...@@ -1350,50 +1398,26 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi ...@@ -1350,50 +1398,26 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
switch_channel_t *channel = switch_core_session_get_channel(*new_session); switch_channel_t *channel = switch_core_session_get_channel(*new_session);
switch_core_session_add_stream(*new_session, NULL); switch_core_session_add_stream(*new_session, NULL);
if ((tech_pvt = (private_t *) switch_core_session_alloc(*new_session, sizeof(private_t))) != 0) { if (!(tech_pvt = (private_t *) switch_core_session_alloc(*new_session, sizeof(private_t)))) {
tech_init(tech_pvt, *new_session, ftdmchan);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Hey where is my memory pool?\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Hey where is my memory pool?\n");
switch_core_session_destroy(new_session); switch_core_session_destroy(new_session);
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
goto fail; goto fail;
} }
snprintf(name, sizeof(name), "FreeTDM/%u:%u/%s", span_id, chan_id, dest);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Connect outbound channel %s\n", name);
switch_channel_set_name(channel, name);
switch_channel_set_variable(channel, "freetdm_span_name", ftdm_channel_get_span_name(ftdmchan));
switch_channel_set_variable_printf(channel, "freetdm_span_number", "%d", span_id);
switch_channel_set_variable_printf(channel, "freetdm_chan_number", "%d", chan_id);
ftdm_channel_set_caller_data(ftdmchan, &caller_data);
caller_profile = switch_caller_profile_clone(*new_session, outbound_profile); caller_profile = switch_caller_profile_clone(*new_session, outbound_profile);
caller_profile->destination_number = switch_core_strdup(caller_profile->pool, switch_str_nil(dest_num)); caller_profile->destination_number = switch_core_strdup(caller_profile->pool, switch_str_nil(dest_num));
caller_profile->caller_id_number = switch_core_strdup(caller_profile->pool, switch_str_nil(callerid_num)); caller_profile->caller_id_number = switch_core_strdup(caller_profile->pool, switch_str_nil(callerid_num));
switch_channel_set_caller_profile(channel, caller_profile); switch_channel_set_caller_profile(channel, caller_profile);
tech_pvt->caller_profile = caller_profile;
switch_channel_set_state(channel, CS_INIT);
if (ftdm_channel_add_token(ftdmchan, switch_core_session_get_uuid(*new_session), ftdm_channel_get_token_count(ftdmchan)) != FTDM_SUCCESS) {
switch_core_session_destroy(new_session);
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
goto fail;
}
hunting.result_cb = on_channel_found;
hunt_data.var_event = var_event;
hunt_data.new_session = *new_session;
hunt_data.caller_profile = caller_profile;
hunt_data.tech_pvt = tech_pvt;
caller_data.priv = &hunt_data;
if (SPAN_CONFIG[span_id].limit_calls) { if ((status = ftdm_call_place(&caller_data, &hunting)) != FTDM_SUCCESS) {
char spanresource[512];
snprintf(spanresource, sizeof(spanresource), "span_%s_%s", ftdm_channel_get_span_name(ftdmchan), caller_data.dnis.digits);
ftdm_log(FTDM_LOG_DEBUG, "Adding rate limit resource on channel %d:%d (%s/%s/%d/%d)\n", span_id, chan_id, FREETDM_LIMIT_REALM,
spanresource, SPAN_CONFIG[span_id].limit_calls, SPAN_CONFIG[span_id].limit_seconds);
if (switch_limit_incr("hash", *new_session, FREETDM_LIMIT_REALM, spanresource, SPAN_CONFIG[span_id].limit_calls, SPAN_CONFIG[span_id].limit_seconds) != SWITCH_STATUS_SUCCESS) {
switch_core_session_destroy(new_session);
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
goto fail;
}
}
if ((status = ftdm_channel_call_place(ftdmchan)) != FTDM_SUCCESS) {
if (tech_pvt->read_codec.implementation) { if (tech_pvt->read_codec.implementation) {
switch_core_codec_destroy(&tech_pvt->read_codec); switch_core_codec_destroy(&tech_pvt->read_codec);
} }
...@@ -1402,28 +1426,22 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi ...@@ -1402,28 +1426,22 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
switch_core_codec_destroy(&tech_pvt->write_codec); switch_core_codec_destroy(&tech_pvt->write_codec);
} }
switch_core_session_destroy(new_session); switch_core_session_destroy(new_session);
if (status == FTDM_BREAK) { /* glare, we don't want to touch the channel since is being used for incoming call now */ if (status == FTDM_BREAK || status == FTDM_EBUSY) {
cause = SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION; cause = SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION;
ftdmchan = NULL;
} else { } else {
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
} }
goto fail; goto fail;
} }
ftdm_channel_init(ftdmchan); ftdm_channel_init(caller_data.fchan);
return SWITCH_CAUSE_SUCCESS; return SWITCH_CAUSE_SUCCESS;
} }
fail: fail:
if (ftdmchan) {
ftdm_channel_call_hangup_with_cause(ftdmchan, FTDM_CAUSE_NORMAL_TEMPORARY_FAILURE);
}
return cause; return cause;
} }
static void ftdm_enable_channel_dtmf(ftdm_channel_t *fchan, switch_channel_t *channel) static void ftdm_enable_channel_dtmf(ftdm_channel_t *fchan, switch_channel_t *channel)
...@@ -1645,6 +1663,7 @@ static FIO_SIGNAL_CB_FUNCTION(on_common_signal) ...@@ -1645,6 +1663,7 @@ static FIO_SIGNAL_CB_FUNCTION(on_common_signal)
case FTDM_SIGEVENT_RELEASED: case FTDM_SIGEVENT_RELEASED:
case FTDM_SIGEVENT_INDICATION_COMPLETED: case FTDM_SIGEVENT_INDICATION_COMPLETED:
case FTDM_SIGEVENT_DIALING:
{ {
/* Swallow these events */ /* Swallow these events */
return FTDM_BREAK; return FTDM_BREAK;
......
...@@ -1425,8 +1425,9 @@ static __inline__ int request_voice_channel(ftdm_channel_t *check, ftdm_channel_ ...@@ -1425,8 +1425,9 @@ static __inline__ int request_voice_channel(ftdm_channel_t *check, ftdm_channel_
* sometimes with the group or span lock held and were * sometimes with the group or span lock held and were
* blocking anyone hunting for channels available and * blocking anyone hunting for channels available and
* I believe teh channel_request() function may take * I believe teh channel_request() function may take
* a bit of time * a bit of time. However channel_request is a callback
* */ * used by boost and may be only a few other old sig mods
* and it should be deprecated */
ftdm_mutex_unlock(check->mutex); ftdm_mutex_unlock(check->mutex);
ftdm_set_caller_data(check->span, caller_data); ftdm_set_caller_data(check->span, caller_data);
status = check->span->channel_request(check->span, check->chan_id, status = check->span->channel_request(check->span, check->chan_id,
...@@ -1439,7 +1440,9 @@ static __inline__ int request_voice_channel(ftdm_channel_t *check, ftdm_channel_ ...@@ -1439,7 +1440,9 @@ static __inline__ int request_voice_channel(ftdm_channel_t *check, ftdm_channel_
if (status == FTDM_SUCCESS) { if (status == FTDM_SUCCESS) {
*ftdmchan = check; *ftdmchan = check;
ftdm_set_flag(check, FTDM_CHANNEL_OUTBOUND); ftdm_set_flag(check, FTDM_CHANNEL_OUTBOUND);
#if 0
ftdm_mutex_unlock(check->mutex); ftdm_mutex_unlock(check->mutex);
#endif
return 1; return 1;
} }
} }
...@@ -1491,9 +1494,9 @@ static ftdm_status_t __inline__ get_best_rated(ftdm_channel_t **fchan, ftdm_chan ...@@ -1491,9 +1494,9 @@ static ftdm_status_t __inline__ get_best_rated(ftdm_channel_t **fchan, ftdm_chan
} }
*fchan = best_rated; *fchan = best_rated;
ftdm_set_flag(best_rated, FTDM_CHANNEL_OUTBOUND); ftdm_set_flag(best_rated, FTDM_CHANNEL_OUTBOUND);
#if 0
ftdm_mutex_unlock(best_rated->mutex); ftdm_mutex_unlock(best_rated->mutex);
#endif
return FTDM_SUCCESS; return FTDM_SUCCESS;
} }
...@@ -1523,7 +1526,7 @@ FT_DECLARE(int) ftdm_channel_get_availability(ftdm_channel_t *ftdmchan) ...@@ -1523,7 +1526,7 @@ FT_DECLARE(int) ftdm_channel_get_availability(ftdm_channel_t *ftdmchan)
return availability; return availability;
} }
FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_group(uint32_t group_id, ftdm_direction_t direction, ftdm_caller_data_t *caller_data, ftdm_channel_t **ftdmchan) static ftdm_status_t _ftdm_channel_open_by_group(uint32_t group_id, ftdm_direction_t direction, ftdm_caller_data_t *caller_data, ftdm_channel_t **ftdmchan)
{ {
ftdm_status_t status = FTDM_FAIL; ftdm_status_t status = FTDM_FAIL;
ftdm_channel_t *check = NULL; ftdm_channel_t *check = NULL;
...@@ -1604,6 +1607,16 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_group(uint32_t group_id, ftdm_dir ...@@ -1604,6 +1607,16 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_group(uint32_t group_id, ftdm_dir
return status; return status;
} }
FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_group(uint32_t group_id, ftdm_direction_t direction, ftdm_caller_data_t *caller_data, ftdm_channel_t **ftdmchan)
{
ftdm_status_t status;
status = _ftdm_channel_open_by_group(group_id, direction, caller_data, ftdmchan);
if (status == FTDM_SUCCESS) {
ftdm_channel_t *fchan = *ftdmchan;
ftdm_channel_unlock(fchan);
}
return status;
}
FT_DECLARE(ftdm_status_t) ftdm_span_channel_use_count(ftdm_span_t *span, uint32_t *count) FT_DECLARE(ftdm_status_t) ftdm_span_channel_use_count(ftdm_span_t *span, uint32_t *count)
{ {
...@@ -1626,7 +1639,8 @@ FT_DECLARE(ftdm_status_t) ftdm_span_channel_use_count(ftdm_span_t *span, uint32_ ...@@ -1626,7 +1639,8 @@ FT_DECLARE(ftdm_status_t) ftdm_span_channel_use_count(ftdm_span_t *span, uint32_
return FTDM_SUCCESS; return FTDM_SUCCESS;
} }
FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_span(uint32_t span_id, ftdm_direction_t direction, ftdm_caller_data_t *caller_data, ftdm_channel_t **ftdmchan) /* Hunt a channel by span, if successful the channel is returned locked */
static ftdm_status_t _ftdm_channel_open_by_span(uint32_t span_id, ftdm_direction_t direction, ftdm_caller_data_t *caller_data, ftdm_channel_t **ftdmchan)
{ {
ftdm_status_t status = FTDM_FAIL; ftdm_status_t status = FTDM_FAIL;
ftdm_channel_t *check = NULL; ftdm_channel_t *check = NULL;
...@@ -1724,6 +1738,17 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_span(uint32_t span_id, ftdm_direc ...@@ -1724,6 +1738,17 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_span(uint32_t span_id, ftdm_direc
return status; return status;
} }
FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_span(uint32_t span_id, ftdm_direction_t direction, ftdm_caller_data_t *caller_data, ftdm_channel_t **ftdmchan)
{
ftdm_status_t status;
status = _ftdm_channel_open_by_span(span_id, direction, caller_data, ftdmchan);
if (status == FTDM_SUCCESS) {
ftdm_channel_t *fchan = *ftdmchan;
ftdm_channel_unlock(fchan);
}
return status;
}
FT_DECLARE(ftdm_status_t) ftdm_channel_open_chan(ftdm_channel_t *ftdmchan) FT_DECLARE(ftdm_status_t) ftdm_channel_open_chan(ftdm_channel_t *ftdmchan)
{ {
ftdm_status_t status = FTDM_FAIL; ftdm_status_t status = FTDM_FAIL;
...@@ -1774,7 +1799,7 @@ done: ...@@ -1774,7 +1799,7 @@ done:
return status; return status;
} }
FT_DECLARE(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)
{ {
ftdm_channel_t *check = NULL; ftdm_channel_t *check = NULL;
ftdm_span_t *span = NULL; ftdm_span_t *span = NULL;
...@@ -1855,6 +1880,10 @@ openchan: ...@@ -1855,6 +1880,10 @@ openchan:
ftdm_set_flag(check, FTDM_CHANNEL_INUSE); ftdm_set_flag(check, FTDM_CHANNEL_INUSE);
ftdm_set_flag(check, FTDM_CHANNEL_OUTBOUND); ftdm_set_flag(check, FTDM_CHANNEL_OUTBOUND);
*ftdmchan = check; *ftdmchan = check;
#if 1
/* we've got the channel, do not unlock it */
goto done;
#endif
unlockchan: unlockchan:
ftdm_mutex_unlock(check->mutex); ftdm_mutex_unlock(check->mutex);
...@@ -1868,6 +1897,17 @@ done: ...@@ -1868,6 +1897,17 @@ done:
return status; return status;
} }
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);
if (status == FTDM_SUCCESS) {
ftdm_channel_t *fchan = *ftdmchan;
ftdm_channel_unlock(fchan);
}
return status;
}
FT_DECLARE(uint32_t) ftdm_channel_get_id(const ftdm_channel_t *ftdmchan) FT_DECLARE(uint32_t) ftdm_channel_get_id(const ftdm_channel_t *ftdmchan)
{ {
return ftdmchan->chan_id; return ftdmchan->chan_id;
...@@ -2048,25 +2088,11 @@ FT_DECLARE(void) ftdm_ack_indication(ftdm_channel_t *fchan, ftdm_channel_indicat ...@@ -2048,25 +2088,11 @@ FT_DECLARE(void) ftdm_ack_indication(ftdm_channel_t *fchan, ftdm_channel_indicat
ftdm_span_send_signal(fchan->span, &msg); ftdm_span_send_signal(fchan->span, &msg);
} }
/*! \brief Answer call without locking the channel. The caller must have locked first /*! Answer call without locking the channel. The caller must have locked first */
* \note This function was added because ftdm_channel_call_indicate needs to answer the call
* when its already locking the channel, ftdm_channel_set_state cannot be called with the same
* lock locked once or more (recursive lock) and wait for the result */
static ftdm_status_t _ftdm_channel_call_answer_nl(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan) static ftdm_status_t _ftdm_channel_call_answer_nl(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan)
{ {
ftdm_status_t status = FTDM_SUCCESS; ftdm_status_t status = FTDM_SUCCESS;
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
status = FTDM_EINVAL;
goto done;
}
if (ftdmchan->state == FTDM_CHANNEL_STATE_TERMINATING) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Ignoring answer because the call is already TERMINATING\n");
status = FTDM_ECANCELED;
goto done;
}
if (!ftdm_test_flag(ftdmchan->span, FTDM_SPAN_USE_SKIP_STATES)) { if (!ftdm_test_flag(ftdmchan->span, FTDM_SPAN_USE_SKIP_STATES)) {
/* We will fail RFC's if we not skip states, but some modules apart from ftmod_sangoma_isdn /* We will fail RFC's if we not skip states, but some modules apart from ftmod_sangoma_isdn
* expect the call to always to go PROGRESS and PROGRESS MEDIA state before going to UP, so * expect the call to always to go PROGRESS and PROGRESS MEDIA state before going to UP, so
...@@ -2116,13 +2142,12 @@ done: ...@@ -2116,13 +2142,12 @@ done:
FT_DECLARE(ftdm_status_t) _ftdm_channel_call_answer(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan) FT_DECLARE(ftdm_status_t) _ftdm_channel_call_answer(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan)
{ {
ftdm_status_t status = FTDM_SUCCESS; ftdm_status_t status;
ftdm_channel_lock(ftdmchan);
status = _ftdm_channel_call_answer_nl(file, func, line, ftdmchan); /* we leave the locking up to ftdm_channel_call_indicate, DO NOT lock here since ftdm_channel_call_indicate expects
* the lock recursivity to be 1 */
status = _ftdm_channel_call_indicate(file, func, line, ftdmchan, FTDM_CHANNEL_INDICATE_ANSWER);
ftdm_channel_unlock(ftdmchan);
return status; return status;
} }
...@@ -2319,7 +2344,6 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const ch ...@@ -2319,7 +2344,6 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const ch
status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, 1); status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, 1);
break; break;
case FTDM_CHANNEL_INDICATE_ANSWER: case FTDM_CHANNEL_INDICATE_ANSWER:
/* _ftdm_channel_call_answer takes care of the indication ack */
status = _ftdm_channel_call_answer_nl(file, func, line, ftdmchan); status = _ftdm_channel_call_answer_nl(file, func, line, ftdmchan);
break; break;
default: default:
...@@ -2365,7 +2389,7 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_reset(const char *file, const char *func ...@@ -2365,7 +2389,7 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_reset(const char *file, const char *func
return FTDM_SUCCESS; return FTDM_SUCCESS;
} }
FT_DECLARE(ftdm_status_t) _ftdm_channel_call_place(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan) static ftdm_status_t _ftdm_channel_call_place_nl(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan)
{ {
ftdm_status_t status = FTDM_FAIL; ftdm_status_t status = FTDM_FAIL;
...@@ -2374,8 +2398,6 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_place(const char *file, const char ...@@ -2374,8 +2398,6 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_place(const char *file, const char
ftdm_set_echocancel_call_begin(ftdmchan); ftdm_set_echocancel_call_begin(ftdmchan);
ftdm_channel_lock(ftdmchan);
if (!ftdmchan->span->outgoing_call) { if (!ftdmchan->span->outgoing_call) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "outgoing_call method not implemented in this span!\n"); ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "outgoing_call method not implemented in this span!\n");
status = FTDM_ENOSYS; status = FTDM_ENOSYS;
...@@ -2427,8 +2449,6 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_place(const char *file, const char ...@@ -2427,8 +2449,6 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_place(const char *file, const char
} }
done: done:
ftdm_channel_unlock(ftdmchan);
#ifdef __WINDOWS__ #ifdef __WINDOWS__
UNREFERENCED_PARAMETER(file); UNREFERENCED_PARAMETER(file);
UNREFERENCED_PARAMETER(func); UNREFERENCED_PARAMETER(func);
...@@ -2437,6 +2457,64 @@ done: ...@@ -2437,6 +2457,64 @@ done:
return status; return status;
} }
FT_DECLARE(ftdm_status_t) _ftdm_channel_call_place(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan)
{
ftdm_status_t status;
ftdm_channel_lock(ftdmchan);
status = _ftdm_channel_call_place_nl(file, func, line, ftdmchan);
ftdm_channel_unlock(ftdmchan);
return status;
}
FT_DECLARE(ftdm_status_t) _ftdm_call_place(const char *file, const char *func, int line,
ftdm_caller_data_t *caller_data, ftdm_hunting_scheme_t *hunting)
{
ftdm_assert_return(caller_data, FTDM_EINVAL, "Invalid caller data\n");
ftdm_assert_return(hunting, FTDM_EINVAL, "Invalid hunting scheme\n");
ftdm_status_t status = FTDM_SUCCESS;
ftdm_channel_t *fchan = NULL;
if (hunting->mode == FTDM_HUNT_SPAN) {
status = _ftdm_channel_open_by_span(hunting->mode_data.span.span_id,
hunting->mode_data.span.direction, caller_data, &fchan);
} else if (hunting->mode == FTDM_HUNT_GROUP) {
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);
} else {
ftdm_log(FTDM_LOG_ERROR, "Cannot make outbound call with invalid hunting mode %d\n", hunting->mode);
return FTDM_EINVAL;
}
if (status != FTDM_SUCCESS) {
return FTDM_EBUSY;
}
/* we have a locked channel and are not afraid of using it! */
status = hunting->result_cb(fchan, caller_data);
if (status != FTDM_SUCCESS) {
status = FTDM_ECANCELED;
goto done;
}
ftdm_channel_set_caller_data(fchan, caller_data);
status = _ftdm_channel_call_place_nl(file, func, line, fchan);
if (status != FTDM_SUCCESS) {
goto done;
}
caller_data->fchan = fchan;
done:
ftdm_channel_unlock(fchan);
return status;
}
FT_DECLARE(ftdm_status_t) ftdm_channel_set_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status_t sigstatus) FT_DECLARE(ftdm_status_t) ftdm_channel_set_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status_t sigstatus)
{ {
ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "Null channel\n"); ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "Null channel\n");
......
...@@ -77,6 +77,12 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_complete_state(const char *file, const c ...@@ -77,6 +77,12 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_complete_state(const char *file, const c
} else if (state == FTDM_CHANNEL_STATE_PROGRESS_MEDIA) { } else if (state == FTDM_CHANNEL_STATE_PROGRESS_MEDIA) {
ftdm_set_flag(fchan, FTDM_CHANNEL_PROGRESS); ftdm_set_flag(fchan, FTDM_CHANNEL_PROGRESS);
ftdm_set_flag(fchan, FTDM_CHANNEL_MEDIA); ftdm_set_flag(fchan, FTDM_CHANNEL_MEDIA);
} else if (state == FTDM_CHANNEL_STATE_DIALING) {
ftdm_sigmsg_t msg;
memset(&msg, 0, sizeof(msg));
msg.channel = fchan;
msg.event_id = FTDM_SIGEVENT_DIALING;
ftdm_span_send_signal(fchan->span, &msg);
} }
/* MAINTENANCE WARNING /* MAINTENANCE WARNING
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论