Domanda

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..

È stato utile?

Soluzione

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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top