From bda1e37157c09be43d4941c47ab599a6eeb9af13 Mon Sep 17 00:00:00 2001 From: marian Date: Tue, 11 Jun 2013 13:41:36 +0000 Subject: [PATCH] Made configurable ping interval, frame retransmission counter and interval. git-svn-id: http://voip.null.ro/svn/yate@5537 acf43c95-373e-0410-b603-e72c3f656dc1 --- conf.d/yiaxchan.conf.sample | 18 +++++++++ libs/yiax/engine.cpp | 57 ++++++++++++++++++---------- libs/yiax/frame.cpp | 11 +++++- libs/yiax/transaction.cpp | 61 ++++++++++++++++------------- libs/yiax/yateiax.h | 76 ++++++++++++++++++++----------------- modules/yiaxchan.cpp | 15 +++----- 6 files changed, 143 insertions(+), 95 deletions(-) diff --git a/conf.d/yiaxchan.conf.sample b/conf.d/yiaxchan.conf.sample index 0ff34ce5..dc7f8d76 100644 --- a/conf.d/yiaxchan.conf.sample +++ b/conf.d/yiaxchan.conf.sample @@ -111,6 +111,24 @@ ; Defaults to yes ;calltoken_rejectmissing=yes +; retrans_count: integer: The number of frame retransmissions +; This parameter is applied on reload for new calls only +; Allowed interval: 1..10 +; Defaults to 4 +;retrans_count=4 + +; retrans_interval: integer: The first frame retransmission interval in milliseconds +; This parameter is applied on reload for new calls only +; Allowed interval: 200..5000 +; Defaults to 500 +;retrans_interval=500 + +; ping_interval: integer: The interval, in milliseconds, to send ping +; This parameter is applied on reload for new calls only +; Minimum allowed value is 10000 +; Defaults to 20000 +;ping_interval=20000 + ; adjust_ts_out_threshold: integer: The difference, in milliseconds, between sent audio data ; timestamp and transaction timestamp at which audio data timestamp will be adjusted ; Its value will be rouded up to a multiple of 10 diff --git a/libs/yiax/engine.cpp b/libs/yiax/engine.cpp index 5135e6bb..aeff4bb0 100644 --- a/libs/yiax/engine.cpp +++ b/libs/yiax/engine.cpp @@ -55,7 +55,7 @@ static void buildSecretDigest(String& buf, const String& secret, unsigned int t, } -IAXEngine::IAXEngine(const char* iface, int port, u_int16_t transListCount, u_int16_t retransCount, u_int16_t retransInterval, +IAXEngine::IAXEngine(const char* iface, int port, u_int16_t transListCount, u_int16_t authTimeout, u_int16_t transTimeout, u_int16_t maxFullFrameDataLen, u_int32_t format, u_int32_t capab, bool authRequired, NamedList* params) : Mutex(true,"IAXEngine"), @@ -64,8 +64,6 @@ IAXEngine::IAXEngine(const char* iface, int port, u_int16_t transListCount, u_in m_maxFullFrameDataLen(maxFullFrameDataLen), m_startLocalCallNo(0), m_transListCount(0), - m_retransCount(retransCount), - m_retransInterval(retransInterval), m_authTimeout(authTimeout), m_transTimeout(transTimeout), m_callToken(false), @@ -80,7 +78,8 @@ IAXEngine::IAXEngine(const char* iface, int port, u_int16_t transListCount, u_in m_adjustTsOutThreshold(IAX2_ADJUSTTSOUT_THRES), m_adjustTsOutOverrun(IAX2_ADJUSTTSOUT_OVER), m_adjustTsOutUnderrun(IAX2_ADJUSTTSOUT_UNDER), - m_mutexTrunk(false,"IAXEngine::Trunk") + m_mutexTrunk(false,"IAXEngine::Trunk"), + m_trunkInfoMutex(false,"IAXEngine::TrunkInfo") { debugName("iaxengine"); Debug(this,DebugAll,"Automatically request authentication set to '%s'.", @@ -410,8 +409,14 @@ void IAXEngine::initialize(const NamedList& params) m_callerNumType = lookup(params["numtype"],IAXInfoElement::s_typeOfNumber); m_callingPres = lookup(params["presentation"],IAXInfoElement::s_presentation) | lookup(params["screening"],IAXInfoElement::s_screening); - m_trunkInfoDef.init(params,"trunk_"); initOutDataAdjust(params); + IAXTrunkInfo* ti = new IAXTrunkInfo; + ti->initTrunking(params,"trunk_",0,true); + ti->initTrunking(params,"trunk_",0,false); + ti->init(params); + Lock lck(m_trunkInfoMutex); + m_trunkInfoDef = ti; + TelEngine::destruct(ti); } void IAXEngine::readSocket(SocketAddr& addr) @@ -782,6 +787,20 @@ void IAXEngine::defaultEventHandler(IAXEvent* event) } } +static bool getTrunkingInfo(RefPointer& ti, IAXEngine* engine, + const NamedList* params, const String& prefix, bool out) +{ + if (!engine->trunkInfo(ti)) + return false; + if (!params) + return true; + IAXTrunkInfo* tmp = new IAXTrunkInfo; + tmp->initTrunking(*params,prefix,ti,out); + ti = tmp; + TelEngine::destruct(tmp); + return true; +} + void IAXEngine::enableTrunking(IAXTransaction* trans, const NamedList* params, const String& prefix) { @@ -797,14 +816,12 @@ void IAXEngine::enableTrunking(IAXTransaction* trans, const NamedList* params, return; } } - IAXTrunkInfo tmp; - IAXTrunkInfo* trunk = &m_trunkInfoDef; - if (params) { - tmp.initTrunking(*params,prefix,trunk,true); - trunk = &tmp; - } - frame = new IAXMetaTrunkFrame(this,trans->remoteAddr(),trunk->m_timestamps, - trunk->m_maxLen,trunk->m_sendInterval); + RefPointer ti; + if (!getTrunkingInfo(ti,this,params,prefix,true)) + return; + frame = new IAXMetaTrunkFrame(this,trans->remoteAddr(),ti->m_timestamps, + ti->m_maxLen,ti->m_sendInterval); + ti = 0; if (trans->enableTrunking(frame)) { m_trunkList.append(frame); Debug(this,DebugAll, @@ -823,14 +840,12 @@ void IAXEngine::initTrunkIn(IAXTransaction* trans, const NamedList* params, { if (!trans) return; - IAXTrunkInfo tmp; - IAXTrunkInfo* trunk = &m_trunkInfoDef; - if (params) { - tmp.initTrunking(*params,prefix,trunk,false); - trunk = &tmp; - } - trans->m_trunkInSyncUsingTs = trunk->m_trunkInSyncUsingTs; - trans->m_trunkInTsDiffRestart = trunk->m_trunkInTsDiffRestart; + RefPointer ti; + if (!getTrunkingInfo(ti,this,params,prefix,false)) + return; + trans->m_trunkInSyncUsingTs = ti->m_trunkInSyncUsingTs; + trans->m_trunkInTsDiffRestart = ti->m_trunkInTsDiffRestart; + ti = 0; } void IAXEngine::runProcessTrunkFrames() diff --git a/libs/yiax/frame.cpp b/libs/yiax/frame.cpp index 9121744c..59af91ec 100644 --- a/libs/yiax/frame.cpp +++ b/libs/yiax/frame.cpp @@ -1447,8 +1447,15 @@ void IAXFrameOut::adjustAuthTimeout(u_int64_t nextTransTime) void IAXTrunkInfo::init(const NamedList& params, const String& prefix, const IAXTrunkInfo* def) { - initTrunking(params,prefix,def,true); - initTrunking(params,prefix,def,false); + m_retransCount = params.getIntValue(prefix + "retrans_count", + def ? def->m_retransCount : IAX2_RETRANS_COUNT_DEF, + IAX2_RETRANS_COUNT_MIN,IAX2_RETRANS_COUNT_MAX); + m_retransInterval = params.getIntValue(prefix + "retrans_interval", + def ? def->m_retransInterval : IAX2_RETRANS_INTERVAL_DEF, + IAX2_RETRANS_INTERVAL_MIN,IAX2_RETRANS_INTERVAL_MAX); + m_pingInterval = params.getIntValue(prefix + "ping_interval", + def ? def->m_retransInterval : IAX2_PING_INTERVAL_DEF, + IAX2_PING_INTERVAL_MIN); } // Init from parameters diff --git a/libs/yiax/transaction.cpp b/libs/yiax/transaction.cpp index 82147653..1f9086c5 100644 --- a/libs/yiax/transaction.cpp +++ b/libs/yiax/transaction.cpp @@ -104,10 +104,6 @@ IAXTransaction::IAXTransaction(IAXEngine* engine, IAXFullFrame* frame, u_int16_t m_trunkInTsDiffRestart(5000), m_trunkInFirstTs(0) { - // Setup transaction - m_retransCount = engine->retransCount(); - m_retransInterval = engine->retransInterval(); - m_timeToNextPing = m_timeStamp + m_pingInterval; switch (frame->subclass()) { case IAXControl::New: m_type = New; @@ -126,11 +122,7 @@ 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); - engine->initTrunkIn(this); + init(); // Append frame to incoming list Lock lock(this); m_inFrames.append(frame); @@ -181,8 +173,6 @@ IAXTransaction::IAXTransaction(IAXEngine* engine, Type type, u_int16_t lcallno, m_trunkInTsDiffRestart(5000), m_trunkInFirstTs(0) { - 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, @@ -190,9 +180,6 @@ IAXTransaction::IAXTransaction(IAXEngine* engine, Type type, u_int16_t lcallno, localCallNo(),remoteCallNo(),this); m_addr.port(4569); } - m_retransCount = engine->retransCount(); - m_retransInterval = engine->retransInterval(); - m_timeToNextPing = m_timeStamp + m_pingInterval; init(ieList); IAXControl::Type frametype; IAXIEList* ies = new IAXIEList; @@ -237,9 +224,7 @@ IAXTransaction::IAXTransaction(IAXEngine* engine, Type type, u_int16_t lcallno, m_type = Incorrect; return; } - engine->getOutDataAdjust(m_adjustTsOutThreshold,m_adjustTsOutOverrun, - m_adjustTsOutUnderrun); - engine->initTrunkIn(this); + init(); postFrameIes(IAXFrame::IAX,frametype,ies); changeState(NewLocalInvite); } @@ -663,13 +648,15 @@ IAXEvent* IAXTransaction::getEvent(u_int64_t time) if (state() == NewRemoteInvite_AuthSent && frame->ack()) frame->adjustAuthTimeout(time + m_engine->authTimeout() * 1000); // No response. Timeout ? - if (frame->timeout() && frame->timeForRetrans(time)) { - if (m_state == Terminating) - // Client already notified: Terminate transaction - ev = terminate(IAXEvent::Timeout,true); - else - // Client not notified: Notify it and terminate transaction - ev = terminate(IAXEvent::Timeout,true,frame,false); + if (!frame->retransCount()) { + if (frame->timeForRetrans(time)) { + if (m_state == Terminating) + // Client already notified: Terminate transaction + ev = terminate(IAXEvent::Timeout,true); + else + // Client not notified: Notify it and terminate transaction + ev = terminate(IAXEvent::Timeout,true,frame,false); + } break; } // Retransmit ? @@ -677,8 +664,10 @@ IAXEvent* IAXTransaction::getEvent(u_int64_t time) if (frame->ack()) frame->transmitted(); // Frame acknoledged: just update retransmission info else { - Debug(m_engine,DebugNote,"Transaction(%u,%u) resending Frame(%u,%u) oseq=%u iseq=%u stamp=%u [%p]", - localCallNo(),remoteCallNo(),frame->type(),frame->subclass(),frame->oSeqNo(),frame->iSeqNo(),frame->timeStamp(),this); + Debug(m_engine,DebugNote, + "Transaction(%u,%u) resending Frame(%u,%u) oseq=%u iseq=%u stamp=%u remaining=%u [%p]", + localCallNo(),remoteCallNo(),frame->type(),frame->subclass(), + frame->oSeqNo(),frame->iSeqNo(),frame->timeStamp(),frame->retransCount() - 1,this); sendFrame(frame); // Retransmission } } @@ -2019,7 +2008,7 @@ void IAXTransaction::postFrame(IAXFrameOut* frame) { if (!frame) return; - DDebug(m_engine,DebugAll, + Debug(m_engine,DebugAll, "Transaction(%u,%u) posting Frame(%u,%u) oseq=%u iseq=%u stamp=%u [%p]", localCallNo(),remoteCallNo(),frame->type(),frame->subclass(), m_oSeqNo,m_iSeqNo,frame->timeStamp(),this); @@ -2041,4 +2030,22 @@ void IAXTransaction::receivedVoiceMiniBeforeFull() sendVNAK(); } +void IAXTransaction::init() +{ + Debug(m_engine,DebugAll,"Transaction %s call=%u type=%s remote=%s:%d [%p]", + outgoing() ? "outgoing" : "incoming",localCallNo(),typeName(),m_addr.host().c_str(), + m_addr.port(),this); + m_engine->getOutDataAdjust(m_adjustTsOutThreshold,m_adjustTsOutOverrun,m_adjustTsOutUnderrun); + RefPointer ti; + if (!m_engine->trunkInfo(ti)) + return; + m_trunkInSyncUsingTs = ti->m_trunkInSyncUsingTs; + m_trunkInTsDiffRestart = ti->m_trunkInTsDiffRestart; + m_retransCount = ti->m_retransCount; + m_retransInterval = ti->m_retransInterval; + m_pingInterval = ti->m_pingInterval; + ti = 0; + m_timeToNextPing = m_timeStamp + m_pingInterval; +} + /* vi: set ts=8 sw=4 sts=4 noet: */ diff --git a/libs/yiax/yateiax.h b/libs/yiax/yateiax.h index 92a04283..bab9525d 100644 --- a/libs/yiax/yateiax.h +++ b/libs/yiax/yateiax.h @@ -79,6 +79,18 @@ class IAXEngine; // IAX engine #define IAX2_TRUNKFRAME_SEND_MIN 5 #define IAX2_TRUNKFRAME_SEND_DEF 20 +// Frame retransmission +#define IAX2_RETRANS_COUNT_MIN 1 +#define IAX2_RETRANS_COUNT_MAX 10 +#define IAX2_RETRANS_COUNT_DEF 4 +#define IAX2_RETRANS_INTERVAL_MIN 200 +#define IAX2_RETRANS_INTERVAL_MAX 5000 +#define IAX2_RETRANS_INTERVAL_DEF 500 + +// Ping +#define IAX2_PING_INTERVAL_MIN 10000 +#define IAX2_PING_INTERVAL_DEF 20000 + /** * This class holds a single Information Element with no data * @short A single IAX2 Information Element @@ -1344,11 +1356,11 @@ public: {} /** - * Get the timeout (retransmission counter) of this frame - * @return True if the retransmission counter is 0 + * Get the retransmission counter of this frame + * @return The retransmission counter is 0 */ - inline bool timeout() const - { return m_retransCount == 0; } + inline unsigned int retransCount() const + { return m_retransCount; } /** * Ask the frame if it's time for retransmit @@ -1406,7 +1418,7 @@ private: * This class holds trunk description * @short Trunk info */ -class YIAX_API IAXTrunkInfo : public GenObject +class YIAX_API IAXTrunkInfo : public RefObject { public: /** @@ -1415,22 +1427,25 @@ public: inline IAXTrunkInfo() : m_timestamps(true), m_sendInterval(IAX2_TRUNKFRAME_SEND_DEF), m_maxLen(IAX2_TRUNKFRAME_LEN_DEF), m_trunkInSyncUsingTs(true), - m_trunkInTsDiffRestart(5000) + m_trunkInTsDiffRestart(5000), + m_retransCount(IAX2_RETRANS_COUNT_DEF), + m_retransInterval(IAX2_RETRANS_INTERVAL_DEF), + m_pingInterval(IAX2_PING_INTERVAL_DEF) {} /** - * Init all data from parameters + * Init non trunking related data * @param params Parameter list - * @param prefix Parameter prefix (used as value for enable parameter also) + * @param prefix Parameter prefix * @param def Optional defaults */ - void init(const NamedList& params, const String& prefix, + void init(const NamedList& params, const String& prefix = String::empty(), const IAXTrunkInfo* def = 0); /** * Init trunking from parameters * @param params Parameter list - * @param prefix Parameter prefix (used as value for enable parameter also) + * @param prefix Parameter prefix * @param def Optional defaults * @param out True to init outgoing trunk data, false to init incoming trunk info */ @@ -1444,6 +1459,9 @@ public: // time or trunk timestamp to re-build frame ts u_int32_t m_trunkInTsDiffRestart; // Incoming trunk without timestamp: diff between // timestamps at which we restart + unsigned int m_retransCount; // Frame retransmission counter + unsigned int m_retransInterval; // Frame retransmission interval in milliseconds + unsigned int m_pingInterval; // Ping interval in milliseconds }; /** @@ -2471,6 +2489,7 @@ private: void adjustTStamp(u_int32_t& tStamp); void postFrame(IAXFrameOut* frame); void receivedVoiceMiniBeforeFull(); + void init(); inline void restartTrunkIn(u_int64_t now, u_int32_t ts) { m_trunkInStartTime = now; u_int64_t dt = (now - m_lastVoiceFrameIn) / 1000; @@ -2500,8 +2519,8 @@ private: IAXEvent* m_currentEvent; // Pointer to last generated event or 0 // Outgoing frames management ObjList m_outFrames; // Transaction & protocol control outgoing frames - u_int16_t m_retransCount; // Retransmission counter. 0 --> Timeout - u_int32_t m_retransInterval; // Frame retransmission interval + unsigned int m_retransCount; // Retransmission counter. 0 --> Timeout + unsigned int m_retransInterval; // Frame retransmission interval // Incoming frames management ObjList m_inFrames; // Transaction & protocol control incoming frames static unsigned char m_maxInFrames; // Max frames number allowed in m_inFrames @@ -2700,8 +2719,6 @@ public: * @param iface Address of the interface to use, default all (0.0.0.0) * @param port UDP port to run the protocol on * @param transListCount Number of entries in the transaction hash table - * @param retransCount Retransmission counter for each transaction belonging to this engine - * @param retransInterval Retransmission interval default value in miliseconds * @param authTimeout Timeout (in seconds) of acknoledged auth frames sent * @param transTimeout Timeout (in seconds) on remote request of transactions belonging to this engine * @param maxFullFrameDataLen Max full frame IE list (buffer) length @@ -2710,7 +2727,7 @@ public: * @param authRequired Automatically challenge all clients for authentication * @param params Optional extra parameter list */ - IAXEngine(const char* iface, int port, u_int16_t transListCount, u_int16_t retransCount, u_int16_t retransInterval, + IAXEngine(const char* iface, int port, u_int16_t transListCount, u_int16_t authTimeout, u_int16_t transTimeout, u_int16_t maxFullFrameDataLen, u_int32_t format, u_int32_t capab, bool authRequired, NamedList* params = 0); @@ -2779,20 +2796,6 @@ public: */ bool process(); - /** - * Get default frame retransmission counter - * @return Frame retransmission counter - */ - inline u_int16_t retransCount() const - { return m_retransCount; } - - /** - * Get default frame retransmission starting interval - * @return Frame retransmission starting interval - */ - inline u_int16_t retransInterval() const - { return m_retransInterval; } - /** * Check if a transaction should automatically request authentication * @return True to automatically request authentication @@ -2972,10 +2975,14 @@ public: /** * Retrieve the default trunk info data - * @return Trunk info pointer, 0 if not found + * @param info Destination to be set with trunk info pointer + * @return True if destination pointr is valid */ - inline IAXTrunkInfo* trunkInfo() - { return &m_trunkInfoDef; } + inline bool trunkInfo(RefPointer& info) { + Lock lck(m_trunkInfoMutex); + info = m_trunkInfoDef; + return info != 0; + } /** * Send an INVAL frame @@ -3129,8 +3136,6 @@ private: int m_maxFullFrameDataLen; // Max full frame data (IE list) length u_int16_t m_startLocalCallNo; // Start index of local call number allocation u_int16_t m_transListCount; // m_transList count - u_int16_t m_retransCount; // Retransmission counter for each transaction belonging to this engine - u_int16_t m_retransInterval; // Retransmission interval default value in miliseconds u_int16_t m_authTimeout; // Timeout (in seconds) of acknoledged auth frames sent u_int32_t m_transTimeout; // Timeout (in seconds) on remote request of transactions // belonging to this engine @@ -3154,7 +3159,8 @@ private: // Trunking Mutex m_mutexTrunk; // Mutex for trunk operations ObjList m_trunkList; // Trunk frames list - IAXTrunkInfo m_trunkInfoDef; // Defaults for trunk data + Mutex m_trunkInfoMutex; // Trunk info mutex + RefPointer m_trunkInfoDef; // Defaults for trunk data }; } diff --git a/modules/yiaxchan.cpp b/modules/yiaxchan.cpp index 2aa29ca2..5b17b328 100644 --- a/modules/yiaxchan.cpp +++ b/modules/yiaxchan.cpp @@ -279,14 +279,12 @@ public: * @param iface Interface address to use * @param port UDP port to use * @param transListCount Number of entries in the transaction hash table - * @param retransCount Retransmission counter for each transaction belonging to this engine - * @param retransInterval Retransmission interval default value in miliseconds * @param authTimeout Timeout (in seconds) of acknoledged auth frames sent * @param transTimeout Timeout (in seconds) on remote request of transactions belonging to this engine * @param maxFullFrameDataLen Max full frame IE list (buffer) length * @param authRequired Automatically challenge all clients for authentication */ - YIAXEngine(const char* iface, int port, u_int16_t transListCount, u_int16_t retransCount, u_int16_t retransInterval, + YIAXEngine(const char* iface, int port, u_int16_t transListCount, u_int16_t authTimeout, u_int16_t transTimeout, u_int16_t maxFullFrameDataLen, bool authRequired, NamedList* params); @@ -1033,10 +1031,9 @@ void YIAXTrunking::run() * YIAXEngine */ YIAXEngine::YIAXEngine(const char* iface, int port, u_int16_t transListCount, - u_int16_t retransCount, u_int16_t retransInterval, u_int16_t authTimeout, - u_int16_t transTimeout, u_int16_t maxFullFrameDataLen, + u_int16_t authTimeout, u_int16_t transTimeout, u_int16_t maxFullFrameDataLen, bool authRequired, NamedList* params) - : IAXEngine(iface,port,transListCount,retransCount,retransInterval,authTimeout, + : IAXEngine(iface,port,transListCount,authTimeout, transTimeout,maxFullFrameDataLen,0,0,authRequired,params), m_threadsCreated(false) { @@ -1448,8 +1445,6 @@ void YIAXDriver::initialize() Engine::install(new YIAXRegDataHandler); // Init IAX engine u_int16_t transListCount = 64; - u_int16_t retransCount = 4; - u_int16_t retransInterval = 500; u_int16_t authTimeout = 30; u_int16_t transTimeout = 10; u_int16_t maxFullFrameDataLen = 1400; @@ -1458,8 +1453,8 @@ void YIAXDriver::initialize() // set max chans maxChans(gen->getIntValue("maxchans",maxChans())); bool authReq = cfg.getBoolValue("registrar","auth_required",true); - m_iaxEngine = new YIAXEngine(iface,m_port,transListCount,retransCount, - retransInterval,authTimeout,transTimeout,maxFullFrameDataLen,authReq,gen); + m_iaxEngine = new YIAXEngine(iface,m_port,transListCount, + authTimeout,transTimeout,maxFullFrameDataLen,authReq,gen); m_iaxEngine->debugChain(this); m_iaxEngine->initFormats(cfg.getSection("formats")); int tos = gen->getIntValue("tos",dict_tos,0);