io.pkts.packet.impl.PCapPacketImpl Maven / Gradle / Ivy
/**
*
*/
package io.pkts.packet.impl;
import io.pkts.buffer.Buffer;
import io.pkts.frame.PcapGlobalHeader;
import io.pkts.frame.PcapRecordHeader;
import io.pkts.framer.EthernetFramer;
import io.pkts.framer.FramingException;
import io.pkts.framer.IPv4Framer;
import io.pkts.framer.SllFramer;
import io.pkts.packet.PCapPacket;
import io.pkts.packet.PacketParseException;
import io.pkts.packet.Packet;
import io.pkts.protocol.Protocol;
import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* TODO: may rename this to a frame instead since this is a little different
* than a "real" protocol packet.
*
* @author [email protected]
*/
public final class PCapPacketImpl extends AbstractPacket implements PCapPacket {
private final PcapRecordHeader pcapHeader;
private static final SllFramer sllFramer = new SllFramer();
private static final EthernetFramer ethernetFramer = new EthernetFramer();
private static final IPv4Framer ipFramer = new IPv4Framer();
private final PcapGlobalHeader pcapGlobalHeader;
/**
* Constructor which assumes an Ethernet link layer.
*/
public PCapPacketImpl(final PcapRecordHeader header, final Buffer payload) {
super(Protocol.PCAP, null, payload);
this.pcapGlobalHeader = PcapGlobalHeader.createDefaultHeader();
this.pcapHeader = header;
}
/**
* Constructor which uses the PCAP file's global header to support more than just Ethernet link layers
*/
public PCapPacketImpl(PcapGlobalHeader pcapGlobalHeader, final PcapRecordHeader header, final Buffer payload) {
super(Protocol.PCAP, null, payload);
this.pcapGlobalHeader = pcapGlobalHeader;
this.pcapHeader = header;
}
/**
* {@inheritDoc}
*/
@Override
public long getArrivalTime() {
final long multiplier = pcapGlobalHeader.timestampsInNs() ? 1000000000 : 1000000;
return this.pcapHeader.getTimeStampSeconds() * multiplier + this.pcapHeader.getTimeStampMicroOrNanoSeconds();
}
@Override
public long getTotalLength() {
return this.pcapHeader.getTotalLength();
}
@Override
public long getCapturedLength() {
return this.pcapHeader.getCapturedLength();
}
/**
* {@inheritDoc}
*/
@Override
public void verify() {
// nothing to verify for the pcap packet since that would
// have been detected when we framed the pcap packet.
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
final SimpleDateFormat formatter = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss.SSS");
final Date date = new Date(getArrivalTime() / 1000);
sb.append("Arrival Time: ").append(formatter.format(date))
.append(" Epoch Time: ").append(this.pcapHeader.getTimeStampSeconds()).append(".")
.append(String.format("%09d", this.pcapHeader.getTimeStampMicroOrNanoSeconds()))
.append(" Frame Length: ").append(getTotalLength())
.append(" Capture Length: ").append(getCapturedLength());
return sb.toString();
}
@Override
public void write(final OutputStream out, final Buffer payload) throws IOException {
final int size = payload.getReadableBytes();
this.pcapHeader.setCapturedLength(size);
this.pcapHeader.setTotalLength(size);
this.pcapHeader.write(out);
out.write(payload.getArray());
}
@Override
public PCapPacket clone() {
throw new RuntimeException("not implemented yet");
}
@Override
public Packet getNextPacket() throws IOException, PacketParseException {
final Buffer payload = getPayload();
if (payload == null) {
return null;
}
switch(pcapGlobalHeader.getDataLinkType())
{
case 1:
default:
try {
return ethernetFramer.frame(this, payload);
} catch (FramingException e) {
throw new PacketParseException(16, "Ethernet parsing failed", e);
}
case 113:
return sllFramer.frame(this, payload);
case 101:
return ipFramer.frame(this, payload);
}
}
}