2009/4/1 Frank Durda IV frank.durda@hypercube-llc.com:
Now, I take it you are asking what happens in the case of the INVITE coming in from the calling party, and later the 183 or 200 comes back from the called party, and for each of these a force_rtp_proxy() is performed. How do you get both directions of the call to go to the same rtpproxy instance, or if something else changes after the 200 OK, even though nathelper maintains no call state? You have three options.
In fact I expected that, being transaction stateful, *SER uses the same RtpProxy when running force_rtpproxy in request and response(s) belongs to the same transaction. I'm not sure of it anyway.
My doubt was about the case of re-INVITE/BYE. More inline:
The limitions implicit in having the script specify the proxy to use via the Nn flag, combined with what I consider to be the most stupid/horrible missing bit of functionality in SER (that of not being able to pass variables to functions/modules*), and you are greatly limited in what smart things you can do to scale SER+rtpproxy, if you do it via the ser.cfg file.
*I note OpenSER supposedly allows you to pass variables to functions (at least reading their lexical scanner seems to have added the rules to allow this, but I don't know if it actually works or not. I would certainly use it for a large number of other things if it was available.)
yes, OpenSER allows pseudo-variable as argument in lots of functions (not all).
Three, SER quietly (and possibly inadvertantly) takes care of this issue by using the Call-ID as the variable value that is used to select the rtpproxy. The Call-ID string is ground-up in a hashing algorithm (see select_rtpp_node() in modules/nathelper/nathelper.c) and a value between 0 and N comes out of that, and that combined with the total number of weight possibilities selected at start time, skipping any disabled proxies (presumably because they became unresponsive in the past) dictates which rtpproxy that call will be sent to.
Ok, but since the chosen RtpProxy depends on the Call-ID and weight combination, how to ensure that force_rtpproxy() in 200 selects the same instance than the one selected by force_rtpproxy() in the INVITE? (the same for re-INVITE/BYE).
This is, a call is established under some circumstances an these cause a selection of a specific RtpProxy. After 30 minutes the call is put on hold by sending a re-INVITE. Now (after 30 minutes) the circumstances have changed so the same Call-ID causes force_rtpproxy() to select other RtpProxy.
This basically means that the RTP session would remain open in the first RtpProxy (until it expires?). And this also means that *SER script cannot rely on the return code of "force_rtpproxy(l)" that is very useful to check if the current in-dialog INVITE belongs to a call for which initially force_rtpproxy() took place.
So, this means that each time force or unforce rtpproxy calls, this same hash gets performed on the same Call-ID for a given call, and except for rare cases where a proxy has failed, you will end up sending the force/unforce for a given Call-ID to the same rtpproxy instance every time. At least, this is how I read the source code.
I believe that if the decision jsut depends on the Call-ID, but since it also depends on the weight... perhaps I miss something?
I'll point out that if the initial selection of rtpproxy from the first force_rtp_proxy() of a given call session had simply been recorded as an integer somewhere with the other trivia that is maintained for the duration of a given call session,
It could be added as parameter to the Record-Route header (obviously loose routing is required if we want the proxy to manage the RTP stream via RtpProxy).
This is:
- In the initial INVITE force_rtpproxy() sets some variable ($rtpproxy_instance = 3).
- After it, the *SER script adds a parameter to Record-Route: Record-Route: sip:1.2.3.4:5060;rtpproxy_instance=1
- Later when processing the 200 (or ACK if it has SDP), re-INVITE or BYE, the *SER script reads the "rtpproxy_instance" from Route header and set the RtpProxy according to it (in Kamailio there is a function "set_rtpproxy").
Does it make sense?
Thanks a lot for your response.