If end user is indicated as known in received ACM interpret it as progress or ringing indication.

Added generic mechanism to set protocol specific parameters in messages.


git-svn-id: http://yate.null.ro/svn/yate/trunk@2484 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
paulc 2009-02-18 17:01:48 +00:00
parent 570511346a
commit 335d0d57a0
4 changed files with 93 additions and 30 deletions

View File

@ -106,6 +106,10 @@
; Defaults to user-provided if missing or incorrect
;screening=user-provided
; earlyacm: boolean: Convert received early ACM user state into progress or ringing
; Defaults to enable
;earlyacm=enable
; format: string: Default data format for outgoing calls. Values: alaw, mulaw, g721
; Defaults to alaw if missing or incorrect
; alaw is used commonly in Europe while mulaw is used commonly in US and Japan.

View File

@ -128,6 +128,9 @@ static const SignallingFlags s_flags_paramcompat[] = {
{ 0, 0, 0 }
};
// Backward call indicators to be copied
static const String s_copyBkInd("BackwardCallIndicators,OptionalBackwardCallIndicators");
// Default decoder, dumps raw octets
static bool decodeRaw(const SS7ISUP* isup, NamedList& list, const IsupParam* param,
const unsigned char* buf, unsigned int len, const String& prefix)
@ -1630,6 +1633,8 @@ bool SS7ISUPCall::sendEvent(SignallingEvent* event)
SS7MsgISUP* m = new SS7MsgISUP(SS7MsgISUP::CPR,id());
m->params().addParam("EventInformation",
event->type() == SignallingEvent::Ringing ? "ringing": "progress");
if (event->message())
m->params().copyParams(event->message()->params(),s_copyBkInd);
m_state = Ringing;
result = transmitMessage(m);
}
@ -1638,8 +1643,7 @@ bool SS7ISUPCall::sendEvent(SignallingEvent* event)
if (validMsgState(true,SS7MsgISUP::ACM)) {
SS7MsgISUP* m = new SS7MsgISUP(SS7MsgISUP::ACM,id());
if (event->message())
m->params().addParam("BackwardCallIndicators",
event->message()->params().getValue("BackwardCallIndicators"));
m->params().copyParams(event->message()->params(),s_copyBkInd);
m_state = Accepted;
result = transmitMessage(m);
}
@ -1647,6 +1651,8 @@ bool SS7ISUPCall::sendEvent(SignallingEvent* event)
case SignallingEvent::Answer:
if (validMsgState(true,SS7MsgISUP::ANM)) {
SS7MsgISUP* m = new SS7MsgISUP(SS7MsgISUP::ANM,id());
if (event->message())
m->params().copyParams(event->message()->params(),s_copyBkInd);
m_state = Answered;
result = transmitMessage(m);
}
@ -1942,11 +1948,33 @@ SignallingEvent* SS7ISUPCall::processSegmented(SS7MsgISUP* sgm, bool timeout)
break;
case SS7MsgISUP::ACM:
m_state = Accepted;
m_lastEvent = new SignallingEvent(SignallingEvent::Accept,m_sgmMsg,this);
{
m_lastEvent = 0;
bool inband = SignallingUtils::hasFlag(m_sgmMsg->params(),"OptionalBackwardCallIndicators","inband");
if (isup() && isup()->m_earlyAcm) {
// If the called party is known free report ringing
// If it may become free or there is inband audio report progress
bool ring = SignallingUtils::hasFlag(m_sgmMsg->params(),"BackwardCallIndicators","called-free");
if (inband || ring || SignallingUtils::hasFlag(m_sgmMsg->params(),"BackwardCallIndicators","called-conn")) {
m_sgmMsg->params().setParam("earlymedia",String::boolText(inband));
m_lastEvent = new SignallingEvent(ring ? SignallingEvent::Ringing : SignallingEvent::Progress,m_sgmMsg,this);
}
}
if (!m_lastEvent) {
if (inband)
m_sgmMsg->params().setParam("earlymedia",String::boolText(true));
m_lastEvent = new SignallingEvent(SignallingEvent::Accept,m_sgmMsg,this);
}
}
break;
case SS7MsgISUP::CPR:
m_state = Ringing;
m_lastEvent = new SignallingEvent(SignallingEvent::Ringing,m_sgmMsg,this);
{
bool ring = SignallingUtils::hasFlag(m_sgmMsg->params(),"EventInformation","ringing");
if (!ring && SignallingUtils::hasFlag(m_sgmMsg->params(),"EventInformation","inband"))
m_sgmMsg->params().setParam("earlymedia",String::boolText(true));
m_lastEvent = new SignallingEvent(ring ? SignallingEvent::Ringing : SignallingEvent::Progress,m_sgmMsg,this);
}
break;
case SS7MsgISUP::ANM:
case SS7MsgISUP::CON:
@ -1957,8 +1985,7 @@ SignallingEvent* SS7ISUPCall::processSegmented(SS7MsgISUP* sgm, bool timeout)
Debug(isup(),DebugStub,"Call(%u). Segment waiting message is '%s' [%p]",
id(),m_sgmMsg->name(),this);
}
m_sgmMsg->deref();
m_sgmMsg = 0;
TelEngine::destruct(m_sgmMsg);
return m_lastEvent;
}
@ -1995,6 +2022,7 @@ SS7ISUP::SS7ISUP(const NamedList& params)
m_remotePoint(0),
m_priossf(0),
m_sls(255),
m_earlyAcm(true),
m_inn(false),
m_l3LinkUp(false),
m_uptTimer(0),
@ -2033,6 +2061,7 @@ SS7ISUP::SS7ISUP(const NamedList& params)
m_priossf |= SS7MSU::getPriority(params.getValue("priority"),SS7MSU::Regular);
m_priossf |= SS7MSU::getNetIndicator(params.getValue("netindicator"),SS7MSU::National);
m_earlyAcm = params.getBoolValue("earlyacm",m_earlyAcm);
m_inn = params.getBoolValue("inn",m_inn);
m_numPlan = params.getValue("numplan");
if (-1 == lookup(m_numPlan,s_dict_numPlan,-1))

View File

@ -5688,6 +5688,7 @@ private:
SS7PointCode* m_remotePoint; // Default remote point code for outgoing calls and maintenance
unsigned char m_priossf; // MSU priority + Subservice field
unsigned char m_sls; // Last known valid SLS
bool m_earlyAcm; // Accept progress/ringing in early ACM
bool m_inn; // Routing to internal network number flag
String m_numPlan; // Numbering plan
String m_numType; // Number type

View File

@ -93,6 +93,8 @@ private:
void evAccept(SignallingEvent* event);
void evAnswer(SignallingEvent* event);
void evRinging(SignallingEvent* event);
// Update circuit and format in source, optionally in consumer too
void updateCircuitFormat(SignallingEvent* event, bool consumer);
// Open or update format source/consumer
// Set force to true to change source/consumer pointer/format
bool updateConsumer(const char* format, bool force);
@ -142,6 +144,8 @@ public:
// event call controller's prefix
void copySigMsgParams(NamedList& dest, SignallingEvent* event,
const String* params = 0);
// Copy outgoing message parameters
void copySigMsgParams(SignallingEvent* event, const NamedList& params);
private:
// Handle command complete requests
virtual bool commandComplete(Message& msg, const String& partLine,
@ -500,6 +504,7 @@ public:
static SigDriver plugin;
static Configuration s_cfg;
static Configuration s_cfgData;
static const String s_noPrefixParams = "format,earlymedia";
static const char s_miniHelp[] = "sigdump component [filename]";
static const char s_fullHelp[] = "Command to dump signalling data to a file";
@ -699,6 +704,7 @@ bool SigChannel::msgProgress(Message& msg)
SignallingEvent* event = new SignallingEvent(SignallingEvent::Progress,sm,m_call);
TelEngine::destruct(sm);
lock.drop();
plugin.copySigMsgParams(event,msg);
event->sendEvent();
return true;
}
@ -719,6 +725,7 @@ bool SigChannel::msgRinging(Message& msg)
SignallingEvent* event = new SignallingEvent(SignallingEvent::Ringing,sm,m_call);
TelEngine::destruct(sm);
lock.drop();
plugin.copySigMsgParams(event,msg);
event->sendEvent();
return true;
}
@ -745,6 +752,7 @@ bool SigChannel::msgAnswered(Message& msg)
SignallingEvent* event = new SignallingEvent(SignallingEvent::Answer,sm,m_call);
TelEngine::destruct(sm);
lock.drop();
plugin.copySigMsgParams(event,msg);
event->sendEvent();
return true;
}
@ -772,6 +780,7 @@ bool SigChannel::msgTone(Message& msg, const char* tone)
SignallingEvent* event = new SignallingEvent(SignallingEvent::Info,sm,m_call);
TelEngine::destruct(sm);
lock.drop();
plugin.copySigMsgParams(event,msg);
event->sendEvent();
return true;
}
@ -787,6 +796,7 @@ bool SigChannel::msgText(Message& msg, const char* text)
SignallingEvent* event = new SignallingEvent(SignallingEvent::Message,sm,m_call);
TelEngine::destruct(sm);
lock.drop();
plugin.copySigMsgParams(event,msg);
event->sendEvent();
return true;
}
@ -805,6 +815,7 @@ bool SigChannel::msgTransfer(Message& msg)
return true;
SignallingEvent* event = new SignallingEvent(SignallingEvent::Transfer,0,m_call);
lock.drop();
plugin.copySigMsgParams(event,msg);
return event->sendEvent();
}
@ -839,8 +850,10 @@ void SigChannel::callAccept(Message& msg)
}
setState("accepted",false);
lock.drop();
if (event)
if (event) {
plugin.copySigMsgParams(event,msg);
event->sendEvent();
}
Channel::callAccept(msg);
}
@ -947,8 +960,9 @@ void SigChannel::evInfo(SignallingEvent* event)
void SigChannel::evProgress(SignallingEvent* event)
{
setState("progressing");
updateCircuitFormat(event,false);
Message* msg = message("call.progress");
plugin.copySigMsgParams(*msg,event);
plugin.copySigMsgParams(*msg,event,&s_noPrefixParams);
Engine::enqueue(msg);
}
@ -964,28 +978,13 @@ void SigChannel::evRelease(SignallingEvent* event)
void SigChannel::evAccept(SignallingEvent* event)
{
setState("accepted",false,false);
const char* format = 0;
bool cicChange = false;
if (event->message()) {
format = event->message()->params().getValue("format");
cicChange = event->message()->params().getBoolValue("circuit-change",false);
}
updateSource(format,cicChange);
updateConsumer(0,cicChange);
updateCircuitFormat(event,true);
}
void SigChannel::evAnswer(SignallingEvent* event)
{
static String params = "format";
setState("answered");
const char* format = 0;
bool cicChange = false;
if (event->message()) {
format = event->message()->params().getValue("format");
cicChange = event->message()->params().getBoolValue("circuit-change",false);
}
updateSource(format,cicChange);
updateConsumer(0,cicChange);
updateCircuitFormat(event,true);
// Start echo training
SignallingCircuit* cic = getCircuit();
if (cic) {
@ -993,24 +992,32 @@ void SigChannel::evAnswer(SignallingEvent* event)
cic->setParam("echotrain",value);
}
Message* msg = message("call.answered",false,true);
plugin.copySigMsgParams(*msg,event,&params);
plugin.copySigMsgParams(*msg,event,&s_noPrefixParams);
msg->clearParam("earlymedia");
Engine::enqueue(msg);
}
void SigChannel::evRinging(SignallingEvent* event)
{
static String params = "format";
setState("ringing");
updateCircuitFormat(event,false);
Message* msg = message("call.ringing",false,true);
plugin.copySigMsgParams(*msg,event,&s_noPrefixParams);
Engine::enqueue(msg);
}
void SigChannel::updateCircuitFormat(SignallingEvent* event, bool consumer)
{
const char* format = 0;
bool cicChange = false;
if (event->message()) {
format = event->message()->params().getValue("format");
cicChange = event->message()->params().getBoolValue("circuit-change",false);
}
DDebug(this,DebugInfo,"Updating format to '%s'%s",format,cicChange ? ", circuit changed" : "");
updateSource(format,cicChange);
Message* msg = message("call.ringing",false,true);
plugin.copySigMsgParams(*msg,event,&params);
Engine::enqueue(msg);
if (consumer)
updateConsumer(0,cicChange);
}
bool SigChannel::updateConsumer(const char* format, bool force)
@ -1365,6 +1372,28 @@ void SigDriver::copySigMsgParams(NamedList& dest, SignallingEvent* event,
dest.clearParam("message-prefix");
}
// Copy outgoing message parameters
void SigDriver::copySigMsgParams(SignallingEvent* event, const NamedList& params)
{
if (!(event && event->message() && event->controller()))
return;
String prefix = event->controller()->msgPrefix();
if (prefix)
prefix = "o" + prefix;
prefix = params.getValue("message-oprefix",prefix);
if (prefix.null())
return;
unsigned int n = params.length();
for (unsigned int i = 0; i < n; i++) {
NamedString* param = params.getParam(i);
if (!param)
continue;
String name = param->name();
if (name.startSkip(prefix,false))
event->message()->params().addParam(name,*param);
}
}
// Handle command complete requests
bool SigDriver::commandComplete(Message& msg, const String& partLine,
const String& partWord)