TXREJ handling (was Re: [Asterisk-Dev] Good quality iaxclient phone)

Steve Kann stevek at stevek.com
Mon Dec 20 10:40:43 MST 2004


Steve Kann wrote:

>
> On Dec 19, 2004, at 4:28 AM, joachim wrote:
>
>>
>> Actually there are some big bugs in iaxclient at the moment causing a 
>> lot of delay. on iax2 to iax2 calls.
>>
>> Try iaxclient to asterisk to iaxclient, a lot of calls will have huge 
>> delays.
>>
>> I think its only in recent iaxclients, the version firefly uses 
>> doesnt seem to be affected. (but latest diax and iaxcomm are).
>>
>> Im not using any iaxclient, but have heard several reports, tried it 
>> myself and confirmed it.
>>
>
>
> I generally don't use/test much native bridging or transferring, but 
> there have been some patches to libiax2 coming from Bill Doll (who is 
> using libiax2, but not iaxclient) affecting how transferring works.
>
> There's a couple of things I see of note:
>
> 1) In complete_transfer, Bill resets a bunch of variables, including 
> the (old) jitterbuffer history and rxcore, Maybe this isn't correct? 
> (also, if it is correct, we ought to clear the (new) jitterbuffer 
> history as well, although the rxcore clearing is more relevant). If 
> problems only happen on native transfer, this seems like the area to 
> look, in libiax2.


OK, I think I've tracked (at least one case of) this issue, but I hope 
someone else can help resolve it:

I made a call from iaxclient -> *1 -> *2, with both legs IAX2. *2 is on 
the internet, and iaxclient and *1 are both behind the same NAT.

In this case, *1 tries to arrange native bridging between iaxclient and 
*2, but this fails, because *2 can't see iaxclient (although, it seems, 
iaxclient should be able to contact *2 through the NAT and make this 
work...)

Then, when iaxclient receives TXREJ, it goes and does lots of bad 
things, including resetting rxcore, which screws up the jitterbuffer 
pretty good.

These issues are all in libiax2, and are all related to Bill Doll's 
patches from a few months ago. There's two bugs here:

1) [I think this is a bug, or at minimum, a design malfeature]: For some 
reason, when setting up the transfer, libiax2 doesn't seem to be 
successfully contacting *2 itself to try to complete the transfer. I 
haven't traced this on the network in the code to see why this is failing.

2) When the transfer fails (as it will in some situations), the handling 
of txreject seems to be broken in iax_handle_txreject() and 
complete_transfer():

static void iax_handle_txreject(struct iax_session *s)
{
struct iax_session *s0, *s1;

complete_transfer(s, s->peercallno, 0, 1);
s->svoiceformat = -1;

s0 = s;
s1 = iax_find_session2(s0->transferpeer);
if (s1 != NULL &&
s0->transferpeer == s1->callno &&
s1->transferring) {
if (s1->transfer_moh) {
s1->transfer_moh = 0;
send_command_immediate(s1, AST_FRAME_IAX, IAX_COMMAND_UNQUELCH, 0, NULL, 
0, s1->iseqno);
}
}
if (s0->transfer_moh) {
s0->transfer_moh = 0;
send_command_immediate(s0, AST_FRAME_IAX, IAX_COMMAND_UNQUELCH, 0, NULL, 
0, s0->iseqno);
}
}
static void complete_transfer(struct iax_session *session, int 
peercallno, int xfr2peer, int preserveSeq)
{
session->peercallno = peercallno;
/* Change from transfer to session now */
if (xfr2peer) {
memcpy(&session->peeraddr, &session->transfer, sizeof(session->peeraddr));
memset(&session->transfer, 0, sizeof(session->transfer));
session->transferring = TRANSFER_NONE;
session->transferpeer = 0;
session->transfer_moh = 0;
/* Force retransmission of a real voice packet, and reset all timing */
session->svoiceformat = -1;
session->voiceformat = 0;
}

memset(&session->rxcore, 0, sizeof(session->rxcore));
memset(&session->offset, 0, sizeof(session->offset));
memset(&session->history, 0, sizeof(session->history));
session->jitterbuffer = 0;
session->jitter = 0;
session->lag = 0;

if (! preserveSeq)
{
/* Reset sequence numbers */
session->aseqno = 0;
session->oseqno = 0;
session->iseqno = 0;
}

session->lastsent = 0;
session->last_ts = 0;
session->lastvoicets = 0;
session->pingtime = 30;
/* We have to dump anything we were going to (re)transmit now that we've 
been
transferred since they're all invalid and for the old host. */
stop_transfer(session);
} /* complete_transfer */


Probably, in the case of txreject, we should just be doing this:

memset(&session->transfer, 0, sizeof(session->transfer));
session->transferring = TRANSFER_NONE;
session->transferpeer = 0;
session->transfer_moh = 0;

This patch seems to fix problem #2 for me, but I'm not sure if it's correct:
RCS file: /cvsroot/iaxclient/iaxclient/lib/libiax2/src/iax.c,v
retrieving revision 1.33
diff -u -w -r1.33 iax.c
--- iax.c 15 Dec 2004 17:56:59 -0000 1.33
+++ iax.c 20 Dec 2004 17:39:55 -0000
@@ -1109,9 +1109,6 @@
{
struct iax_session *s0, *s1;

- complete_transfer(s, s->peercallno, 0, 1);
- s->svoiceformat = -1;
-
s0 = s;
s1 = iax_find_session2(s0->transferpeer);
if (s1 != NULL &&
@@ -1126,6 +1123,11 @@
s0->transfer_moh = 0;
send_command_immediate(s0, AST_FRAME_IAX, IAX_COMMAND_UNQUELCH, 0, NULL, 
0, s0->iseqno);
}
+
+ memset(&s->transfer, 0, sizeof(s->transfer));
+ s->transferring = TRANSFER_NONE;
+ s->transferpeer = 0;
+ s->transfer_moh = 0;
}

static void destroy_session(struct iax_session *session)







More information about the asterisk-dev mailing list