Changed the handling of the "timeout" parameter so it (re)starts when call is answered.

Added "maxcall" and "timeout" setting and handling to channels that lacked it.


git-svn-id: http://voip.null.ro/svn/yate@5282 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
paulc 2012-09-25 09:39:49 +00:00
parent bd18d97dd0
commit f5230b501c
6 changed files with 67 additions and 54 deletions

View File

@ -334,8 +334,8 @@ static Mutex s_paramMutex(true,"ChannelParams");
Channel::Channel(Driver* driver, const char* id, bool outgoing)
: CallEndpoint(id),
m_parameters(""), m_driver(driver), m_outgoing(outgoing),
m_timeout(0), m_maxcall(0),
m_dtmfTime(0), m_dtmfSeq(0), m_answered(false)
m_timeout(0), m_maxcall(0), m_dtmfTime(0),
m_toutAns(0), m_dtmfSeq(0), m_answered(false)
{
init();
}
@ -343,8 +343,8 @@ Channel::Channel(Driver* driver, const char* id, bool outgoing)
Channel::Channel(Driver& driver, const char* id, bool outgoing)
: CallEndpoint(id),
m_parameters(""), m_driver(&driver), m_outgoing(outgoing),
m_timeout(0), m_maxcall(0),
m_dtmfTime(0), m_dtmfSeq(0), m_answered(false)
m_timeout(0), m_maxcall(0), m_dtmfTime(0),
m_toutAns(0), m_dtmfSeq(0), m_answered(false)
{
init();
}
@ -529,8 +529,11 @@ void Channel::status(const char* newstat)
Lock lock(mutex());
m_status = newstat;
if (!m_answered && (m_status == YSTRING("answered"))) {
m_maxcall = 0;
m_answered = true;
// stop pre-answer timeout, restart answered timeout
m_maxcall = 0;
if (m_toutAns)
timeout(Time::now() + m_toutAns*(u_int64_t)1000);
}
}
@ -539,19 +542,27 @@ const char* Channel::direction() const
return m_outgoing ? "outgoing" : "incoming";
}
void Channel::setMaxcall(const Message* msg)
void Channel::setMaxcall(const Message* msg, int defTout)
{
int tout = msg ? msg->getIntValue(YSTRING("maxcall")) : 0;
if (tout > 0)
maxcall(Time::now() + tout*(u_int64_t)1000);
else
int tout = msg ? msg->getIntValue(YSTRING("timeout"),defTout) : defTout;
if (tout > 0) {
m_toutAns = tout;
timeout(Time::now() + tout*(u_int64_t)1000);
}
else if (tout == 0) {
m_toutAns = 0;
timeout(0);
}
if (m_answered)
maxcall(0);
if (msg) {
tout = msg->getIntValue(YSTRING("timeout"),-1);
if (tout > 0)
timeout(Time::now() + tout*(u_int64_t)1000);
else if (tout == 0)
else if (msg) {
tout = msg->getIntValue(YSTRING("maxcall"),-1);
if (tout > 0) {
timeout(0);
maxcall(Time::now() + tout*(u_int64_t)1000);
}
else if (tout == 0)
maxcall(0);
}
}
@ -647,8 +658,10 @@ bool Channel::msgRinging(Message& msg)
bool Channel::msgAnswered(Message& msg)
{
m_maxcall = 0;
m_answered = true;
int tout = msg.getIntValue(YSTRING("timeout"),m_toutAns);
m_toutAns = (tout > 0) ? tout : 0;
status("answered");
m_answered = true;
if (m_billid.null())
m_billid = msg.getValue(YSTRING("billid"));
return true;
@ -752,14 +765,14 @@ void Channel::statusParams(String& str)
if (m_timeout) {
str << ",timeout=";
if (m_timeout > t)
str << (unsigned int)((m_timeout - t) / 1000);
str << (unsigned int)((m_timeout - t + 500) / 1000);
else
str << "expired";
}
if (m_maxcall) {
str << ",maxcall=";
if (m_maxcall > t)
str << (unsigned int)((m_maxcall - t) / 1000);
str << (unsigned int)((m_maxcall - t + 500) / 1000);
else
str << "expired";
}
@ -795,9 +808,7 @@ bool Channel::callRouted(Message& msg)
void Channel::callAccept(Message& msg)
{
status("accepted");
int tout = msg.getIntValue("timeout", m_driver ? m_driver->timeout() : 0);
if (tout > 0)
timeout(Time::now() + tout*(u_int64_t)1000);
setMaxcall(msg,m_driver ? m_driver->timeout() : 0);
if (m_billid.null())
m_billid = msg.getValue(YSTRING("billid"));
m_targetid = msg.getValue(YSTRING("targetid"));

View File

@ -3059,6 +3059,7 @@ bool YateH323Chan::msgRinging(Message& msg)
bool YateH323Chan::msgAnswered(Message& msg)
{
Channel::msgAnswered(msg);
if (!m_conn)
return false;
m_conn->rtpForward(msg);

View File

@ -1293,6 +1293,7 @@ void SigChannel::handleEvent(SignallingEvent* event)
bool SigChannel::msgProgress(Message& msg)
{
Channel::msgProgress(msg);
Lock lock(m_mutex);
setState("progressing");
if (!m_call)
@ -1321,6 +1322,7 @@ bool SigChannel::msgProgress(Message& msg)
bool SigChannel::msgRinging(Message& msg)
{
Channel::msgRinging(msg);
Lock lock(m_mutex);
setState("ringing");
if (!m_call)
@ -1358,6 +1360,7 @@ bool SigChannel::msgRinging(Message& msg)
bool SigChannel::msgAnswered(Message& msg)
{
Channel::msgAnswered(msg);
Lock lock(m_mutex);
setState("answered");
if (!m_call)
@ -1672,16 +1675,17 @@ void SigChannel::setState(const char* state, bool updateStatus, bool showReason)
m_call,this);
return;
}
#ifndef DEBUG
if (!updateStatus)
return;
#endif
String show;
show << "Call " << state;
if (showReason)
show << ". Reason: '" << m_reason << "'";
if (!m_call)
show << ". No signalling call ";
if (updateStatus)
Debug(this,DebugCall,"%s [%p]",show.c_str(),this);
else
DDebug(this,DebugCall,"%s [%p]",show.c_str(),this);
Debug(this,DebugCall,"%s [%p]",show.c_str(),this);
}
void SigChannel::evInfo(SignallingEvent* event)

View File

@ -353,7 +353,7 @@ private:
bool m_hangup; // Hang up flag: True - already hung up
String m_reason; // Hangup reason
// Timeouts
u_int64_t m_timeout; // Timeout for not answered outgoing connections
int64_t m_presTimeout; // Maxcall after waiting for presence
// Transfer
bool m_transferring; // The call is already involved in a transfer
String m_transferStanzaId; // Sent transfer stanza id used to track the result
@ -850,7 +850,7 @@ YJGConnection::YJGConnection(Message& msg, const char* caller, const char* calle
m_offerP2PTransport(false), m_offerGRawTransport(false),
m_redirectCount(s_redirectCount), m_dtmfMeth(s_dtmfMeth),
m_secure(s_useCrypto), m_secureRequired(s_cryptoMandatory),
m_hangup(false), m_timeout(0), m_transferring(false), m_recvTransferStanza(0),
m_hangup(false), m_presTimeout(-1), m_transferring(false), m_recvTransferStanza(0),
m_dataFlags(0), m_ftStatus(FTNone), m_ftHostDirection(FTHostNone),
m_connSocksServer(msg.getBoolValue("socksserver",true))
{
@ -907,28 +907,13 @@ YJGConnection::YJGConnection(Message& msg, const char* caller, const char* calle
m_transferFrom ? ". Transferred from=": "",
m_transferFrom.safe(),this);
// Set timeout and maxcall
int tout = msg.getIntValue("timeout",-1);
if (tout > 0)
timeout(Time::now() + tout*(u_int64_t)1000);
else if (tout == 0)
timeout(0);
m_timeout = msg.getIntValue("maxcall",0) * (u_int64_t)1000;
u_int64_t pendingTimeout = s_pendingTimeout * (u_int64_t)1000;
u_int64_t timenow = Time::now();
if (m_timeout && pendingTimeout >= m_timeout) {
maxcall(timenow + m_timeout);
m_timeout = 1;
}
else {
maxcall(timenow + pendingTimeout);
if (m_timeout) {
// Set a greater timeout for file transfer due to
// TCP connect
if (m_ftStatus == FTNone)
m_timeout += timenow - pendingTimeout;
else
m_timeout += timenow;
}
setMaxcall(msg);
if (!available) {
u_int64_t timeNow = Time::now();
// Save maxcall for later, set presence retrieval timeout instead
m_presTimeout = maxcall() ? maxcall() - timeNow : 0;
if (s_pendingTimeout)
maxcall(s_pendingTimeout * (u_int64_t)1000 + timeNow);
}
XDebug(this,DebugInfo,"Time: " FMT64 ". Maxcall set to " FMT64 " us. [%p]",
Time::now(),maxcall(),this);
@ -957,7 +942,7 @@ YJGConnection::YJGConnection(JGEvent* event)
m_offerP2PTransport(false), m_offerGRawTransport(false),
m_redirectCount(0), m_dtmfMeth(s_dtmfMeth),
m_secure(s_useCrypto), m_secureRequired(s_cryptoMandatory),
m_hangup(false), m_timeout(0), m_transferring(false), m_recvTransferStanza(0),
m_hangup(false), m_presTimeout(-1), m_transferring(false), m_recvTransferStanza(0),
m_dataFlags(0), m_ftStatus(FTNone), m_ftHostDirection(FTHostNone),
m_connSocksServer(false)
{
@ -1201,6 +1186,7 @@ void YJGConnection::disconnected(bool final, const char* reason)
bool YJGConnection::msgProgress(Message& msg)
{
DDebug(this,DebugInfo,"msgProgress [%p]",this);
Channel::msgProgress(msg);
if (m_ftStatus != FTNone)
return true;
if (ringFlag(RingWithContent) && msg.getBoolValue("earlymedia",true) &&
@ -1215,6 +1201,7 @@ bool YJGConnection::msgProgress(Message& msg)
bool YJGConnection::msgRinging(Message& msg)
{
DDebug(this,DebugInfo,"msgRinging [%p]",this);
Channel::msgRinging(msg);
if (m_ftStatus != FTNone)
return true;
m_ringFlags |= RingRinging;
@ -1226,6 +1213,7 @@ bool YJGConnection::msgRinging(Message& msg)
bool YJGConnection::msgAnswered(Message& msg)
{
Debug(this,DebugCall,"msgAnswered [%p]",this);
m_presTimeout = -1;
if (m_ftStatus == FTNone) {
m_mutex.lock();
if (!m_audioContent || ((m_sessVersion != JGSession::Version0) && m_audioContent->isEarlyMedia()))
@ -1892,7 +1880,11 @@ bool YJGConnection::presenceChanged(bool available, NamedList* params)
Lock lock(m_mutex);
if (m_state == Terminated)
return false;
maxcall(m_timeout);
if (m_presTimeout > 0)
maxcall(m_presTimeout + Time::now());
else if (m_presTimeout)
maxcall(0);
m_presTimeout = -1;
// Check if unavailable in any other states
if (!available) {
if (!m_hangup) {
@ -2164,6 +2156,7 @@ void YJGConnection::processActionAccept(JGEvent* event)
{
// Update media
Debug(this,DebugCall,"Remote peer answered the call [%p]",this);
m_presTimeout = -1;
m_state = Active;
status("answered");
for (ObjList* o = event->m_contents.skipNull(); o; o = o->skipNext()) {

View File

@ -6529,6 +6529,7 @@ bool YateSIPConnection::msgRinging(Message& msg)
bool YateSIPConnection::msgAnswered(Message& msg)
{
Channel::msgAnswered(msg);
Lock lock(driver());
if (m_hungup)
return false;

View File

@ -1631,6 +1631,7 @@ private:
u_int64_t m_timeout;
u_int64_t m_maxcall;
u_int64_t m_dtmfTime;
unsigned int m_toutAns;
unsigned int m_dtmfSeq;
String m_dtmfText;
String m_dtmfDetected;
@ -1910,15 +1911,17 @@ public:
/**
* Set the time this channel will time out on outgoing calls
* @param msg Reference of message possibly holding "maxcall" parameter
* @param defTout Default timeout to apply, negative to not alter
*/
inline void setMaxcall(const Message& msg)
{ setMaxcall(&msg); }
inline void setMaxcall(const Message& msg, int defTout = -1)
{ setMaxcall(&msg,defTout); }
/**
* Set the time this channel will time out on outgoing calls
* @param msg Pointer to message possibly holding "maxcall" parameter
* @param defTout Default timeout to apply, negative to not alter
*/
void setMaxcall(const Message* msg);
void setMaxcall(const Message* msg, int defTout = -1);
/**
* Get the connected channel identifier.