[Freeswitch-dev] thesis on live sip calls migration
Stefano Bossi
ste.bossi at gmail.com
Sat Jan 23 11:43:21 PST 2010
Hi,
I have a little patch to enable sofia_glue_do_invite to send a
(fake)reinvite instead of a regular invite.
The changes allow to set to_tag,from_tag and cseq from the originate
command.
To simply try this function I do these steps:
1 start freeswitch
2 sofia profile internal siptrace on
3 originate sofia/internal/1000%mydomain.it &park()
4 when the call is active I read from the 200 OK header the cseq, the
from_tag, the to_tag and the call-id
5 create the command for resurrecting the call on a text editor:
originate originate
{sip_outgoing_call_id=798e29c9-82f7-122d-2b9a-00163e2b53e5,sip_invite_from_tag=UgDZZegc8Q2rF,sip_invite_to_tag=947294406,sip_invite_cseq=126018935}sofia/internal/1000%mydomain.it &park()
(those are my last values, put yours)
6 at this point, with the call still active, kill -9 freeswitch
7 start freeswitch immediately
8 launch the command previously prepared
9 the phone still thinks to be connected with the old FS instance
10 now you can hangup and, if you enable the siptrace again, see the
correct tear down of the call.
Obviously this can be done with 2 call legs but it is a little more
complicated. If someone is interested I can explain how to do.
And of course if you have another identical machine with the same IP,
with registrations sharing enabled, ready to wake up after the crash of
the first one you can do the same procedure :)
I hope the procedure is clear and sorry for my poor English
bye
Stefano
On mar, 2010-01-19 at 15:04 +0100, stefano bossi wrote:
> Hi Anthony,
>
>
> your last commit on sofia.c adds a very helpful function to extract
> sip_to_tag and sip_from_tag..
> I was working on something similar but I also read the Cseq.. you can
> do this with these 3 lines of code
>
>
> if (sip->sip_cseq && sip->sip_cseq->cs_seq) {
> const char *sip_cseq = switch_core_session_sprintf(session,"%d",
> sip->sip_cseq->cs_seq);
> switch_channel_set_variable(channel, "sip_cseq", sip_cseq);
> }
>
>
> (It compiles, I hope it is correct too :)
>
>
> This cseq can be used for calls failover in the most part of cases, I
> only wonder if this is still true after any other request during
> dialog than INVITE.
>
>
> bye
>
> On Mon, Jan 4, 2010 at 5:16 PM, Anthony Minessale
> <anthony.minessale at gmail.com> wrote:
> Hi,
> When would you like to continue this conversation?
>
>
>
> On Fri, Dec 18, 2009 at 4:38 AM, stefano bossi
> <ste.bossi at gmail.com> wrote:
>
>
> Hi all,
>
> as promised in #freeswitch-dev I'll try to explain
> better what I've done and I would like to achieve for
> my thesis.
>
>
> At the moment I successfully patched sofsip_cli and
> now it can do something near active call migration :)
> Thanks to the versatility of nua api I could achieve
> my objective with little effort.
> Basically I call someone, then I kill sofsip_cli and I
> restart it. I launch my "reinvite" command and the
> call can continue normally. The called client doesn't
> realize what happened.
> In this case I write call data in a file and when I
> launch the reinvite I read directly from this file.
> Sofsip_cli sends an INVITE message with some TAG
> appended to the nua_handle. So the called phone thinks
> to receive an in-session invite and simply refreshes
> the call, but Sofsip_cli instead allocates all the
> stuff for a new call. In this way I can avoid to
> modify directly the RTP part. It seems to be all
> simpler.
>
> I even wrote a little module for FS able to
> monitor(using the SIP OPTION message) the life of a
> specific sofia profile.. It's just a proof of concept
> but it can do failover(without live call migration)
> between 2 machines in about 50ms.
> This is possible with these actions:
> * registrations are shared with odbc
> * on the start of the module(present only on the
> backup machine):
> 1. I set an arp rule blocking the arp response
> for the virtual IP (set on the primary
> machine)
> 2. I set the virtual IP on the backup
> machine( but no one knows thanks to the arp
> rule and so I can bind to vIP)
> 3. I prepare and run the sip profile (on the
> backup)... loading here the profile permits to
> save a lot of time during reaction
> * on the reaction
> 1. I remove the arp rule
> 2. I send a gratuitous arp request
> As I said in about 50ms sip clients can call again.
> Maybe this time can decrease using NETLINK socket for
> the arp table.
>
> The union of these 2 works will give us a very fast
> "live profile migration" :D
>
>
> There some points to discuss:
> * switch_core_session_resurrect_channel: I
> didn't know this function, I need to
> understand what it offers, maybe tomorrow ;)
> * the propagation of call state variables: my
> first idea was to use the multicast events
> adding some headers to send all the necessary
> data (but anthm proposed XML)
> * I thought only to sofia aspects..
> In next days I'll try to understand where to hook in
> FS to try these ideas. When I'll have something ready
> (and without very very big errors:) I'll be happy to
> send you the patch.
> This is my first work on something real like FS.. I'm
> opened to any kind of suggestions!
>
> please contact me for further clarifications
>
> Thanks
>
> Stefano Bossi
>
>
>
>
>
>
> _______________________________________________
> FreeSWITCH-dev mailing list
> FreeSWITCH-dev at lists.freeswitch.org
> http://lists.freeswitch.org/mailman/listinfo/freeswitch-dev
> UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-dev
> http://www.freeswitch.org
>
>
>
>
> --
> Anthony Minessale II
>
> FreeSWITCH http://www.freeswitch.org/
> ClueCon http://www.cluecon.com/
> Twitter: http://twitter.com/FreeSWITCH_wire
>
> AIM: anthm
> MSN:anthony_minessale at hotmail.com
> GTALK/JABBER/PAYPAL:anthony.minessale at gmail.com
> IRC: irc.freenode.net #freeswitch
>
> FreeSWITCH Developer Conference
> sip:888 at conference.freeswitch.org
> iax:guest at conference.freeswitch.org/888
> googletalk:conf+888 at conference.freeswitch.org
> pstn:+19193869900
>
> _______________________________________________
> FreeSWITCH-dev mailing list
> FreeSWITCH-dev at lists.freeswitch.org
> http://lists.freeswitch.org/mailman/listinfo/freeswitch-dev
> UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-dev
> http://www.freeswitch.org
>
>
>
> _______________________________________________
> FreeSWITCH-dev mailing list
> FreeSWITCH-dev at lists.freeswitch.org
> http://lists.freeswitch.org/mailman/listinfo/freeswitch-dev
> UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-dev
> http://www.freeswitch.org
-------------- next part --------------
Index: src/mod/endpoints/mod_sofia/sofia_glue.c
===================================================================
--- src/mod/endpoints/mod_sofia/sofia_glue.c (revision 16485)
+++ src/mod/endpoints/mod_sofia/sofia_glue.c (working copy)
@@ -1457,6 +1457,10 @@
sofia_destination_t *dst = NULL;
sofia_cid_type_t cid_type = tech_pvt->profile->cid_type;
+ //int failover_flag = 0;
+ sip_cseq_t *cseq = NULL;
+ //char *sip_invite_cseq = NULL;
+
rep = switch_channel_get_variable(channel, SOFIA_REPLACES_HEADER);
switch_assert(tech_pvt != NULL);
@@ -1503,8 +1507,11 @@
const char *invite_from_params = switch_channel_get_variable(tech_pvt->channel, "sip_invite_from_params");
const char *from_var = switch_channel_get_variable(tech_pvt->channel, "sip_from_uri");
const char *from_display = switch_channel_get_variable(tech_pvt->channel, "sip_from_display");
-
-
+ const char *invite_from_tag = switch_channel_get_variable(tech_pvt->channel, "sip_invite_from_tag");
+ const char *invite_to_tag = switch_channel_get_variable(tech_pvt->channel, "sip_invite_to_tag");
+ sip_from_t *from = NULL;
+ sip_to_t *to = NULL;
+
if (zstr(tech_pvt->dest)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "URL Error!\n");
return SWITCH_STATUS_FALSE;
@@ -1544,6 +1551,8 @@
sipip);
}
+
+
if (from_var) {
if (strncasecmp(from_var, "sip:", 4) || strncasecmp(from_var, "sips:", 5)) {
use_from_str = switch_core_session_strdup(tech_pvt->session, from_var);
@@ -1669,11 +1678,19 @@
}
}
+ from = sip_from_make(tech_pvt->profile->home, from_str);
+ if (!zstr(invite_from_tag))
+ sip_from_tag(tech_pvt->profile->home,from,invite_from_tag);
+
+ to = sip_to_make(tech_pvt->profile->home, to_str);
+ if (!zstr(invite_to_tag))
+ sip_to_tag(tech_pvt->profile->home,to,invite_to_tag);
+
tech_pvt->nh = nua_handle(tech_pvt->profile->nua, NULL,
NUTAG_URL(url_str),
TAG_IF(call_id, SIPTAG_CALL_ID_STR(call_id)),
- SIPTAG_TO_STR(to_str),
- SIPTAG_FROM_STR(from_str),
+ SIPTAG_TO(to),
+ SIPTAG_FROM(from),
SIPTAG_CONTACT_STR(invite_contact),
TAG_END());
@@ -1825,7 +1842,12 @@
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "%s Setting proxy route to %s\n", route_uri, switch_channel_get_name(channel));
tech_pvt->route_uri = switch_core_session_strdup(tech_pvt->session, route_uri);
}
-
+
+ if (( val = switch_channel_get_variable(tech_pvt->channel, "sip_invite_cseq"))) {
+ uint32_t callsequence = (uint32_t)strtoul(val,NULL,10);
+ cseq = sip_cseq_create(tech_pvt->profile->home, callsequence, SIP_METHOD_INVITE);
+ }
+
switch_channel_clear_flag(channel, CF_MEDIA_ACK);
if (sofia_use_soa(tech_pvt)) {
@@ -1845,6 +1867,7 @@
TAG_IF(!zstr(route_uri), NUTAG_PROXY(route_uri)),
TAG_IF(!zstr(route), SIPTAG_ROUTE_STR(route)),
TAG_IF(tech_pvt->profile->minimum_session_expires, NUTAG_MIN_SE(tech_pvt->profile->minimum_session_expires)),
+ TAG_IF(cseq,SIPTAG_CSEQ(cseq)),
SOATAG_ADDRESS(tech_pvt->adv_sdp_audio_ip),
SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str),
SOATAG_REUSE_REJECTED(1),
@@ -1871,6 +1894,7 @@
TAG_IF(!zstr(route_uri), NUTAG_PROXY(route_uri)),
TAG_IF(!zstr(route), SIPTAG_ROUTE_STR(route)),
TAG_IF(tech_pvt->profile->minimum_session_expires, NUTAG_MIN_SE(tech_pvt->profile->minimum_session_expires)),
+ TAG_IF(cseq,SIPTAG_CSEQ(cseq)),
NUTAG_MEDIA_ENABLE(0),
SIPTAG_CONTENT_TYPE_STR("application/sdp"),
SIPTAG_PAYLOAD_STR(tech_pvt->local_sdp_str),
More information about the FreeSWITCH-dev
mailing list