
io.pkts.packet.sctp.impl.DefaultSctpChunk Maven / Gradle / Ivy
package io.pkts.packet.sctp.impl;
import io.pkts.buffer.Buffer;
import io.pkts.packet.sctp.SctpChunk;
import io.pkts.packet.sctp.SctpParseException;
import java.io.IOException;
import static io.pkts.buffer.Buffers.assertNotEmpty;
import static io.pkts.packet.PreConditions.assertArgument;
public class DefaultSctpChunk implements SctpChunk {
private final SctpChunk.Type type;
private final Buffer header;
/**
* This contains the full value as was seen on the wire, including padding.
* The reason we save this is if we have to write back the chunk to the
* wire (or rather in a pcap) then it is ready to go.
*/
// private final Buffer valueOnWire;
/**
* This is just the value excluding padding.
*/
private final Buffer value;
private final int padding;
public static DefaultSctpChunk frame(final Buffer buffer) {
try {
assertNotEmpty(buffer, "The buffer cannot be null or empty");
assertArgument(buffer.getReadableBytes() >= 4, "There must be at least 4 bytes to read");
final Buffer header = buffer.readBytes(4);
final SctpChunk.Type type = SctpChunk.lookup(header.getUnsignedByte(0));
final int length = header.getUnsignedShort(2) - 4;
final int padding = DefaultSctpChunk.calculatePadding(length);
assertArgument(buffer.getReadableBytes() >= length + padding, "Unable to read Chunk Value. Not enough bytes. Needed "
+ (length + padding) + " bytes but only " + buffer.getReadableBytes() + " bytes available");
final Buffer value = buffer.readBytes(length);
buffer.readBytes(padding);
return new DefaultSctpChunk(type, header, value, padding);
} catch (final IOException e) {
throw new SctpParseException(buffer.getReaderIndex(), "Unable to read from buffer. Message (if any) " + e.getMessage());
}
}
private DefaultSctpChunk(final Type type, final Buffer header, final Buffer valueOnWire, final int padding) {
this.type = type;
this.header = header;
this.value = valueOnWire;
this.padding = padding;
}
@Override
public Type getType() {
return type;
}
@Override
public int getLength() {
return 4 + value.capacity() + padding;
}
@Override
public Buffer getHeader() {
return header;
}
@Override
public Buffer getValue() {
return value;
}
@Override
public byte getFlags() {
try {
return header.getByte(1);
} catch (final IOException e) {
throw new SctpParseException(1, "IOException when reading flags");
}
}
/**
* The length of the value of the chunk.
*
* Note that the length as encoded into the Chunk "header" includes the 4 bytes containing the size of
* the fields making up the header. This length is JUST the length of the actual value. Also, it does not
* include padding.
*/
@Override
public int getValueLength() {
return value.capacity();
}
@Override
public int getPadding() {
return padding;
}
private static int calculatePadding(final int length) {
final int padding = length % 4;
if (padding != 0) {
return 4 - padding;
}
return 0;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy