Added prev_state in tsx_state event

git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@110 74dad513-b988-da41-8d7b-12977e46ad98
diff --git a/pjsip/src/pjsip/sip_transaction.c b/pjsip/src/pjsip/sip_transaction.c
index 885b5bb..d982456 100644
--- a/pjsip/src/pjsip/sip_transaction.c
+++ b/pjsip/src/pjsip/sip_transaction.c
@@ -892,6 +892,8 @@
 			   pjsip_event_id_e event_src_type,
                            void *event_src )
 {
+    pjsip_tsx_state_e prev_state = tsx->state;
+
     PJ_LOG(5, (tsx->obj_name, "State changed from %s to %s, event=%s",
 	       state_str[tsx->state], state_str[state], 
                pjsip_event_str(event_src_type)));
@@ -909,7 +911,8 @@
     /* Inform TU */
     if (tsx->tsx_user && tsx->tsx_user->on_tsx_state) {
 	pjsip_event e;
-	PJSIP_EVENT_INIT_TSX_STATE(e, tsx, event_src_type, event_src);
+	PJSIP_EVENT_INIT_TSX_STATE(e, tsx, event_src_type, event_src,
+				   prev_state);
 	(*tsx->tsx_user->on_tsx_state)(tsx, &e);
     }
     
@@ -2106,7 +2109,12 @@
 	}
 	pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer, &timeout);
 
-	/* Inform TU. */
+	/* Inform TU. 
+	 * blp: You might be tempted to move this notification before
+	 *      sending ACK, but I think you shouldn't. Better set-up
+	 *      everything before calling tsx_user's callback to avoid
+	 *      mess up.
+	 */
 	tsx_set_state( tsx, PJSIP_TSX_STATE_COMPLETED, 
                        PJSIP_EVENT_RX_MSG, event->body.rx_msg.rdata );
 
diff --git a/pjsip/src/pjsip/sip_transport_loop.c b/pjsip/src/pjsip/sip_transport_loop.c
index de2f85a..33b9f22 100644
--- a/pjsip/src/pjsip/sip_transport_loop.c
+++ b/pjsip/src/pjsip/sip_transport_loop.c
@@ -253,6 +253,11 @@
 static int loop_thread(void *arg)
 {
     struct loop_transport *loop = arg;
+    struct recv_list r;
+    struct send_list s;
+
+    pj_list_init(&r);
+    pj_list_init(&s);
 
     while (!loop->thread_quit_flag) {
 	pj_time_val now;
@@ -262,7 +267,7 @@
 
 	pj_lock_acquire(loop->base.lock);
 
-	/* Process pending send notification. */
+	/* Move expired send notification to local list. */
 	while (!pj_list_empty(&loop->send_list)) {
 	    struct send_list *node = loop->send_list.next;
 
@@ -270,26 +275,54 @@
 	    if (PJ_TIME_VAL_GTE(node->sent_time, now))
 		break;
 
+	    /* Delete this from the list. */
+	    pj_list_erase(node);
+
+	    /* Add to local list. */
+	    pj_list_push_back(&s, node);
+	}
+
+	/* Move expired "incoming" packet to local list. */
+	while (!pj_list_empty(&loop->recv_list)) {
+	    struct recv_list *node = loop->recv_list.next;
+
+	    /* Break when next node time is greater than now. */
+	    if (PJ_TIME_VAL_GTE(node->rdata.pkt_info.timestamp, now))
+		break;
+
+	    /* Delete this from the list. */
+	    pj_list_erase(node);
+
+	    /* Add to local list. */
+	    pj_list_push_back(&r, node);
+
+	}
+
+	pj_lock_release(loop->base.lock);
+
+	/* Process send notification and incoming packet notification
+	 * without holding down the loop's mutex.
+	 */
+	while (!pj_list_empty(&s)) {
+	    struct send_list *node = s.next;
+
+	    pj_list_erase(node);
+
 	    /* Notify callback. */
 	    if (node->callback) {
 		(*node->callback)(&loop->base, node->token, node->sent);
 	    }
 
-	    /* Delete this from the list. */
-	    pj_list_erase(node);
-
 	    /* Decrement tdata reference counter. */
 	    pjsip_tx_data_dec_ref(node->tdata);
 	}
 
-	/* Process "incoming" packets. */
-	while (!pj_list_empty(&loop->recv_list)) {
-	    struct recv_list *node = loop->recv_list.next;
+	/* Process "incoming" packet. */
+	while (!pj_list_empty(&r)) {
+	    struct recv_list *node = r.next;
 	    pj_ssize_t size_eaten;
 
-	    /* Break when next node time is greater than now. */
-	    if (PJ_TIME_VAL_GTE(node->rdata.pkt_info.timestamp, now))
-		break;
+	    pj_list_erase(node);
 
 	    /* Notify transport manager about the "incoming packet" */
 	    size_eaten = pjsip_tpmgr_receive_packet(loop->base.tpmgr,
@@ -298,15 +331,10 @@
 	    /* Must "eat" all the packets. */
 	    pj_assert(size_eaten == node->rdata.pkt_info.len);
 
-	    /* Delete this from the list. */
-	    pj_list_erase(node);
-
 	    /* Done. */
 	    pjsip_endpt_release_pool(loop->base.endpt,
 				     node->rdata.tp_info.pool);
 	}
-
-	pj_lock_release(loop->base.lock);
     }
 
     return 0;