提交 7972837f authored 作者: David Yat Sin's avatar David Yat Sin

Merge branch 'nsg-4.3' of ssh://git.sangoma.com/smg_freeswitch into nsg-4.3

......@@ -178,6 +178,7 @@ static const char* channel_get_variable(switch_core_session_t *session, switch_e
ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session_t **sp);
void dump_chan(ftdm_span_t *span, uint32_t chan_id, switch_stream_handle_t *stream);
void dump_chan_xml(ftdm_span_t *span, uint32_t chan_id, switch_stream_handle_t *stream);
void ctdm_init(switch_loadable_module_interface_t *module_interface);
static switch_core_session_t *ftdm_channel_get_session(ftdm_channel_t *channel, int32_t id)
{
......@@ -5359,6 +5360,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_freetdm_load)
SWITCH_ADD_APP(app_interface, "disable_dtmf", "Disable DTMF Detection", "Disable DTMF Detection", disable_dtmf_function, "", SAF_NONE);
SWITCH_ADD_APP(app_interface, "enable_dtmf", "Enable DTMF Detection", "Enable DTMF Detection", enable_dtmf_function, "", SAF_NONE);
ctdm_init(*module_interface);
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;
}
......
......@@ -38,6 +38,7 @@ void ctdm_init(switch_loadable_module_interface_t *module_interface);
#define kSPAN_ID "span"
#define kCHAN_ID "chan"
#define kSPAN_NAME "span_name"
static struct {
switch_memory_pool_t *pool;
......@@ -96,8 +97,8 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
switch_memory_pool_t **pool,
switch_originate_flag_t flags, switch_call_cause_t *cancel_cause)
{
const char *szspanid = switch_event_get_header(var_event, kSPAN_ID),
*szchanid = switch_event_get_header(var_event, kCHAN_ID);
const char *szchanid = switch_event_get_header(var_event, kCHAN_ID),
*span_name = switch_event_get_header(var_event, kSPAN_NAME);
int chan_id;
int span_id;
......@@ -111,14 +112,21 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
ctdm_private_t *tech_pvt = NULL;
if (zstr(szchanid) || zstr(szspanid)) {
if (zstr(szchanid) || zstr(span_name)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Both ["kSPAN_ID"] and ["kCHAN_ID"] have to be set.\n");
goto fail;
}
chan_id = atoi(szchanid);
span_id = atoi(szspanid);
if (ftdm_span_find_by_name(span_name, &span) == FTDM_SUCCESS) {
span_id = ftdm_span_get_id(span);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot find span [%s]\n", span_name);
goto fail;
}
if (!(*new_session = switch_core_session_request(ctdm.endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, 0, pool))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't request session.\n");
......@@ -262,9 +270,9 @@ static switch_status_t channel_on_destroy(switch_core_session_t *session)
if (tech_pvt->write_codec.implementation) {
switch_core_codec_destroy(&tech_pvt->write_codec);
}
ftdm_channel_close(&tech_pvt->ftdm_channel);
}
ftdm_channel_close(&tech_pvt->ftdm_channel);
return SWITCH_STATUS_SUCCESS;
}
......
......@@ -88,19 +88,6 @@ switch_status_t megaco_activate_termination(mg_termination_t *term)
switch_status_t status = SWITCH_STATUS_SUCCESS;
char dialstring[100];
switch_call_cause_t cause;
if (!zstr(term->uuid)) {
/* A UUID is present, check if the channel still exists */
switch_core_session_t *session;
if ((session = switch_core_session_locate(term->uuid))) {
switch_core_session_rwunlock(session);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Channel [%s] already exists for termination [%s]\n", term->uuid, term->name);
return SWITCH_STATUS_SUCCESS;
}
/* The referenced channel doesn't exist anymore, clear it */
term->uuid = NULL;
}
switch_event_create(&var_event, SWITCH_EVENT_CLONE);
......@@ -120,20 +107,43 @@ switch_status_t megaco_activate_termination(mg_termination_t *term)
} else if (term->type == MG_TERM_TDM) {
switch_snprintf(dialstring, sizeof dialstring, "tdm/%s", term->name);
switch_event_add_header(var_event, SWITCH_STACK_BOTTOM, kSPAN_ID, "%d", term->u.tdm.span);
switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, kSPAN_NAME, term->u.tdm.span_name);
switch_event_add_header(var_event, SWITCH_STACK_BOTTOM, kCHAN_ID, "%d", term->u.tdm.channel);
}
/* Set common variables on the channel */
switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, SWITCH_PARK_AFTER_BRIDGE_VARIABLE, "true");
if (!zstr(term->uuid)) {
/* A UUID is present, check if the channel still exists */
switch_core_session_t *session;
if ((session = switch_core_session_locate(term->uuid))) {
switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "command", "media_modify");
switch_core_session_receive_event(session, &var_event);
if (switch_ivr_originate(NULL, &session, &cause, dialstring, 0, NULL, NULL, NULL, NULL, var_event, 0, NULL) != SWITCH_CAUSE_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to instanciate termination [%s]: %s\n", term->name, switch_channel_cause2str(cause));
status = SWITCH_STATUS_FALSE;
goto done;
switch_core_session_rwunlock(session);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Sent refresh to channel [%s], for termination [%s]\n", term->uuid, term->name);
return SWITCH_STATUS_SUCCESS;
}
/* The referenced channel doesn't exist anymore, clear it */
term->uuid = NULL;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Termination [%s] successfully instanciated as [%s] [%s]\n", term->name, dialstring, switch_core_session_get_uuid(session));
if (zstr(term->uuid)) {
if (switch_ivr_originate(NULL, &session, &cause, dialstring, 0, NULL, NULL, NULL, NULL, var_event, 0, NULL) != SWITCH_CAUSE_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to instanciate termination [%s]: %s\n", term->name, switch_channel_cause2str(cause));
status = SWITCH_STATUS_FALSE;
goto done;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Termination [%s] successfully instanciated as [%s] [%s]\n", term->name, dialstring, switch_core_session_get_uuid(session));
}
switch_set_flag(term, MGT_ACTIVE);
done:
if (session) {
......@@ -151,6 +161,7 @@ mg_termination_t *megaco_choose_termination(megaco_profile_t *profile, const cha
mg_termination_t *term = NULL;
char name[100];
int term_id;
size_t prefixlen = strlen(prefix);
/* Check the termination type by prefix */
if (strncasecmp(prefix, profile->rtp_termination_id_prefix, strlen(profile->rtp_termination_id_prefix)) == 0) {
......@@ -158,8 +169,14 @@ mg_termination_t *megaco_choose_termination(megaco_profile_t *profile, const cha
term_id = mg_rtp_request_id(profile);
switch_snprintf(name, sizeof name, "%s/%d", profile->rtp_termination_id_prefix, term_id);
} else {
for (term = profile->physical_terminations; term; term = term->next) {
if (!switch_test_flag(term, MGT_ALLOCATED) && !strncasecmp(prefix, term->name, prefixlen)) {
switch_set_flag(term, MGT_ALLOCATED);
return term;
}
}
return term;
return NULL;
}
switch_core_new_memory_pool(&pool);
......@@ -168,6 +185,7 @@ mg_termination_t *megaco_choose_termination(megaco_profile_t *profile, const cha
term->type = termtype;
term->active_events = NULL;
term->profile = profile;
switch_set_flag(term, MGT_ALLOCATED);
if (termtype == MG_TERM_RTP) {
/* Fill in local address and reserve an rtp port */
......@@ -175,6 +193,7 @@ mg_termination_t *megaco_choose_termination(megaco_profile_t *profile, const cha
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->u.rtp.ptime = 20;
term->name = switch_core_strdup(term->pool, name);
}
......@@ -212,6 +231,9 @@ void megaco_termination_destroy(mg_termination_t *term)
term->active_events = NULL;
}
switch_clear_flag(term, MGT_ALLOCATED);
switch_clear_flag(term, MGT_ACTIVE);
if (term->type == MG_TERM_RTP) {
switch_core_hash_delete_wrlock(term->profile->terminations, term->name, term->profile->terminations_rwlock);
switch_core_destroy_memory_pool(&term->pool);
......
......@@ -77,8 +77,6 @@ switch_status_t config_profile(megaco_profile_t *profile, switch_bool_t reload)
//const char *tech = switch_xml_attr(mg_term, "tech");
const char *channel_prefix = switch_xml_attr(mg_term, "channel-prefix");
const char *channel_map = switch_xml_attr(mg_term, "channel-map");
const char *szspan_id = switch_xml_attr(mg_term, "span-id");
const int span_id = !zstr(szspan_id) ? atoi(szspan_id) : 0;
if (!zstr(channel_map)) {
......@@ -102,12 +100,14 @@ switch_status_t config_profile(megaco_profile_t *profile, switch_bool_t reload)
term->type = MG_TERM_TDM;
term->profile = profile;
term->name = switch_core_sprintf(pool, "%s%d", prefix, j);
term->u.tdm.span = span_id;
term->u.tdm.channel = j;
term->u.tdm.span_name = switch_core_strdup(pool, channel_prefix);
switch_core_hash_insert_wrlock(profile->terminations, term->name, term, profile->terminations_rwlock);
term->next = profile->physical_terminations;
profile->physical_terminations = term;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Mapped termination [%s] to freetdm span: %d chan: %d\n", term->name, term->u.tdm.span, term->u.tdm.channel);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Mapped termination [%s] to freetdm span: %s chan: %d\n", term->name, term->u.tdm.span_name, term->u.tdm.channel);
}
}
}
......
......@@ -83,10 +83,17 @@ typedef struct mg_context_s mg_context_t;
/* TDM parameters understood by the controllable channel */
#define kSPAN_ID "span"
#define kCHAN_ID "chan"
#define kSPAN_NAME "span_name"
typedef struct mg_termination_s mg_termination_t;
enum {
MGT_ALLOCATED = (1 << 0),
MGT_ACTIVE = (1 << 1),
} mg_termination_flags;
struct mg_termination_s {
switch_memory_pool_t *pool;
mg_termination_type_t type;
......@@ -96,6 +103,7 @@ struct mg_termination_s {
megaco_profile_t *profile; /*!< Parent MG profile */
MgMgcoReqEvtDesc *active_events; /* !< active megaco events */
mg_termination_t *next; /*!< List for physical terminations */
uint32_t flags;
union {
struct {
......@@ -116,8 +124,8 @@ struct mg_termination_s {
} rtp;
struct {
int span;
int channel;
const char *span_name;
} tdm;
} u;
};
......@@ -165,6 +173,9 @@ struct megaco_profile_s {
uint8_t rtpid_bitmap[MG_MAX_CONTEXTS/8];
uint32_t rtpid_next;
mg_termination_t *physical_terminations;
switch_hash_t *terminations;
switch_thread_rwlock_t *terminations_rwlock;
};
......
......@@ -93,6 +93,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id);
static switch_status_t channel_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg);
static switch_status_t channel_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf);
static switch_status_t channel_receive_event(switch_core_session_t *session, switch_event_t *event);
switch_state_handler_table_t crtp_state_handlers = {
.on_init = channel_on_init,
......@@ -104,6 +105,7 @@ switch_io_routines_t crtp_io_routines = {
.read_frame = channel_read_frame,
.write_frame = channel_write_frame,
.receive_message = channel_receive_message,
.receive_event = channel_receive_event,
.send_dtmf = channel_send_dtmf
};
......@@ -395,6 +397,42 @@ static switch_status_t channel_send_dtmf(switch_core_session_t *session, const s
return SWITCH_STATUS_SUCCESS;
}
static switch_bool_t compare_var(switch_event_t *event, switch_channel_t *channel, const char *varname)
{
const char *chan_val = switch_channel_get_variable_dup(channel, varname, SWITCH_FALSE, -1);
const char *event_val = switch_event_get_header(event, varname);
return strcasecmp(chan_val, event_val);
}
static switch_status_t channel_receive_event(switch_core_session_t *session, switch_event_t *event)
{
const char *command = switch_event_get_header(event, "command");
switch_channel_t *channel = switch_core_session_get_channel(session);
if (!zstr(command) && !strcasecmp(command, "media_modify")) {
/* Compare parameters */
if (compare_var(event, channel, kREMOTEADDR) ||
compare_var(event, channel, kREMOTEPORT) ||
compare_var(event, channel, kLOCALADDR) ||
compare_var(event, channel, kLOCALPORT)) {
/* We need to reset the rtp session */
}
if (compare_var(event, channel, kCODEC) ||
compare_var(event, channel, kPTIME) ||
compare_var(event, channel, kPT) ||
compare_var(event, channel, kRATE)) {
/* Reset codec */
}
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Received unknown command [%s] in event.\n", !command ? "null" : command);
}
}
static switch_status_t channel_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg)
{
crtp_private_t *tech_pvt = NULL;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论