Skip to content

Commit

Permalink
RTP inactivity checking for non-multiplexed calls
Browse files Browse the repository at this point in the history
  • Loading branch information
willamowius committed Jan 29, 2018
1 parent 680ed61 commit afbd923
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 31 deletions.
56 changes: 50 additions & 6 deletions ProxyChannel.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1126,6 +1126,7 @@ class RTPLogicalChannel : public LogicalChannel {

void GetRTPPorts(PIPSocket::Address & fSrcIP, PIPSocket::Address & fDestIP, PIPSocket::Address & rSrcIP, PIPSocket::Address & rDestIP,
WORD & fSrcPort, WORD & dDestPort, WORD & rSrcPort, WORD & rDestPort) const;
bool IsRTPInactive() const;

private:
void SetNAT(bool);
Expand Down Expand Up @@ -1250,8 +1251,8 @@ class H245ProxyHandler : public H245Handler {
H245ProxyHandler * GetPeer() const { return peer; }
void UpdateLogicalChannelSessionID(WORD flcn, WORD id);
LogicalChannel * FindLogicalChannel(WORD flcn);
RTPLogicalChannel * FindRTPLogicalChannelBySessionID(WORD id);
RTPLogicalChannel * FindRTPLogicalChannelBySessionType(RTPSessionTypes sessionType);
RTPLogicalChannel * FindRTPLogicalChannelBySessionID(WORD id) const;
RTPLogicalChannel * FindRTPLogicalChannelBySessionType(RTPSessionTypes sessionType) const;
bool UsesH46019() const { return m_useH46019; }
void SetTraversalRole(H46019TraversalType type) { m_traversalType = type; m_useH46019 = (type != None); }
H46019TraversalType GetTraversalRole() const { return m_traversalType; }
Expand All @@ -1269,6 +1270,8 @@ class H245ProxyHandler : public H245Handler {
void SetRoles(bool isCaller, bool isH245Master) { m_isCaller = isCaller; m_isH245Master = isH245Master; }
bool IsCaller() const { return m_isCaller; }
bool IsH245Master() const { return m_isH245Master; }
bool IsRTPInactive(short session) const;


protected:
// override from class H245Handler
Expand Down Expand Up @@ -9059,6 +9062,17 @@ void CallSignalSocket::SetCallTypePlan(Q931 *q931)
}
}

bool CallSignalSocket::IsRTPInactive(short session) const
{
H245ProxyHandler * proxyhandler = dynamic_cast<H245ProxyHandler *>(m_h245handler);
if (proxyhandler) {
return proxyhandler->IsRTPInactive(session);
} else {
return false;
}
}


// class H245Handler
H245Handler::H245Handler(const PIPSocket::Address & local, const PIPSocket::Address & remote, const PIPSocket::Address & masq)
: localAddr(local), remoteAddr(remote), masqAddr(masq), isH245ended(false), m_lastVideoFastUpdatePicture(0)
Expand Down Expand Up @@ -10980,6 +10994,7 @@ UDPProxySocket::UDPProxySocket(const char *t, const H225_CallIdentifier & id)
}
m_lastPacketFromForwardSrc = time(NULL);
m_lastPacketFromReverseSrc = time(NULL);
m_inactivityTimeout = GkConfig()->GetInteger(ProxySection, "RTPInactivityTimeout", 300); // 300 sec = 5 min
}

UDPProxySocket::~UDPProxySocket()
Expand Down Expand Up @@ -11256,6 +11271,20 @@ void UDPProxySocket::SetMediaIP(bool isSRC, const Address & ip)
}
}

bool UDPProxySocket::IsRTPInactive() const
{
time_t now = time(NULL);
if ( (fSrcIP != 0 && fSrcPort != 0) && (now - m_lastPacketFromForwardSrc > m_inactivityTimeout) ) {
PTRACE(1, "RTP\tTerminating call because of RTP inactivity from " << AsString(fSrcIP, fSrcPort) << " CallID " << AsString(m_callID.m_guid));
return true;
}
if ( (rSrcIP != 0 && rSrcPort != 0) && (now - m_lastPacketFromReverseSrc > m_inactivityTimeout) ) {
PTRACE(1, "RTP\tTerminating call because of RTP inactivity from " << AsString(rSrcIP, rSrcPort) << " CallID " << AsString(m_callID.m_guid));
return true;
}
return false;
}

// this method handles either RTP, RTCP or T.38 data
ProxySocket::Result UDPProxySocket::ReceiveData()
{
Expand Down Expand Up @@ -12542,6 +12571,11 @@ void RTPLogicalChannel::GetRTPPorts(PIPSocket::Address & fSrcIP, PIPSocket::Addr
}
}

bool RTPLogicalChannel::IsRTPInactive() const
{
return (rtp && rtp->IsRTPInactive());
}

void RTPLogicalChannel::SetRTPSessionID(WORD id)
{
if (rtp)
Expand Down Expand Up @@ -14330,15 +14364,15 @@ LogicalChannel * H245ProxyHandler::FindLogicalChannel(WORD flcn)
return (iter != logicalChannels.end()) ? iter->second : NULL;
}

RTPLogicalChannel * H245ProxyHandler::FindRTPLogicalChannelBySessionID(WORD id)
RTPLogicalChannel * H245ProxyHandler::FindRTPLogicalChannelBySessionID(WORD id) const
{
siterator iter = sessionIDs.find(id);
const_siterator iter = sessionIDs.find(id);
return (iter != sessionIDs.end()) ? iter->second : NULL;
}

RTPLogicalChannel * H245ProxyHandler::FindRTPLogicalChannelBySessionType(RTPSessionTypes sessionType)
RTPLogicalChannel * H245ProxyHandler::FindRTPLogicalChannelBySessionType(RTPSessionTypes sessionType) const
{
for (siterator iter = sessionIDs.begin(); iter != sessionIDs.end() ; ++iter) {
for (const_siterator iter = sessionIDs.begin(); iter != sessionIDs.end() ; ++iter) {
if (iter->second->GetType() == sessionType) {
RTPLogicalChannel * lc = iter->second;
return lc;
Expand All @@ -14347,6 +14381,16 @@ RTPLogicalChannel * H245ProxyHandler::FindRTPLogicalChannelBySessionType(RTPSess
return NULL;
}

bool H245ProxyHandler::IsRTPInactive(short session) const
{
bool inactive = false;
RTPLogicalChannel * lc = FindRTPLogicalChannelBySessionID(session);
if (lc) {
inactive = lc->IsRTPInactive();
}
return inactive;
}

//void H245ProxyHandler::DumpChannels(const PString & msg, bool dumpPeer) const
//{
// if (PTrace::CanTrace(7)) {
Expand Down
6 changes: 5 additions & 1 deletion ProxyChannel.h
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ class UDPProxySocket : public UDPSocket, public ProxySocket {
WORD & _fSrcPort, WORD & _fDestPort, WORD & _rSrcPort, WORD & _rDestPort) const;
void ZeroAllIPs();
void ForwardAndReverseSeen() { PTRACE(7, "JW RTP ForwardAndReverseSeen"); m_forwardAndReverseSeen = true; }
bool IsRTPInactive() const;


protected:
Expand Down Expand Up @@ -302,6 +303,7 @@ class UDPProxySocket : public UDPSocket, public ProxySocket {
bool m_portDetectionDone;
bool m_forwardAndReverseSeen; // did we see logical channels for both directions, yet ?
bool m_legacyPortDetection;
unsigned m_inactivityTimeout;
time_t m_lastPacketFromForwardSrc;
time_t m_lastPacketFromReverseSrc;
};
Expand Down Expand Up @@ -428,6 +430,8 @@ class CallSignalSocket : public TCPProxySocket {

CallSignalSocket * GetRemote() const { return dynamic_cast<CallSignalSocket *>(remote); }

bool IsRTPInactive(short session) const;

protected:
void ForwardCall(FacilityMsg *msg);

Expand Down Expand Up @@ -719,7 +723,7 @@ class MultiplexedRTPHandler : public Singleton<MultiplexedRTPHandler> {
MultiplexedRTPHandler();
virtual ~MultiplexedRTPHandler();

virtual void OnReload() { /* currently not runtime changable */ }
virtual void OnReload() { /* currently not runtime changeable */ }

virtual void AddChannel(const H46019Session & cha);
virtual void UpdateChannelSession(const H225_CallIdentifier & callid, WORD flcn, void * openedBy, WORD session);
Expand Down
4 changes: 3 additions & 1 deletion RasSrv.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1612,8 +1612,10 @@ void RasServer::HouseKeeping()

ReadLock lock(ConfigReloadMutex);

if (!(count % 60)) // one minute
if (!(count % 60)) { // one minute
RegistrationTable::Instance()->CheckEndpoints();
CallTable::Instance()->CheckRTPInactive();
}

CallTable::Instance()->CheckCalls(this);

Expand Down
55 changes: 36 additions & 19 deletions RasTbl.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -5117,6 +5117,14 @@ BYTE CallRec::GetNewDynamicPayloadType()
}
#endif

bool CallRec::IsRTPInactive(short session) const
{
if (m_callingSocket) {
return m_callingSocket->IsRTPInactive(session);
} else {
return (m_calledSocket && m_calledSocket->IsRTPInactive(session));
}
}

/*
bool CallRec::IsTimeout(
Expand Down Expand Up @@ -5217,28 +5225,28 @@ void CallTable::LoadConfig()
SetTotalBandwidth(GKCapacity); // will take into account ongoing calls
m_minimumBandwidthPerCall = GkConfig()->GetInteger("MinimumBandwidthPerCall", -1);
m_maximumBandwidthPerCall = GkConfig()->GetInteger("MaximumBandwidthPerCall", -1);
m_signalTimeout = std::max(
GkConfig()->GetInteger(RoutedSec, "SignalTimeout", DEFAULT_SIGNAL_TIMEOUT),
5000L
);
m_alertingTimeout = std::max(
GkConfig()->GetInteger(RoutedSec, "AlertingTimeout", DEFAULT_ALERTING_TIMEOUT),
5000L
);
m_defaultDurationLimit = GkConfig()->GetInteger(
CallTableSection, "DefaultCallDurationLimit", 0
);
m_signalTimeout = std::max(GkConfig()->GetInteger(RoutedSec, "SignalTimeout", DEFAULT_SIGNAL_TIMEOUT), 5000L);
m_alertingTimeout = std::max(GkConfig()->GetInteger(RoutedSec, "AlertingTimeout", DEFAULT_ALERTING_TIMEOUT), 5000L);
m_defaultDurationLimit = GkConfig()->GetInteger(CallTableSection, "DefaultCallDurationLimit", 0);
// backward compatibility - check DefaultCallTimeout
if (m_defaultDurationLimit == 0)
m_defaultDurationLimit = GkConfig()->GetInteger(
CallTableSection, "DefaultCallTimeout", 0
);
m_defaultDurationLimit = GkConfig()->GetInteger(CallTableSection, "DefaultCallTimeout", 0);
m_acctUpdateInterval = GkConfig()->GetInteger(CallTableSection, "AcctUpdateInterval", 0);
if( m_acctUpdateInterval != 0)
m_acctUpdateInterval = std::max(m_acctUpdateInterval, 10L);

m_timestampFormat = GkConfig()->GetString(CallTableSection, "TimestampFormat", "RFC822");
m_singleFailoverCDR = Toolkit::AsBool(GkConfig()->GetString(CallTableSection, "SingleFailoverCDR", "1"));
m_inactivityCheck = GkConfig()->GetBoolean(ProxySection, "RTPInactivityCheck", false);
PCaselessString sessionType = GkConfig()->GetString(ProxySection, "RTPInactivityCheckSession", "Audio");
if (sessionType == "Audio") {
m_inactivityCheckSession = 1;
} else if (sessionType == "Video") {
m_inactivityCheckSession = 2;
} else {
PTRACE(1, "CallTable\tError: You can only check audio or video sessions for inactivity");
m_inactivityCheckSession = 1; // default to audio
}
}

void CallTable::Insert(CallRec * NewRec)
Expand Down Expand Up @@ -5374,12 +5382,11 @@ void CallTable::CheckCalls(RasServer * rassrv)
{
std::list<callptr> m_callsToDisconnect;
std::list<callptr> m_callsToUpdate;
time_t now;
time_t now = time(NULL);

{
WriteLock lock(listLock);
iterator Iter = CallList.begin(), eIter = CallList.end();
now = time(0);
while (Iter != eIter) {
if ((*Iter)->IsTimeout(now))
m_callsToDisconnect.push_back(callptr(*Iter));
Expand All @@ -5397,10 +5404,9 @@ void CallTable::CheckCalls(RasServer * rassrv)

std::list<callptr>::iterator call = m_callsToDisconnect.begin();
while (call != m_callsToDisconnect.end()) {
(*call)->SetDisconnectCause((*call)->IsConnected()
? Q931::ResourceUnavailable : Q931::TemporaryFailure
);
(*call)->SetDisconnectCause((*call)->IsConnected() ? Q931::ResourceUnavailable : Q931::TemporaryFailure);
(*call)->SetReleaseSource(CallRec::ReleasedByGatekeeper);

if (((*call)->GetNoRemainingRoutes() == 0)
|| (! (*call)->IsFailoverActive())
|| (now - (*call)->GetSetupTime() > (GetSignalTimeout() / 1000) * 5)) {
Expand All @@ -5425,6 +5431,17 @@ void CallTable::CheckCalls(RasServer * rassrv)
}
}

void CallTable::CheckRTPInactive()
{
WriteLock lock(listLock);
for (iterator iter = CallList.begin(); iter != CallList.end(); ++iter) {
if (m_inactivityCheck && (*iter)->IsRTPInactive(m_inactivityCheckSession)) {
PTRACE(1, "CallTable\tTerminating call because of RTP inactivity CallID " << AsString((*iter)->GetCallIdentifier().m_guid));
(*iter)->Disconnect();
}
}
}

#ifdef HAS_H460

static PTextFile* OpenQoSFile(const PFilePath & fn)
Expand Down
13 changes: 9 additions & 4 deletions RasTbl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1214,8 +1214,8 @@ class CallRec {
true if the address has been retrieved successfully, false otherwise.
*/
bool GetSrcSignalAddr(
PIPSocket::Address& addr, /// will receive the IP address
WORD& port /// will receive the port number
PIPSocket::Address & addr, /// will receive the IP address
WORD & port /// will receive the port number
) const;

H225_TransportAddress GetDestSignalAddr() const;
Expand Down Expand Up @@ -1441,7 +1441,7 @@ class CallRec {
#endif

// should we use TLS on the outgoing leg, incoming determined by port caller uses
bool ConnectWithTLS() const { return m_connectWithTLS || (m_Called && m_Called->UseTLS()); } // per call dynamicly and config setting
bool ConnectWithTLS() const { return m_connectWithTLS || (m_Called && m_Called->UseTLS()); } // per call dynamically and config setting
void SetConnectWithTLS(bool val) { m_connectWithTLS = val; }

#ifdef HAS_H235_MEDIA
Expand All @@ -1453,6 +1453,8 @@ class CallRec {
BYTE GetNewDynamicPayloadType();
#endif

bool IsRTPInactive(short session) const;

private:
void SendDRQ();
void InternalSetEP(endptr &, const endptr &);
Expand Down Expand Up @@ -1758,6 +1760,7 @@ class CallTable : public Singleton<CallTable>
void CheckCalls(
RasServer* rassrv // to avoid call RasServer::Instance every second
);
void CheckRTPInactive();

void RemoveCall(const H225_DisengageRequest & obj_drq, const endptr &);
void RemoveCall(const callptr &);
Expand Down Expand Up @@ -1850,9 +1853,11 @@ class CallTable : public Singleton<CallTable>
PString m_timestampFormat;
/// flag to trigger per call leg accounting
bool m_singleFailoverCDR;
bool m_inactivityCheck;
short m_inactivityCheckSession;

CallTable(const CallTable &);
CallTable& operator==(const CallTable &);
CallTable & operator==(const CallTable &);
};

// inline functions of EndpointRec
Expand Down

0 comments on commit afbd923

Please sign in to comment.