Question

I have a Kamailio 4.0.4 proxy (K) running registrar and tm. There are multiple clients for some AORs and they all auto-accept certain INVITEs which is causing a race condition and having 200 OKs from multiple branches being sent to the callee.

Scenario: - A sends invite to B

  • K finds 2 contacts in the uloc for B, let's call them B1 & B2
  • INVITE is branched and sent to B1 and B2 Note: B1 has a link latency of 100ms and B2 latency of 150ms

  • Both B1 and B2 auto-accept with 200 OK instantly as they get it

  • 200ms after branching INVITE, K gets 200 OK from B1 and relays it to A

  • K also CANCELs the INVITE to B2
  • A is actually a local AS which ACKs the 200 OK back to B1 instantly

  • Now the problem is that B2 already sent a 200 OK 50ms ago and won't be receiving the CANCEL for another 150ms

  • So the 200 OK from B2 comes to K but the call is already setup between A and B1

  • What happens is that the 200 OK is relayed to A which at this point gets utterly confused because it's not a very good AS to be honest.

Now to the actual question, how do I stop the extra 200 OK from going to A?

I can see a few options of how it should work:

  • Drop the 200 OK, just throw it away. B2 should not resend it because the CANCEL will hit it soon
  • ACK + BYE the 200 OK from inside Kamailio, but this will result in a media session being brought up and torn down immediately by B2

I can't even find an RFC covering this race condition..

Was it helpful?

Solution

IIRC, according to the rfc, the 200ok responses have to be always forwarded, being the decision of caller to pick one and send a ACK+BYE for the other.

The easy solution with kamailio is to drop any 200ok once you got one. The callee might not stop resending it even when a CANCEL arrives, will wait for ACK and eventually BYE.

TM module will always forward the 200ok, as per rfc. If you want to drop in kamailio.cfg, a possible solution:

  • use reply_route { ... } block to intercept 200ok for invite
  • use htable to store when first 200ok is received (the key can be call-id)
  • use cfgutils to get locks that will protect against races to access/update the htable
  • processing logic: if it is a 200ok for INVITE, lock for htable, check if there is a key for that callid. If yes, unlock and drop. If not, add an item with call-id as a key, unlock and let the response go on
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top