]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
Fri Jan 16 13:27:39 CST 2009 Pekka Pessi <first.last@nokia.com>
authorMichael Jerris <mike@jerris.com>
Wed, 11 Feb 2009 17:07:59 +0000 (17:07 +0000)
committerMichael Jerris <mike@jerris.com>
Wed, 11 Feb 2009 17:07:59 +0000 (17:07 +0000)
  * soa: fixed restoring state after failed offer

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@11835 d0543943-73ff-0310-b7d9-9358b9ac24b2

libs/sofia-sip/.update
libs/sofia-sip/libsofia-sip-ua/soa/soa.c
libs/sofia-sip/libsofia-sip-ua/soa/soa_static.c

index 37ad46c79629715ba909bacd434701743480a05f..4f2f64fd5d6f4a61efcb67ccedd079edb78aeb4f 100644 (file)
@@ -1 +1 @@
-Wed Feb 11 11:06:56 CST 2009
+Wed Feb 11 11:07:52 CST 2009
index eb45c9cadff23738e2b3ad411420fcb5c689a65e..77f1ab6a4691285e73c51578f5d10e7c46d00de7 100644 (file)
@@ -938,7 +938,7 @@ soa_base_set_capability_sdp(soa_session_t *ss,
  *
  * <i>User SDP</i> is used as basis for SDP Offer/Answer negotiation. It can
  * be very minimal template, consisting just m= line containing media name,
- * transport protocol port number and list of supported codecs.
+ * transport protocol, port number and list of supported codecs.
  *
  * The SDP used as an offer or answer (generated by soa_generate_answer() or
  * soa_generate_offer()) is known as <i>local SDP</i> and it is available
@@ -1703,13 +1703,10 @@ int soa_base_process_reject(soa_session_t *ss,
 
   (void)completed;
 
-  if (!l_sdp)
-    return -1;
-
-  soa_set_activity(ss, l_sdp->sdp_media, soa_activity_session);
-
   ss->ss_offer_sent = 0;
 
+  soa_set_activity(ss, l_sdp ? l_sdp->sdp_media : NULL, soa_activity_session);
+
   return 0;
 }
 
index 60e78e77db1847deb9bfdd6df90bd70bb050da6b..2210d4976068e36fd189ba01fa528d1d6aa46b3c 100644 (file)
@@ -84,6 +84,11 @@ typedef struct soa_static_session
   /** Mapping from session SDP m= lines to user SDP m= lines */
   int *sss_s2u;
 
+  /** State kept from SDP before current offer */
+  struct {
+    int  *u2s, *s2u;
+  } sss_previous;
+
   /** Our latest offer or answer */
   sdp_session_t *sss_latest;
 }
@@ -886,6 +891,7 @@ int soa_sdp_upgrade(soa_session_t *ss,
   return 0;
 }
 
+static
 int *u2s_alloc(su_home_t *home, int const *u2s)
 {
   if (u2s) {
@@ -1318,6 +1324,8 @@ static int offer_answer_step(soa_session_t *ss,
   }
 
   soa_description_free(ss, ss->ss_previous);
+  su_free(ss->ss_home, sss->sss_previous.u2s), sss->sss_previous.u2s = NULL;
+  su_free(ss->ss_home, sss->sss_previous.s2u), sss->sss_previous.s2u = NULL;
 
   if (u2s) {
     u2s = u2s_alloc(ss->ss_home, u2s);
@@ -1358,10 +1366,18 @@ static int offer_answer_step(soa_session_t *ss,
 
     if (action == generate_offer) {
       /* Keep a copy of previous session state */
+      int *previous_u2s = u2s_alloc(ss->ss_home, sss->sss_u2s);
+      int *previous_s2u = u2s_alloc(ss->ss_home, sss->sss_s2u);
+
+      if ((sss->sss_u2s && !previous_u2s) || (sss->sss_s2u && !previous_s2u))
+       goto internal_error;
+
       *ss->ss_previous = *ss->ss_local;
       memset(ss->ss_local, 0, (sizeof *ss->ss_local));
       ss->ss_previous_user_version = ss->ss_local_user_version;
       ss->ss_previous_remote_version = ss->ss_local_remote_version;
+      sss->sss_previous.u2s = previous_u2s;
+      sss->sss_previous.s2u = previous_s2u;
     }
 
     SU_DEBUG_7(("soa_static(%p, %s): %s\n", (void *)ss, by,
@@ -1374,6 +1390,8 @@ static int offer_answer_step(soa_session_t *ss,
        memset(ss->ss_previous, 0, (sizeof *ss->ss_previous));
        ss->ss_previous_user_version = 0;
        ss->ss_previous_remote_version = 0;
+       su_free(ss->ss_home, sss->sss_previous.u2s), sss->sss_previous.u2s = NULL;
+       su_free(ss->ss_home, sss->sss_previous.s2u), sss->sss_previous.s2u = NULL;
       }
 
       su_free(ss->ss_home, u2s), su_free(ss->ss_home, s2u);
@@ -1467,21 +1485,26 @@ static int soa_static_process_answer(soa_session_t *ss,
 static int soa_static_process_reject(soa_session_t *ss,
                                     soa_callback_f *completed)
 {
+  soa_static_session_t *sss = (soa_static_session_t *)ss;
   struct soa_description d[1];
 
-  if (ss->ss_previous_user_version) {
-    *d = *ss->ss_local;
-    *ss->ss_local = *ss->ss_previous;
-    ss->ss_local_user_version = ss->ss_previous_user_version;
-    ss->ss_local_remote_version = ss->ss_previous_remote_version;
+  soa_base_process_reject(ss, NULL);
 
-    memset(ss->ss_previous, 0, (sizeof *ss->ss_previous));
-    soa_description_free(ss, d);
-    ss->ss_previous_user_version = 0;
-    ss->ss_previous_remote_version = 0;
-  }
+  *d = *ss->ss_local;
+  *ss->ss_local = *ss->ss_previous;
+  ss->ss_local_user_version = ss->ss_previous_user_version;
+  ss->ss_local_remote_version = ss->ss_previous_remote_version;
+
+  memset(ss->ss_previous, 0, (sizeof *ss->ss_previous));
+  soa_description_free(ss, d);
+  su_free(ss->ss_home, sss->sss_previous.u2s), sss->sss_previous.u2s = NULL;
+  su_free(ss->ss_home, sss->sss_previous.s2u), sss->sss_previous.s2u = NULL;
+  ss->ss_previous_user_version = 0;
+  ss->ss_previous_remote_version = 0;
 
-  return soa_base_process_reject(ss, NULL);
+  su_free(ss->ss_home, sss->sss_latest), sss->sss_latest = NULL;
+
+  return 0;
 }
 
 static int soa_static_activate(soa_session_t *ss, char const *option)
@@ -1496,6 +1519,19 @@ static int soa_static_deactivate(soa_session_t *ss, char const *option)
 
 static void soa_static_terminate(soa_session_t *ss, char const *option)
 {
-  soa_description_free(ss, ss->ss_user);
+  soa_static_session_t *sss = (soa_static_session_t *)ss;
+
+  soa_description_free(ss, ss->ss_local);
+  su_free(ss->ss_home, sss->sss_u2s), sss->sss_u2s = NULL;
+  su_free(ss->ss_home, sss->sss_s2u), sss->sss_s2u = NULL;
+
+  soa_description_free(ss, ss->ss_previous);
+  ss->ss_previous_user_version = 0;
+  ss->ss_previous_remote_version = 0;
+  su_free(ss->ss_home, sss->sss_previous.u2s), sss->sss_previous.u2s = NULL;
+  su_free(ss->ss_home, sss->sss_previous.s2u), sss->sss_previous.s2u = NULL;
+
+  su_free(ss->ss_home, sss->sss_latest), sss->sss_latest = NULL;
+
   soa_base_terminate(ss, option);
 }