[jitsi-dev] ice4j issues


#1

I've found a few issues in ice4j, I don't mind committing fixes if that
would help:

- Transport.parse() is case sensitive - this means it can't accept the
upper case UDP from a candidate line. The RFC examples use uppercase

- When I add an RTP and RTCP component on a single audio stream, I
notice that the StunCandidateHarvester is in the disabled state when
harvesting for the second component (RTCP), so gathering only finds the
host candidate


#2

Hi Daniel,

Le 10/01/12 11:55, Daniel Pocock a �crit :

I've found a few issues in ice4j, I don't mind committing fixes if that
would help:

- Transport.parse() is case sensitive - this means it can't accept the
upper case UDP from a candidate line. The RFC examples use uppercase

Good catch. We will fix it.

- When I add an RTP and RTCP component on a single audio stream, I
notice that the StunCandidateHarvester is in the disabled state when
harvesting for the second component (RTCP), so gathering only finds the
host candidate

Strange, does it happen with Jitsi or an application you write ?
If it the second ones, can you send us part that deals with ice4j. In any cases the pcap logs (maybe the STUN servers doesn't reply to RTCP STUN query, ...).

Jitsi uses intensively ice4j for XMPP Jingle and all the components (RTP/RTCP) correctly gather STUN candidates.

We suggest you to see net.java.sip.communicator.impl.protocol.jabber.IceUdpTransportManager class that Jitsi uses to setup ice4j's Agent.

Regards,

···

--
Seb


#3

- When I add an RTP and RTCP component on a single audio stream, I
notice that the StunCandidateHarvester is in the disabled state when
harvesting for the second component (RTCP), so gathering only finds the
host candidate

Strange, does it happen with Jitsi or an application you write ?
If it the second ones, can you send us part that deals with ice4j. In
any cases the pcap logs (maybe the STUN servers doesn't reply to RTCP
STUN query, ...).

I am using TURN and trying both the open turnserver and reTurn from
reSIProcate

I noticed that in StunCandidateHarvester.harvest(), after the call
waitForResolutionEnd(), there were no new candidates found

However, if I add the line
Thread.sleep(5000)
to make it wait a little more after waitForResolutionEnd(), then it
finds the candidates

In the case where candidates are not found, (without the sleep), then
ice4j disables the harvester
(CandidateHarvesterSetElement.setDisabled(false))

Have you seen problems with waitForResolutionEnd() elsewhere?

In case it's relevant, I'm running the code on android (not a regular JVM)

Jitsi uses intensively ice4j for XMPP Jingle and all the components
(RTP/RTCP) correctly gather STUN candidates.

Have you got a SIP implementation in the works? It would be good to
have inter-op with my own app.

We suggest you to see
net.java.sip.communicator.impl.protocol.jabber.IceUdpTransportManager
class that Jitsi uses to setup ice4j's Agent.

Thanks for referring me to that, I'll go over that now


#4

Hi,

Le 10/01/12 15:18, Daniel Pocock a �crit :

- When I add an RTP and RTCP component on a single audio stream, I
notice that the StunCandidateHarvester is in the disabled state when
harvesting for the second component (RTCP), so gathering only finds the
host candidate

Strange, does it happen with Jitsi or an application you write ?
If it the second ones, can you send us part that deals with ice4j. In
any cases the pcap logs (maybe the STUN servers doesn't reply to RTCP
STUN query, ...).

I am using TURN and trying both the open turnserver and reTurn from
reSIProcate

I noticed that in StunCandidateHarvester.harvest(), after the call
waitForResolutionEnd(), there were no new candidates found

However, if I add the line
Thread.sleep(5000)
to make it wait a little more after waitForResolutionEnd(), then it
finds the candidates

In the case where candidates are not found, (without the sleep), then
ice4j disables the harvester
(CandidateHarvesterSetElement.setDisabled(false))

Have you seen problems with waitForResolutionEnd() elsewhere?

In case it's relevant, I'm running the code on android (not a regular JVM)

I think the STUN transactions timed out maybe because android device does not send/receive "quickly" the STUN answer. Do you use Wi-Fi or 3G to communicate with your android device ? Is it a recent model (power, ...) ?

StunCandidateHarvester (in its constructor) sets some properties about retransmission timer and number or retransmission. The default is 400 ms for the retransmission timer and it try 3 times so in other words if STUN answer is not received in 1600 ms (which is quite long for a delay) it will disable StunCandidateHarvester. I don't know if it is possible to get pcap traces on android devices but it will inform us the time when device received STUN answer (and so the delay with STUN query). You can try to play with these parameters or modify the code in order to determine the delay between STUN query sent and STUN response received.

Jitsi uses intensively ice4j for XMPP Jingle and all the components
(RTP/RTCP) correctly gather STUN candidates.

Have you got a SIP implementation in the works? It would be good to
have inter-op with my own app.

IIRC ICE support for SIP is planned for this year, but we have no precise roadmap about it right now.

We suggest you to see
net.java.sip.communicator.impl.protocol.jabber.IceUdpTransportManager
class that Jitsi uses to setup ice4j's Agent.

Thanks for referring me to that, I'll go over that now

Regards,

···

--
Seb


#5

Hi,

Le 10/01/12 15:18, Daniel Pocock a �crit :

- When I add an RTP and RTCP component on a single audio stream, I
notice that the StunCandidateHarvester is in the disabled state when
harvesting for the second component (RTCP), so gathering only finds the
host candidate

Strange, does it happen with Jitsi or an application you write ?
If it the second ones, can you send us part that deals with ice4j. In
any cases the pcap logs (maybe the STUN servers doesn't reply to RTCP
STUN query, ...).

I am using TURN and trying both the open turnserver and reTurn from
reSIProcate

I noticed that in StunCandidateHarvester.harvest(), after the call
waitForResolutionEnd(), there were no new candidates found

However, if I add the line
Thread.sleep(5000)
to make it wait a little more after waitForResolutionEnd(), then it
finds the candidates

In the case where candidates are not found, (without the sleep), then
ice4j disables the harvester
(CandidateHarvesterSetElement.setDisabled(false))

Have you seen problems with waitForResolutionEnd() elsewhere?

In case it's relevant, I'm running the code on android (not a regular
JVM)

I think the STUN transactions timed out maybe because android device
does not send/receive "quickly" the STUN answer. Do you use Wi-Fi or 3G
to communicate with your android device ? Is it a recent model (power,
...) ?

I've tried all combinations of wifi, 3G and the Android emulator

StunCandidateHarvester (in its constructor) sets some properties about
retransmission timer and number or retransmission. The default is 400 ms
for the retransmission timer and it try 3 times so in other words if
STUN answer is not received in 1600 ms (which is quite long for a delay)
it will disable StunCandidateHarvester. I don't know if it is possible
to get pcap traces on android devices but it will inform us the time
when device received STUN answer (and so the delay with STUN query). You
can try to play with these parameters or modify the code in order to
determine the delay between STUN query sent and STUN response received.

I'll have a closer look at that and I'm quite happy to share the
solution that I find

Jitsi uses intensively ice4j for XMPP Jingle and all the components
(RTP/RTCP) correctly gather STUN candidates.

Have you got a SIP implementation in the works? It would be good to
have inter-op with my own app.

IIRC ICE support for SIP is planned for this year, but we have no
precise roadmap about it right now.

My code is close to working now using SIP, but it is only a test
version, it needs refinement. Once I get around to generalising it,
I'll see if I can do so in such a way that some of the code can be
shared between projects

···

On 10/01/12 15:44, Sebastien Vincent wrote:


#6

Hi,

Le 10/01/12 15:18, Daniel Pocock a �crit :

- When I add an RTP and RTCP component on a single audio stream, I
notice that the StunCandidateHarvester is in the disabled state when
harvesting for the second component (RTCP), so gathering only finds the
host candidate

Strange, does it happen with Jitsi or an application you write ?
If it the second ones, can you send us part that deals with ice4j. In
any cases the pcap logs (maybe the STUN servers doesn't reply to RTCP
STUN query, ...).

I am using TURN and trying both the open turnserver and reTurn from
reSIProcate

I noticed that in StunCandidateHarvester.harvest(), after the call
waitForResolutionEnd(), there were no new candidates found

However, if I add the line
Thread.sleep(5000)
to make it wait a little more after waitForResolutionEnd(), then it
finds the candidates

In the case where candidates are not found, (without the sleep), then
ice4j disables the harvester
(CandidateHarvesterSetElement.setDisabled(false))

Have you seen problems with waitForResolutionEnd() elsewhere?

In case it's relevant, I'm running the code on android (not a regular
JVM)

I think the STUN transactions timed out maybe because android device
does not send/receive "quickly" the STUN answer. Do you use Wi-Fi or 3G
to communicate with your android device ? Is it a recent model (power,
...) ?

I've tried all combinations of wifi, 3G and the Android emulator

StunCandidateHarvester (in its constructor) sets some properties about
retransmission timer and number or retransmission. The default is 400 ms
for the retransmission timer and it try 3 times so in other words if
STUN answer is not received in 1600 ms (which is quite long for a delay)
it will disable StunCandidateHarvester. I don't know if it is possible
to get pcap traces on android devices but it will inform us the time
when device received STUN answer (and so the delay with STUN query). You
can try to play with these parameters or modify the code in order to
determine the delay between STUN query sent and STUN response received.

I'll have a closer look at that and I'm quite happy to share the
solution that I find

Gotcha... race condition

Here is a revised version of
StunCandidateHarvester.completedResolvingCandidate that seems more
stable on the Android devices and high latency environments

However, it is still not perfect, in one test, for example, I got the
srflx candidate for RTP, and both srflx and relay for RTCP

However, I think it is mandatory not to call notify until
completedHarvests is populated:

    void completedResolvingCandidate(StunCandidateHarvest harvest)
    {
      boolean doNotify = false;
        synchronized (startedHarvests)
        {
            startedHarvests.remove(harvest);

            //if this was the last candidate, we are done with the STUN
            //resolution and need to notify the waiters.
            if (startedHarvests.isEmpty())
                doNotify = true;
        }

        synchronized (completedHarvests)
        {
            if (harvest.getCandidateCount() < 1)
                completedHarvests.remove(harvest);
            else if (!completedHarvests.contains(harvest))
                completedHarvests.add(harvest);
        }

        synchronized (startedHarvests) {
          if(doNotify)
            startedHarvests.notify();
        }
    }

···

On 10/01/12 16:01, Daniel Pocock wrote:

On 10/01/12 15:44, Sebastien Vincent wrote:

Jitsi uses intensively ice4j for XMPP Jingle and all the components
(RTP/RTCP) correctly gather STUN candidates.

Have you got a SIP implementation in the works? It would be good to
have inter-op with my own app.

IIRC ICE support for SIP is planned for this year, but we have no
precise roadmap about it right now.

My code is close to working now using SIP, but it is only a test
version, it needs refinement. Once I get around to generalising it,
I'll see if I can do so in such a way that some of the code can be
shared between projects


#7

Le 10/01/12 17:00, Daniel Pocock a �crit :

Hi,

Le 10/01/12 15:18, Daniel Pocock a �crit :

- When I add an RTP and RTCP component on a single audio stream, I
notice that the StunCandidateHarvester is in the disabled state when
harvesting for the second component (RTCP), so gathering only finds the
host candidate

Strange, does it happen with Jitsi or an application you write ?
If it the second ones, can you send us part that deals with ice4j. In
any cases the pcap logs (maybe the STUN servers doesn't reply to RTCP
STUN query, ...).

I am using TURN and trying both the open turnserver and reTurn from
reSIProcate

I noticed that in StunCandidateHarvester.harvest(), after the call
waitForResolutionEnd(), there were no new candidates found

However, if I add the line
Thread.sleep(5000)
to make it wait a little more after waitForResolutionEnd(), then it
finds the candidates

In the case where candidates are not found, (without the sleep), then
ice4j disables the harvester
(CandidateHarvesterSetElement.setDisabled(false))

Have you seen problems with waitForResolutionEnd() elsewhere?

In case it's relevant, I'm running the code on android (not a regular
JVM)

I think the STUN transactions timed out maybe because android device
does not send/receive "quickly" the STUN answer. Do you use Wi-Fi or 3G
to communicate with your android device ? Is it a recent model (power,
...) ?

I've tried all combinations of wifi, 3G and the Android emulator

StunCandidateHarvester (in its constructor) sets some properties about
retransmission timer and number or retransmission. The default is 400 ms
for the retransmission timer and it try 3 times so in other words if
STUN answer is not received in 1600 ms (which is quite long for a delay)
it will disable StunCandidateHarvester. I don't know if it is possible
to get pcap traces on android devices but it will inform us the time
when device received STUN answer (and so the delay with STUN query). You
can try to play with these parameters or modify the code in order to
determine the delay between STUN query sent and STUN response received.

I'll have a closer look at that and I'm quite happy to share the
solution that I find

Gotcha... race condition

Here is a revised version of
StunCandidateHarvester.completedResolvingCandidate that seems more
stable on the Android devices and high latency environments

However, it is still not perfect, in one test, for example, I got the
srflx candidate for RTP, and both srflx and relay for RTCP

However, I think it is mandatory not to call notify until
completedHarvests is populated:

     void completedResolvingCandidate(StunCandidateHarvest harvest)
     {
       boolean doNotify = false;
         synchronized (startedHarvests)
         {
             startedHarvests.remove(harvest);

             //if this was the last candidate, we are done with the STUN
             //resolution and need to notify the waiters.
             if (startedHarvests.isEmpty())
                 doNotify = true;
         }

         synchronized (completedHarvests)
         {
             if (harvest.getCandidateCount()< 1)
                 completedHarvests.remove(harvest);
             else if (!completedHarvests.contains(harvest))
                 completedHarvests.add(harvest);
         }

         synchronized (startedHarvests) {
           if(doNotify)
             startedHarvests.notify();
         }
     }

Thanks, we will review your modification this week and come back to you if we have comments.

Regards,

···

On 10/01/12 16:01, Daniel Pocock wrote:

On 10/01/12 15:44, Sebastien Vincent wrote:

--
Seb

Jitsi uses intensively ice4j for XMPP Jingle and all the components
(RTP/RTCP) correctly gather STUN candidates.

Have you got a SIP implementation in the works? It would be good to
have inter-op with my own app.

IIRC ICE support for SIP is planned for this year, but we have no
precise roadmap about it right now.

My code is close to working now using SIP, but it is only a test
version, it needs refinement. Once I get around to generalising it,
I'll see if I can do so in such a way that some of the code can be
shared between projects