Fixed endpoint incrementation algorithm and circuit creation.

Fixed MGCP connection and SDP creation.
Detect protocol version from RSIP message.


git-svn-id: http://yate.null.ro/svn/yate/trunk@2595 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
paulc 2009-04-24 17:36:25 +00:00
parent 725a105827
commit 5040465935
2 changed files with 75 additions and 26 deletions

View File

@ -54,3 +54,9 @@
; The first gateway which is not explicitely disabled or the last that is
; explicitely enabled will become default
;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

View File

@ -29,6 +29,7 @@
#include <yatesig.h>
#include <stdlib.h>
#include <string.h>
using namespace TelEngine;
namespace { // anonymous
@ -102,6 +103,8 @@ public:
{ return m_operational; }
inline const String& address() const
{ return m_address; }
inline const char* version() const
{ return m_version.null() ? m_version.c_str() : "MGCP 1.0"; }
inline bool fxo() const
{ return m_fxo; }
inline bool fxs() const
@ -127,6 +130,7 @@ private:
bool m_fxs;
String m_notify;
String m_address;
String m_version;
};
class MGCPCircuit : public SignallingCircuit
@ -177,10 +181,13 @@ private:
String m_rtpId;
String m_localIp;
int m_localPort;
int m_sdpSession;
int m_sdpVersion;
// Remote (MGCP GW side) RTP data
String m_remoteIp;
int m_remotePort;
int m_remotePayload;
const char* m_payloads;
// Synchronous transaction data
MGCPTransaction* m_tr;
RefPointer<MGCPMessage> m_msg;
@ -219,6 +226,8 @@ public:
YSIGFACTORY2(MGCPSpan);
static const char* s_payloads = "0 8";
static YMGCPEngine* s_engine = 0;
static MGCPEndpoint* s_endpoint = 0;
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
static bool increment(String& name, unsigned int offs)
{
unsigned int i = name.length();
while (i--) {
char c = name.at(i);
if ((c < '0') || (c > '9'))
return false;
int d = offs % 10;
offs /= 10;
if (d) {
c += d;
if (c > '9') {
c -= 10;
offs++;
}
const_cast<char*>(name.c_str())[i] = c;
}
if (0 == offs)
return true;
Regexp r("\\([0-9]\\+\\)@");
if (name.matches(r)) {
int pos = name.matchOffset(1);
unsigned int len = name.matchLength(1);
String num(offs + name.matchString(1).toInteger(0,10));
while (num.length() < len)
num = "0" + num;
name = name.substr(0,pos) + num + name.substr(pos + len);
return true;
}
return false;
}
@ -708,7 +709,7 @@ MGCPSpan* MGCPSpan::findNotify(const String& id)
MGCPSpan::MGCPSpan(const NamedList& params, const char* name, const MGCPEpInfo& ep)
: SignallingCircuitSpan(params.getValue("debugname",name),
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)
{
Debug(&splugin,DebugAll,"MGCPSpan::MGCPSpan(%p,'%s') [%p]",
@ -759,9 +760,19 @@ void MGCPSpan::clearCircuits()
bool MGCPSpan::init(const NamedList& params)
{
clearCircuits();
const String* sect = params.getParam("voice");
int cicStart = params.getIntValue("start");
if (cicStart < 0)
if ((cicStart < 0) || !sect)
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)
return false;
@ -803,6 +814,13 @@ void MGCPSpan::operational(bool active)
Debug(&splugin,DebugCall,"MGCPSpan '%s' is%s operational [%p]",
id().c_str(),(active ? "" : " not"),this);
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
@ -810,6 +828,9 @@ void MGCPSpan::operational(const SocketAddr& address)
{
if (address.valid() && 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);
}
@ -923,6 +944,11 @@ bool MGCPSpan::processRestart(MGCPTransaction* tr, MGCPMessage* mm, const String
DDebug(&splugin,DebugInfo,"MGCPSpan::processRestart(%p,%p,'%s') [%p]",
tr,mm,method.c_str(),this);
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());
}
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)
: SignallingCircuit(RTP,code,Missing,span->group(),span),
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]",
code,span,id,this);
@ -967,7 +995,7 @@ MGCPCircuit::~MGCPCircuit()
void* MGCPCircuit::getObject(const String& name) const
{
if (SignallingCircuit::status() == Connected) {
if (connected()) {
if (name == "DataSource")
return m_source;
if (name == "DataConsumer")
@ -1054,11 +1082,18 @@ bool MGCPCircuit::setupConn()
if (m_connId)
mm->params.addParam("I",m_connId);
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 ");
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;
sdp->addLine("v","0");
sdp->addLine("o",m_localIp);
sdp->addLine("o",oLine);
sdp->addLine("s","PSTN Circuit");
sdp->addLine("c","IN IP4 " + m_localIp);
sdp->addLine("t","0 0");
@ -1114,13 +1149,14 @@ void MGCPCircuit::clearConn()
m_connId.clear();
m_remoteIp.clear();
m_remotePort = 0;
m_sdpSession = 0;
sendAsync(mm);
}
// Build a MGCP message
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
@ -1198,6 +1234,7 @@ bool MGCPCircuit::status(Status newStat, bool sync)
m_statusReq = SignallingCircuit::status();
return false;
default:
m_payloads = s_payloads;
cleanupRtp();
clearConn();
}
@ -1209,9 +1246,15 @@ bool MGCPCircuit::updateFormat(const char* format, int direction)
{
if (!format)
return false;
Debug(&splugin,DebugStub,"MGCPCircuit::updateFormat('%s',%d) %u [%p]",
Debug(&splugin,DebugInfo,"MGCPCircuit::updateFormat('%s',%d) %u [%p]",
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