[SR-Users] rtpengine_manage() in async tasks

Daniel-Constantin Mierla miconda at gmail.com
Fri Jan 18 10:30:16 CET 2019


Hello,

rtpengine_manage() as well as rtpproxy_manage() do a delete command if
it is a failure processing context, like failure_route or resuming a
suspended transaction (which is like canceling the suspended branch).

The reason for doing delete is to allow disengaging rtpengine after a
forwarding failure, to allow the option of no rtp relay for next
attempts. The manage function has its roots in the default configuration
time from several years ago where in failur_route there was an unforce
proxy command, and engaging the rtpproxy was in branch route.

So, in such cases, if you want to route to a new destination, you should
use the function in branch_route. Which is actually a good practice,
using rtp relay makes sense only if there is an outgoing branch.

Cheers,
Daniel

On 15.01.19 02:36, Alex Balashov wrote:
> Hi,
>
> I've run into an issue with handling reinvites in async task
> workers--which I need to do in order to introduce a small delay to avoid
> a UA race condition--in which some state that is necessary for
> rtpengine_manage() to do the right thing seems to be lost.
>
> Specifically, if I do this:
>
> --
> loadmodule "mqueue"
> loadmodule "rtimer"
>
> ...
>
> modparam("rtimer", "timer", "name=reinvite_q1;interval=10000u;mode=1;")
> modparam("rtimer", "exec", "timer=reinvite_q1;route=REINVITE_DEQUEUE")
>
> modparam("mqueue", "mqueue", "name=reinvite_q");
>
> ...
>
> route {
>    ...
>
>    if(has_totag()) {
>       if(loose_route()) {
>          ...
>
> 	 if(is_method("INVITE")) {
> 	    if(!t_suspend()) {
> 	       sl_send_reply("500", "Server Internal Error");
>                exit;
>             }
>
>             mq_add("reinvite_q", "$T(id_index):$T(id_label)", "");
>          } else 
> 	    route(IN_DLG_REQ);
> 	
>       exit;
>    }
>
>    ...
> }
>
> route[REINVITE_DEQUEUE] {
>    while(mq_fetch("reinvite_q")) {
>       $var(id) = $(mqk(reinvite_q){s.select,0,:}{s.int});
>       $var(label) = $(mqk(reinvite_q){s.select,1,:}{s.int});
>
>       t_continue("$var(id)", "$var(label)", "IN_DLG_REQ");
>    }
> }
>
> route[IN_DLG_REQ] {
>    handle_ruri_alias();
>
>    if(is_method("BYE"))
>       rtpengine_manage();
>    else if(is_method("INVITE") && sdp_content()) 
>       rtpengine_manage("replace-origin replace-session-connection ICE=remove")
>
>    t_on_reply("MAIN_REPLY");
>
>    if(!t_relay())
>       sl_reply_error();
> }
>
> onreply_route[MAIN_REPLY] {
>    if(is_method("INVITE") && sdp_content()) 
>       rtpengine_manage("replace-origin replace-session-connection ICE=remove");
> }
> --
>
> What I find is that if I generate a reinvite from either side,
> rtpengine_manage() passes through the SDP offer in the reinvite
> unadulterated, although the answer returns properly adulterated by
> RTPEngine.
>
> The same thing occurs if I use 'async', which as I gather is just a
> wrapper of convenience around t_suspend/t_continue() anyway. That module
> won't do for my purposes because I need a millisecond-level delay
> resolution rather than second-level, anyhow.
>
> Anyway, surely enough, this is because the execution context is one that
> insinuates a stream deletion. When the reinvite offer comes across and I
> call rtpengine_manage(), the command sent is 'delete':
>
> --
> Jan 14 20:24:23 staccato.evaristesys.com rtpengine[33830]: INFO: [c94347dcf92e7ccc10dee84c4e0d1c8a]: Received command 'delete' from 209.51.167.66:39788
> --
>
> The RTPEngine module documentation actually warns about this:
>
> https://kamailio.org/docs/modules/5.2.x/modules/rtpengine.html#rtpengine.f.rtpengine_manage
>
> But this insight is buried in the fourth bullet point:
>
>    "If BYE or CANCEL, or called within a FAILURE_ROUTE[], then call 
>     rtpengine_delete(). Be careful with calling this function after 
>     resuming a suspended transaction (e.g., after t_continue()), 
>     because the context of executed route is FAILURE ROUTE (in other 
>     words, rtpengine_manage() in the route block of t_continue() 
>     does the same as in failure_route)."
>
> This would lead one to believe that it applies only in the context of
> handling a BYE or CANCEL in a resumed transaction, when in fact it seems
> to hold true of non-BYE/CANCEL and non-failure contexts as well, as can
> be clearly seen with the reinvite. 
>
> The behaviour is exactly as expected if I don't use rtpengine_manage()
> and instead manually call rtpengine_offer()/rtpengine_answer(). And
> expected behaviour comes from rtpengine_manage() if I don't handle the
> request in a resumed transaction context. 
>
> This yields the fundamental question:
>
> Is there any way to have my cake and eat it too? I really want to use
> rtpengine_manage() because I need to handle a potential SDP offer-in-ACK
> scenario and don't want to do a bunch of state-keeping in order to use
> the correct choice of rtpengine_{offer|answer}() in the right context,
> which is a problem rtpengine_manage() solves beautifully. At the same
> time, I absolutely need the slight reinvite delay that can be
> accomplished via async processing; a UA on this side has a nasty habit
> of sending a reinvite almost simultaneously to the 2xx answer for the
> INVITE transaction, leading to indeterminate egress velocity for those
> respective messages out of Kamailio worker threads.
>
> Many thanks in advance!
>
> -- Alex
>
-- 
Daniel-Constantin Mierla -- www.asipto.com
www.twitter.com/miconda -- www.linkedin.com/in/miconda
Kamailio World Conference - May 6-8, 2019 -- www.kamailioworld.com
Kamailio Advanced Training - Mar 4-6, 2019 in Berlin; Mar 25-27, 2019, in Washington, DC, USA -- www.asipto.com




More information about the sr-users mailing list