ipv4fragmentlist.java

来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 143 行

JAVA
143
字号
/*
 * $Id: IPv4FragmentList.java,v 1.1 2003/11/25 11:52:24 epr Exp $
 */
package org.jnode.net.ipv4;

import java.util.Iterator;
import java.util.Vector;

import org.apache.log4j.Logger;
import org.jnode.net.SocketBuffer;

/**
 * Class used to reconstruct fragmented IP packets
 * @author epr
 */
public class IPv4FragmentList implements IPv4Constants {
	
	/** My logger */
	private final Logger log = Logger.getLogger(getClass());
	/** When was this object created */
	private final long creationTime;
	/** List of fragments */
	private final Vector fragments;
	/** The key of this fragment list */
	private final Object key;
	/** Is the first fragment in the list? */
	private boolean haveFirstFragment;
	/** Is the last fragment in the list? */
	private boolean haveLastFragment;
	
	/**
	 * Create a new instance
	 * @param firstFragment
	 */
	public IPv4FragmentList(SocketBuffer firstFragment) {
		this.creationTime = System.currentTimeMillis();
		this.fragments = new Vector();
		this.haveFirstFragment = false;
		this.haveLastFragment = false;
		final IPv4Header hdr = (IPv4Header)firstFragment.getNetworkLayerHeader();
		this.key = hdr.getFragmentListKey();
		add(firstFragment);
	}
	
	/**
	 * Add a packet to this object.
	 * @param skbuf
	 */
	public void add(SocketBuffer skbuf) {
		final IPv4Header hdr = (IPv4Header)skbuf.getNetworkLayerHeader();
		if (!hdr.isFragment()) {
			throw new IllegalArgumentException("Buffer does not contain a fragment");
		}
		final int myFrOfs = hdr.getFragmentOffset();
		final int mySize = hdr.getDataLength();
		
		// Fixup some member variables
		this.haveFirstFragment |= (myFrOfs == 0);
		this.haveLastFragment |= !hdr.hasMoreFragments();
		
		//log.debug("first=" + haveFirstFragment + ", last=" + haveLastFragment);
		
		// Insert the fragment at the correct index in the list
		for (Iterator i = fragments.iterator(); i.hasNext(); ) {
			final SocketBuffer f = (SocketBuffer)i.next();
			final IPv4Header fhdr = (IPv4Header)f.getNetworkLayerHeader();
			final int fOfs = fhdr.getFragmentOffset();
			final int fSize = f.getSize();
			
			if (myFrOfs == (fOfs + fSize)) {
				// skbuf directly follows f, attach it.
				f.append(skbuf);
				//log.debug("Adding fragment directly after another " + myFrOfs + "," + mySize + "," + fOfs + "," + fSize);
				
				// See if we can attach the following fragment directly to me
				if (i.hasNext()) {
					final SocketBuffer f2 = (SocketBuffer)i.next();
					final IPv4Header f2hdr = (IPv4Header)f2.getNetworkLayerHeader();
					final int f2Ofs = f2hdr.getFragmentOffset();
					if (f2Ofs == (myFrOfs + skbuf.getSize())) {
						// Yes we can attach it
						skbuf.append(f2);
						fragments.remove(f2);
					}
				}
				return;
			} else if (myFrOfs < fOfs) {
				// skbuf is before f, insert it here
				fragments.insertElementAt(skbuf, fragments.indexOf(f));
				//log.debug("Inserting fragment before another " + myFrOfs + "," + mySize + "," + fOfs + "," + fSize);
				return;
			} else if (myFrOfs < (fOfs + fSize)) {
				// Fragment offset in the middle of an existing fragment,
				// this is an error!
				log.debug("Fragment offset(" + myFrOfs + mySize + "," + ") falls in another fragment (" + fOfs + "," + fSize + ").");
				return;
			}
		}
		// The fragment has not been added, so it must be the last on the list
		// with a gap before it.
		//log.debug("Adding fragment at end of list " + myFrOfs + "," + mySize);
		fragments.add(skbuf);
	}
	
	/**
	 * Is this fragmentlist still alive. 
	 * A fragmentlist is alive when is was created no more then IP_FRAGTIMEOUT
	 * milliseconds ago.
	 */
	public boolean isAlive() {
		final long now = System.currentTimeMillis();
		return ((now - creationTime) <= IP_FRAGTIMEOUT);
	}
	
	/**
	 * Do we have all fragments?
	 */
	public boolean isComplete() {
		if (haveFirstFragment && haveLastFragment) {
			if (fragments.size() == 1) {
				return true;
			}
		}
		return false;
	}
	
	/**
	 * Gets the complete packet
	 * This method can only be called when <code>isComplete</code> returns true.
	 */
	public SocketBuffer getPacket() {
		return (SocketBuffer)fragments.get(0);
	}

	/**
	 * Gets the key of this fragmentlist.
	 * @see IPv4Header#getFragmentListKey()
	 */
	public Object getKey() {
		return key;
	}
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?