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

This commit is contained in:
David Yat Sin 2012-07-30 13:37:20 -04:00
commit c06e3d7653
10 changed files with 894 additions and 1040 deletions

View File

@ -84,7 +84,7 @@ switch_io_routines_t ctdm_io_routines = {
.receive_message = channel_receive_message
};
static void ctdm_report_alarms(ftdm_channel_t *channel, const char* mg_profile_name)
static void ctdm_report_alarms(ftdm_channel_t *channel)
{
switch_event_t *event = NULL;
ftdm_alarm_flag_t alarmflag = 0;
@ -109,8 +109,6 @@ static void ctdm_report_alarms(ftdm_channel_t *channel, const char* mg_profile_n
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "condition", "ftdm-alarm-trap");
}
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "mg-profile-name", mg_profile_name);
if (alarmflag & FTDM_ALARM_RED) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "red");
}
@ -130,6 +128,8 @@ static void ctdm_report_alarms(ftdm_channel_t *channel, const char* mg_profile_n
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "general");
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Reporting [%s] alarms for %s:%d\n",
(alarmflag?"ftdm-alarm-clear":"ftdm-alarm-trap"), ftdm_channel_get_span_name(channel), ftdm_channel_get_id(channel));
switch_event_fire(&event);
return;
@ -149,7 +149,6 @@ static void ctdm_event_handler(switch_event_t *event)
const char *chan_number = NULL;
uint32_t chan_id = 0;
const char *cond = switch_event_get_header(event, "condition");
const char *mg_profile_name = switch_event_get_header(event, "mg-profile-name");
if (zstr(cond)) {
return;
@ -187,7 +186,10 @@ static void ctdm_event_handler(switch_event_t *event)
return;
}
ctdm_report_alarms(channel, mg_profile_name);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Requesting alarm status for %s:%d\n",
ftdm_channel_get_span_name(channel), ftdm_channel_get_id(channel));
ctdm_report_alarms(channel);
}
}
break;

View File

@ -22,6 +22,8 @@ megaco_profile_t *megaco_profile_locate(const char *name)
return profile;
}
mg_peer_profile_t *megaco_peer_profile_locate(const char *name)
{
mg_peer_profile_t *profile = switch_core_hash_find_rdlock(megaco_globals.peer_profile_hash, name, megaco_globals.peer_profile_rwlock);
@ -171,7 +173,6 @@ switch_status_t megaco_prepare_tdm_termination(mg_termination_t *term)
return SWITCH_STATUS_SUCCESS;
}
/* @Kapil Call this function once H.248 link is up */
switch_status_t megaco_check_tdm_termination(mg_termination_t *term)
{
switch_event_t *event = NULL;
@ -186,7 +187,6 @@ switch_status_t megaco_check_tdm_termination(mg_termination_t *term)
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "span-name", "%s", term->u.tdm.span_name);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "chan-number", "%d", term->u.tdm.channel);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "condition", "mg-tdm-check");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "mg-profile-name", term->profile->name);
switch_event_fire(&event);
return SWITCH_STATUS_SUCCESS;
@ -241,7 +241,34 @@ mg_termination_t *megaco_choose_termination(megaco_profile_t *profile, const cha
return term;
}
mg_termination_t* megaco_find_termination_by_span_chan(megaco_profile_t *profile, char *span_name, char *chan_number)
mg_termination_t *megaco_term_locate_by_span_chan_id(const char *span_name, const char *chan_number)
{
void *val = NULL;
switch_hash_index_t *hi = NULL;
mg_termination_t *term = NULL;
megaco_profile_t *profile = NULL;
const void *var;
switch_assert(span_name);
switch_assert(chan_number);
/* span + chan will be unique across all the mg_profiles *
* loop through all profiles and then all terminations to *
* get the mg termination associated with input span+chan */
switch_thread_rwlock_rdlock(megaco_globals.profile_rwlock);
for (hi = switch_hash_first(NULL, megaco_globals.profile_hash); hi; hi = switch_hash_next(hi)) {
switch_hash_this(hi, &var, NULL, &val);
profile = (megaco_profile_t *) val;
if(NULL != (term = megaco_find_termination_by_span_chan(profile, span_name, chan_number))) break;
}
switch_thread_rwlock_unlock(megaco_globals.profile_rwlock);
return term;
}
mg_termination_t* megaco_find_termination_by_span_chan(megaco_profile_t *profile, const char *span_name, const char *chan_number)
{
void *val = NULL;
switch_hash_index_t *hi = NULL;
@ -262,7 +289,8 @@ mg_termination_t* megaco_find_termination_by_span_chan(megaco_profile_t *profile
if ((!strcasecmp(span_name, term->u.tdm.span_name))&& (atoi(chan_number) == term->u.tdm.channel)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,
"Got term[%s] associated with span[%s], channel[%s]\n",term->name, span_name, chan_number);
"Got term[%s] associated with span[%s], channel[%s] in MG profile[%s]\n",
term->name, span_name, chan_number, profile->name);
found = 0x01;
break;
}
@ -271,7 +299,8 @@ mg_termination_t* megaco_find_termination_by_span_chan(megaco_profile_t *profile
if(!found){
term = NULL;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
" Not able to find termination associated with span[%s], channel[%s]\n", span_name, chan_number);
" MG profile[%s] does not have termination associated with span[%s], channel[%s]\n",
profile->name, span_name, chan_number);
}
return term;
@ -549,8 +578,9 @@ switch_status_t megaco_profile_start(const char *profilename)
switch_core_new_memory_pool(&pool);
profile = switch_core_alloc(pool, sizeof(*profile));
profile->pool = pool;
profile->physical_terminations = NULL;
profile->name = switch_core_strdup(pool, profilename);
profile->next_context_id++;
profile->next_context_id++;
profile->inact_tmr = 0x00;
profile->inact_tmr_task_id = 0x00;

View File

@ -2288,18 +2288,15 @@ U32 get_txn_id(){
return outgoing_txn_id;
}
/*****************************************************************************************************************************/
switch_status_t mg_send_term_service_change(char* mg_profile_name,char *span_name, char *chan_number, mg_term_states_e term_state)
switch_status_t mg_send_term_service_change(char *span_name, char *chan_number, mg_term_states_e term_state)
{
mg_termination_t* term = NULL;
switch_status_t ret = SWITCH_STATUS_SUCCESS;
megaco_profile_t *profile = NULL;
switch_assert(span_name);
switch_assert(chan_number);
profile = megaco_profile_locate(mg_profile_name);
term = megaco_find_termination_by_span_chan(profile, span_name, chan_number);
term = megaco_term_locate_by_span_chan_id(span_name, chan_number);
if(!term || !term->profile){
return SWITCH_STATUS_FALSE;
@ -2309,12 +2306,22 @@ switch_status_t mg_send_term_service_change(char* mg_profile_name,char *span_nam
{
case MG_TERM_SERVICE_STATE_IN_SERVICE:
{
ret = mg_send_ins_service_change(term->profile, term->name, 0x00 );
if(switch_test_flag(term, MG_OUT_OF_SERVICE)){
/* set INS flag...clear oos flag */
switch_clear_flag(term, MG_OUT_OF_SERVICE);
switch_set_flag(term, MG_IN_SERVICE);
ret = mg_send_ins_service_change(term->profile, term->name, 0x00 );
}
break;
}
case MG_TERM_SERVICE_STATE_OUT_OF_SERVICE:
{
ret = mg_send_oos_service_change(term->profile, term->name, 0x00 );
if(switch_test_flag(term, MG_IN_SERVICE)){
/* set OOS flag...clear ins flag */
switch_clear_flag(term, MG_IN_SERVICE);
switch_set_flag(term, MG_OUT_OF_SERVICE);
ret = mg_send_oos_service_change(term->profile, term->name, 0x00 );
}
break;
}
default:

View File

@ -164,8 +164,7 @@ void mg_util_set_err_string ( MgStr *errTxt, char* str);
switch_status_t mg_build_sdp(MgMgcoMediaDesc* out, MgMgcoMediaDesc* inc, megaco_profile_t* mg_profile, mg_termination_t* term, CmMemListCp *memCp);
switch_status_t mg_add_local_descriptor(MgMgcoMediaDesc* media, megaco_profile_t* mg_profile, mg_termination_t* term, CmMemListCp *memCp);
switch_status_t mg_send_term_service_change(char* mg_profile_name, char *span_name, char *chan_number, mg_term_states_e term_state);
mg_termination_t* megaco_find_termination_by_span_chan(megaco_profile_t *profile , char *span_name, char *chan_number);
switch_status_t mg_send_term_service_change(char *span_name, char *chan_number, mg_term_states_e term_state);
switch_status_t sng_mgco_cfg(megaco_profile_t* profile);
@ -190,7 +189,8 @@ void mg_util_set_txn_string(MgStr *errTxt, U32 *txnId);
switch_status_t mg_build_mgco_err_request(MgMgcoInd **errcmd,U32 trans_id, MgMgcoContextId *ctxt_id, U32 err, MgStr *errTxt);
switch_status_t mg_send_audit_rsp(SuId suId, MgMgcoCommand *req);
switch_status_t handle_mg_audit_cmd(SuId suId, MgMgcoCommand *auditReq);
switch_status_t mg_stack_termination_is_in_service(char* term_str, int len);
switch_status_t mg_stack_termination_is_in_service(megaco_profile_t* mg_profile, char* term_str, int len);
void mg_create_tdm_term(megaco_profile_t *profile, const char *tech, const char *channel_prefix, const char *prefix, int j);
void mg_util_set_cmd_name_string (MgStr *errTxt, MgMgcoCommand *cmd);
switch_status_t mgco_init_ins_service_change(SuId suId);

View File

@ -80,10 +80,16 @@ switch_status_t mg_stack_free_mem(void* msg)
/*****************************************************************************************************************************/
/* TODO - Matt - to see if term is in service or not */
switch_status_t mg_stack_termination_is_in_service(char* term_str,int len)
/* To see if term is in service or not */
switch_status_t mg_stack_termination_is_in_service(megaco_profile_t* mg_profile, char* term_str,int len)
{
return SWITCH_STATUS_SUCCESS;
mg_termination_t* term = NULL;
term = megaco_find_termination(mg_profile, term_str);
if(switch_test_flag(term, MG_IN_SERVICE)){
return SWITCH_STATUS_SUCCESS;
} else {
return SWITCH_STATUS_FALSE;
}
}
/*****************************************************************************************************************************/

View File

@ -65,62 +65,74 @@ switch_status_t config_profile(megaco_profile_t *profile, switch_bool_t reload)
profile->idx = ++mg_sap_id;
if ((mg_phys_terms = switch_xml_child(mg_interface, "physical_terminations"))) {
for (mg_term = switch_xml_child(mg_phys_terms, "map"); mg_term; mg_term = mg_term->next) {
switch_memory_pool_t *pool;
mg_termination_t *term;
// <map termination-id-prefix="Term1/" termination-id-base="1" tech="freetdm" channel-prefix="wp2" channel-map"1-15,17-31"/>
const char *prefix = switch_xml_attr(mg_term, "termination-id-prefix");
//const char *sztermination_id_base = switch_xml_attr(mg_term, "termination-id-base");
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");
if (!zstr(channel_map)) {
/* Split channel-map */
char *channel_map_dup = strdup(channel_map);
char *chanmap[24];
int chanmap_count, i;
chanmap_count = switch_split(channel_map_dup, ',', chanmap);
for (i = 0; i < chanmap_count; i++) {
char *p = strchr(chanmap[i], '-');
if (p) {
int startchan, endchan, j;
*p++ = '\0';
startchan = atoi(chanmap[i]);
endchan = atoi(p);
for (j = startchan; j < endchan; j++) {
switch_core_new_memory_pool(&pool);
term = switch_core_alloc(profile->pool, sizeof *term);
term->pool = pool;
term->type = MG_TERM_TDM;
term->profile = profile;
term->mg_ctxt = NULL;
term->tech = switch_core_strdup(pool, tech);
term->active_events = NULL;
term->name = switch_core_sprintf(pool, "%s%d", prefix, j);
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: %s chan: %d\n", term->name, term->u.tdm.span_name, term->u.tdm.channel);
megaco_prepare_tdm_termination(term);
}
}
}
free(channel_map_dup);
}
}
}
if ((mg_phys_terms = switch_xml_child(mg_interface, "physical_terminations"))) {
for (mg_term = switch_xml_child(mg_phys_terms, "map"); mg_term; mg_term = mg_term->next) {
// <map termination-id-prefix="Term1/" termination-id-base="1" tech="freetdm" channel-prefix="wp2" channel-map"1-15,17-31"/>
const char *prefix = switch_xml_attr(mg_term, "termination-id-prefix");
//const char *sztermination_id_base = switch_xml_attr(mg_term, "termination-id-base");
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");
char *p = NULL;
if (!zstr(channel_map)) {
/* Split channel-map */
char *channel_map_dup = strdup(channel_map);
char *chanmap[24] = {0};
int chanmap_count = 0;
int i = 0;
int startchan, endchan, j;
/* we can have following combinations *
* i) only one channel i.e. channel-map="1"
* ii) only one chanel range i.e channel-map="1-15"
* iii) full channel range i.e. channel-map="1-15,17-31"
*/
chanmap_count = switch_split(channel_map_dup, ',', chanmap);
if(1 == chanmap_count) {
p = strchr(channel_map_dup, '-');
if(NULL != p){
/* case (ii) */
i = switch_split(channel_map_dup, '-', chanmap);
if(i && chanmap[0] && chanmap[1]) {
startchan = atoi(chanmap[0]);
endchan = atoi(chanmap[1]);
for (j = startchan; j < endchan; j++) {
mg_create_tdm_term(profile, tech, channel_prefix, prefix, j);
}
}
}else{
/* case (i) */
p = channel_map_dup;
startchan = endchan = atoi(p);
mg_create_tdm_term(profile, tech, channel_prefix, prefix, startchan);
}
}else
{
/* case (iii) */
for (i = 0; i < chanmap_count; i++) {
p = strchr(chanmap[i], '-');
if (p) {
*p++ = '\0';
startchan = atoi(chanmap[i]);
endchan = atoi(p);
for (j = startchan; j < endchan; j++) {
mg_create_tdm_term(profile, tech, channel_prefix, prefix, j);
}
}
}
}
free(channel_map_dup);
}
}
}
/* we should break from here , profile name should be unique */
@ -129,7 +141,7 @@ switch_status_t config_profile(megaco_profile_t *profile, switch_bool_t reload)
if (!mg_interface) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error profile %s not found\n", profile->name);
return SWITCH_STATUS_FALSE;
return SWITCH_STATUS_FALSE;
}
/* go through the peer configuration and get the mg profile associated peers only */
@ -169,7 +181,7 @@ switch_status_t config_profile(megaco_profile_t *profile, switch_bool_t reload)
}
}
}
/* configure the MEGACO stack */
status = sng_mgco_cfg(profile);
@ -184,6 +196,34 @@ done:
return status;
}
/****************************************************************************************************************************/
void mg_create_tdm_term(megaco_profile_t *profile, const char *tech, const char *channel_prefix, const char *prefix, int chan_num)
{
mg_termination_t *term;
switch_memory_pool_t *pool;
switch_core_new_memory_pool(&pool);
term = switch_core_alloc(profile->pool, sizeof *term);
term->pool = pool;
term->type = MG_TERM_TDM;
term->profile = profile;
term->mg_ctxt = NULL;
term->tech = switch_core_strdup(pool, tech);
term->active_events = NULL;
term->name = switch_core_sprintf(pool, "%s%d", prefix, chan_num);
term->u.tdm.channel = chan_num;
term->u.tdm.span_name = switch_core_strdup(pool, channel_prefix);
switch_set_flag(term, MG_OUT_OF_SERVICE);
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: %s chan: %d\n",
term->name, term->u.tdm.span_name, term->u.tdm.channel);
megaco_prepare_tdm_termination(term);
}
/****************************************************************************************************************************/
switch_status_t mg_config_cleanup(megaco_profile_t* profile)
{

View File

@ -64,38 +64,23 @@ static void mg_event_handler(switch_event_t *event)
const char *span_name = NULL;
const char *chan_number = NULL;
const char *cond = NULL;
const char *mg_profile_name = NULL;
cond = switch_event_get_header(event, "condition");
if (zstr(cond)) {
printf("Condition NULL, returning \n");
return;
}
mg_profile_name = switch_event_get_header(event, "mg-profile-name");
if (zstr(mg_profile_name)) {
printf("mg_profile_name NULL, returning \n");
return;
}
span_name = switch_event_get_header(event, "span-name");
span_name = switch_event_get_header(event, "span-name");
chan_number = switch_event_get_header(event, "chan-number");
if (!strcmp(cond, "ftdm-alarm-trap")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,
"ftdm-alarm-trap for span_name[%s] chan_number[%s] associated with MG profile[%s]\n",
span_name,chan_number, mg_profile_name);
/* @KAPIL: TDM is in alarm, notify MGC */
mg_send_term_service_change(
(char*)mg_profile_name, (char*)span_name, (char*)chan_number, MG_TERM_SERVICE_STATE_OUT_OF_SERVICE);
"ftdm-alarm-trap for span_name[%s] chan_number[%s]\n", span_name,chan_number);
mg_send_term_service_change((char*)span_name, (char*)chan_number, MG_TERM_SERVICE_STATE_OUT_OF_SERVICE);
} else if (!strcmp(cond, "ftdm-alarm-clear")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,
"ftdm-alarm-clear for span_name[%s] chan_number[%s] associated with MG profile[%s] \n",
span_name,chan_number, mg_profile_name);
/* TDM alarm cleared, notify MGC */
mg_send_term_service_change(
(char*)mg_profile_name, (char*)span_name, (char*)chan_number, MG_TERM_SERVICE_STATE_IN_SERVICE);
"ftdm-alarm-clear for span_name[%s] chan_number[%s] \n", span_name,chan_number);
mg_send_term_service_change( (char*)span_name, (char*)chan_number, MG_TERM_SERVICE_STATE_IN_SERVICE);
}
}
break;
@ -561,8 +546,10 @@ void handle_mgco_cmd_ind(Pst *pst, SuId suId, MgMgcoCommand* cmd)
}
/*If term type is other then check if that term is configured with us..for term type CHOOSE/ALL , no need to check */
if (MGT_TERMID_OTHER == termId->type.val){
if(SWITCH_STATUS_FALSE == mg_stack_termination_is_in_service((char*)termId->name.lcl.val, termId->name.lcl.len)){
if ((CH_CMD_TYPE_IND == cmd->cmdType.val) &&
(MGT_TERMID_OTHER == termId->type.val)){
if(SWITCH_STATUS_FALSE == mg_stack_termination_is_in_service(mg_profile, (char*)termId->name.lcl.val, termId->name.lcl.len)){
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Termination[%s] not in service \n", (char*)termId->name.lcl.val);
mg_util_set_term_string(&errTxt, termId);
err_code = MGT_MGCO_RSP_CODE_UNKNOWN_TERM_ID;
goto error;

View File

@ -89,8 +89,10 @@ typedef struct mg_context_s mg_context_t;
typedef struct mg_termination_s mg_termination_t;
enum {
MGT_ALLOCATED = (1 << 0),
MGT_ACTIVE = (1 << 1),
MGT_ALLOCATED = (1 << 0),
MGT_ACTIVE = (1 << 1),
MG_IN_SERVICE = (1 << 2),
MG_OUT_OF_SERVICE = (1 << 3),
} mg_termination_flags;
@ -222,8 +224,10 @@ static inline megaco_codec_t megaco_codec_parse(const char *codec) {
megaco_profile_t *megaco_profile_locate(const char *name);
mg_termination_t *megaco_term_locate_by_span_chan_id(const char *span_name, const char *chan_number);
mg_peer_profile_t *megaco_peer_profile_locate(const char *name);
void megaco_profile_release(megaco_profile_t *profile);
mg_termination_t* megaco_find_termination_by_span_chan(megaco_profile_t *profile, const char *span_name, const char *chan_number);
switch_status_t megaco_profile_start(const char *profilename);
switch_status_t megaco_profile_destroy(megaco_profile_t **profile);

File diff suppressed because it is too large Load Diff

View File

@ -4,6 +4,7 @@
* Version: MPL 1.1
*
* Copyright (c) 2007 Tuyan Ozipek (tuyanozipek@gmail.com)
* Copyright (c) 2008-2012 Vox Lucida Pty. Ltd. (robertj@voxlucida.com.au)
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
@ -46,6 +47,8 @@
#define HAVE_APR
#include <switch.h>
#include <switch_version.h>
#define MODNAME "mod_opal"
@ -53,206 +56,239 @@ class FSEndPoint;
class FSManager;
struct mod_opal_globals {
int trace_level;
char *codec_string;
char *context;
char *dialplan;
class FSProcess : public PLibraryProcess
{
PCLASSINFO(FSProcess, PLibraryProcess);
public:
FSProcess();
~FSProcess();
bool Initialise(switch_loadable_module_interface_t *iface);
FSManager & GetManager() const
{
return *m_manager;
}
protected:
FSManager * m_manager;
};
extern struct mod_opal_globals mod_opal_globals;
struct FSListener
{
FSListener() : m_port(H323EndPoint::DefaultTcpSignalPort) { }
PString m_name;
PIPSocket::Address m_address;
uint16_t m_port;
};
class FSProcess:public PLibraryProcess {
PCLASSINFO(FSProcess, PLibraryProcess);
class FSManager : public OpalManager
{
PCLASSINFO(FSManager, OpalManager);
public:
FSProcess();
~FSProcess();
FSManager();
bool Initialise(switch_loadable_module_interface_t *iface);
bool Initialise(switch_loadable_module_interface_t *iface);
FSManager & GetManager() const {
return *m_manager;
} protected:
FSManager * m_manager;
};
switch_status_t ReadConfig(int reload);
struct FSListener {
FSListener() {
} PString name;
OpalTransportAddress listenAddress;
PString localUserName;
PString gatekeeper;
};
class FSCall:public OpalCall {
PCLASSINFO(FSCall, OpalCall);
public:
FSCall(OpalManager & manager);
virtual PBoolean OnSetUp(OpalConnection & connection);
};
class FSManager:public OpalManager {
PCLASSINFO(FSManager, OpalManager);
public:
FSManager();
bool Initialise(switch_loadable_module_interface_t *iface);
switch_status_t ReadConfig(int reload);
switch_endpoint_interface_t *GetSwitchInterface() const {
return m_FreeSwitch;
} virtual OpalCall *CreateCall(void *userData);
switch_endpoint_interface_t *GetSwitchInterface() const { return m_FreeSwitch; }
const PString & GetContext() const { return m_context; }
const PString & GetDialPlan() const { return m_dialplan; }
const PString & GetCodecPrefs() const { return m_codecPrefs; }
private:
switch_endpoint_interface_t *m_FreeSwitch;
switch_endpoint_interface_t *m_FreeSwitch;
H323EndPoint *m_h323ep;
IAX2EndPoint *m_iaxep;
FSEndPoint *m_fsep;
H323EndPoint *m_h323ep;
IAX2EndPoint *m_iaxep;
FSEndPoint *m_fsep;
PString m_gkAddress;
PString m_gkIdentifer;
PString m_gkInterface;
PString m_context;
PString m_dialplan;
PString m_codecPrefs;
PString m_gkAddress;
PString m_gkIdentifer;
PString m_gkInterface;
list < FSListener > m_listeners;
list <FSListener> m_listeners;
};
class FSEndPoint : public OpalLocalEndPoint
{
PCLASSINFO(FSEndPoint, OpalLocalEndPoint);
public:
FSEndPoint(FSManager & manager);
virtual OpalLocalConnection *CreateConnection(OpalCall & call, void *userData, unsigned options, OpalConnection::StringOptions * stringOptions);
FSManager & GetManager() const { return m_manager; }
protected:
FSManager & m_manager;
};
class FSConnection;
typedef struct {
switch_timer_t read_timer;
switch_codec_t read_codec;
switch_codec_t write_codec;
switch_timer_t vid_read_timer;
switch_codec_t vid_read_codec;
switch_codec_t vid_write_codec;
FSConnection *me;
} opal_private_t;
class FSEndPoint:public OpalLocalEndPoint {
PCLASSINFO(FSEndPoint, OpalLocalEndPoint);
class FSMediaStream : public OpalMediaStream
{
PCLASSINFO(FSMediaStream, OpalMediaStream);
public:
FSEndPoint(FSManager & manager);
FSMediaStream(
FSConnection & conn,
const OpalMediaFormat & mediaFormat, ///< Media format for stream
unsigned sessionID, ///< Session number for stream
bool isSource ///< Is a source stream
);
virtual bool OnIncomingCall(OpalLocalConnection &);
virtual OpalLocalConnection *CreateConnection(OpalCall & call, void *userData, unsigned options, OpalConnection::StringOptions * stringOptions);
virtual PBoolean Open();
virtual PBoolean IsSynchronous() const;
virtual PBoolean RequiresPatchThread(OpalMediaStream *) const;
switch_status_t read_frame(switch_frame_t **frame, switch_io_flag_t flags);
switch_status_t write_frame(const switch_frame_t *frame, switch_io_flag_t flags);
protected:
virtual void InternalClose();
int StartReadWrite(PatchPtr & mediaPatch) const;
private:
bool CheckPatchAndLock();
FSConnection &m_connection;
switch_timer_t *m_switchTimer;
switch_codec_t *m_switchCodec;
switch_frame_t m_readFrame;
RTP_DataFrame m_readRTP;
};
#define DECLARE_CALLBACK0(name) \
static switch_status_t name(switch_core_session_t *session) { \
opal_private_t *tech_pvt = (opal_private_t *) switch_core_session_get_private(session); \
return tech_pvt && tech_pvt->me != NULL ? tech_pvt->me->name() : SWITCH_STATUS_FALSE; } \
switch_status_t name()
FSConnection *tech_pvt = (FSConnection *) switch_core_session_get_private(session); \
return tech_pvt != NULL ? tech_pvt->name() : SWITCH_STATUS_FALSE; } \
switch_status_t name()
#define DECLARE_CALLBACK1(name, type1, name1) \
static switch_status_t name(switch_core_session_t *session, type1 name1) { \
opal_private_t *tech_pvt = (opal_private_t *) switch_core_session_get_private(session); \
return tech_pvt && tech_pvt->me != NULL ? tech_pvt->me->name(name1) : SWITCH_STATUS_FALSE; } \
switch_status_t name(type1 name1)
FSConnection *tech_pvt = (FSConnection *) switch_core_session_get_private(session); \
return tech_pvt != NULL ? tech_pvt->name(name1) : SWITCH_STATUS_FALSE; } \
switch_status_t name(type1 name1)
#define DECLARE_CALLBACK3(name, type1, name1, type2, name2, type3, name3) \
static switch_status_t name(switch_core_session_t *session, type1 name1, type2 name2, type3 name3) { \
opal_private_t *tech_pvt = (opal_private_t *) switch_core_session_get_private(session); \
return tech_pvt && tech_pvt->me != NULL ? tech_pvt->me->name(name1, name2, name3) : SWITCH_STATUS_FALSE; } \
switch_status_t name(type1 name1, type2 name2, type3 name3)
FSConnection *tech_pvt = (FSConnection *) switch_core_session_get_private(session); \
return tech_pvt != NULL ? tech_pvt->name(name1, name2, name3) : SWITCH_STATUS_FALSE; } \
switch_status_t name(type1 name1, type2 name2, type3 name3)
class FSConnection:public OpalLocalConnection {
PCLASSINFO(FSConnection, OpalLocalConnection)
class FSConnection : public OpalLocalConnection
{
PCLASSINFO(FSConnection, OpalLocalConnection)
public:
FSConnection(OpalCall & call,
FSEndPoint & endpoint,
void *userData,
unsigned options,
OpalConnection::StringOptions * stringOptions,
switch_caller_profile_t *outbound_profile, switch_core_session_t *fsSession, switch_channel_t *fsChannel);
struct outgoing_params {
switch_event_t *var_event;
switch_caller_profile_t *outbound_profile;
switch_core_session_t **new_session;
switch_memory_pool_t **pool;
switch_originate_flag_t flags;
switch_call_cause_t *cancel_cause;
switch_call_cause_t fail_cause;
};
virtual bool OnIncoming();
virtual void OnReleased();
virtual PBoolean SetAlerting(const PString & calleeName, PBoolean withMedia);
virtual void OnAlerting();
virtual void OnEstablished();
virtual OpalMediaStream *CreateMediaStream(const OpalMediaFormat &, unsigned, PBoolean);
virtual PBoolean OnOpenMediaStream(OpalMediaStream & stream);
virtual OpalMediaFormatList GetMediaFormats() const;
virtual PBoolean SendUserInputTone(char tone, unsigned duration);
virtual PBoolean SendUserInputString(const PString & value);
FSConnection(OpalCall & call,
FSEndPoint & endpoint,
unsigned options,
OpalConnection::StringOptions * stringOptions,
outgoing_params * params);
void SetCodecs();
virtual bool OnOutgoingSetUp();
virtual bool OnIncoming();
virtual void OnReleased();
virtual PBoolean SetAlerting(const PString & calleeName, PBoolean withMedia);
virtual OpalMediaStream *CreateMediaStream(const OpalMediaFormat &, unsigned, PBoolean);
virtual void OnPatchMediaStream(PBoolean isSource, OpalMediaPatch & patch);
virtual OpalMediaFormatList GetMediaFormats() const;
virtual PBoolean SendUserInputTone(char tone, unsigned duration);
DECLARE_CALLBACK0(on_init);
DECLARE_CALLBACK0(on_routing);
DECLARE_CALLBACK0(on_execute);
void SetCodecs();
bool WaitForMedia();
DECLARE_CALLBACK0(on_exchange_media);
DECLARE_CALLBACK0(on_soft_execute);
DECLARE_CALLBACK0(on_init);
DECLARE_CALLBACK0(on_destroy);
DECLARE_CALLBACK0(on_routing);
DECLARE_CALLBACK0(on_execute);
DECLARE_CALLBACK0(on_hangup);
DECLARE_CALLBACK1(kill_channel, int, sig);
DECLARE_CALLBACK1(send_dtmf, const switch_dtmf_t *, dtmf);
DECLARE_CALLBACK1(receive_message, switch_core_session_message_t *, msg);
DECLARE_CALLBACK1(receive_event, switch_event_t *, event);
DECLARE_CALLBACK0(state_change);
DECLARE_CALLBACK3(read_audio_frame, switch_frame_t **, frame, switch_io_flag_t, flags, int, stream_id);
DECLARE_CALLBACK3(write_audio_frame, switch_frame_t *, frame, switch_io_flag_t, flags, int, stream_id);
DECLARE_CALLBACK3(read_video_frame, switch_frame_t **, frame, switch_io_flag_t, flag, int, stream_id);
DECLARE_CALLBACK3(write_video_frame, switch_frame_t *, frame, switch_io_flag_t, flag, int, stream_id);
DECLARE_CALLBACK0(on_exchange_media);
DECLARE_CALLBACK0(on_soft_execute);
switch_status_t read_frame(const OpalMediaType & mediaType, switch_frame_t **frame, switch_io_flag_t flags);
switch_status_t write_frame(const OpalMediaType & mediaType, const switch_frame_t *frame, switch_io_flag_t flags);
DECLARE_CALLBACK1(kill_channel, int, sig);
DECLARE_CALLBACK1(send_dtmf, const switch_dtmf_t *, dtmf);
DECLARE_CALLBACK1(receive_message, switch_core_session_message_t *, msg);
DECLARE_CALLBACK1(receive_event, switch_event_t *, event);
DECLARE_CALLBACK0(state_change);
DECLARE_CALLBACK3(read_audio_frame, switch_frame_t **, frame, switch_io_flag_t, flags, int, stream_id);
DECLARE_CALLBACK3(write_audio_frame, switch_frame_t *, frame, switch_io_flag_t, flags, int, stream_id);
DECLARE_CALLBACK3(read_video_frame, switch_frame_t **, frame, switch_io_flag_t, flag, int, stream_id);
DECLARE_CALLBACK3(write_video_frame, switch_frame_t *, frame, switch_io_flag_t, flag, int, stream_id);
switch_core_session_t *GetSession() const {
return m_fsSession;
} private:
FSEndPoint & m_endpoint;
switch_core_session_t *m_fsSession;
switch_channel_t *m_fsChannel;
PSyncPoint m_rxAudioOpened;
PSyncPoint m_txAudioOpened;
OpalMediaFormatList m_switchMediaFormats;
};
switch_status_t read_frame(const OpalMediaType & mediaType, switch_frame_t **frame, switch_io_flag_t flags);
switch_status_t write_frame(const OpalMediaType & mediaType, const switch_frame_t *frame, switch_io_flag_t flags);
__inline switch_core_session_t *GetSession() const
{
return m_fsSession;
}
class FSMediaStream:public OpalMediaStream {
PCLASSINFO(FSMediaStream, OpalMediaStream);
public:
FSMediaStream(FSConnection & conn, const OpalMediaFormat & mediaFormat, ///< Media format for stream
unsigned sessionID, ///< Session number for stream
bool isSource ///< Is a source stream
);
__inline switch_channel_t *GetChannel() const
{
return m_fsChannel;
}
virtual PBoolean Open();
virtual PBoolean Close();
virtual PBoolean IsSynchronous() const;
virtual PBoolean RequiresPatchThread(OpalMediaStream *) const;
bool IsChannelReady() const
{
return m_fsChannel != NULL && switch_channel_ready(m_fsChannel);
}
switch_status_t read_frame(switch_frame_t **frame, switch_io_flag_t flags);
switch_status_t write_frame(const switch_frame_t *frame, switch_io_flag_t flags);
bool NeedFlushAudio()
{
if (!m_flushAudio)
return false;
m_flushAudio = false;
return true;
}
private:
switch_core_session_t *m_fsSession;
switch_channel_t *m_fsChannel;
switch_timer_t *m_switchTimer;
switch_codec_t *m_switchCodec;
switch_frame_t m_readFrame;
unsigned char m_buf[SWITCH_RECOMMENDED_BUFFER_SIZE];
RTP_DataFrame m_readRTP;
bool m_callOnStart;
uint32_t m_timeStamp;
FSEndPoint &m_endpoint;
switch_core_session_t *m_fsSession;
switch_channel_t *m_fsChannel;
PSyncPoint m_rxAudioOpened;
PSyncPoint m_txAudioOpened;
OpalMediaFormatList m_switchMediaFormats;
bool CheckPatchAndLock();
// If FS ever supports more than one audio and one video, this needs to change
switch_timer_t m_read_timer;
switch_codec_t m_read_codec;
switch_codec_t m_write_codec;
switch_timer_t m_vid_read_timer;
switch_codec_t m_vid_read_codec;
switch_codec_t m_vid_write_codec;
bool m_flushAudio;
friend PBoolean FSMediaStream::Open();
};