Fixed endpoint incrementation algorithm and circuit creation.
Fixed MGCP connection and SDP creation. Detect protocol version from RSIP message. git-svn-id: http://voip.null.ro/svn/yate@2595 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
6a9e663408
commit
c48de42554
|
@ -54,3 +54,9 @@
|
||||||
; The first gateway which is not explicitely disabled or the last that is
|
; The first gateway which is not explicitely disabled or the last that is
|
||||||
; explicitely enabled will become default
|
; explicitely enabled will become default
|
||||||
;default=no
|
;default=no
|
||||||
|
|
||||||
|
; chans: int: Number of PSTN circuits to create in span
|
||||||
|
;chans=1
|
||||||
|
|
||||||
|
; offset: int: Offset of circuit code relative to start in span
|
||||||
|
;offset=0
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include <yatesig.h>
|
#include <yatesig.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
using namespace TelEngine;
|
using namespace TelEngine;
|
||||||
namespace { // anonymous
|
namespace { // anonymous
|
||||||
|
@ -102,6 +103,8 @@ public:
|
||||||
{ return m_operational; }
|
{ return m_operational; }
|
||||||
inline const String& address() const
|
inline const String& address() const
|
||||||
{ return m_address; }
|
{ return m_address; }
|
||||||
|
inline const char* version() const
|
||||||
|
{ return m_version.null() ? m_version.c_str() : "MGCP 1.0"; }
|
||||||
inline bool fxo() const
|
inline bool fxo() const
|
||||||
{ return m_fxo; }
|
{ return m_fxo; }
|
||||||
inline bool fxs() const
|
inline bool fxs() const
|
||||||
|
@ -127,6 +130,7 @@ private:
|
||||||
bool m_fxs;
|
bool m_fxs;
|
||||||
String m_notify;
|
String m_notify;
|
||||||
String m_address;
|
String m_address;
|
||||||
|
String m_version;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MGCPCircuit : public SignallingCircuit
|
class MGCPCircuit : public SignallingCircuit
|
||||||
|
@ -177,10 +181,13 @@ private:
|
||||||
String m_rtpId;
|
String m_rtpId;
|
||||||
String m_localIp;
|
String m_localIp;
|
||||||
int m_localPort;
|
int m_localPort;
|
||||||
|
int m_sdpSession;
|
||||||
|
int m_sdpVersion;
|
||||||
// Remote (MGCP GW side) RTP data
|
// Remote (MGCP GW side) RTP data
|
||||||
String m_remoteIp;
|
String m_remoteIp;
|
||||||
int m_remotePort;
|
int m_remotePort;
|
||||||
int m_remotePayload;
|
int m_remotePayload;
|
||||||
|
const char* m_payloads;
|
||||||
// Synchronous transaction data
|
// Synchronous transaction data
|
||||||
MGCPTransaction* m_tr;
|
MGCPTransaction* m_tr;
|
||||||
RefPointer<MGCPMessage> m_msg;
|
RefPointer<MGCPMessage> m_msg;
|
||||||
|
@ -219,6 +226,8 @@ public:
|
||||||
|
|
||||||
YSIGFACTORY2(MGCPSpan);
|
YSIGFACTORY2(MGCPSpan);
|
||||||
|
|
||||||
|
static const char* s_payloads = "0 8";
|
||||||
|
|
||||||
static YMGCPEngine* s_engine = 0;
|
static YMGCPEngine* s_engine = 0;
|
||||||
static MGCPEndpoint* s_endpoint = 0;
|
static MGCPEndpoint* s_endpoint = 0;
|
||||||
static String s_defaultEp;
|
static String s_defaultEp;
|
||||||
|
@ -244,23 +253,15 @@ static bool copyRename(NamedList& dest, const char* dname, const NamedList& src,
|
||||||
// Increment the number at the end of a name by an offset
|
// Increment the number at the end of a name by an offset
|
||||||
static bool increment(String& name, unsigned int offs)
|
static bool increment(String& name, unsigned int offs)
|
||||||
{
|
{
|
||||||
unsigned int i = name.length();
|
Regexp r("\\([0-9]\\+\\)@");
|
||||||
while (i--) {
|
if (name.matches(r)) {
|
||||||
char c = name.at(i);
|
int pos = name.matchOffset(1);
|
||||||
if ((c < '0') || (c > '9'))
|
unsigned int len = name.matchLength(1);
|
||||||
return false;
|
String num(offs + name.matchString(1).toInteger(0,10));
|
||||||
int d = offs % 10;
|
while (num.length() < len)
|
||||||
offs /= 10;
|
num = "0" + num;
|
||||||
if (d) {
|
name = name.substr(0,pos) + num + name.substr(pos + len);
|
||||||
c += d;
|
return true;
|
||||||
if (c > '9') {
|
|
||||||
c -= 10;
|
|
||||||
offs++;
|
|
||||||
}
|
|
||||||
const_cast<char*>(name.c_str())[i] = c;
|
|
||||||
}
|
|
||||||
if (0 == offs)
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -708,7 +709,7 @@ MGCPSpan* MGCPSpan::findNotify(const String& id)
|
||||||
MGCPSpan::MGCPSpan(const NamedList& params, const char* name, const MGCPEpInfo& ep)
|
MGCPSpan::MGCPSpan(const NamedList& params, const char* name, const MGCPEpInfo& ep)
|
||||||
: SignallingCircuitSpan(params.getValue("debugname",name),
|
: SignallingCircuitSpan(params.getValue("debugname",name),
|
||||||
static_cast<SignallingCircuitGroup*>(params.getObject("SignallingCircuitGroup"))),
|
static_cast<SignallingCircuitGroup*>(params.getObject("SignallingCircuitGroup"))),
|
||||||
m_circuits(0), m_count(1), m_epId(ep), m_operational(false),
|
m_circuits(0), m_count(0), m_epId(ep), m_operational(false),
|
||||||
m_fxo(false), m_fxs(false)
|
m_fxo(false), m_fxs(false)
|
||||||
{
|
{
|
||||||
Debug(&splugin,DebugAll,"MGCPSpan::MGCPSpan(%p,'%s') [%p]",
|
Debug(&splugin,DebugAll,"MGCPSpan::MGCPSpan(%p,'%s') [%p]",
|
||||||
|
@ -759,9 +760,19 @@ void MGCPSpan::clearCircuits()
|
||||||
bool MGCPSpan::init(const NamedList& params)
|
bool MGCPSpan::init(const NamedList& params)
|
||||||
{
|
{
|
||||||
clearCircuits();
|
clearCircuits();
|
||||||
|
const String* sect = params.getParam("voice");
|
||||||
int cicStart = params.getIntValue("start");
|
int cicStart = params.getIntValue("start");
|
||||||
if (cicStart < 0)
|
if ((cicStart < 0) || !sect)
|
||||||
return false;
|
return false;
|
||||||
|
Configuration cfg(Engine::configFile("mgcpca"));
|
||||||
|
const NamedList* config = cfg.getSection("gw " + *sect);
|
||||||
|
if (!config) {
|
||||||
|
Debug(m_group,DebugWarn,"MGCPSpan('%s'). Failed to find config section [%p]",
|
||||||
|
id().safe(),this);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_count = config->getIntValue("chans",1);
|
||||||
|
cicStart += config->getIntValue("offset");
|
||||||
|
|
||||||
if (!m_count)
|
if (!m_count)
|
||||||
return false;
|
return false;
|
||||||
|
@ -803,6 +814,13 @@ void MGCPSpan::operational(bool active)
|
||||||
Debug(&splugin,DebugCall,"MGCPSpan '%s' is%s operational [%p]",
|
Debug(&splugin,DebugCall,"MGCPSpan '%s' is%s operational [%p]",
|
||||||
id().c_str(),(active ? "" : " not"),this);
|
id().c_str(),(active ? "" : " not"),this);
|
||||||
m_operational = active;
|
m_operational = active;
|
||||||
|
if (!m_circuits)
|
||||||
|
return;
|
||||||
|
for (unsigned int i = 0; i < m_count; i++) {
|
||||||
|
MGCPCircuit* circuit = m_circuits[i];
|
||||||
|
if (circuit)
|
||||||
|
circuit->status((active ? SignallingCircuit::Idle : SignallingCircuit::Missing),true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the operational state and copy GW address
|
// Set the operational state and copy GW address
|
||||||
|
@ -810,6 +828,9 @@ void MGCPSpan::operational(const SocketAddr& address)
|
||||||
{
|
{
|
||||||
if (address.valid() && address.host())
|
if (address.valid() && address.host())
|
||||||
m_address = address.host();
|
m_address = address.host();
|
||||||
|
MGCPEpInfo* ep = s_endpoint->find(epId().id());
|
||||||
|
if (ep && !(m_operational && ep->address.valid()))
|
||||||
|
ep->address = address;
|
||||||
operational(true);
|
operational(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -923,6 +944,11 @@ bool MGCPSpan::processRestart(MGCPTransaction* tr, MGCPMessage* mm, const String
|
||||||
DDebug(&splugin,DebugInfo,"MGCPSpan::processRestart(%p,%p,'%s') [%p]",
|
DDebug(&splugin,DebugInfo,"MGCPSpan::processRestart(%p,%p,'%s') [%p]",
|
||||||
tr,mm,method.c_str(),this);
|
tr,mm,method.c_str(),this);
|
||||||
if ((method &= "X-KeepAlive") || (method &= "disconnected") || (method &= "restart")) {
|
if ((method &= "X-KeepAlive") || (method &= "disconnected") || (method &= "restart")) {
|
||||||
|
if (m_version.null()) {
|
||||||
|
m_version = mm->version();
|
||||||
|
Debug(&splugin,DebugNote,"MGCPSpan '%s' using version '%s' [%p]",
|
||||||
|
id().c_str(),m_version.c_str(),this);
|
||||||
|
}
|
||||||
operational(tr->addr());
|
operational(tr->addr());
|
||||||
}
|
}
|
||||||
else if (method &= "graceful")
|
else if (method &= "graceful")
|
||||||
|
@ -939,7 +965,9 @@ bool MGCPSpan::processRestart(MGCPTransaction* tr, MGCPMessage* mm, const String
|
||||||
MGCPCircuit::MGCPCircuit(unsigned int code, MGCPSpan* span, const char* id)
|
MGCPCircuit::MGCPCircuit(unsigned int code, MGCPSpan* span, const char* id)
|
||||||
: SignallingCircuit(RTP,code,Missing,span->group(),span),
|
: SignallingCircuit(RTP,code,Missing,span->group(),span),
|
||||||
m_epId(id), m_statusReq(Missing),
|
m_epId(id), m_statusReq(Missing),
|
||||||
m_localPort(0), m_remotePort(0), m_remotePayload(-1), m_tr(0)
|
m_localPort(0), m_sdpSession(0), m_sdpVersion(0),
|
||||||
|
m_remotePort(0), m_remotePayload(-1),
|
||||||
|
m_payloads(s_payloads), m_tr(0)
|
||||||
{
|
{
|
||||||
Debug(&splugin,DebugAll,"MGCPCircuit::MGCPCircuit(%u,%p,'%s') [%p]",
|
Debug(&splugin,DebugAll,"MGCPCircuit::MGCPCircuit(%u,%p,'%s') [%p]",
|
||||||
code,span,id,this);
|
code,span,id,this);
|
||||||
|
@ -967,7 +995,7 @@ MGCPCircuit::~MGCPCircuit()
|
||||||
|
|
||||||
void* MGCPCircuit::getObject(const String& name) const
|
void* MGCPCircuit::getObject(const String& name) const
|
||||||
{
|
{
|
||||||
if (SignallingCircuit::status() == Connected) {
|
if (connected()) {
|
||||||
if (name == "DataSource")
|
if (name == "DataSource")
|
||||||
return m_source;
|
return m_source;
|
||||||
if (name == "DataConsumer")
|
if (name == "DataConsumer")
|
||||||
|
@ -1054,11 +1082,18 @@ bool MGCPCircuit::setupConn()
|
||||||
if (m_connId)
|
if (m_connId)
|
||||||
mm->params.addParam("I",m_connId);
|
mm->params.addParam("I",m_connId);
|
||||||
if (m_localIp && m_localPort) {
|
if (m_localIp && m_localPort) {
|
||||||
|
mm->params.addParam("M","sendrecv");
|
||||||
|
if (m_sdpSession)
|
||||||
|
++m_sdpVersion;
|
||||||
|
else
|
||||||
|
m_sdpSession = m_sdpVersion = Time::secNow();
|
||||||
String mLine("audio ");
|
String mLine("audio ");
|
||||||
mLine << m_localPort << " RTP/AVP 0 8";
|
String oLine("yate ");
|
||||||
|
mLine << m_localPort << " RTP/AVP " << m_payloads;
|
||||||
|
oLine << m_sdpSession << " " << m_sdpVersion << " IN IP4 " << m_localIp;
|
||||||
MimeSdpBody* sdp = new MimeSdpBody;
|
MimeSdpBody* sdp = new MimeSdpBody;
|
||||||
sdp->addLine("v","0");
|
sdp->addLine("v","0");
|
||||||
sdp->addLine("o",m_localIp);
|
sdp->addLine("o",oLine);
|
||||||
sdp->addLine("s","PSTN Circuit");
|
sdp->addLine("s","PSTN Circuit");
|
||||||
sdp->addLine("c","IN IP4 " + m_localIp);
|
sdp->addLine("c","IN IP4 " + m_localIp);
|
||||||
sdp->addLine("t","0 0");
|
sdp->addLine("t","0 0");
|
||||||
|
@ -1114,13 +1149,14 @@ void MGCPCircuit::clearConn()
|
||||||
m_connId.clear();
|
m_connId.clear();
|
||||||
m_remoteIp.clear();
|
m_remoteIp.clear();
|
||||||
m_remotePort = 0;
|
m_remotePort = 0;
|
||||||
|
m_sdpSession = 0;
|
||||||
sendAsync(mm);
|
sendAsync(mm);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build a MGCP message
|
// Build a MGCP message
|
||||||
MGCPMessage* MGCPCircuit::message(const char* cmd)
|
MGCPMessage* MGCPCircuit::message(const char* cmd)
|
||||||
{
|
{
|
||||||
return new MGCPMessage(s_engine,cmd,epId());
|
return new MGCPMessage(s_engine,cmd,epId(),mySpan()->version());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send a MGCP message asynchronously
|
// Send a MGCP message asynchronously
|
||||||
|
@ -1198,6 +1234,7 @@ bool MGCPCircuit::status(Status newStat, bool sync)
|
||||||
m_statusReq = SignallingCircuit::status();
|
m_statusReq = SignallingCircuit::status();
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
|
m_payloads = s_payloads;
|
||||||
cleanupRtp();
|
cleanupRtp();
|
||||||
clearConn();
|
clearConn();
|
||||||
}
|
}
|
||||||
|
@ -1209,9 +1246,15 @@ bool MGCPCircuit::updateFormat(const char* format, int direction)
|
||||||
{
|
{
|
||||||
if (!format)
|
if (!format)
|
||||||
return false;
|
return false;
|
||||||
Debug(&splugin,DebugStub,"MGCPCircuit::updateFormat('%s',%d) %u [%p]",
|
Debug(&splugin,DebugInfo,"MGCPCircuit::updateFormat('%s',%d) %u [%p]",
|
||||||
format,direction,code(),this);
|
format,direction,code(),this);
|
||||||
return false;
|
if (0 == ::strcmp(format,"mulaw"))
|
||||||
|
m_payloads = "0";
|
||||||
|
else if (0 == ::strcmp(format,"alaw"))
|
||||||
|
m_payloads = "8";
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send out an event on this circuit
|
// Send out an event on this circuit
|
||||||
|
|
Loading…
Reference in New Issue