atom feed6 messages in RFC 2543 old style transactions
FromSent OnAttachments
Frederic TardifAug 16, 2012 5:15 pm 
M. RanganathanAug 16, 2012 5:48 pm 
Frederic TardifAug 16, 2012 6:38 pm 
Jean DeruelleAug 17, 2012 1:28 am 
Frederic TardifAug 17, 2012 10:18 am 
M. RanganathanAug 17, 2012 10:43 am 
Subject:Re: RFC 2543 old style transactions
From:M. Ranganathan (
Date:Aug 17, 2012 10:43:33 am

You could mark a request "old style" when the via header branch is being parsed so as to avoid having to compare again while looking for transaction matches. (i.e. look for the magic cookie prefix while it is being read by the parser and store it in the message somewhere). It would be a very minor optimization.


(I noticed the idle loop consumes 100% CPU when nothing else is running... :-) )

On Fri, Aug 17, 2012 at 1:18 PM, Frederic Tardif <>wrote:

you were right Jean, it was probably too late when I started to fiddle in this yesterday evening...

I kept skeptic about the lower case magic cookie, but I figured out that the request.transactionId (key) is always lower case, so no reason to get into the loop. However, I had profiling traces under load that showed the heavy usage of this method. But these traces had been taken a while ago, maybe some stack optimization happened in the mean time.

On Fri, Aug 17, 2012 at 4:28 AM, Jean Deruelle <>wrote:

Hi Frederic,

If you look at the code you pasted previously you will see that it is used as well already in if (key.startsWith(SIPConstants.BRANCH_MAGIC_COOKIE_LOWER_CASE)) { return retval; } right above the code in yellow you want to add. key being the TransactionId ie branchId from the via header for RFC 3261 or other means for RFC 2543. This would prevent the stack from looping over the transactions as it will return directly even if retval is null (ie no transactions found from the lookup in the map). It would seem to happen only if the message doesn't have a branchId set at the time of the calling which would come only from RFC 2543 endpoints.

I would be interested to understand why it takes 3% of the CPU, some step by step debugging would be interesting here.

On Fri, Aug 17, 2012 at 3:38 AM, Frederic Tardif <> wrote:

you are right Ranga, but the magic cookie is only used within the SipServerTransaction#isMessagePartOfTransaction(); this does not avoid the full loop though all the Tx on initial requests.

But I agree we should better use the Magic cookie instead of adding a new stack configuration.

here is my suggestion for SipTransactionStack#findTransaction :

public SIPTransaction findTransaction(SIPMessage sipMessage, boolean isServer) { SIPTransaction retval = null; try { if (isServer) { Via via = sipMessage.getTopmostVia(); if (via.getBranch() != null) { String key = sipMessage.getTransactionId();

retval = (SIPTransaction) serverTransactionTable.get(key); if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) logger.logDebug("serverTx: looking for key " + key + " existing=" + serverTransactionTable); if (key.startsWith(SIPConstants.BRANCH_MAGIC_COOKIE_LOWER_CASE)) { return retval; }

if (!via.getBranch().startsWith(SIPConstants.BRANCH_MAGIC_COOKIE)) { // Need to scan the table for old style transactions (RFC 2543 // style) Iterator<SIPServerTransaction> it = serverTransactionTable.values().iterator(); while (it.hasNext()) { SIPServerTransaction sipServerTransaction = (SIPServerTransaction); if (sipServerTransaction.isMessagePartOfTransaction(sipMessage)) { retval = sipServerTransaction; return retval; } } } }

} else { Via via = sipMessage.getTopmostVia(); if (via.getBranch() != null) { String key = sipMessage.getTransactionId(); if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) logger.logDebug("clientTx: looking for key " + key); retval = (SIPTransaction) clientTransactionTable.get(key); if (key.startsWith(SIPConstants.BRANCH_MAGIC_COOKIE_LOWER_CASE)) { return retval; } if (!via.getBranch().startsWith(SIPConstants.BRANCH_MAGIC_COOKIE)) { // Need to scan the table for old style transactions (RFC 2543 // style). This is terribly slow but we need to do this // for backasswords compatibility. Iterator<SIPClientTransaction> it = clientTransactionTable.values().iterator(); while (it.hasNext()) { SIPClientTransaction clientTransaction = (SIPClientTransaction); if (clientTransaction.isMessagePartOfTransaction(sipMessage)) { retval = clientTransaction; return retval; } } } } }

} finally { if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { logger.logDebug("findTransaction: returning : " + retval); } } return retval; }

On Thu, Aug 16, 2012 at 8:48 PM, M. Ranganathan <>wrote:

Hello Frederic,

I thought that check is triggered by looking at the magic cookie that precedes the branch ID.

Does that not suffice? If that does NOT suffice (please explain why) then there's a stack already in SIPTransactionStack which can be exposed.

On Thu, Aug 16, 2012 at 8:15 PM, Frederic Tardif <> wrote:


in SipTransactionStack#findTransaction, if the serverTx is not found within the serverTransactionTable (Map), an extra check is done according to "old style transaction" RFC 2543. This extra check requires a complete loop through all existing serverTx with a quite fancy matching rule (SipServerTransaction#isMessagePartOfTransaction()). When analyzing class/object time allocation under load, this method uses more than 3% of the processing allocation (when using AUTOMATIC_DIALOG_SUPPORT). Each initiating request will miss the serverTx in the normal serverTransactionMap and will try to loop through all serverTx in order to possibly match an "old style RFC 2543 transaction type". In production environment that deals with more than hundred cps with allocation counted in minutes, the loop can be fairly costly.

To avoid this extra cost when possible, I suggest a new Stack Configuration RFC_2543_TRANSACTION_SUPPORT set by default to true. This would aim to alleviate extra computation when the context guarantee non "old style RFC 2543" endpoints.

any objections?

merci Frederic