Discussion:
[SR-Users] Dispatcher - failure_route to specific node
Nicholas Gill
2014-09-12 06:39:13 UTC
Permalink
Hello sr-users,

We're evaluating Kamailio to proxy to a number of FreeSWITCH backend
servers with the dispatcher module.

In some specific scenarios it matters to which node the request is sent.
In these cases we've configured FS to respond to the invite with 302 and
provide a custom header which contains the uri of the needed backend
server (Intending to emulate the behaviour of 305 Use Proxy).

To attempt to handle this I've tried the following in kamailio:

onreply_route[MANAGE_REPLY] {
...
if (t_check_status("302") and is_present_hf("X-imx-redirect"))
{
$avp(imx-redirect) = $hdr(X-imx-redirect);
xlog("SCRIPT: REDIRECT, Store avp for redirect:
$avp(imx-redirect)\n");
}
}

Then in the dispatch failure route:

if ($avp(imx-redirect) != $null)
{
$du = $avp(imx-redirect);
xlog("SCRIPT: REDIRECT: going to <$ru> via <$du>\n");
route(RELAY);
exit;
}

Which results in the following sip event sequence:

// Normal invite sequence
FS1 -> Kamailio SIP/2.0 302 Moved Temporarily (X-imx-redirect = sip:FS2...)
Kamailio -> FS1 ACK
Kamailio -> Caller SIP/2.0 407 Proxy Authentication Required

Then the caller generates a new INVITE however I'm unsure how to route
this INVITE to the specific node. The avp appears (intentionally) tied
to the transaction so doesn't seem to be able to be used to correlate in
this scenario.

Advice on how to redirect from a backend server to another specific
backend server behind Kamailio would be greatly appreciated.

Cheers,

-nick
Nicholas Gill
2014-09-12 06:02:15 UTC
Permalink
Hello sr-users,

We're using Kamailio to proxy to a number of FreeSWITCH backend servers
with the dispatcher module.

In some specific scenarios it matters to which node the request is sent.
In these cases we've configured FS to respond to the invite with 302 and
provide a custom header which contains the uri of the needed backend
server (Intending to emulate the behaviour of 305 Use Proxy).

To attempt to handle this I've tried the following in kamailio:

onreply_route[MANAGE_REPLY] {
...
if (t_check_status("302") and is_present_hf("X-imx-redirect"))
{
$avp(imx-redirect) = $hdr(X-imx-redirect);
xlog("SCRIPT: REDIRECT, Store avp for redirect:
$avp(imx-redirect)\n");
}
}

Then in the dispatch failure route:

if ($avp(imx-redirect) != $null)
{
$du = $avp(imx-redirect);
xlog("SCRIPT: REDIRECT: going to <$ru> via <$du>\n");
route(RELAY);
exit;
}

Which results in the following sip event sequence:

// Normal invite sequence
FS1 -> Kamailio SIP/2.0 302 Moved Temporarily (X-imx-redirect = sip:FS2...)
Kamailio -> FS1 ACK
Kamailio -> Caller SIP/2.0 407 Proxy Authentication Required

Then the caller generates a new INVITE however I'm unsure how to route
this INVITE to the specific node. The avp appears (intentionally) tied
to the transaction so doesn't seem to be able to be used to correlate in
this scenario.

Advice on how to redirect from a backend server to another specific
backend server behind Kamailio would be greatly appreciated.

Cheers,

-nick
Federico Cabiddu
2014-09-13 16:34:23 UTC
Permalink
Hi,

I'm not sure that I fully understand your scenario, there are things not
clear to me, like: who is sending the 407? In your script snippets it seems
that upon receiving the 302, in the failure route you set the $du and then
you pass the message to a RELAY route, which I suppose sends the 407 reply.
If you don't need for special reasons that the user performs a proxy
authentication, in the failure route you could just relay the INVITE to the
target FreeSWITCH after setting $du to the value of your custom header.

Hope this helps.

Regards,

Federico
Post by Nicholas Gill
Hello sr-users,
We're using Kamailio to proxy to a number of FreeSWITCH backend servers
with the dispatcher module.
In some specific scenarios it matters to which node the request is sent.
In these cases we've configured FS to respond to the invite with 302 and
provide a custom header which contains the uri of the needed backend server
(Intending to emulate the behaviour of 305 Use Proxy).
onreply_route[MANAGE_REPLY] {
...
if (t_check_status("302") and is_present_hf("X-imx-redirect"))
{
$avp(imx-redirect) = $hdr(X-imx-redirect);
$avp(imx-redirect)\n");
}
}
if ($avp(imx-redirect) != $null)
{
$du = $avp(imx-redirect);
xlog("SCRIPT: REDIRECT: going to <$ru> via <$du>\n");
route(RELAY);
exit;
}
// Normal invite sequence
FS1 -> Kamailio SIP/2.0 302 Moved Temporarily (X-imx-redirect = sip:FS2...)
Kamailio -> FS1 ACK
Kamailio -> Caller SIP/2.0 407 Proxy Authentication Required
Then the caller generates a new INVITE however I'm unsure how to route
this INVITE to the specific node. The avp appears (intentionally) tied to
the transaction so doesn't seem to be able to be used to correlate in this
scenario.
Advice on how to redirect from a backend server to another specific
backend server behind Kamailio would be greatly appreciated.
Cheers,
-nick
_______________________________________________
SIP Express Router (SER) and Kamailio (OpenSER) - sr-users mailing list
http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-users
Nicholas Gill
2014-09-14 23:09:38 UTC
Permalink
Post by Federico Cabiddu
In your script snippets it seems
that upon receiving the 302, in the failure route you set the $du and then
you pass the message to a RELAY route, which I suppose sends the 407 reply.
This seems to be the case, yes. The 407 comes from kamailio on the
already authenticated call. I presume this is done to trigger the caller
to send another INVITE.
Post by Federico Cabiddu
If you don't need for special reasons that the user performs a proxy
authentication, in the failure route you could just relay the INVITE to the
target FreeSWITCH after setting $du to the value of your custom header.
This is exactly what I'm hoping to do, but I'm not sure of the correct
configuration to achieve this.

It was my intention to relay the INVITE to the target server by setting
the $du and then trigger the RELAY route. I have also tried setting $du
and then calling t_relay() directly, but I suspect I'm missing something
minor but important.

Cheers,

-nick
Federico Cabiddu
2014-09-15 06:03:06 UTC
Permalink
What happens if you call t_relay() after setting $du?

Cheers,

Federico
Post by Federico Cabiddu
In your script snippets it seems
that upon receiving the 302, in the failure route you set the $du and then
you pass the message to a RELAY route, which I suppose sends the 407 reply.
This seems to be the case, yes. The 407 comes from kamailio on the already
authenticated call. I presume this is done to trigger the caller to send
another INVITE.
Post by Federico Cabiddu
If you don't need for special reasons that the user performs a proxy
authentication, in the failure route you could just relay the INVITE to the
target FreeSWITCH after setting $du to the value of your custom header.
This is exactly what I'm hoping to do, but I'm not sure of the correct
configuration to achieve this.
It was my intention to relay the INVITE to the target server by setting
the $du and then trigger the RELAY route. I have also tried setting $du and
then calling t_relay() directly, but I suspect I'm missing something minor
but important.
Cheers,
-nick
_______________________________________________
SIP Express Router (SER) and Kamailio (OpenSER) - sr-users mailing list
http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-users
Nicholas Gill
2014-09-16 01:28:22 UTC
Permalink
Post by Federico Cabiddu
What happens if you call t_relay() after setting $du?
Same result. Kamailio sends 407 to caller, which then creates a new INVITE.

I suspect my configuration doesn't reflect the intent, so I'm adding it
below along with other particulars of the test environment.

Is there a specific way to cause kamailio to relay the INVITE to a
particular server based on a dynamic variable?

Cheers,

-nick

192.168.20.215 - Caller
192.168.20.214:5060 Kamailio (node1.etellicom.com)
192.168.20.214:5080 FS1 (node1.etellicom.com)
192.168.20.198:5080 FS2 (node2.etellicom.com)

Kamailio:

version: kamailio 4.1.5 (x86_64/linux) 2b3d4b

Configuration diff from default:

*** kamailio.cfg.default 2014-08-29 15:07:42.336496172 +1000
--- kamailio.cfg 2014-09-16 10:43:50.199400261 +1000
*************** loadmodule "xmlrpc.so"
*** 283,288 ****
--- 283,296 ----
loadmodule "debugger.so"
#!endif

+ loadmodule "dispatcher.so"
+ modparam("dispatcher", "flags", 2)
+ modparam("dispatcher", "list_file", "/root/dispatcher.list")
+ modparam("dispatcher", "dst_avp", "$avp(AVP_DST)")
+ modparam("dispatcher", "grp_avp", "$avp(AVP_GRP)")
+ modparam("dispatcher", "cnt_avp", "$avp(AVP_CNT)")
+ #modparam("dispatcher", "ds_ping_interval", 60)
+
# ----------------- setting module-specific parameters ---------------


*************** request_route {
*** 491,496 ****
--- 499,509 ----
setflag(FLT_ACC); # do accounting
}

+ if(!ds_is_from_list("1"))
+ {
+ route(DISPATCH);
+ }
+
# dispatch requests to foreign domains
route(SIPOUT);

*************** request_route {
*** 516,521 ****
--- 529,576 ----
route(LOCATION);
}

+ # Dispatch requests
+ route[DISPATCH] {
+
+ # Hash over to uri for test purposes
+ if(!ds_select_dst("1", "2"))
+ {
+ send_reply("404", "No destination");
+ exit;
+ }
+ xlog("L_DBG", "--- SCRIPT: going to <$ru> via <$du>\n");
+ t_on_failure("RTF_DISPATCH");
+ route(RELAY);
+ exit;
+ }
+
+ # Dispatch failure route
+ failure_route[RTF_DISPATCH] {
+ if (t_is_canceled()) {
+ exit;
+ }
+ # next DST - only for 500 or local timeout
+ if (t_check_status("500")
+ or (t_branch_timeout() and !t_branch_replied()))
+ {
+ if(ds_next_dst())
+ {
+ t_on_failure("RTF_DISPATCH");
+ route(RELAY);
+ exit;
+ }
+ }
+
+ if ($avp(imx-redirect) != $null)
+ {
+ $du = $avp(imx-redirect);
+ xlog("SCRIPT: REDIRECT: going to <$ru> via <$du>\n");
+ # route(RELAY);
+ t_relay();
+ exit;
+ }
+
+ }

route[RELAY] {

*************** onreply_route[MANAGE_REPLY] {
*** 911,916 ****
--- 966,977 ----
xdbg("incoming reply\n");
if(status=~"[12][0-9][0-9]")
route(NATMANAGE);
+
+ if (t_check_status("3[0-9][0-9]") and is_present_hf("X-imx-redirect"))
+ {
+ $avp(imx-redirect) = $hdr(X-imx-redirect);
+ xlog("SCRIPT: REDIRECT, Store avp for redirect:
$avp(imx-redirect)\n");
+ }
}

# manage failure routing cases


SIP trace of call intended to be redirected to a specific server.

Scenario starts with normal INVITE, 100, proxy auth from backend server,
INVITE with auth.
When FS2 receives the authenticated invite, it responds with 302 and
indicates via the X-imx-redirect header to redirect the request to FS1.

Then I want to send the INVITE to the given server by setting $du and
calling t_relay() but my current configuration seems to cause kamailio
to respond to the caller with 407 instead.


10:46:27.361991 IP 192.168.20.215.5062 > 192.168.20.214.5060
INVITE sip:*591000-yHh2dn5kNv/R/pZH/***@public.gmane.org SIP/2.0
Via: SIP/2.0/UDP 192.168.20.215:5062;branch=z9hG4bK1598556947
From: "1001" <sip:1001-yHh2dn5kNv/R/pZH/***@public.gmane.org>;tag=1860002040
To: <sip:*591000-yHh2dn5kNv/R/pZH/***@public.gmane.org>
Call-ID: 1766438446-***@public.gmane.org
CSeq: 1 INVITE
Contact: <sip:1001-***@public.gmane.org:5062>
Content-Type: application/sdp
Allow: INVITE, INFO, PRACK, ACK, BYE, CANCEL, OPTIONS, NOTIFY, REGISTER,
SUBSCRIBE, REFER, PUBLISH, UPDATE, MESSAGE
Max-Forwards: 70
User-Agent: Yealink SIP-T38G 38.70.0.115
Supported: replaces
Allow-Events: talk,hold,conference,refer,check-sync
Content-Length: 310

SDP

10:46:27.362567 IP 192.168.20.214.5060 > 192.168.20.215.5062
SIP/2.0 100 trying -- your call is important to us
Via: SIP/2.0/UDP 192.168.20.215:5062;branch=z9hG4bK1598556947
From: "1001" <sip:1001-yHh2dn5kNv/R/pZH/***@public.gmane.org>;tag=1860002040
To: <sip:*591000-yHh2dn5kNv/R/pZH/***@public.gmane.org>
Call-ID: 1766438446-***@public.gmane.org
CSeq: 1 INVITE
Server: kamailio (4.1.5 (x86_64/linux))
Content-Length: 0


10:46:27.362745 IP 192.168.20.214.5060 > 192.168.20.198.5080
INVITE sip:*591000-yHh2dn5kNv/R/pZH/***@public.gmane.org SIP/2.0
Record-Route: <sip:192.168.20.214;lr=on>
Via: SIP/2.0/UDP
192.168.20.214;branch=z9hG4bKa4a8.9a165b4901cf1602b3146c7f0bf0a191.0
Via: SIP/2.0/UDP 192.168.20.215:5062;branch=z9hG4bK1598556947
From: "1001" <sip:1001-yHh2dn5kNv/R/pZH/***@public.gmane.org>;tag=1860002040
To: <sip:*591000-yHh2dn5kNv/R/pZH/***@public.gmane.org>
Call-ID: 1766438446-***@public.gmane.org
CSeq: 1 INVITE
Contact: <sip:1001-***@public.gmane.org:5062>
Content-Type: application/sdp
Allow: INVITE, INFO, PRACK, ACK, BYE, CANCEL, OPTIONS, NOTIFY, REGISTER,
SUBSCRIBE, REFER, PUBLISH, UPDATE, MESSAGE
Max-Forwards: 69
User-Agent: Yealink SIP-T38G 38.70.0.115
Supported: replaces
Allow-Events: talk,hold,conference,refer,check-sync
Content-Length: 310

SDP

10:46:27.383907 IP 192.168.20.198.5080 > 192.168.20.214.5060
SIP/2.0 100 Trying
Via: SIP/2.0/UDP
192.168.20.214;branch=z9hG4bKa4a8.9a165b4901cf1602b3146c7f0bf0a191.0
Via: SIP/2.0/UDP 192.168.20.215:5062;branch=z9hG4bK1598556947
Record-Route: <sip:192.168.20.214;lr=on>
From: "1001" <sip:1001-yHh2dn5kNv/R/pZH/***@public.gmane.org>;tag=1860002040
To: <sip:*591000-yHh2dn5kNv/R/pZH/***@public.gmane.org>
Call-ID: 1766438446-***@public.gmane.org
CSeq: 1 INVITE
User-Agent: IMX
Content-Length: 0


10:46:27.553363 IP 192.168.20.198.5080 > 192.168.20.214.5060
SIP/2.0 407 Proxy Authentication Required
Via: SIP/2.0/UDP
192.168.20.214;branch=z9hG4bKa4a8.9a165b4901cf1602b3146c7f0bf0a191.0
Via: SIP/2.0/UDP 192.168.20.215:5062;branch=z9hG4bK1598556947
From: "1001" <sip:1001-yHh2dn5kNv/R/pZH/***@public.gmane.org>;tag=1860002040
To: <sip:*591000-yHh2dn5kNv/R/pZH/***@public.gmane.org>;tag=Ke2rvve07SK3N
Call-ID: 1766438446-***@public.gmane.org
CSeq: 1 INVITE
User-Agent: IMX
Accept: application/sdp
Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE,
REGISTER, REFER, NOTIFY, PUBLISH, SUBSCRIBE
Supported: timer, path, replaces
Allow-Events: talk, hold, conference, presence, as-feature-event,
dialog, line-seize, call-info, sla, include-session-description,
presence.winfo, message-summary, refer
Proxy-Authenticate: Digest realm="test.etellicom.com", nonce="xxx",
algorithm=MD5, qop="auth"
Content-Length: 0


10:46:27.553574 IP 192.168.20.214.5060 > 192.168.20.198.5080
ACK sip:*591000-yHh2dn5kNv/R/pZH/***@public.gmane.org SIP/2.0
Via: SIP/2.0/UDP
192.168.20.214;branch=z9hG4bKa4a8.9a165b4901cf1602b3146c7f0bf0a191.0
From: "1001" <sip:1001-yHh2dn5kNv/R/pZH/***@public.gmane.org>;tag=1860002040
To: <sip:*591000-yHh2dn5kNv/R/pZH/***@public.gmane.org>;tag=Ke2rvve07SK3N
Call-ID: 1766438446-***@public.gmane.org
CSeq: 1 ACK
Max-Forwards: 69
Content-Length: 0


10:46:27.553718 IP 192.168.20.214.5060 > 192.168.20.215.5062
SIP/2.0 407 Proxy Authentication Required
Via: SIP/2.0/UDP 192.168.20.215:5062;branch=z9hG4bK1598556947
From: "1001" <sip:1001-yHh2dn5kNv/R/pZH/***@public.gmane.org>;tag=1860002040
To: <sip:*591000-yHh2dn5kNv/R/pZH/***@public.gmane.org>;tag=Ke2rvve07SK3N
Call-ID: 1766438446-***@public.gmane.org
CSeq: 1 INVITE
User-Agent: IMX
Accept: application/sdp
Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE,
REGISTER, REFER, NOTIFY, PUBLISH, SUBSCRIBE
Supported: timer, path, replaces
Allow-Events: talk, hold, conference, presence, as-feature-event,
dialog, line-seize, call-info, sla, include-session-description,
presence.winfo, message-summary, refer
Proxy-Authenticate: Digest realm="test.etellicom.com", nonce="xxx",
algorithm=MD5, qop="auth"
Content-Length: 0


10:46:27.592662 IP 192.168.20.215.5062 > 192.168.20.214.5060
ACK sip:*591000-yHh2dn5kNv/R/pZH/***@public.gmane.org SIP/2.0
Via: SIP/2.0/UDP 192.168.20.215:5062;branch=z9hG4bK1598556947
From: "1001" <sip:1001-yHh2dn5kNv/R/pZH/***@public.gmane.org>;tag=1860002040
To: <sip:*591000-yHh2dn5kNv/R/pZH/***@public.gmane.org>;tag=Ke2rvve07SK3N
Call-ID: 1766438446-***@public.gmane.org
CSeq: 1 ACK
Content-Length: 0


10:46:27.630142 IP 192.168.20.215.5062 > 192.168.20.214.5060
INVITE sip:*591000-yHh2dn5kNv/R/pZH/***@public.gmane.org SIP/2.0
Via: SIP/2.0/UDP 192.168.20.215:5062;branch=z9hG4bK416062902
From: "1001" <sip:1001-yHh2dn5kNv/R/pZH/***@public.gmane.org>;tag=1860002040
To: <sip:*591000-yHh2dn5kNv/R/pZH/***@public.gmane.org>
Call-ID: 1766438446-***@public.gmane.org
CSeq: 2 INVITE
Contact: <sip:1001-***@public.gmane.org:5062>
Proxy-Authorization: Digest username="1001", realm="test.etellicom.com",
nonce="xxx", uri="sip:*591000-yHh2dn5kNv/R/pZH/***@public.gmane.org", response="xxx",
algorithm=MD5, cnonce="xxx", qop=auth, nc=00000001
Content-Type: application/sdp
Allow: INVITE, INFO, PRACK, ACK, BYE, CANCEL, OPTIONS, NOTIFY, REGISTER,
SUBSCRIBE, REFER, PUBLISH, UPDATE, MESSAGE
Max-Forwards: 70
User-Agent: Yealink SIP-T38G 38.70.0.115
Supported: replaces
Allow-Events: talk,hold,conference,refer,check-sync
Content-Length: 310

SDP

10:46:27.630721 IP 192.168.20.214.5060 > 192.168.20.215.5062
SIP/2.0 100 trying -- your call is important to us
Via: SIP/2.0/UDP 192.168.20.215:5062;branch=z9hG4bK416062902
From: "1001" <sip:1001-yHh2dn5kNv/R/pZH/***@public.gmane.org>;tag=1860002040
To: <sip:*591000-yHh2dn5kNv/R/pZH/***@public.gmane.org>
Call-ID: 1766438446-***@public.gmane.org
CSeq: 2 INVITE
Server: kamailio (4.1.5 (x86_64/linux))
Content-Length: 0


10:46:27.630896 IP 192.168.20.214.5060 > 192.168.20.198.5080
INVITE sip:*591000-yHh2dn5kNv/R/pZH/***@public.gmane.org SIP/2.0
Record-Route: <sip:192.168.20.214;lr=on>
Via: SIP/2.0/UDP
192.168.20.214;branch=z9hG4bK74a8.d3d3ad8bb9b1c73c12e16cdab447472e.0
Via: SIP/2.0/UDP 192.168.20.215:5062;branch=z9hG4bK416062902
From: "1001" <sip:1001-yHh2dn5kNv/R/pZH/***@public.gmane.org>;tag=1860002040
To: <sip:*591000-yHh2dn5kNv/R/pZH/***@public.gmane.org>
Call-ID: 1766438446-***@public.gmane.org
CSeq: 2 INVITE
Contact: <sip:1001-***@public.gmane.org:5062>
Proxy-Authorization: Digest username="1001", realm="test.etellicom.com",
nonce="xxx", uri="sip:*591000-yHh2dn5kNv/R/pZH/***@public.gmane.org", response="xxx",
algorithm=MD5, cnonce="xxx", qop=auth, nc=00000001
Content-Type: application/sdp
Allow: INVITE, INFO, PRACK, ACK, BYE, CANCEL, OPTIONS, NOTIFY, REGISTER,
SUBSCRIBE, REFER, PUBLISH, UPDATE, MESSAGE
Max-Forwards: 69
User-Agent: Yealink SIP-T38G 38.70.0.115
Supported: replaces
Allow-Events: talk,hold,conference,refer,check-sync
Content-Length: 310

SDP

10:46:27.631731 IP 192.168.20.198.5080 > 192.168.20.214.5060
SIP/2.0 100 Trying
Via: SIP/2.0/UDP
192.168.20.214;branch=z9hG4bK74a8.d3d3ad8bb9b1c73c12e16cdab447472e.0
Via: SIP/2.0/UDP 192.168.20.215:5062;branch=z9hG4bK416062902
Record-Route: <sip:192.168.20.214;lr=on>
From: "1001" <sip:1001-yHh2dn5kNv/R/pZH/***@public.gmane.org>;tag=1860002040
To: <sip:*591000-yHh2dn5kNv/R/pZH/***@public.gmane.org>
Call-ID: 1766438446-***@public.gmane.org
CSeq: 2 INVITE
User-Agent: IMX
Content-Length: 0


10:46:29.187901 IP 192.168.20.198.5080 > 192.168.20.214.5060
SIP/2.0 302 Moved Temporarily
Via: SIP/2.0/UDP
192.168.20.214;branch=z9hG4bK74a8.d3d3ad8bb9b1c73c12e16cdab447472e.0
Via: SIP/2.0/UDP 192.168.20.215:5062;branch=z9hG4bK416062902
Max-Forwards: 69
From: "1001" <sip:1001-yHh2dn5kNv/R/pZH/***@public.gmane.org>;tag=1860002040
To: <sip:*591000-yHh2dn5kNv/R/pZH/***@public.gmane.org>;tag=mQUHyQZ3429NH
Call-ID: 1766438446-***@public.gmane.org
CSeq: 2 INVITE
Contact: "unknown" <sip:node1.etellicom.com>
User-Agent: IMX
Accept: application/sdp
Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE,
REGISTER, REFER, NOTIFY, PUBLISH, SUBSCRIBE
Supported: timer, path, replaces
Allow-Events: talk, hold, conference, presence, as-feature-event,
dialog, line-seize, call-info, sla, include-session-description,
presence.winfo, message-summary, refer
Reason: Q.850;cause=31;text="NORMAL_UNSPECIFIED"
Content-Length: 0
X-imx-redirect: sip:192.168.20.214:5080


10:46:29.188327 IP 192.168.20.214.5060 > 192.168.20.198.5080
ACK sip:*591000-yHh2dn5kNv/R/pZH/***@public.gmane.org SIP/2.0
Via: SIP/2.0/UDP
192.168.20.214;branch=z9hG4bK74a8.d3d3ad8bb9b1c73c12e16cdab447472e.0
From: "1001" <sip:1001-yHh2dn5kNv/R/pZH/***@public.gmane.org>;tag=1860002040
To: <sip:*591000-yHh2dn5kNv/R/pZH/***@public.gmane.org>;tag=mQUHyQZ3429NH
Call-ID: 1766438446-***@public.gmane.org
CSeq: 2 ACK
Max-Forwards: 69
Content-Length: 0


7(17488) ERROR: <script>: SCRIPT: REDIRECT, Store avp for redirect:
sip:192.168.20.214:5080
7(17488) ERROR: <script>: SCRIPT: REDIRECT: going to
<sip:*591000-yHh2dn5kNv/R/pZH/***@public.gmane.org> via <sip:192.168.20.214:5080>

10:46:29.432573 IP 192.168.20.214.5060 > 192.168.20.215.5062
SIP/2.0 407 Proxy Authentication Required
Via: SIP/2.0/UDP 192.168.20.215:5062;branch=z9hG4bK416062902
From: "1001" <sip:1001-yHh2dn5kNv/R/pZH/***@public.gmane.org>;tag=1860002040
To: <sip:*591000-yHh2dn5kNv/R/pZH/***@public.gmane.org>;tag=ZS5Q6Xem0Umaj
Call-ID: 1766438446-***@public.gmane.org
CSeq: 2 INVITE
User-Agent: IMX
Accept: application/sdp
Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE,
REGISTER, REFER, NOTIFY, PUBLISH, SUBSCRIBE
Supported: timer, path, replaces
Allow-Events: talk, hold, conference, presence, as-feature-event,
dialog, line-seize, call-info, sla, include-session-description,
presence.winfo, message-summary, refer
Proxy-Authenticate: Digest realm="test.etellicom.com",
nonce="eac7076b-4c13-4492-838c-14039cc2beb6", stale=true, algorithm=MD5,
qop="auth"
Content-Length: 0


10:46:29.452446 IP 192.168.20.215.5062 > 192.168.20.214.5060
ACK sip:*591000-yHh2dn5kNv/R/pZH/***@public.gmane.org SIP/2.0
Via: SIP/2.0/UDP 192.168.20.215:5062;branch=z9hG4bK416062902
From: "1001" <sip:1001-yHh2dn5kNv/R/pZH/***@public.gmane.org>;tag=1860002040
To: <sip:*591000-yHh2dn5kNv/R/pZH/***@public.gmane.org>;tag=ZS5Q6Xem0Umaj
Call-ID: 1766438446-***@public.gmane.org
CSeq: 2 ACK
Content-Length: 0


10:46:29.490390 IP 192.168.20.215.5062 > 192.168.20.214.5060
INVITE sip:*591000-yHh2dn5kNv/R/pZH/***@public.gmane.org SIP/2.0
Via: SIP/2.0/UDP 192.168.20.215:5062;branch=z9hG4bK2079130033
From: "1001" <sip:1001-yHh2dn5kNv/R/pZH/***@public.gmane.org>;tag=1860002040
To: <sip:*591000-yHh2dn5kNv/R/pZH/***@public.gmane.org>
Call-ID: 1766438446-***@public.gmane.org
CSeq: 3 INVITE
Contact: <sip:1001-***@public.gmane.org:5062>
Proxy-Authorization: Digest username="1001", realm="test.etellicom.com",
nonce="xxx", uri="sip:*591000-yHh2dn5kNv/R/pZH/***@public.gmane.org", response="xxx",
algorithm=MD5, cnonce="xxx", qop=auth, nc=00000001
Content-Type: application/sdp
Allow: INVITE, INFO, PRACK, ACK, BYE, CANCEL, OPTIONS, NOTIFY, REGISTER,
SUBSCRIBE, REFER, PUBLISH, UPDATE, MESSAGE
Max-Forwards: 70
User-Agent: Yealink SIP-T38G 38.70.0.115
Supported: replaces
Allow-Events: talk,hold,conference,refer,check-sync
Content-Length: 310

SDP

10:46:29.490694 IP 192.168.20.214.5060 > 192.168.20.215.5062
SIP/2.0 100 trying -- your call is important to us
Via: SIP/2.0/UDP 192.168.20.215:5062;branch=z9hG4bK2079130033
From: "1001" <sip:1001-yHh2dn5kNv/R/pZH/***@public.gmane.org>;tag=1860002040
To: <sip:*591000-yHh2dn5kNv/R/pZH/***@public.gmane.org>
Call-ID: 1766438446-***@public.gmane.org
CSeq: 3 INVITE
Server: kamailio (4.1.5 (x86_64/linux))
Content-Length: 0


10:46:29.490782 IP 192.168.20.214.5060 > 192.168.20.198.5080
INVITE sip:*591000-yHh2dn5kNv/R/pZH/***@public.gmane.org SIP/2.0
Record-Route: <sip:192.168.20.214;lr=on>
Via: SIP/2.0/UDP
192.168.20.214;branch=z9hG4bK84a8.289b7cd802ed6efd2f25721d6b8f29d6.0
Via: SIP/2.0/UDP 192.168.20.215:5062;branch=z9hG4bK2079130033
From: "1001" <sip:1001-yHh2dn5kNv/R/pZH/***@public.gmane.org>;tag=1860002040
To: <sip:*591000-yHh2dn5kNv/R/pZH/***@public.gmane.org>
Call-ID: 1766438446-***@public.gmane.org
CSeq: 3 INVITE
Contact: <sip:1001-***@public.gmane.org:5062>
Proxy-Authorization: Digest username="1001", realm="test.etellicom.com",
nonce="xxx", uri="sip:*591000-yHh2dn5kNv/R/pZH/***@public.gmane.org", response="xxx",
algorithm=MD5, cnonce="xxx", qop=auth, nc=00000001
Content-Type: application/sdp
Allow: INVITE, INFO, PRACK, ACK, BYE, CANCEL, OPTIONS, NOTIFY, REGISTER,
SUBSCRIBE, REFER, PUBLISH, UPDATE, MESSAGE
Max-Forwards: 69
User-Agent: Yealink SIP-T38G 38.70.0.115
Supported: replaces
Allow-Events: talk,hold,conference,refer,check-sync
Content-Length: 310

SDP
Federico Cabiddu
2014-09-16 05:55:07 UTC
Permalink
Hi,
looking at the trace, it seems to me that the 407 is not sent by Kamailio
but by the FS1 server ("User-Agent: IMX" in the 407, as for the 1st 407
sent by FS2), and that you are probably missing in the trace the messages
between Kamailio and FS1.
If this is the case you could either:
- disable the authentication in freeswitch if you don't need it
- store the custom header when receiving the 302 and use it to set $du upon
receiving the 2nd INVITE
For the latter you can have several solutions, I suggest you to have a a
look at the htable module. For example you could use it to store the key
USERID::CALLID with the value of your custom header and retrieve it when
you receive the authenticated INVITE from the client. Something like

sht(TABLE_NAME=>$fU::$ci) = $avp(imx-redirect);

to store it, and then

$avp(imx-redirect) = sht(TABLE_NAME=>$fU::$ci);

to retrieve it.

Hope this helps.

CHeers,

Federico
Post by Nicholas Gill
Post by Federico Cabiddu
What happens if you call t_relay() after setting $du?
Same result. Kamailio sends 407 to caller, which then creates a new INVITE.
I suspect my configuration doesn't reflect the intent, so I'm adding it
below along with other particulars of the test environment.
Is there a specific way to cause kamailio to relay the INVITE to a
particular server based on a dynamic variable?
Cheers,
-nick
192.168.20.215 - Caller
192.168.20.214:5060 Kamailio (node1.etellicom.com)
192.168.20.214:5080 FS1 (node1.etellicom.com)
192.168.20.198:5080 FS2 (node2.etellicom.com)
version: kamailio 4.1.5 (x86_64/linux) 2b3d4b
*** kamailio.cfg.default 2014-08-29 15:07:42.336496172 +1000
--- kamailio.cfg 2014-09-16 10:43:50.199400261 +1000
*************** loadmodule "xmlrpc.so"
*** 283,288 ****
--- 283,296 ----
loadmodule "debugger.so"
#!endif
+ loadmodule "dispatcher.so"
+ modparam("dispatcher", "flags", 2)
+ modparam("dispatcher", "list_file", "/root/dispatcher.list")
+ modparam("dispatcher", "dst_avp", "$avp(AVP_DST)")
+ modparam("dispatcher", "grp_avp", "$avp(AVP_GRP)")
+ modparam("dispatcher", "cnt_avp", "$avp(AVP_CNT)")
+ #modparam("dispatcher", "ds_ping_interval", 60)
+
# ----------------- setting module-specific parameters ---------------
*************** request_route {
*** 491,496 ****
--- 499,509 ----
setflag(FLT_ACC); # do accounting
}
+ if(!ds_is_from_list("1"))
+ {
+ route(DISPATCH);
+ }
+
# dispatch requests to foreign domains
route(SIPOUT);
*************** request_route {
*** 516,521 ****
--- 529,576 ----
route(LOCATION);
}
+ # Dispatch requests
+ route[DISPATCH] {
+
+ # Hash over to uri for test purposes
+ if(!ds_select_dst("1", "2"))
+ {
+ send_reply("404", "No destination");
+ exit;
+ }
+ xlog("L_DBG", "--- SCRIPT: going to <$ru> via <$du>\n");
+ t_on_failure("RTF_DISPATCH");
+ route(RELAY);
+ exit;
+ }
+
+ # Dispatch failure route
+ failure_route[RTF_DISPATCH] {
+ if (t_is_canceled()) {
+ exit;
+ }
+ # next DST - only for 500 or local timeout
+ if (t_check_status("500")
+ or (t_branch_timeout() and !t_branch_replied()))
+ {
+ if(ds_next_dst())
+ {
+ t_on_failure("RTF_DISPATCH");
+ route(RELAY);
+ exit;
+ }
+ }
+
+ if ($avp(imx-redirect) != $null)
+ {
+ $du = $avp(imx-redirect);
+ xlog("SCRIPT: REDIRECT: going to <$ru> via <$du>\n");
+ # route(RELAY);
+ t_relay();
+ exit;
+ }
+
+ }
route[RELAY] {
*************** onreply_route[MANAGE_REPLY] {
*** 911,916 ****
--- 966,977 ----
xdbg("incoming reply\n");
if(status=~"[12][0-9][0-9]")
route(NATMANAGE);
+
+ if (t_check_status("3[0-9][0-9]") and is_present_hf("X-imx-redirect"
))
+ {
+ $avp(imx-redirect) = $hdr(X-imx-redirect);
$avp(imx-redirect)\n");
+ }
}
# manage failure routing cases
SIP trace of call intended to be redirected to a specific server.
Scenario starts with normal INVITE, 100, proxy auth from backend server,
INVITE with auth.
When FS2 receives the authenticated invite, it responds with 302 and
indicates via the X-imx-redirect header to redirect the request to FS1.
Then I want to send the INVITE to the given server by setting $du and
calling t_relay() but my current configuration seems to cause kamailio to
respond to the caller with 407 instead.
10:46:27.361991 IP 192.168.20.215.5062 > 192.168.20.214.5060
Via: SIP/2.0/UDP 192.168.20.215:5062;branch=z9hG4bK1598556947
CSeq: 1 INVITE
Content-Type: application/sdp
Allow: INVITE, INFO, PRACK, ACK, BYE, CANCEL, OPTIONS, NOTIFY, REGISTER,
SUBSCRIBE, REFER, PUBLISH, UPDATE, MESSAGE
Max-Forwards: 70
User-Agent: Yealink SIP-T38G 38.70.0.115
Supported: replaces
Allow-Events: talk,hold,conference,refer,check-sync
Content-Length: 310
SDP
10:46:27.362567 IP 192.168.20.214.5060 > 192.168.20.215.5062
SIP/2.0 100 trying -- your call is important to us
Via: SIP/2.0/UDP 192.168.20.215:5062;branch=z9hG4bK1598556947
CSeq: 1 INVITE
Server: kamailio (4.1.5 (x86_64/linux))
Content-Length: 0
10:46:27.362745 IP 192.168.20.214.5060 > 192.168.20.198.5080
Record-Route: <sip:192.168.20.214;lr=on>
Via: SIP/2.0/UDP 192.168.20.214;branch=z9hG4bKa4a8.
9a165b4901cf1602b3146c7f0bf0a191.0
Via: SIP/2.0/UDP 192.168.20.215:5062;branch=z9hG4bK1598556947
CSeq: 1 INVITE
Content-Type: application/sdp
Allow: INVITE, INFO, PRACK, ACK, BYE, CANCEL, OPTIONS, NOTIFY, REGISTER,
SUBSCRIBE, REFER, PUBLISH, UPDATE, MESSAGE
Max-Forwards: 69
User-Agent: Yealink SIP-T38G 38.70.0.115
Supported: replaces
Allow-Events: talk,hold,conference,refer,check-sync
Content-Length: 310
SDP
10:46:27.383907 IP 192.168.20.198.5080 > 192.168.20.214.5060
SIP/2.0 100 Trying
Via: SIP/2.0/UDP 192.168.20.214;branch=z9hG4bKa4a8.
9a165b4901cf1602b3146c7f0bf0a191.0
Via: SIP/2.0/UDP 192.168.20.215:5062;branch=z9hG4bK1598556947
Record-Route: <sip:192.168.20.214;lr=on>
CSeq: 1 INVITE
User-Agent: IMX
Content-Length: 0
10:46:27.553363 IP 192.168.20.198.5080 > 192.168.20.214.5060
SIP/2.0 407 Proxy Authentication Required
Via: SIP/2.0/UDP 192.168.20.214;branch=z9hG4bKa4a8.
9a165b4901cf1602b3146c7f0bf0a191.0
Via: SIP/2.0/UDP 192.168.20.215:5062;branch=z9hG4bK1598556947
CSeq: 1 INVITE
User-Agent: IMX
Accept: application/sdp
Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE, REGISTER,
REFER, NOTIFY, PUBLISH, SUBSCRIBE
Supported: timer, path, replaces
Allow-Events: talk, hold, conference, presence, as-feature-event, dialog,
line-seize, call-info, sla, include-session-description, presence.winfo,
message-summary, refer
Proxy-Authenticate: Digest realm="test.etellicom.com", nonce="xxx",
algorithm=MD5, qop="auth"
Content-Length: 0
10:46:27.553574 IP 192.168.20.214.5060 > 192.168.20.198.5080
Via: SIP/2.0/UDP 192.168.20.214;branch=z9hG4bKa4a8.
9a165b4901cf1602b3146c7f0bf0a191.0
CSeq: 1 ACK
Max-Forwards: 69
Content-Length: 0
10:46:27.553718 IP 192.168.20.214.5060 > 192.168.20.215.5062
SIP/2.0 407 Proxy Authentication Required
Via: SIP/2.0/UDP 192.168.20.215:5062;branch=z9hG4bK1598556947
CSeq: 1 INVITE
User-Agent: IMX
Accept: application/sdp
Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE, REGISTER,
REFER, NOTIFY, PUBLISH, SUBSCRIBE
Supported: timer, path, replaces
Allow-Events: talk, hold, conference, presence, as-feature-event, dialog,
line-seize, call-info, sla, include-session-description, presence.winfo,
message-summary, refer
Proxy-Authenticate: Digest realm="test.etellicom.com", nonce="xxx",
algorithm=MD5, qop="auth"
Content-Length: 0
10:46:27.592662 IP 192.168.20.215.5062 > 192.168.20.214.5060
Via: SIP/2.0/UDP 192.168.20.215:5062;branch=z9hG4bK1598556947
CSeq: 1 ACK
Content-Length: 0
10:46:27.630142 IP 192.168.20.215.5062 > 192.168.20.214.5060
Via: SIP/2.0/UDP 192.168.20.215:5062;branch=z9hG4bK416062902
CSeq: 2 INVITE
Proxy-Authorization: Digest username="1001", realm="test.etellicom.com",
algorithm=MD5, cnonce="xxx", qop=auth, nc=00000001
Content-Type: application/sdp
Allow: INVITE, INFO, PRACK, ACK, BYE, CANCEL, OPTIONS, NOTIFY, REGISTER,
SUBSCRIBE, REFER, PUBLISH, UPDATE, MESSAGE
Max-Forwards: 70
User-Agent: Yealink SIP-T38G 38.70.0.115
Supported: replaces
Allow-Events: talk,hold,conference,refer,check-sync
Content-Length: 310
SDP
10:46:27.630721 IP 192.168.20.214.5060 > 192.168.20.215.5062
SIP/2.0 100 trying -- your call is important to us
Via: SIP/2.0/UDP 192.168.20.215:5062;branch=z9hG4bK416062902
CSeq: 2 INVITE
Server: kamailio (4.1.5 (x86_64/linux))
Content-Length: 0
10:46:27.630896 IP 192.168.20.214.5060 > 192.168.20.198.5080
Record-Route: <sip:192.168.20.214;lr=on>
Via: SIP/2.0/UDP 192.168.20.214;branch=z9hG4bK74a8.
d3d3ad8bb9b1c73c12e16cdab447472e.0
Via: SIP/2.0/UDP 192.168.20.215:5062;branch=z9hG4bK416062902
CSeq: 2 INVITE
Proxy-Authorization: Digest username="1001", realm="test.etellicom.com",
algorithm=MD5, cnonce="xxx", qop=auth, nc=00000001
Content-Type: application/sdp
Allow: INVITE, INFO, PRACK, ACK, BYE, CANCEL, OPTIONS, NOTIFY, REGISTER,
SUBSCRIBE, REFER, PUBLISH, UPDATE, MESSAGE
Max-Forwards: 69
User-Agent: Yealink SIP-T38G 38.70.0.115
Supported: replaces
Allow-Events: talk,hold,conference,refer,check-sync
Content-Length: 310
SDP
10:46:27.631731 IP 192.168.20.198.5080 > 192.168.20.214.5060
SIP/2.0 100 Trying
Via: SIP/2.0/UDP 192.168.20.214;branch=z9hG4bK74a8.
d3d3ad8bb9b1c73c12e16cdab447472e.0
Via: SIP/2.0/UDP 192.168.20.215:5062;branch=z9hG4bK416062902
Record-Route: <sip:192.168.20.214;lr=on>
CSeq: 2 INVITE
User-Agent: IMX
Content-Length: 0
10:46:29.187901 IP 192.168.20.198.5080 > 192.168.20.214.5060
SIP/2.0 302 Moved Temporarily
Via: SIP/2.0/UDP 192.168.20.214;branch=z9hG4bK74a8.
d3d3ad8bb9b1c73c12e16cdab447472e.0
Via: SIP/2.0/UDP 192.168.20.215:5062;branch=z9hG4bK416062902
Max-Forwards: 69
CSeq: 2 INVITE
Contact: "unknown" <sip:node1.etellicom.com>
User-Agent: IMX
Accept: application/sdp
Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE, REGISTER,
REFER, NOTIFY, PUBLISH, SUBSCRIBE
Supported: timer, path, replaces
Allow-Events: talk, hold, conference, presence, as-feature-event, dialog,
line-seize, call-info, sla, include-session-description, presence.winfo,
message-summary, refer
Reason: Q.850;cause=31;text="NORMAL_UNSPECIFIED"
Content-Length: 0
X-imx-redirect: sip:192.168.20.214:5080
10:46:29.188327 IP 192.168.20.214.5060 > 192.168.20.198.5080
Via: SIP/2.0/UDP 192.168.20.214;branch=z9hG4bK74a8.
d3d3ad8bb9b1c73c12e16cdab447472e.0
CSeq: 2 ACK
Max-Forwards: 69
Content-Length: 0
192.168.20.214:5080
7(17488) ERROR: <script>: SCRIPT: REDIRECT: going to <sip:*
10:46:29.432573 IP 192.168.20.214.5060 > 192.168.20.215.5062
SIP/2.0 407 Proxy Authentication Required
Via: SIP/2.0/UDP 192.168.20.215:5062;branch=z9hG4bK416062902
CSeq: 2 INVITE
User-Agent: IMX
Accept: application/sdp
Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE, REGISTER,
REFER, NOTIFY, PUBLISH, SUBSCRIBE
Supported: timer, path, replaces
Allow-Events: talk, hold, conference, presence, as-feature-event, dialog,
line-seize, call-info, sla, include-session-description, presence.winfo,
message-summary, refer
Proxy-Authenticate: Digest realm="test.etellicom.com",
nonce="eac7076b-4c13-4492-838c-14039cc2beb6", stale=true, algorithm=MD5,
qop="auth"
Content-Length: 0
10:46:29.452446 IP 192.168.20.215.5062 > 192.168.20.214.5060
Via: SIP/2.0/UDP 192.168.20.215:5062;branch=z9hG4bK416062902
CSeq: 2 ACK
Content-Length: 0
10:46:29.490390 IP 192.168.20.215.5062 > 192.168.20.214.5060
Via: SIP/2.0/UDP 192.168.20.215:5062;branch=z9hG4bK2079130033
CSeq: 3 INVITE
Proxy-Authorization: Digest username="1001", realm="test.etellicom.com",
algorithm=MD5, cnonce="xxx", qop=auth, nc=00000001
Content-Type: application/sdp
Allow: INVITE, INFO, PRACK, ACK, BYE, CANCEL, OPTIONS, NOTIFY, REGISTER,
SUBSCRIBE, REFER, PUBLISH, UPDATE, MESSAGE
Max-Forwards: 70
User-Agent: Yealink SIP-T38G 38.70.0.115
Supported: replaces
Allow-Events: talk,hold,conference,refer,check-sync
Content-Length: 310
SDP
10:46:29.490694 IP 192.168.20.214.5060 > 192.168.20.215.5062
SIP/2.0 100 trying -- your call is important to us
Via: SIP/2.0/UDP 192.168.20.215:5062;branch=z9hG4bK2079130033
CSeq: 3 INVITE
Server: kamailio (4.1.5 (x86_64/linux))
Content-Length: 0
10:46:29.490782 IP 192.168.20.214.5060 > 192.168.20.198.5080
Record-Route: <sip:192.168.20.214;lr=on>
Via: SIP/2.0/UDP 192.168.20.214;branch=z9hG4bK84a8.
289b7cd802ed6efd2f25721d6b8f29d6.0
Via: SIP/2.0/UDP 192.168.20.215:5062;branch=z9hG4bK2079130033
CSeq: 3 INVITE
Proxy-Authorization: Digest username="1001", realm="test.etellicom.com",
algorithm=MD5, cnonce="xxx", qop=auth, nc=00000001
Content-Type: application/sdp
Allow: INVITE, INFO, PRACK, ACK, BYE, CANCEL, OPTIONS, NOTIFY, REGISTER,
SUBSCRIBE, REFER, PUBLISH, UPDATE, MESSAGE
Max-Forwards: 69
User-Agent: Yealink SIP-T38G 38.70.0.115
Supported: replaces
Allow-Events: talk,hold,conference,refer,check-sync
Content-Length: 310
SDP
_______________________________________________
SIP Express Router (SER) and Kamailio (OpenSER) - sr-users mailing list
http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-users
Nicholas Gill
2014-09-16 06:07:24 UTC
Permalink
Post by Federico Cabiddu
looking at the trace, it seems to me that the 407 is not sent by
Kamailio but by the FS1 server ("User-Agent: IMX" in the 407, as for
the 1st 407 sent by FS2), and that you are probably missing in the
trace the messages between Kamailio and FS1.
This shouldn't be the case as the tcpdump was executed on that server
itself, but it seems plausible (perhaps lo -vs- ethX).
Post by Federico Cabiddu
- disable the authentication in freeswitch if you don't need it
Unfortunately necessary until we transition to Kamailio performing the
authentication.
Post by Federico Cabiddu
- store the custom header when receiving the 302 and use it to set $du
upon receiving the 2nd INVITE
For the latter you can have several solutions, I suggest you to have a
a look at the htable module. For example you could use it to store the
key USERID::CALLID with the value of your custom header and retrieve
it when you receive the authenticated INVITE from the client.
Something like
sht(TABLE_NAME=>$fU::$ci) = $avp(imx-redirect);
to store it, and then
$avp(imx-redirect) = sht(TABLE_NAME=>$fU::$ci);
This is very useful, thank you. I'll investigate this option.

Cheers,

-nick

Loading...