diff --git a/lib/installer-exclude/ice4j.jar b/lib/installer-exclude/ice4j.jar index 71330075b..fdc82de6a 100644 Binary files a/lib/installer-exclude/ice4j.jar and b/lib/installer-exclude/ice4j.jar differ diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/JingleNodesCandidateDatagramSocket.java b/src/net/java/sip/communicator/impl/protocol/jabber/JingleNodesCandidateDatagramSocket.java index 7a896e7d1..a34624f55 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/JingleNodesCandidateDatagramSocket.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/JingleNodesCandidateDatagramSocket.java @@ -9,8 +9,10 @@ import java.io.*; import java.net.*; +import net.java.sip.communicator.util.*; import org.ice4j.*; import org.ice4j.socket.*; +import org.ice4j.stack.*; /** * Represents an application-purposed (as opposed to an ICE-specific) @@ -20,6 +22,121 @@ */ public class JingleNodesCandidateDatagramSocket extends DatagramSocket { + /** + * The Logger used by the + * JingleNodesCandidateDatagramSocket class and its instances for + * logging output. + */ + private static final Logger logger + = Logger.getLogger(JingleNodesCandidateDatagramSocket.class); + + /** + * Determines whether a packet should be logged, given the number of sent + * or received packets. + * + * @param numOfPacket the number of packets sent or received. + */ + private static boolean logPacket(long numOfPacket) + { + return (numOfPacket == 1) + || (numOfPacket == 300) + || (numOfPacket == 500) + || (numOfPacket == 1000) + || ((numOfPacket % 5000) == 0); + } + + /** + * Logs information about RTP losses if there is more then 5% of RTP packet + * lost (at most every 5 seconds). + * + * @param totalNbLost The total number of lost packet since the beginning of + * this stream. + * @param totalNbReceived The total number of received packet since the + * beginning of this stream. + * @param lastLogTime The last time we have logged information about RTP + * losses. + * + * @return the last log time updated if this function as log new information + * about RTP losses. Otherwise, returns the same last log time value as + * given in parameter. + */ + private static long logRtpLosses( + long totalNbLost, + long totalNbReceived, + long lastLogTime) + { + double percentLost = ((double) totalNbLost) + / ((double) (totalNbLost + totalNbReceived)); + // Log the information if the loss rate is upper 5% and if the last + // log is before 5 seconds. + if(percentLost > 0.05) + { + long currentTime = System.currentTimeMillis(); + if(currentTime - lastLogTime >= 5000) + { + logger.info("RTP lost > 5%: " + percentLost); + return currentTime; + } + } + return lastLogTime; + } + + /** + * Return the number of loss between the 2 last RTP packets received. + * + * @param lastRtpSequenceNumber The previous RTP sequence number. + * @param newSeq The current RTP sequence number. + * + * @return the number of loss between the 2 last RTP packets received. + */ + private static long getNbLost( + long lastRtpSequenceNumber, + long newSeq) + { + long newNbLost = 0; + if(lastRtpSequenceNumber <= newSeq) + { + newNbLost = newSeq - lastRtpSequenceNumber; + } + else + { + newNbLost = (0xffff - lastRtpSequenceNumber) + newSeq; + } + + if(newNbLost > 1) + { + if(newNbLost < 0x00ff) + { + return newNbLost - 1; + } + // Else the paquet is desequenced, then count it as a + // single loss. + else + { + return 1; + } + } + return 0; + } + + /** + * Determines the sequence number of an RTP packet. + * + * @param p the last RTP packet received. + * @return The last RTP sequence number. + */ + private static long getRtpSequenceNumber(DatagramPacket p) + { + // The sequence number is contained in the third and fourth bytes of the + // RTP header (stored in big endian). + byte[] data = p.getData(); + int offset = p.getOffset(); + long seq_high = data[offset + 2] & 0xff; + long seq_low = data[offset + 3] & 0xff; + + return seq_high << 8 | seq_low; + } + /** * TransportAddress of the Jingle Nodes relay where we will send * our packet. @@ -107,14 +224,14 @@ public void send(DatagramPacket p) //XXX reuse an existing DatagramPacket ? super.send(packet); - // no exception packet is successfully sent, log it. - ++nbSentRtpPackets; - DelegatingDatagramSocket.logPacketToPcap( - packet, - this.nbSentRtpPackets, - true, - super.getLocalAddress(), - super.getLocalPort()); + if (logPacket(++nbSentRtpPackets)) + { + StunStack.logPacketToPcap( + packet, + true, + super.getLocalAddress(), + super.getLocalPort()); + } } /** @@ -131,14 +248,14 @@ public void receive(DatagramPacket p) { super.receive(p); - // no exception packet is successfully received, log it. - ++nbReceivedRtpPackets; - DelegatingDatagramSocket.logPacketToPcap( - p, - this.nbReceivedRtpPackets, - false, - super.getLocalAddress(), - super.getLocalPort()); + if (logPacket(++nbReceivedRtpPackets)) + { + StunStack.logPacketToPcap( + p, + false, + super.getLocalAddress(), + super.getLocalPort()); + } // Log RTP losses if > 5%. updateRtpLosses(p); } @@ -210,15 +327,16 @@ private void updateRtpLosses(DatagramPacket p) // If this is not a STUN/TURN packet, then this is a RTP packet. if(!StunDatagramPacketFilter.isStunPacket(p)) { - long newSeq = DelegatingDatagramSocket.getRtpSequenceNumber(p); + long newSeq = getRtpSequenceNumber(p); if(this.lastRtpSequenceNumber != -1) { - nbLostRtpPackets += DelegatingDatagramSocket - .getNbLost(this.lastRtpSequenceNumber, newSeq); + nbLostRtpPackets += + getNbLost(this.lastRtpSequenceNumber, newSeq); } this.lastRtpSequenceNumber = newSeq; - this.lastLostPacketLogTime = DelegatingDatagramSocket.logRtpLosses( + this.lastLostPacketLogTime + = logRtpLosses( this.nbLostRtpPackets, this.nbReceivedRtpPackets, this.lastLostPacketLogTime);