Mon Oct  8 07:54:24 EDT 2007  Pekka.Pessi@nokia.com
  * nua.c: nua event callback does not use nua_t object after nua_destroy() call. sf.net bug #1803686
  
diff -rN -u old-sofia-sip.trunk-darcs-sync/libsofia-sip-ua/nua/nua.c new-sofia-sip.trunk-darcs-sync-1/libsofia-sip-ua/nua/nua.c
--- old-sofia-sip.trunk-darcs-sync/libsofia-sip-ua/nua/nua.c	2007-10-22 18:57:04.000000000 -0400
+++ new-sofia-sip.trunk-darcs-sync-1/libsofia-sip-ua/nua/nua.c	2007-10-22 18:57:04.000000000 -0400
@@ -195,6 +195,13 @@
   nua_signal(nua, NULL, NULL, 1, nua_r_shutdown, 0, NULL, TAG_END());
 }
 
+/** @internal Linked stack frames from nua event callback */
+struct nua_event_frame_s {
+  nua_event_frame_t *nf_next;
+  nua_t *nf_nua;
+  nua_saved_event_t nf_saved[1];
+};
+
 /** Destroy the @nua stack.
  *
  * Before calling nua_destroy() the application
@@ -220,6 +227,8 @@
   enter;
 
   if (nua) {
+    nua_event_frame_t *nf;
+
     if (!nua->nua_shutdown_final) {
       SU_DEBUG_0(("nua_destroy(%p): FATAL: nua_shutdown not completed\n",
 		  (void *)nua));
@@ -227,6 +236,13 @@
       return;
     }
 
+    nua->nua_callback = NULL;
+
+    for (nf = nua->nua_current; nf; nf = nf->nf_next) {
+      nf->nf_nua = NULL;
+    }
+    nua->nua_current = NULL;
+
     su_task_deinit(nua->nua_server);
     su_task_deinit(nua->nua_client);
 
@@ -984,9 +1000,10 @@
 {
   nua_t *nua;
   nua_handle_t *nh = e->e_nh;
-
   enter;
 
+  e->e_nh = NULL;
+
   if (nh) {
     if (!nh->nh_ref_by_user && nh->nh_valid) {
       nh->nh_ref_by_user = 1;
@@ -1013,40 +1030,40 @@
 
   nua = nh->nh_nua; assert(nua);
 
-  if (e->e_event == nua_r_shutdown && e->e_status >= 200)
-    nua->nua_shutdown_final = 1;
-
-  if (!nua->nua_callback)
-    return;
-
   if (NH_IS_DEFAULT(nh))
     nh = NULL;
 
-  su_msg_save(nua->nua_current, sumsg);
+  if (e->e_event == nua_r_shutdown && e->e_status >= 200)
+    nua->nua_shutdown_final = 1;
 
-  e->e_nh = NULL;
+  if (nua->nua_callback) {
+    nua_event_frame_t frame[1];
+    
+    su_msg_remove_refs(sumsg);    /* Remove references to tasks */
+    su_msg_save(frame->nf_saved, sumsg);
+    frame->nf_nua = nua;
+    frame->nf_next = nua->nua_current, nua->nua_current = frame;
+
+    nua->nua_callback(e->e_event, e->e_status, e->e_phrase,
+		      nua, nua->nua_magic,
+		      nh, nh ? nh->nh_magic : NULL,
+		      e->e_msg ? sip_object(e->e_msg) : NULL,
+		      e->e_tags);
 
-  nua->nua_callback(e->e_event, e->e_status, e->e_phrase,
-		    nua, nua->nua_magic,
-		    nh, nh ? nh->nh_magic : NULL,
-		    e->e_msg ? sip_object(e->e_msg) : NULL,
-		    e->e_tags);
+    su_msg_destroy(frame->nf_saved);
+
+    if (frame->nf_nua == NULL)
+      return;
+    nua->nua_current = frame->nf_next;
+  }
 
-  if (nh && !NH_IS_DEFAULT(nh) && nua_handle_unref(nh)) {
+  if (nh && nua_handle_unref(nh)) {
 #if HAVE_NUA_HANDLE_DEBUG
     SU_DEBUG_0(("nua(%p): freed by application\n", (void *)nh));
 #else
     SU_DEBUG_9(("nua(%p): freed by application\n", (void *)nh));
 #endif
   }
-
-  if (!su_msg_is_non_null(nua->nua_current))
-    return;
-
-  if (e->e_msg)
-    msg_destroy(e->e_msg), e->e_msg = NULL;
-
-  su_msg_destroy(nua->nua_current);
 }
 
 /** Get current request message. @NEW_1_12_4.
@@ -1057,7 +1074,9 @@
  */
 msg_t *nua_current_request(nua_t const *nua)
 {
-  return nua && nua->nua_current ? su_msg_data(nua->nua_current)->e_msg : NULL;
+  if (nua && nua->nua_current && su_msg_is_non_null(nua->nua_current->nf_saved))
+    return su_msg_data(nua->nua_current->nf_saved)->e_msg;
+  return NULL;
 }
 
 /** Get request message from saved nua event. @NEW_1_12_4. 
@@ -1075,14 +1094,15 @@
  */
 int nua_save_event(nua_t *nua, nua_saved_event_t return_saved[1])
 {
-  if (nua && return_saved) {
-    su_msg_save(return_saved, nua->nua_current);
-    if (su_msg_is_non_null(return_saved)) {
-      /* Remove references to tasks */
-      su_msg_remove_refs(return_saved);
-      return 1;
+  if (return_saved) {
+    if (nua && nua->nua_current) {
+      su_msg_save(return_saved, nua->nua_current->nf_saved);
+      return su_msg_is_non_null(return_saved);
     }
+    else
+      *return_saved = NULL;
   }
+
   return 0;
 }
 
diff -rN -u old-sofia-sip.trunk-darcs-sync/libsofia-sip-ua/nua/nua_stack.h new-sofia-sip.trunk-darcs-sync-1/libsofia-sip-ua/nua/nua_stack.h
--- old-sofia-sip.trunk-darcs-sync/libsofia-sip-ua/nua/nua_stack.h	2007-10-22 18:57:04.000000000 -0400
+++ new-sofia-sip.trunk-darcs-sync-1/libsofia-sip-ua/nua/nua_stack.h	2007-10-22 18:57:04.000000000 -0400
@@ -197,6 +197,8 @@
   return nh == NULL || nh->nh_special;
 }
 
+typedef struct nua_event_frame_s nua_event_frame_t;
+
 extern char const nua_internal_error[];
 
 #define NUA_INTERNAL_ERROR 900, nua_internal_error
@@ -214,7 +216,7 @@
   nua_callback_f       nua_callback;
   nua_magic_t         *nua_magic;
 
-  nua_saved_event_t    nua_current[1];
+  nua_event_frame_t   *nua_current;
   nua_saved_event_t    nua_signal[1];
 
   /* Engine state flags */

