diff -urN asterisk-1.4.9.orig/channels/chan_iax2.c asterisk-1.4.9/channels/chan_iax2.c --- asterisk-1.4.9.orig/channels/chan_iax2.c 2007-07-24 12:32:20.000000000 -0400 +++ asterisk-1.4.9/channels/chan_iax2.c 2007-07-31 16:25:40.000000000 -0400 @@ -1866,12 +1866,27 @@ static void __attempt_transmit(void *data) { /* Attempt to transmit the frame to the remote peer... - Called without iaxsl held. */ - struct iax_frame *f = data; - int freeme=0; - int callno = f->callno; - /* Make sure this call is still active */ - if (callno) + Called without iaxsl held. */ + struct iax_frame *f; + //int freeme = 0; + int callno = 0; + int found = 0; + + /* Check if data is still a valid frame -- if it is, it should be in the queue*/ + AST_LIST_LOCK(&iaxq.queue); + AST_LIST_TRAVERSE_SAFE_BEGIN(&iaxq.queue, f, list) { + if (f == data) { + found = 1; + callno = f->callno; + break; + } + } + AST_LIST_TRAVERSE_SAFE_END + AST_LIST_UNLOCK(&iaxq.queue); + if (!found) + return; + + /* The frame is valid,, process it */ if (callno) ast_mutex_lock(&iaxsl[callno]); if (callno && iaxs[callno]) { if ((f->retries < 0) /* Already ACK'd */ || @@ -1908,7 +1923,7 @@ } } - freeme++; + //freeme++; } else { /* Update it if it needs it */ update_packet(f); @@ -1927,21 +1942,21 @@ } else { /* Make sure it gets freed */ f->retries = -1; - freeme++; + //freeme++; } if (callno) ast_mutex_unlock(&iaxsl[callno]); /* Do not try again */ - if (freeme) { - /* Don't attempt delivery, just remove it from the queue */ - AST_LIST_LOCK(&iaxq.queue); - AST_LIST_REMOVE(&iaxq.queue, f, list); - iaxq.count--; - AST_LIST_UNLOCK(&iaxq.queue); - f->retrans = -1; - /* Free the IAX frame */ - iax2_frame_free(f); - } +// if (freeme) { +// /* Don't attempt delivery, just remove it from the queue */ +// AST_LIST_LOCK(&iaxq.queue); +// AST_LIST_REMOVE(&iaxq.queue, f, list); +// iaxq.count--; +// AST_LIST_UNLOCK(&iaxq.queue); +// f->retrans = -1; +// /* Free the IAX frame */ +// iax2_frame_free(f); +// } } static int attempt_transmit(void *data) @@ -5938,13 +5953,18 @@ AST_LIST_TRAVERSE(&iaxq.queue, f, list) { /* Send a copy immediately */ if ((f->callno == callno) && iaxs[f->callno] && - ((unsigned char ) (f->oseqno - last) < 128)) { - send_packet(f); + ((unsigned char)(f->oseqno - last) < 128)) { + if (f->dcallno != iaxs[f->callno]->peercallno ) + { + ast_log(LOG_WARNING, "Callno inconsistency detected: callno=%d, peercallno=%d, f->dcallno=%d, f->retries=%d, f->retrans=%d\n", callno, iaxs[f->callno]->peercallno, f->dcallno, f->retries, f->retrans); + } else if ( f->retries == -1 ) { + ast_log(LOG_WARNING, "NO LONGER retransmitting frame with -1 retries (src %d, dest %d, retrans %d)\n", f->callno, f->dcallno, f->retrans); + } else + send_packet(f); } } AST_LIST_UNLOCK(&iaxq.queue); } - static void __iax2_poke_peer_s(void *data) { struct iax2_peer *peer = data; @@ -8317,9 +8337,23 @@ count = 0; wakeup = -1; AST_LIST_TRAVERSE_SAFE_BEGIN(&iaxq.queue, f, list) { - if (f->sentyet) + if (f->sentyet) { + /* Remove frames marked for cleanup */ + if (f->retries < 0) { + unsigned short callno = f->callno; + /* Attempt to lock the call pvt -- if we fail, try again later */ + if (ast_mutex_trylock(&iaxsl[callno])) { + wakeup = 1; + continue; + } + AST_LIST_REMOVE_CURRENT(&iaxq.queue, list); + iaxq.count--; + iax2_frame_free(f); + ast_mutex_unlock(&iaxsl[callno]); + } continue; - + } + /* Try to lock the pvt, if we can't... don't fret - defer it till later */ if (ast_mutex_trylock(&iaxsl[f->callno])) { wakeup = 1;