/* The Java RTP/I library, Version 0.1 alpha.
*
* This library provides the functionality of RTP/I as it is specified in
* Internet Draft draft-mauve-rtpi-00.txt.
*
* Copyright (C) 2000 Martin Mauve
* University of Mannheim / Germany
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Martin Mauve
*
* e-mail:
* mauve@informatik.uni-mannheim.de
*
* paper mail:
* Martin Mauve
* University of Mannheim
* Lehrstuhl Praktische Informatik IV
* L15, 16
* 68131 Mannheim
* Germany
*/
package rtpi.packets;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import rtpi.IllegalValueException;
/**
* This class represents RTCP/I Application packets.
* Application packets allow an application to send
* custom RTCP/I packets. This should be used with
* caution, since it may impair the RTCP/I protocol
* performance.
*
* @author Martin Mauve
*/
public final class RtcpiApplicationPacket extends RtcpiPacket {
/**
* The payload type for application packets.
*/
public static final int APP = 73;
private byte[] data=null;
private byte[] name=null;
/**
* This creates an RTCP/I application packet that is to
* be transmitted over the network.
*
* @param pid The Id of the participant sending the packet.
* @param n The 4 byte name string identifying this application RTCP/I packet type.
* @param d The data contained in this packet.
*/
public RtcpiApplicationPacket(int pid, byte[] n, byte[] d) throws IllegalValueException {
super(pid);
payloadType=APP;
name=n;
data=d;
if (name.length!=4) {
throw new IllegalValueException("RtcpiApplicationPacket: illegal name length: "+name.length+" should be 4");
}
if (data.length%4!=0) {
throw new IllegalValueException("RtcpiApplicationPacket: illegal data length: "+data.length+" should be divisble by 4");
}
length=1+data.length/4;
}
/**
* This creates an RTCP/I application packet from a transport packet
* that has been received.
*
* @param d The transport packet.
* @param s The start of the RTCP/I packet in the transport packet
* (position of the first byte of the RTCP/I header.
*/
public RtcpiApplicationPacket(byte[] d, int s) {
super(d, s);
}
/**
* This method flushes the packet to a byte array.
*/
public void flush() throws RtpiFlushException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
flushHeader(dos);
try {
dos.write(name);
dos.write(data);
} catch (Exception ex) {
throw new RtpiFlushException("RtcpiApplicationPacket: Couldn't write name & data");
}
try {
dos.flush();
bos.flush();
} catch (Exception ex) {
throw new RtpiFlushException("RtcpiApplicationPacket: Couldn't flush output streams");
}
packetData = bos.toByteArray();
if (packetData.length!=(length+2)*4) {
throw new RtpiFlushException("RtcpiApplicationPacket: Illegal packet length after flushing packet");
}
try {
dos.close();
bos.close();
} catch (Exception ex) {
throw new RtpiFlushException("RtcpiApplicationPacket: Couldn't close output streams");
}
}
/**
* This method parses an RTCP/I application packet.
*/
public void parse() throws RtpiParseException {
ByteArrayInputStream bis = new ByteArrayInputStream(packetData, packetStart, packetData.length-packetStart);
DataInputStream dis = new DataInputStream(bis);
parseHeader(dis);
if (payloadType!=APP) {
throw new RtpiParseException("RtcpiApplicationPacket:wrong payload type, was "+payloadType);
}
if (length<2) {
throw new RtpiParseException("RtcpiApplicationPacket: size of application RTCP/I packet too small (less than 2)");
}
name= new byte[4];
data= new byte[(length-1)*4];
try {
dis.readFully(name);
dis.readFully(data);
} catch (Exception exe) {
throw new RtpiParseException("RtcpiApplicationPacket: Could not read name and data from packet");
}
try {
dis.close();
bis.close();
} catch (Exception exe) {
throw new RtpiParseException("RtcpiApplicationPacket: Could not close input stream for packet");
}
}
/**
* Get the 4 byte name identifying the type of this RTCP/I application packet.
*
* @return The name.
*/
public byte[] getName() {
return name;
}
/**
* Get the data that is contained in this RTCP/I application packet.
*
* @return The data.
*/
public byte[] getData() {
return data;
}
/**
* Convert this object to a string.
*
* @return This object as a string.
*/
public String toString() {
String returnValue;
returnValue ="RtcpiApplicationPacket: {\n";
returnValue+=toStringDetails();
returnValue+="}\n";
return returnValue;
}
String toStringDetails() {
String returnValue;
returnValue=super.toStringDetails();
returnValue+=" Name: "+new String(name)+"\n";
returnValue+=" Data: "+new String(data)+"\n";
return returnValue;
}
}