/* * Copyright 2007 Sun Microsystems, Inc. * * This file is part of jVoiceBridge. * * jVoiceBridge is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation and distributed hereunder * to you. * * jVoiceBridge is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * Sun designates this particular file as subject to the "Classpath" * exception as provided by Sun in the License file that accompanied this * code. */ package com.sun.voip; import java.io.IOException; import java.net.DatagramPacket; /* * From RFC1889 * * Receiver Report * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |V=2|P| RC | PT=RR=201 | length | header * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | SSRC of packet sender | * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * | SSRC_1 (SSRC of first source) | report * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block * | fraction lost | cumulative number of packets lost | 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | extended highest sequence number received | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | interarrival jitter | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | last SR (LSR) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | delay since last SR (DLSR) | * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * | SSRC_2 (SSRC of second source) | report * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block * : ... : 2 * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * | profile-specific extensions | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ public class RtcpReceiverPacket extends RtcpPacket { /* * This constructor is used for a packet which has been received. */ public RtcpReceiverPacket(DatagramPacket packet) { super(packet); } /* * This constructor is used to create a packet to send */ public RtcpReceiverPacket(int SSRC) { super(SSRC, false); setSSRC_1(SSRC); } public void setSSRC_1(int SSRC) { rtcpData[8] = (byte) ((SSRC >> 24) & 0xff); rtcpData[9] = (byte) ((SSRC >> 16) & 0xff); rtcpData[10] = (byte) ((SSRC >> 8) & 0xff); rtcpData[11] = (byte) (SSRC & 0xff); } public void setFractionLost(byte fractionLost) { rtcpData[12] = fractionLost; } public byte getFractionLost() { return rtcpData[12]; } public void setCumulativeLost(int cumulativeLost) { rtcpData[13] = (byte) ((cumulativeLost >> 16) & 0xff); rtcpData[14] = (byte) ((cumulativeLost >> 8) & 0xff); rtcpData[15] = (byte) (cumulativeLost & 0xff); } public int getCumulativeLost() { int cumulativeLost = ((((int)rtcpData[13]) << 16) & 0x00ff0000) | ((((int)rtcpData[14]) << 8) & 0x0000ff00) | (rtcpData[15] & 0xff); if ((rtcpData[13] & 0x80) != 0) { cumulativeLost |= 0xff000000; // it's negative } return cumulativeLost; } public void setHighestSeqReceived(int seq) { rtcpData[16] = (byte) ((seq >> 24) & 0xff); rtcpData[17] = (byte) ((seq >> 16) & 0xff); rtcpData[18] = (byte) ((seq >> 8) & 0xff); rtcpData[19] = (byte) (seq & 0xff); } public int getHighestSeqReceived() { return ((((int)rtcpData[16]) << 24) & 0xff000000) | ((((int)rtcpData[17]) << 16) & 0x00ff0000) | ((((int)rtcpData[18]) << 8) & 0x0000ff00) | (rtcpData[19] & 0xff); } public void setInterArrivalJitter(int interArrivalJitter) { rtcpData[20] = (byte) ((interArrivalJitter >> 24) & 0xff); rtcpData[21] = (byte) ((interArrivalJitter >> 16) & 0xff); rtcpData[22] = (byte) ((interArrivalJitter >> 8) & 0xff); rtcpData[23] = (byte) (interArrivalJitter & 0xff); } public int getInterArrivalJitter() { return ((((int)rtcpData[20]) << 24) & 0xff000000) | ((((int)rtcpData[21]) << 16) & 0x00ff0000) | ((((int)rtcpData[22]) << 8) & 0x0000ff00) | (rtcpData[23] & 0xff); } public void setLSR(int LSR) { rtcpData[24] = (byte) ((LSR >> 24) & 0xff); rtcpData[25] = (byte) ((LSR >> 16) & 0xff); rtcpData[26] = (byte) ((LSR >> 8) & 0xff); rtcpData[27] = (byte) (LSR & 0xff); } public int getLSR() { return ((((int)rtcpData[24]) << 24) & 0xff000000) | ((((int)rtcpData[25]) << 16) & 0x00ff0000) | ((((int)rtcpData[26]) << 8) & 0x0000ff00) | (rtcpData[27] & 0xff); } public void setDLSR(int DLSR) { rtcpData[28] = (byte) ((DLSR >> 24) & 0xff); rtcpData[29] = (byte) ((DLSR >> 16) & 0xff); rtcpData[30] = (byte) ((DLSR >> 8) & 0xff); rtcpData[31] = (byte) (DLSR & 0xff); } public void printReport() { if (Logger.logLevel >= Logger.LOG_INFO) { Logger.writeFile(" RTCP Receiver report: " + " from " + from + ", fractionLost " + getFractionLost() + ", highest sequence " + Integer.toHexString(getHighestSeqReceived()) + ", cumulativeLost " + getCumulativeLost() + ", jitter " + getInterArrivalJitter() + " LSR " + getLSR()); } } }