Fixed bug: avoid leaking incoming registration transactions. Improved debug.
git-svn-id: http://yate.null.ro/svn/yate/trunk@5512 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
a5385c2f47
commit
e3b028dfa3
|
@ -150,27 +150,27 @@ IAXTransaction* IAXEngine::addFrame(const SocketAddr& addr, IAXFrame* frame)
|
|||
{
|
||||
if (!frame)
|
||||
return 0;
|
||||
IAXTransaction* tr;
|
||||
ObjList* l;
|
||||
IAXTransaction* tr = 0;
|
||||
ObjList* l = 0;
|
||||
Lock lock(this);
|
||||
// Transaction exists for this frame?
|
||||
// Incomplete transactions. They MUST receive a full frame
|
||||
IAXFullFrame* fullFrame = frame->fullFrame();
|
||||
if (fullFrame) {
|
||||
// Incomplete transactions. They MUST receive a full frame with destination call number set
|
||||
IAXFullFrame* full = frame->fullFrame();
|
||||
if (full && full->destCallNo()) {
|
||||
l = m_incompleteTransList.skipNull();
|
||||
for (; l; l = l->next()) {
|
||||
tr = static_cast<IAXTransaction*>(l->get());
|
||||
if (!(tr && tr->localCallNo() == fullFrame->destCallNo() && addr == tr->remoteAddr()))
|
||||
if (!(tr && tr->localCallNo() == full->destCallNo() && addr == tr->remoteAddr()))
|
||||
continue;
|
||||
// Incomplete outgoing receiving call token
|
||||
if (fullFrame->type() == IAXFrame::IAX &&
|
||||
fullFrame->subclass() == IAXControl::CallToken) {
|
||||
if (full->type() == IAXFrame::IAX &&
|
||||
full->subclass() == IAXControl::CallToken) {
|
||||
RefPointer<IAXTransaction> t = tr;
|
||||
lock.drop();
|
||||
if (!t)
|
||||
return 0;
|
||||
fullFrame->updateIEList(true);
|
||||
IAXIEList* list = fullFrame->ieList();
|
||||
full->updateIEList(true);
|
||||
IAXIEList* list = full->ieList();
|
||||
DataBlock db;
|
||||
if (list)
|
||||
list->getBinary(IAXInfoElement::CALLTOKEN,db);
|
||||
|
@ -192,12 +192,14 @@ IAXTransaction* IAXEngine::addFrame(const SocketAddr& addr, IAXFrame* frame)
|
|||
}
|
||||
// Complete transactions
|
||||
l = m_transList[frame->sourceCallNo() % m_transListCount];
|
||||
for (; l; l = l->next()) {
|
||||
if (l)
|
||||
l = l->skipNull();
|
||||
for (; l; l = l->skipNext()) {
|
||||
tr = static_cast<IAXTransaction*>(l->get());
|
||||
if (!(tr && tr->remoteCallNo() == frame->sourceCallNo()))
|
||||
if (tr->remoteCallNo() != frame->sourceCallNo())
|
||||
continue;
|
||||
// Mini frame
|
||||
if (!fullFrame) {
|
||||
if (!full) {
|
||||
if (addr == tr->remoteAddr()) {
|
||||
// keep transaction referenced but unlock the engine
|
||||
RefPointer<IAXTransaction> t = tr;
|
||||
|
@ -208,7 +210,7 @@ IAXTransaction* IAXEngine::addFrame(const SocketAddr& addr, IAXFrame* frame)
|
|||
}
|
||||
// Full frame
|
||||
// Has a local number assigned? If not, test socket
|
||||
if (fullFrame->destCallNo() || addr == tr->remoteAddr()) {
|
||||
if (full->destCallNo() || addr == tr->remoteAddr()) {
|
||||
// keep transaction referenced but unlock the engine
|
||||
RefPointer<IAXTransaction> t = tr;
|
||||
lock.drop();
|
||||
|
@ -217,11 +219,11 @@ IAXTransaction* IAXEngine::addFrame(const SocketAddr& addr, IAXFrame* frame)
|
|||
}
|
||||
// Frame doesn't belong to an existing transaction
|
||||
// Test if it is a full frame with an IAX control message that needs a new transaction
|
||||
if (!fullFrame || frame->type() != IAXFrame::IAX)
|
||||
if (!full || frame->type() != IAXFrame::IAX)
|
||||
return 0;
|
||||
switch (fullFrame->subclass()) {
|
||||
switch (full->subclass()) {
|
||||
case IAXControl::New:
|
||||
if (!checkCallToken(addr,*fullFrame))
|
||||
if (!checkCallToken(addr,*full))
|
||||
return 0;
|
||||
case IAXControl::RegReq:
|
||||
case IAXControl::RegRel:
|
||||
|
@ -234,28 +236,29 @@ IAXTransaction* IAXEngine::addFrame(const SocketAddr& addr, IAXFrame* frame)
|
|||
// These are often used as keepalives
|
||||
return 0;
|
||||
default:
|
||||
if (fullFrame) {
|
||||
if (fullFrame->destCallNo() == 0)
|
||||
Debug(this,DebugAll,"Unsupported incoming transaction Frame(%u,%u). Source call no: %u",
|
||||
frame->type(),fullFrame->subclass(),fullFrame->sourceCallNo());
|
||||
else
|
||||
Debug(this,DebugAll,"Unmatched Frame(%u,%u) for (%u,%u)",
|
||||
frame->type(),fullFrame->subclass(),fullFrame->destCallNo(),fullFrame->sourceCallNo());
|
||||
|
||||
sendInval(fullFrame,addr);
|
||||
}
|
||||
if (full->destCallNo() == 0)
|
||||
Debug(this,DebugAll,
|
||||
"Unsupported incoming transaction Frame(%u,%u). Source call no: %u",
|
||||
frame->type(),full->subclass(),full->sourceCallNo());
|
||||
else
|
||||
Debug(this,DebugAll,"Unmatched Frame(%u,%u) for (%u,%u)",
|
||||
frame->type(),full->subclass(),full->destCallNo(),full->sourceCallNo());
|
||||
sendInval(full,addr);
|
||||
return 0;
|
||||
}
|
||||
// Generate local number
|
||||
u_int16_t lcn = generateCallNo();
|
||||
if (!lcn)
|
||||
return 0;
|
||||
// Create and add transaction
|
||||
tr = IAXTransaction::factoryIn(this,fullFrame,lcn,addr);
|
||||
if (tr)
|
||||
m_transList[frame->sourceCallNo() % m_transListCount]->append(tr);
|
||||
else
|
||||
releaseCallNo(lcn);
|
||||
if (lcn) {
|
||||
// Create and add transaction
|
||||
tr = IAXTransaction::factoryIn(this,full,lcn,addr);
|
||||
if (tr)
|
||||
m_transList[frame->sourceCallNo() % m_transListCount]->append(tr);
|
||||
else
|
||||
releaseCallNo(lcn);
|
||||
}
|
||||
if (!tr)
|
||||
Debug(this,DebugInfo,"Failed to build incoming transaction for Frame(%u,%u)",
|
||||
frame->type(),full->subclass());
|
||||
return tr;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,15 @@
|
|||
|
||||
using namespace TelEngine;
|
||||
|
||||
const TokenDict IAXTransaction::s_typeName[] = {
|
||||
{"New", New},
|
||||
{"RegReq", RegReq},
|
||||
{"RegRel", RegRel},
|
||||
{"Poke", Poke},
|
||||
{"Incorrect", Incorrect},
|
||||
{0,0},
|
||||
};
|
||||
|
||||
String IAXTransaction::s_iax_modNoAuthMethod("Unsupported or missing authentication method or missing challenge");
|
||||
String IAXTransaction::s_iax_modNoMediaFormat("Unsupported or missing media format or capability");
|
||||
String IAXTransaction::s_iax_modInvalidAuth("Invalid authentication request, response or challenge");
|
||||
|
@ -34,6 +43,11 @@ String IAXTransaction::s_iax_modNoUsername("Username is missing");
|
|||
|
||||
unsigned char IAXTransaction::m_maxInFrames = 100;
|
||||
|
||||
static inline bool canUpdLastAckSeq(u_int32_t seq, u_int32_t last)
|
||||
{
|
||||
int32_t interval = (int32_t)seq - last;
|
||||
return (interval <= 32767 && interval > 0) || interval <= -32767;
|
||||
}
|
||||
|
||||
// Print statistics
|
||||
void IAXMediaData::print(String& buf)
|
||||
|
@ -83,8 +97,6 @@ IAXTransaction::IAXTransaction(IAXEngine* engine, IAXFullFrame* frame, u_int16_t
|
|||
m_trunkFrame(0),
|
||||
m_trunkInOffsetTimeMs(0), m_trunkInLastTs(0), m_warnTrunkInTimestamp(true)
|
||||
{
|
||||
Debug(m_engine,DebugAll,"Transaction(%u,%u) incoming type=%u remote=%s:%d [%p]",
|
||||
localCallNo(),remoteCallNo(),m_type,m_addr.host().c_str(),m_addr.port(),this);
|
||||
// Setup transaction
|
||||
m_retransCount = engine->retransCount();
|
||||
m_retransInterval = engine->retransInterval();
|
||||
|
@ -107,6 +119,8 @@ IAXTransaction::IAXTransaction(IAXEngine* engine, IAXFullFrame* frame, u_int16_t
|
|||
localCallNo(),remoteCallNo(),frame->subclass(),this);
|
||||
return;
|
||||
}
|
||||
Debug(m_engine,DebugAll,"Transaction(%u,%u) incoming type=%s remote=%s:%d [%p]",
|
||||
localCallNo(),remoteCallNo(),typeName(),m_addr.host().c_str(),m_addr.port(),this);
|
||||
engine->getOutDataAdjust(m_adjustTsOutThreshold,m_adjustTsOutOverrun,
|
||||
m_adjustTsOutUnderrun);
|
||||
// Append frame to incoming list
|
||||
|
@ -152,8 +166,8 @@ IAXTransaction::IAXTransaction(IAXEngine* engine, Type type, u_int16_t lcallno,
|
|||
m_trunkFrame(0),
|
||||
m_trunkInOffsetTimeMs(0), m_trunkInLastTs(0), m_warnTrunkInTimestamp(true)
|
||||
{
|
||||
Debug(m_engine,DebugAll,"Transaction(%u,%u) outgoing type=%u remote=%s:%d [%p]",
|
||||
localCallNo(),remoteCallNo(),m_type,m_addr.host().c_str(),m_addr.port(),this);
|
||||
Debug(m_engine,DebugAll,"Transaction(%u,%u) outgoing type=%s remote=%s:%d [%p]",
|
||||
localCallNo(),remoteCallNo(),typeName(),m_addr.host().c_str(),m_addr.port(),this);
|
||||
// Init data members
|
||||
if (!m_addr.port()) {
|
||||
XDebug(m_engine,DebugAll,
|
||||
|
@ -238,18 +252,23 @@ IAXTransaction* IAXTransaction::processFrame(IAXFrame* frame)
|
|||
sendInval();
|
||||
return 0;
|
||||
}
|
||||
IAXFullFrame* full = frame->fullFrame();
|
||||
if (state() == Terminating) {
|
||||
// Local terminate: Accept only Ack. Remote terminate: Accept none.
|
||||
if (m_localReqEnd && frame->fullFrame()) {
|
||||
if (!(frame->type() == IAXFrame::IAX && (frame->fullFrame()->subclass() == IAXControl::Ack ||
|
||||
frame->fullFrame()->subclass() == IAXControl::Inval || frame->fullFrame()->subclass() == IAXControl::VNAK)))
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
bool ok = false;
|
||||
if (m_localReqEnd && full)
|
||||
ok = frame->type() == IAXFrame::IAX && (full->subclass() == IAXControl::Ack ||
|
||||
full->subclass() == IAXControl::Inval || full->subclass() == IAXControl::VNAK);
|
||||
if (!ok) {
|
||||
if (full)
|
||||
Debug(m_engine,DebugAll,
|
||||
"Transaction(%u,%u) dropping Frame(%u,%u): terminating [%p]",
|
||||
localCallNo(),remoteCallNo(),frame->type(),full->subclass(),this);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// Mini frame
|
||||
if (!frame->fullFrame()) {
|
||||
if (!full) {
|
||||
int t = 0;
|
||||
if (frame->type() == IAXFrame::Voice)
|
||||
t = IAXFormat::Audio;
|
||||
|
@ -262,8 +281,8 @@ IAXTransaction* IAXTransaction::processFrame(IAXFrame* frame)
|
|||
Lock lock(this);
|
||||
m_inTotalFramesCount++;
|
||||
// Frame is VNAK ?
|
||||
if (frame->type() == IAXFrame::IAX && frame->fullFrame()->subclass() == IAXControl::VNAK)
|
||||
return retransmitOnVNAK(frame->fullFrame()->iSeqNo());
|
||||
if (frame->type() == IAXFrame::IAX && full->subclass() == IAXControl::VNAK)
|
||||
return retransmitOnVNAK(full->iSeqNo());
|
||||
// Do we have enough space to keep this frame ?
|
||||
if (m_inFrames.count() == m_maxInFrames) {
|
||||
Debug(m_engine,DebugWarn,"Transaction(%u,%u). processFrame. Buffer overrun! (MAX=%u)",
|
||||
|
@ -272,8 +291,8 @@ IAXTransaction* IAXTransaction::processFrame(IAXFrame* frame)
|
|||
return 0;
|
||||
}
|
||||
bool fAck = frame->type() == IAXFrame::IAX &&
|
||||
(frame->fullFrame()->subclass() == IAXControl::Ack || frame->fullFrame()->subclass() == IAXControl::Inval);
|
||||
if (!fAck && !isFrameAcceptable(frame->fullFrame()))
|
||||
(full->subclass() == IAXControl::Ack || full->subclass() == IAXControl::Inval);
|
||||
if (!fAck && !isFrameAcceptable(full))
|
||||
return 0;
|
||||
// Video/Voice full frame: process data & format
|
||||
if (type() == New && (frame->type() == IAXFrame::Voice ||
|
||||
|
@ -281,14 +300,14 @@ IAXTransaction* IAXTransaction::processFrame(IAXFrame* frame)
|
|||
int t = IAXFormat::Audio;
|
||||
if (frame->type() == IAXFrame::Video)
|
||||
t = IAXFormat::Video;
|
||||
if (!processMediaFrame(frame->fullFrame(),t))
|
||||
if (!processMediaFrame(full,t))
|
||||
return 0;
|
||||
// Frame accepted: process voice data
|
||||
lock.drop();
|
||||
return processMedia(frame->data(),frame->timeStamp(),t,true,frame->mark());
|
||||
}
|
||||
// Process incoming Ping
|
||||
if (frame->type() == IAXFrame::IAX && frame->fullFrame()->subclass() == IAXControl::Ping) {
|
||||
if (frame->type() == IAXFrame::IAX && full->subclass() == IAXControl::Ping) {
|
||||
DDebug(m_engine,DebugAll,"Transaction(%u,%u) received Ping iseq=%u oseq=%u stamp=%u [%p]",
|
||||
localCallNo(),remoteCallNo(),frame->fullFrame()->iSeqNo(),frame->fullFrame()->oSeqNo(),
|
||||
frame->timeStamp(),this);
|
||||
|
@ -297,9 +316,10 @@ IAXTransaction* IAXTransaction::processFrame(IAXFrame* frame)
|
|||
}
|
||||
// Append frame to incoming frame list
|
||||
m_inFrames.append(frame);
|
||||
DDebug(m_engine,DebugAll,"Transaction(%u,%u) enqueued Frame(%u,%u) iseq=%u oseq=%u stamp=%u [%p]",
|
||||
localCallNo(),remoteCallNo(),frame->type(),frame->fullFrame()->subclass(),
|
||||
frame->fullFrame()->iSeqNo(),frame->fullFrame()->oSeqNo(),frame->timeStamp(),this);
|
||||
Debug(m_engine,DebugAll,
|
||||
"Transaction(%u,%u) enqueued Frame(%u,%u) iseq=%u oseq=%u stamp=%u [%p]",
|
||||
localCallNo(),remoteCallNo(),frame->type(),full->subclass(),
|
||||
full->iSeqNo(),full->oSeqNo(),frame->timeStamp(),this);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -655,20 +675,27 @@ IAXEvent* IAXTransaction::getEvent(u_int64_t time)
|
|||
if (ev)
|
||||
return keepEvent(ev);
|
||||
// Process incoming frames
|
||||
ListIterator lin(m_inFrames);
|
||||
for (; (obj = lin.get());) {
|
||||
IAXFullFrame* frame = static_cast<IAXFullFrame*>(obj);
|
||||
for (ObjList* o = m_inFrames.skipNull(); o; o = (delFrame ? o->skipNull() : o->skipNext())) {
|
||||
delFrame = false;
|
||||
IAXFullFrame* frame = static_cast<IAXFullFrame*>(o->get());
|
||||
// If frame is ACK, ignore it
|
||||
if (frame->type() == IAXFrame::IAX && frame->subclass() == IAXControl::Ack)
|
||||
continue;
|
||||
DDebug(m_engine,DebugAll,"Transaction(%u,%u) dequeued Frame(%u,%u) iseq=%u oseq=%u stamp=%u [%p]",
|
||||
localCallNo(),remoteCallNo(),frame->type(),frame->subclass(),frame->iSeqNo(),frame->oSeqNo(),frame->timeStamp(),this);
|
||||
DDebug(m_engine,DebugAll,
|
||||
"Transaction(%u,%u) processing Frame(%u,%u) iseq=%u oseq=%u stamp=%u [%p]",
|
||||
localCallNo(),remoteCallNo(),frame->type(),frame->subclass(),frame->iSeqNo(),
|
||||
frame->oSeqNo(),frame->timeStamp(),this);
|
||||
if (m_state == IAXTransaction::Unknown)
|
||||
ev = getEventStartTrans(frame,delFrame); // New transaction
|
||||
else
|
||||
ev = getEventRequest(frame,delFrame);
|
||||
if (delFrame)
|
||||
m_inFrames.remove(frame,true); // frame is no longer needded
|
||||
if (delFrame) {
|
||||
Debug(m_engine,DebugAll,
|
||||
"Transaction(%u,%u) removing incoming Frame(%u,%u) iseq=%u oseq=%u stamp=%u [%p]",
|
||||
localCallNo(),remoteCallNo(),frame->type(),frame->subclass(),
|
||||
frame->iSeqNo(),frame->oSeqNo(),frame->timeStamp(),this);
|
||||
o->remove();
|
||||
}
|
||||
if (ev)
|
||||
return keepEvent(ev);
|
||||
}
|
||||
|
@ -1231,8 +1258,19 @@ IAXEvent* IAXTransaction::getEventResponse(IAXFrameOut* frame, bool& delFrame)
|
|||
if (findInFrameAck(frame)) {
|
||||
frame->setAck();
|
||||
// Terminating frame sent
|
||||
if (m_state == Terminating && frame->type() == IAXFrame::IAX && frame->subclass() == IAXControl::Hangup)
|
||||
return terminate(IAXEvent::Terminated,true);
|
||||
if (m_state == Terminating) {
|
||||
if (frame->type() == IAXFrame::IAX && frame->subclass() == IAXControl::Hangup)
|
||||
return terminate(IAXEvent::Terminated,true);
|
||||
if (!outgoing()) {
|
||||
if (m_type == RegReq || m_type == RegRel) {
|
||||
if (frame->type() == IAXFrame::IAX) {
|
||||
if (frame->subclass() == IAXControl::RegAck ||
|
||||
frame->subclass() == IAXControl::RegRej)
|
||||
return terminate(IAXEvent::Terminated,true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Frame only need ACK
|
||||
if (frame->ackOnly())
|
||||
return 0;
|
||||
|
@ -1457,6 +1495,10 @@ IAXEvent* IAXTransaction::getEventStartTrans(IAXFullFrame* frame, bool& delFrame
|
|||
|
||||
IAXEvent* IAXTransaction::getEventRequest(IAXFullFrame* frame, bool& delFrame)
|
||||
{
|
||||
XDebug(m_engine,DebugAll,
|
||||
"Transaction(%u,%u) getEventRequest() frame %p (%u,%u) oseq: %u iseq: %u [%p]",
|
||||
localCallNo(),remoteCallNo(),frame,frame->type(),frame->subclass(),
|
||||
frame->oSeqNo(),frame->iSeqNo(),this);
|
||||
IAXEvent* ev;
|
||||
delFrame = true;
|
||||
// INVAL ?
|
||||
|
@ -1488,6 +1530,10 @@ IAXEvent* IAXTransaction::getEventRequest(IAXFullFrame* frame, bool& delFrame)
|
|||
|
||||
IAXEvent* IAXTransaction::getEventRequest_New(IAXFullFrame* frame, bool& delFrame)
|
||||
{
|
||||
XDebug(m_engine,DebugAll,
|
||||
"Transaction(%u,%u) getEventRequest_New() frame %p (%u,%u) oseq: %u iseq: %u [%p]",
|
||||
localCallNo(),remoteCallNo(),frame,frame->type(),frame->subclass(),
|
||||
frame->oSeqNo(),frame->iSeqNo(),this);
|
||||
IAXEvent* ev;
|
||||
delFrame = true;
|
||||
switch (m_state) {
|
||||
|
@ -1578,20 +1624,17 @@ bool IAXTransaction::findInFrameAck(const IAXFullFrame* frameOut)
|
|||
void IAXTransaction::ackInFrames()
|
||||
{
|
||||
IAXFullFrame* ack = 0;
|
||||
for (ObjList* l = m_inFrames.skipNull(); l; l = l->next()) {
|
||||
for (ObjList* l = m_inFrames.skipNull(); l; l = l->skipNext()) {
|
||||
IAXFullFrame* frame = static_cast<IAXFullFrame*>(l->get());
|
||||
if (frame && !(frame->type() == IAXFrame::IAX && (frame->subclass() == IAXControl::Ack || frame->subclass() == IAXControl::Inval
|
||||
|| frame->subclass() == IAXControl::LagRq || frame->subclass() == IAXControl::Ping)))
|
||||
if (ack && ack->oSeqNo() > frame->oSeqNo())
|
||||
continue;
|
||||
if (!(frame->type() == IAXFrame::IAX &&
|
||||
(frame->subclass() == IAXControl::Ack || frame->subclass() == IAXControl::Inval
|
||||
|| frame->subclass() == IAXControl::LagRq || frame->subclass() == IAXControl::Ping)))
|
||||
ack = frame;
|
||||
}
|
||||
if (ack) {
|
||||
int32_t interval = (int32_t)ack->oSeqNo() - m_lastAck;
|
||||
if (interval > 32767 || (interval > -32767 && interval <= 0))
|
||||
// Frame is older then the last ack'd
|
||||
return;
|
||||
m_lastAck = ack->oSeqNo();
|
||||
if (ack && canUpdLastAckSeq(ack->oSeqNo(),m_lastAck))
|
||||
sendAck(ack);
|
||||
}
|
||||
}
|
||||
|
||||
bool IAXTransaction::sendConnected(IAXFullFrame::ControlType subclass, IAXFrame::Type frametype)
|
||||
|
@ -1606,10 +1649,14 @@ void IAXTransaction::sendAck(const IAXFullFrame* frame)
|
|||
{
|
||||
if (!frame)
|
||||
return;
|
||||
if (canUpdLastAckSeq(frame->oSeqNo(),m_lastAck))
|
||||
m_lastAck = frame->oSeqNo();
|
||||
IAXFullFrame* f = new IAXFullFrame(IAXFrame::IAX,IAXControl::Ack,localCallNo(),
|
||||
remoteCallNo(),frame->iSeqNo(),m_iSeqNo,frame->timeStamp());
|
||||
DDebug(m_engine,DebugInfo,"Transaction(%u,%u). Send ACK for Frame(%u,%u) oseq: %u iseq: %u",
|
||||
localCallNo(),remoteCallNo(),frame->type(),frame->subclass(),frame->oSeqNo(),frame->iSeqNo());
|
||||
DDebug(m_engine,DebugInfo,
|
||||
"Transaction(%u,%u). Send ACK for Frame(%u,%u) oseq: %u iseq: %u [%p]",
|
||||
localCallNo(),remoteCallNo(),frame->type(),frame->subclass(),frame->oSeqNo(),
|
||||
frame->iSeqNo(),this);
|
||||
m_engine->writeSocket(f->data().data(),f->data().length(),remoteAddr(),f);
|
||||
f->deref();
|
||||
}
|
||||
|
@ -1661,22 +1708,32 @@ IAXEvent* IAXTransaction::processInternalOutgoingRequest(IAXFrameOut* frame, boo
|
|||
|
||||
IAXEvent* IAXTransaction::processInternalIncomingRequest(const IAXFullFrame* frame, bool& delFrame)
|
||||
{
|
||||
delFrame = false;
|
||||
if (frame->type() != IAXFrame::IAX)
|
||||
if (!frame)
|
||||
return 0;
|
||||
if (frame->subclass() == IAXControl::LagRq) {
|
||||
postFrame(IAXFrame::IAX,IAXControl::LagRp,0,0,frame->timeStamp(),true);
|
||||
delFrame = true;
|
||||
}
|
||||
if (frame->subclass() == IAXControl::Pong) {
|
||||
sendAck(frame);
|
||||
delFrame = true;
|
||||
delFrame = true;
|
||||
if (frame->type() == IAXFrame::IAX) {
|
||||
if (frame->subclass() == IAXControl::LagRq) {
|
||||
postFrame(IAXFrame::IAX,IAXControl::LagRp,0,0,frame->timeStamp(),true);
|
||||
return 0;
|
||||
}
|
||||
if (frame->subclass() == IAXControl::Pong) {
|
||||
sendAck(frame);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
Debug(m_engine,DebugAll,
|
||||
"Transaction(%u,%u) dropping unhandled Frame(%u,%u) oseq: %u iseq: %u [%p]",
|
||||
localCallNo(),remoteCallNo(),frame->type(),frame->subclass(),frame->oSeqNo(),
|
||||
frame->iSeqNo(),this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
IAXEvent* IAXTransaction::processMidCallControl(IAXFullFrame* frame, bool& delFrame)
|
||||
{
|
||||
XDebug(m_engine,DebugAll,
|
||||
"Transaction(%u,%u) processMidCallControl() frame %p (%u,%u) oseq: %u iseq: %u [%p]",
|
||||
localCallNo(),remoteCallNo(),frame,frame->type(),frame->subclass(),
|
||||
frame->oSeqNo(),frame->iSeqNo(),this);
|
||||
delFrame = true;
|
||||
switch (frame->subclass()) {
|
||||
case IAXFullFrame::Hangup:
|
||||
|
@ -1702,11 +1759,15 @@ IAXEvent* IAXTransaction::processMidCallControl(IAXFullFrame* frame, bool& delFr
|
|||
default: ;
|
||||
}
|
||||
delFrame = false;
|
||||
return 0;
|
||||
return processInternalIncomingRequest(frame,delFrame);
|
||||
}
|
||||
|
||||
IAXEvent* IAXTransaction::processMidCallIAXControl(IAXFullFrame* frame, bool& delFrame)
|
||||
{
|
||||
XDebug(m_engine,DebugAll,
|
||||
"Transaction(%u,%u) processMidCallIAXControl() frame %p (%u,%u) oseq: %u iseq: %u [%p]",
|
||||
localCallNo(),remoteCallNo(),frame,frame->type(),frame->subclass(),
|
||||
frame->oSeqNo(),frame->iSeqNo(),this);
|
||||
delFrame = true;
|
||||
switch (frame->subclass()) {
|
||||
case IAXControl::Ping:
|
||||
|
@ -1749,7 +1810,9 @@ IAXEvent* IAXTransaction::processMidCallIAXControl(IAXFullFrame* frame, bool& de
|
|||
case IAXControl::FwData:
|
||||
sendUnsupport(frame->subclass());
|
||||
return createEvent(IAXEvent::NotImplemented,false,frame,state());
|
||||
default: ;
|
||||
default:
|
||||
sendUnsupport(frame->subclass());
|
||||
return 0;
|
||||
}
|
||||
delFrame = false;
|
||||
return 0;
|
||||
|
|
|
@ -1535,6 +1535,13 @@ public:
|
|||
inline Type type() const
|
||||
{ return m_type; }
|
||||
|
||||
/**
|
||||
* Retrieve transaction type name
|
||||
* @return Transaction type name
|
||||
*/
|
||||
inline const char* typeName()
|
||||
{ return typeName(type()); }
|
||||
|
||||
/**
|
||||
* Get the state of this transaction
|
||||
* @return The state of the transaction as enumeration
|
||||
|
@ -1894,6 +1901,19 @@ public:
|
|||
*/
|
||||
void print(bool printStats = false, bool printFrames = false, const char* location = "status");
|
||||
|
||||
/**
|
||||
* Retrieve transaction type name from transaction type
|
||||
* @param type Transaction type
|
||||
* @return Requested type name
|
||||
*/
|
||||
static inline const char* typeName(int type)
|
||||
{ return lookup(type,s_typeName); }
|
||||
|
||||
/**
|
||||
* Transaction type name
|
||||
*/
|
||||
static const TokenDict s_typeName[];
|
||||
|
||||
/**
|
||||
* Standard message sent if unsupported/unknown/none authentication methosd was received
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue