package com.netifera.platform.net.internal.sniffing.reassembly; import java.nio.ByteBuffer; import java.util.Comparator; import java.util.SortedSet; import java.util.TreeSet; import com.netifera.platform.net.packets.tcpip.IP; import com.netifera.platform.net.packets.tcpip.IPFragment; class IPReassemblyQueue { final private SortedSet<IPFragment> fragments = new TreeSet<IPFragment>(new Comparator<IPFragment>() { public int compare(IPFragment o1, IPFragment o2) { return Integer.valueOf(o1.getFragmentOffset()).compareTo( Integer.valueOf(o2.getFragmentOffset())); } }); public synchronized void addFragment(IPFragment packet) { fragments.add(packet); } public synchronized boolean isComplete() { if (fragments.first().getFragmentOffset() != 0) { return false; } if (fragments.last().hasMoreFragments()) { return false; } int lastOffset = 0; for (IPFragment packet: fragments) { int offset = packet.getFragmentOffset(); if (offset > lastOffset) { return false; } lastOffset = offset + packet.getLength(); // XXX lentgh()? } return true; } private int reassembledSize() { IPFragment lastFragment = fragments.last(); return lastFragment.getFragmentOffset() + lastFragment.getLength(); } public synchronized IP getReassembled() { ByteBuffer buffer = ByteBuffer.allocate(reassembledSize()); buffer.put(fragments.first().toByteBuffer()); for (IPFragment fragment: fragments) { buffer.position(fragment.getFragmentOffset()); buffer.put(fragment.payload().toByteBuffer()); } buffer.flip(); IP answer = fragments.first().createPacket(); answer.unpack(buffer); answer.setTotalLength(answer.getTotalLength() + buffer.limit() - fragments.first().getLength()); return answer; } }