public void RemoveExpiredTransactions()
{
try
{
lock (m_transactions)
{
List <string> expiredTransactionIds = new List <string>();
foreach (SIPTransaction transaction in m_transactions.Values)
{
if (transaction.TransactionType == SIPTransactionTypesEnum.Invite)
{
if (transaction.TransactionState == SIPTransactionStatesEnum.Confirmed)
{
// Need to wait until the transaction timeout period is reached in case any ACK re-transmits are received.
if (DateTime.Now.Subtract(transaction.CompletedAt).TotalMilliseconds >= m_t6)
{
expiredTransactionIds.Add(transaction.TransactionId);
}
}
else if (transaction.TransactionState == SIPTransactionStatesEnum.Completed)
{
if (DateTime.Now.Subtract(transaction.CompletedAt).TotalMilliseconds >= m_t6)
{
expiredTransactionIds.Add(transaction.TransactionId);
}
}
else if (transaction.HasTimedOut)
{
// For INVITES need to give timed out transactions time to send the reliable repsonses and receive the ACKs.
if (DateTime.Now.Subtract(transaction.TimedOutAt).TotalSeconds >= m_t6)
{
expiredTransactionIds.Add(transaction.TransactionId);
}
}
else if (transaction.TransactionState == SIPTransactionStatesEnum.Proceeding)
{
if (DateTime.Now.Subtract(transaction.Created).TotalMilliseconds >= m_maxRingTime)
{
// INVITE requests that have been ringing too long.
transaction.HasTimedOut = true;
transaction.TimedOutAt = DateTime.Now;
transaction.DeliveryPending = false;
transaction.DeliveryFailed = true;
transaction.FireTransactionTimedOut();
}
}
else if (DateTime.Now.Subtract(transaction.Created).TotalMilliseconds >= m_t6)
{
//logger.LogDebug("INVITE transaction (" + transaction.TransactionId + ") " + transaction.TransactionRequestURI.ToString() + " in " + transaction.TransactionState + " has been alive for " + DateTime.Now.Subtract(transaction.Created).TotalSeconds.ToString("0") + ".");
if (transaction.TransactionState == SIPTransactionStatesEnum.Calling ||
transaction.TransactionState == SIPTransactionStatesEnum.Trying)
{
transaction.HasTimedOut = true;
transaction.TimedOutAt = DateTime.Now;
transaction.DeliveryPending = false;
transaction.DeliveryFailed = true;
transaction.FireTransactionTimedOut();
}
}
}
else if (transaction.HasTimedOut)
{
expiredTransactionIds.Add(transaction.TransactionId);
}
else if (DateTime.Now.Subtract(transaction.Created).TotalMilliseconds >= m_t6)
{
if (transaction.TransactionState == SIPTransactionStatesEnum.Calling ||
transaction.TransactionState == SIPTransactionStatesEnum.Trying ||
transaction.TransactionState == SIPTransactionStatesEnum.Proceeding)
{
//logger.LogWarning("Timed out transaction in SIPTransactionEngine, should have been timed out in the SIP Transport layer. " + transaction.TransactionRequest.Method + ".");
transaction.DeliveryPending = false;
transaction.DeliveryFailed = true;
transaction.TimedOutAt = DateTime.Now;
transaction.HasTimedOut = true;
transaction.FireTransactionTimedOut();
}
expiredTransactionIds.Add(transaction.TransactionId);
}
}
foreach (string transactionId in expiredTransactionIds)
{
if (m_transactions.ContainsKey(transactionId))
{
SIPTransaction expiredTransaction = m_transactions[transactionId];
expiredTransaction.FireTransactionRemoved();
RemoveTransaction(expiredTransaction);
}
}
}
//PrintPendingTransactions();
}
catch (Exception excp)
{
logger.LogError("Exception RemoveExpiredTransaction. " + excp.Message);
}
}