Package rtpi.packets

Source Code of rtpi.packets.RtpiDataPacket

/* 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 rtpi.IllegalValueException;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;

/**
* This class represents an RTP/I data packet.
*
* @author Martin Mauve
*/

final public class RtpiDataPacket {

    /**
     * The RTP/I header size.
     */

    public final static int HEADER_SIZE = 28;

    /**
     * The protocol version number.
     */

    public final static int VERSION = 1;

    /**
     * EVENT ADU type.
     */

    public final static int EVENT        = 0;

    /**
     * STATE ADU type.
     */

    public final static int STATE        = 1;

    /**
     * DELTA_STATE ADU type.
     */

    public final static int DELTA_STATE  = 2;

    /**
     * STATE_QUERY ADU type.
     */

    public final static int STATE_QUERY  = 3;

    /**
     * ILLEGAL ADU type.
     */

    public final static int ILLEGAL_TYPE = 16;

    /**
     * Reliability mapping ID for unreliable transmission.
     */

    public final static int NO_RELIABILITY           = 0;

    /**
     * Reliability mapping ID for transprent transport level reliability (such as TCP).
     */

    public final static int RELIABLE_TRANSPORT       = 1;

    /**
     * Illegal value for the reliability mapping.
     */

    public final static int ILLEGAL_RELIABILITY_TYPE = 64;

    /**
     * Illegal value for the payload type field.
     */

    public final static int ILLEGAL_PAYLOAD_TYPE     = 0xFF;

    // fixed header fields

    private int    version=VERSION;
    private int    end=0;
    private int    extension=0;
    private int    type=ILLEGAL_TYPE;
    private int    payloadType=ILLEGAL_PAYLOAD_TYPE;
    private int    length=0;
    private int    reliabilityType=ILLEGAL_RELIABILITY_TYPE;
    private int    priority=0;
    private byte   profileInformation=0x0;
    private byte[] reliabilityInformation=new byte[2];
    private int    participantID=0;
    private long   subcomponentID=0;
    private int    sequenceNumber=0;
    private int    fragmentCount=0;
    private long   timestamp=0;

    // optional header extension

    private int reliabilityHeaderLength=0;
    private byte[] reliabilityHeader=null;

    // binary representation of the packet

    private byte[] packetData=null;
    private int payloadStart=0;
    private int headerStart=0;
    private int payloadLength=0;

    // Bitmasks for parsing:

    private final static int VERSION_BITMASK          = 0xC0;
    private final static int END_BITMASK              = 0x20;
    private final static int EXTENSION_BITMASK        = 0x10;
    private final static int TYPE_BITMASK             = 0x0F;
    private final static int RELIABILITY_TYPE_BITMASK = 0xFC;
    private final static int PRIORITY_BITMASK         = 0x03;

    // Bitmasks for removing the sign

    private final static int INT_REMOVE_SIGN_BITMASK     = 0x7fffffff;
    private final static int INT_SIGN_BITMASK            = 0x80000000;


    /**
     * This creates ab RtpiDataPacket from an incoming packet. The
     * incoming transport layer packet may contain more than one
     * RtpiDataPacket.
     *
     * @param transportPacket The transport packet that has been received.
     * @param start The start of the RtpiDataPacket within the transport packet.
     *              This identifies the position of the first byte of the header
     *              of this RtpiDataPacket in the transportPacket. It must be
     *              in the range between 0 and transportPacket.length.
     */

    public RtpiDataPacket(byte[] transportPacket, int start) {
  packetData=transportPacket;
  headerStart=start;
    }

    /**
     * This creates a new RtpiDataPacket that is to be transmitted
     * over the network.
     *
     * @param rtpiDataPacket The payload data.
     * @param start The start of the payload data in the byte array. Ideally this should
     *              be identical to the sum of RTP/I header and reliability header. Then
     *              the header can be prepended to tha payload without copy operation.
     * @param size The size of the payload data in the data array.
     */

    public RtpiDataPacket(byte[] data, int begin, int size) {
  packetData=data;
  payloadStart=begin;
  payloadLength=size;
    }


    /**
     * This returns the position of the first byte of this packet's payload.
     *
     * @return The position of the first byte of the payload.
     */

    public int getPayloadStart() {
  return payloadStart;
    }

    /**
     * This returns the length of the payload in bytes.
     *
     * @return The length of the payload.
     */

    public int getPayloadLength() {
  return payloadLength;
    }

    /**
     * This returns the protocol version of the packet.
     *
     * @return The protocol version of this packet
     */

    public int getVersion() {
  return version;
    }

    /**
     * This returns the value of this packets end bit.
     *
     * @return Value of the end bit.
     */

    public int getEnd() {
  return end;
    }

    /**
     * This sets the value of the end bit for this packet.
     *
     * @param e The end bit.
     */

    public void setEnd(int e) {
  end=e;
    }

    /**
     * This returns the value of the extension bit.
     *
     * @return The value of the extension bit.
     */

    public int getExtension() {
  return extension;
    }

    /**
     * This sets the value of the extension bit for this packet.
     *
     * @param e The value of the extension bit.
     */

    public void setExtension(int e) {
  extension=e;
    }

    /**
     * This returns the ADU type of the packet.
     *
     * @return The ADU type (e.g. STATE or EVENT).
     */

    public int getType() {
  return type;
    }

    /**
     * This sets the ADU type for this packet.
     *
     * @param t The ADU type (e.g. STATE or EVENT).
     */

    public void setType(int t) {
  type=t;
    }

    /**
     * This returns the payload type of the packet.
     *
     * @return The payload type.
     */

    public int getPayloadType() {
  return payloadType;
    }

    /**
     * This sets the payload type for the packet.
     *
     * @param pt The payload type.
     */

    public void setPayloadType(int pt) {
  payloadType=pt;
    }

    /**
     * This gets the length field of the packet.
     *
     * @return The length field of the packet.
     */

    public int getLength() {
  return length;
    }


    /**
     * This returns the reliability type of the packet.
     *
     * @return The reliability Type.
     */

    public int getReliabilityType() {
  return reliabilityType;
    }

    /**
     * This sets the reliability type of the packet.
     *
     * @param rt The reliability Type.
     */

    public void setReliabilityType(int rt) {
  reliabilityType=rt;
    }

    /**
     * This gets the priority of the packet.
     *
     * @return The priority.
     */

    public int getPriority() {
  return priority;
    }

    /**
     * This sets the priority of the packet.
     *
     * @param The Priority.
     */

    public void setPriority(int p) {
  priority=p;
    }

    /**
     * This gets the profile specific information contained in
     * this packet.
     *
     * @return The profile specific information.
     */

    public byte getProfileInformation() {
  return profileInformation;
    }

    /**
     * This sets the profile specific information for this
     * packet.
     *
     * @param pi The profile specific information.
     */

    public void setProfileInformation(byte pi) {
  profileInformation=pi;
    }

    /**
     * This gets the reliability specific information contained
     * in the packet.
     *
     * @return The profile specific information.
     */

    public byte[] getReliabilityInformation() {
  return reliabilityInformation;
    }

    /**
     * This sets the reliability specific information for
     * this packet.
     *
     * @param The reliability specific information.
     */

    public void setReliabilityInformation(byte b0, byte b1) {
  reliabilityInformation[0]=b0;
  reliabilityInformation[1]=b1;
    }

    /**
     * This gets the participant ID of this packets sender.
     *
     * @return The participant ID.
     */

    public int getParticipantID() {
  return participantID;
    }

    /**
     * This sets the participant ID of this packet.
     *
     * @param The participant ID.
     */

    public void setParticipantID(int pid) {
  participantID=pid;
    }

    /**
     * This gets the subcomponent ID of the subcomponent
     * this packet refers to.
     *
     * @return The subcomponent ID.
     */

    public long getSubcomponentID() {
  return subcomponentID;
    }

    /**
     * This sets the subcomponent ID for this packet.
     *
     * @param The subcomponent ID.
     */

    public void setSubcomponentID(long subID) {
  subcomponentID=subID;
    }

    /**
     * This returns the sequence number of the ADU
     * this packet belongs to.
     *
     * @return The sequence number.
     */
   
    public int getSequenceNumber() {
  return sequenceNumber;
    }

    /**
     * This sets the sequence number of the packet.
     *
     * @param nr The sequence number of the ADU this packet belongs to.
     */

    public void setSequenceNumber(int nr) {
  sequenceNumber=nr;
    }

    /**
     * This gets the fragment count of this packet.
     *
     * @return The fragment count of this packet.
     */

    public int getFragmentCount() {
  return fragmentCount;
    }

    /**
     * Thist sets the fragment count of this packet.
     *
     * @prarm fc The fragment count.
     */

    public void setFragmentCount(int fc) {
  fragmentCount=fc;
    }

    /**
     * This returns the timestamp of this packet.
     *
     * @return The timestamp.
     */

    public long getTimestamp() {
  return timestamp;
    }

    /**
     * This sets the timestamp of this packet.
     *
     * @param The timestamp.
     */

    public void setTimestamp(long ts) {
  timestamp=ts;
    }

    /**
     * This gets the raw bytes of the encoded packet. This
     * method should be called AFTER flush has been performed
     * successfully.
     *
     * @return The byte array containing the encoded packet.
     */

    public byte[] getPacketData() {
  return packetData;
    }

    /**
     * This sets the reliablity extension header.
     *
     * @param header A reliability specific extension header that, when added
     *                one byte for the header length field, must be a multiple
     *                of four bytes in length.
     */
    public void setReliabilityHeader(byte[] header) throws IllegalValueException {
  if (header==null) {
      throw new IllegalValueException("RtpiDataPacket: Reliability header needs to be a non null value");
  }

  if ((header.length+1)%4!=0) {
      throw new IllegalValueException("RtpiDataPacket: The size of a reliability header need to be a multiple of 4 bytes");
  }
  extension=1;
  reliabilityHeader=header;
  reliabilityHeaderLength=(header.length+1)/4-1;
    }

    /**
     * This deletes the reliability header of a packet.
     */

    public void deleteReliabilityHeader() {
  extension=0;
  reliabilityHeader=null;
  reliabilityHeaderLength=0;
    }

    /**
     * This returns the length of the reliability header in multiples
     * of four bytes.
     *
     * @return The length of the reliability header.
     */

    public int getReliabilityHeaderLength() {
  return reliabilityHeaderLength;
    }

    /**
     * This returns the reliability header.
     *
     * @return The reliability header.
     */

    public byte[] getReliabilityHeader() {
  return reliabilityHeader;
    }
   
    /**
     * This parses a packet.
     */

    public void parse() throws RtpiParseException {

  if (packetData==null || headerStart>=packetData.length) {
      throw new RtpiParseException("RtpiDataPacket: the size of packetData does not match the start of the packet header");
  }

  ByteArrayInputStream bis = new ByteArrayInputStream(packetData, headerStart, packetData.length-headerStart);
  DataInputStream dis = new DataInputStream(bis);

  byte b=0;
  int word=0;

  try {
      b = dis.readByte();
  } catch (Exception exe) {
      throw new RtpiParseException("RtpiDataPacket: Could not read first two bytes from the RTP/I header");
  }
 
  version=(b & VERSION_BITMASK) >>> 6;

  if (version != VERSION) {
      throw new RtpiParseException("RtpiDataPacket: wrong RTP/I Version");
  }

  end=(b & END_BITMASK) >>> 5;
  extension=(b & EXTENSION_BITMASK) >>> 4;
  type=(b & TYPE_BITMASK);

  try {
      payloadType = dis.readUnsignedByte();
  } catch (Exception exe) {
      throw new RtpiParseException("RtpiDataPacket: Could not read payload type from the RTP/I header");
  }

  try {
      length = dis.readUnsignedShort();
  } catch (Exception exe) {
      throw new RtpiParseException("RtpiDataPacket: Could not read length from the RTP/I header");
  }
 
  try {
      b = dis.readByte();
  } catch (Exception exe) {
      throw new RtpiParseException("RtpiDataPacket: Could not read fifth byte from the RTP/I header");
  }

  reliabilityType = (b & RELIABILITY_TYPE_BITMASK) >>> 2;
  priority = (b & PRIORITY_BITMASK);
     
  try {
      profileInformation = dis.readByte();
  } catch (Exception exe) {
      throw new RtpiParseException("RtpiDataPacket: Could not read profile information from the RTP/I header");
  }

  try {
      reliabilityInformation[0] = dis.readByte();
  } catch (Exception exe) {
      throw new RtpiParseException("RtpiDataPacket: Could not read reliability information byte 0 from the RTP/I header");
  }

  try {
      reliabilityInformation[1] = dis.readByte();
  } catch (Exception exe) {
      throw new RtpiParseException("RtpiDataPacket: Could not read reliability information byte 1 from the RTP/I header");
  }

  try {
      participantID = dis.readInt();
  } catch (Exception exe) {
      throw new RtpiParseException("RtpiDataPacket: Could not read participant ID from the RTP/I header");
  }

  try {
      subcomponentID = dis.readLong();
  } catch (Exception exe) {
      throw new RtpiParseException("RtpiDataPacket: Could not read SUBID from the RTP/I header");
  }

  try {
      sequenceNumber = dis.readUnsignedShort();
  } catch (Exception exe) {
      throw new RtpiParseException("RtpiDataPacket: Could not read sequence number from the RTP/I header");
  }
 
  try {
      fragmentCount = dis.readUnsignedShort();
  } catch (Exception exe) {
      throw new RtpiParseException("RtpiDataPacket: Could not read fragement count from the RTP/I header");
  }

  try {
      word = dis.readInt();
  } catch (Exception exe) {
      throw new RtpiParseException("RtpiDataPacket: Could not read timestamp from the RTP/I header");
  }

  long intLeadingBit = (word & INT_SIGN_BITMASK) >>> 31;
  timestamp=word&INT_REMOVE_SIGN_BITMASK;
  timestamp=timestamp|(intLeadingBit<<31);

  payloadStart=headerStart+HEADER_SIZE;
  payloadLength=length;
  if (extension==1) {
      try {
    reliabilityHeaderLength=dis.readUnsignedByte();
      } catch (Exception exe) {
    throw new RtpiParseException("RtpiDataPacket: Could not read reliability header length from the RTP/I header");
      }
      reliabilityHeader=new byte[reliabilityHeaderLength*4+3];
      try {
    dis.readFully(reliabilityHeader);
      } catch (Exception exe) {
    throw new RtpiParseException("RtpiDataPacket: Could not read reliability header from the RTP/I header");
      }
      payloadStart+=reliabilityHeader.length+1;
      payloadLength-=reliabilityHeader.length+1;
  }
 
  try {
      dis.close();
      bis.close();
  } catch (Exception exe) {
      throw new RtpiParseException("RtpiDataPacket: Could not close input stream for RTP/I packet");
  }
    }

    /**
     * This flushes a packet.
     */
    public void flush() throws RtpiFlushException {
 
  length=payloadLength;

  if (extension==1) {
      length+=(reliabilityHeaderLength+1)*4;
  }

  ByteArrayOutputStream bos = new ByteArrayOutputStream();
  DataOutputStream dos = new DataOutputStream(bos);
 
  int word;
  byte b;

  word=version<<6;
  word=word|(end<<5);
  word=word|(extension<<4);
  word=word|type;

  try {
      dos.writeByte((byte) word);
  } catch (Exception ex) {
      throw new RtpiFlushException("RtpiDataPacket: Couldn't write first byte to RTP/I header");
  }

  try {
      dos.writeByte((short) payloadType);
  } catch (Exception ex) {
      throw new RtpiFlushException("RtpiDataPacket: Couldn't write second byte to RTP/I header");
  }

  try {
      dos.writeShort((short) length);
  } catch (Exception ex) {
      throw new RtpiFlushException("RtpiDataPacket: Couldn't write length to RTP/I header");
  }

  word=reliabilityType<<2;
  word=word|priority;

  try {
      dos.writeByte((byte) word);
  } catch (Exception ex) {
      throw new RtpiFlushException("RtpiDataPacket: Couldn't write fifth byte to RTP/I header");
  }

  try {
      dos.writeByte((byte) profileInformation);
  } catch (Exception ex) {
      throw new RtpiFlushException("RtpiDataPacket: Couldn't write profile information to RTP/I header");
  }

    try {
      dos.writeByte(reliabilityInformation[0]);
  } catch (Exception ex) {
      throw new RtpiFlushException("RtpiDataPacket: Couldn't write reliability informatioin byte 0 to RTP/I header");
  }

    try {
      dos.writeByte(reliabilityInformation[1]);
  } catch (Exception ex) {
      throw new RtpiFlushException("RtpiDataPacket: Couldn't write reliability informatioin byte 1 to RTP/I header");
  }

  try {
      dos.writeInt(participantID);
  } catch (Exception ex) {
      throw new RtpiFlushException("RtpiDataPacket: Couldn't write participant ID to RTP/I header");
  }

  try {
      dos.writeLong(subcomponentID);
  } catch (Exception ex) {
      throw new RtpiFlushException("RtpiDataPacket: Couldn't write subcomponent ID to RTP/I header");
  }

  try {
      dos.writeShort(sequenceNumber);
  } catch (Exception ex) {
      throw new RtpiFlushException("RtpiDataPacket: Couldn't write sequence number to RTP/I header");
  }

  try {
      dos.writeShort(fragmentCount);
  } catch (Exception ex) {
      throw new RtpiFlushException("RtpiDataPacket: Couldn't write fragment count to RTP/I header");
  }

  try {
      dos.writeInt((int)timestamp);
  } catch (Exception ex) {
      throw new RtpiFlushException("RtpiDataPacket: Couldn't write timestamp to RTP/I header");
  }


  if (extension==1) {
      try {
    dos.writeByte((byte)reliabilityHeaderLength);
      } catch (Exception ex) {
    throw new RtpiFlushException("RtpiDataPacket: Couldn't write reliability header length to RTP/I header");
      }  
  }

  try {
      dos.flush();
      bos.flush();
  } catch (Exception ex) {
      throw new RtpiFlushException("RtpiDataPacket: Couldn't flush output streams to RTP/I header!");
  }

  byte[] header = bos.toByteArray();

  int payloadShouldStart=HEADER_SIZE;

  if (extension==1) {
      payloadShouldStart+=(reliabilityHeaderLength+1)*4;
  }

  if (payloadStart!=payloadShouldStart) {
      byte[] buf = packetData;
      packetData = new byte[HEADER_SIZE+length];
      System.arraycopy(buf, payloadStart, packetData, payloadShouldStart, payloadLength);
      payloadStart=payloadShouldStart;
  }

  System.arraycopy(header,0,packetData,0,header.length);

  if (extension==1) {
      System.arraycopy(reliabilityHeader,0,packetData,HEADER_SIZE+1,reliabilityHeaderLength*4+3);
 

  try {
      dos.close();
      bos.close();
  } catch (Exception ex) {
      throw new RtpiFlushException("RtpiDataPacket: Couldn't close output streams to RTP/I header");
  }
    }

    public int flushToArray(byte[] destination, int start) throws RtpiFlushException {
  flush();
  if (start+length+HEADER_SIZE>destination.length) {
      throw new RtpiFlushException("RtpiDataPacket: Couldn't flush to array, array too small!");
  }
  System.arraycopy(packetData, headerStart, destination, start, length+HEADER_SIZE);
  return start+length+HEADER_SIZE;
    }

    /**
     * Print this object to a String.
     *
     * @return This object as a String.
     */

    public String toString() {
  String returnValue;
  returnValue ="RtpiDataPacket: {\n";
  returnValue+="  version: "+version+"\n";
  returnValue+="  end: "+end+"\n";
  returnValue+="  extension: "+extension+"\n";
  returnValue+="  type: "+type+"\n";
  returnValue+="  payload type: "+payloadType+"\n";
  returnValue+="  length: "+length+"\n";
  returnValue+="  reliability type: "+reliabilityType+"\n";
  returnValue+="  profile information: "+profileInformation+"\n";
  returnValue+="  reliability information byte 0: "+reliabilityInformation[0]+"\n";
  returnValue+="  reliability information byte 1: "+reliabilityInformation[1]+"\n";
  returnValue+="  participant identifier: "+participantID+"\n";
  returnValue+="  sub-component identifier: "+subcomponentID+"\n";
  returnValue+="  sequence number: "+sequenceNumber+"\n";
  returnValue+="  fragment count: "+fragmentCount+"\n";
  returnValue+="  timestamp: "+timestamp+"\n";
  returnValue+="  payload start: "+payloadStart+"\n";
  returnValue+="  header start: "+headerStart+"\n";
  returnValue+="  payload length: "+payloadLength+"\n";
  if (extension==1) {
      returnValue+="  reliabilityHeaderLength: "+reliabilityHeaderLength+"\n";
      returnValue+="  reliabilityHeader: ";
      for (int i=0;i<reliabilityHeaderLength*4+3;i++) {
    returnValue+=reliabilityHeader[i]+" ";
      }
      returnValue+="\n";
  }
  returnValue+="  payloadData: ";
  for (int i=payloadStart;i<payloadStart+payloadLength;i++) {
      returnValue+=packetData[i]+" ";
  }
  returnValue+="\n";
  returnValue+="}\n";
  return returnValue;
    }   
}

TOP

Related Classes of rtpi.packets.RtpiDataPacket

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.