socketbuffer.java

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

JAVA
655
字号
/*
 * $Id: SocketBuffer.java,v 1.1 2003/11/25 11:52:21 epr Exp $
 */
package org.jnode.net;

import org.apache.log4j.Logger;
import org.jnode.driver.Device;

/**
 * A SocketBuffer is container of a network packet. It enables efficient
 * storage even when various network layers prefix and/or postfix header/footers.
 * It also contains other information of a network packet, such as the headers
 * of the various network layers.
 * 
 * All numbers larger then a single byte written into this class are 
 * converted to network byte order.
 * 
 * All numbers larger then a single byte read from this class are 
 * converted from network byte order.
 * 
 * @author epr
 */
public class SocketBuffer {

	private static final int INITIAL_SIZE = 256;

	/** My logger */
	private final Logger log = Logger.getLogger(getClass());
	/** Actual data */
	private byte[] data;
	/** Size of the buffer that is in use */
	private int size;
	/** Start offset in data */
	private int start;
	/** Next buffer, that is concatenated with this one */
	private SocketBuffer next;

	/** The network device who will be sending, or has received this buffer */
	private Device device;
	/** Identifying type of the packettype */
	private int protocolID;
	/** Link layer header (if any) */
	private LinkLayerHeader linkLayerHeader;
	/** Network layer header (if any) */
	private NetworkLayerHeader networkLayerHeader;
	/** Transport layer header (if any) */
	private TransportLayerHeader transportLayerHeader;

	/**
	 * Create a new instance
	 */
	public SocketBuffer() {
	}

	/**
	 * Create a new instance with a buffer of a given capacity
	 */
	public SocketBuffer(int initialCapacity) {
		this(initialCapacity, 0);
	}

	/**
	 * Create a new instance with a buffer of a given capacity
	 */
	public SocketBuffer(int initialCapacity, int initialStart) {
		this.data = new byte[initialCapacity];
	}

	/**
	 * Create a clone of the data of src.
	 * Other attributes are not cloned!.
	 * 
	 * @param src
	 */
	public SocketBuffer(SocketBuffer src) {
		this.start = 0;
		this.size = src.getSize();
		this.data = src.toByteArray();
		this.next = null;
	}

	/**
	 * Create a new instance, using the given byte array as data.
	 * No copy of the data is made!
	 * @param data
	 * @param offset
	 * @param length
	 */
	public SocketBuffer(byte[] data, int offset, int length) {
		this.data = data;
		this.start = offset;
		this.size = length;
		testBuffer();
	}

	/**
	 * Gets the network device who will be sending, or has received this buffer
	 */
	public Device getDevice() {
		return device;
	}

	/**
	 * Sets the network device who will be sending, or has received this buffer
	 * @param device
	 */
	public void setDevice(Device device) {
		this.device = device;
	}

	/**
	 * Gets the identifying type of the packettype.
	 */
	public int getProtocolID() {
		return protocolID;
	}

	/**
	 * Sets the identifying type of the packettype.
	 * @param i
	 */
	public void setProtocolID(int i) {
		protocolID = i;
	}

	/**
	 * Clear this buffer, so it can be used for another purpose
	 *
	 */
	public void clear() {
		size = 0;
		start = 0;
		next = null;
		protocolID = 0;
		linkLayerHeader = null;
		networkLayerHeader = null;
		transportLayerHeader = null;
		device = null;
		// preserve data (if set), we can used it again
	}

	/**
	 * Insert a given number of bytes to the front of the buffer.
	 * The inserted bytes are cleaned with a value of <code>(byte)0</code>.
	 * @param count
	 */
	public void insert(int count) {
		if (start >= count) {
			start -= count;
			size += count;
		} else {
			setSize(size + count);
			for (int i = size - 1; i >= count; i--) {
				data[start + i] = data[start + i - count];
			}
		}
		for (int i = 0; i < count; i++) {
			data[start + i] = 0;
		}
		testBuffer();
	}

	/**
	 * Remove a given number of bytes from the front of the buffer
	 * @param count
	 */
	public void pull(int count) {
		if (count > size) {
			if (next != null) {
				// Pull a bit of myself and the rest of next
				count -= size;
				start = size;
				size = 0;
				next.pull(count);
			} else {
				throw new IllegalArgumentException("Cannot pull " + count + " bytes (" + start + "," + size + ")");
			}
		} else {
			start += count;
			size -= count;
		}
		testBuffer();
	}

	/**
	 * Undo a pull action.
	 * This method is different from insert, as this method can only unpull 
	 * that what has been removed by an earlier call to pull, insert will
	 * actually make new room at the head on the buffer. 
	 * @param count
	 * @throws IllegalArgumentException It is not possible to unpull count bytes.
	 */
	public void unpull(int count) {
		if (start >= count) {
			start -= count;
			size += count;
		} else {
			if (next != null) {
				// Unpull most of next and that what I can from me
				final int remaining = (count - start);
				size += start;
				start = 0;
				next.unpull(remaining);
			} else {
				throw new IllegalArgumentException("Cannot unpull " + count + " bytes (" + start + "," + size + ")");
			}
		}
		testBuffer();
	}

	/**
	 * Remove data from the tail of the buffer, until size <= length.
	 * If the current size < length, nothing happens.
	 * @param length
	 */
	public void trim(int length) {
		if (length < size) {
			// Cut the tail of myself and remove any next buffer
			size = length;
			next = null;
		} else if (length == size) {
			// Remove any next buffer
			next = null;
		} else {
			// Length > size
			if (next != null) {
				next.trim(length - size);
			}
		}
	}

	/**
	 * Insert a given number of bytes to the back of the buffer
	 * @param count
	 */
	public void append(int count) {
		if (next != null) {
			next.append(count);
		} else {
			setSize(size + count);
		}
		testBuffer();
	}

	/**
	 * Insert a given number of bytes to the front of the buffer
	 * @param src
	 * @param srcOffset
	 * @param length
	 */
	public void append(byte[] src, int srcOffset, int length) {
		if (next != null) {
			next.append(src, srcOffset, length);
		} else {
			final int dstOffset = start + size;
			setSize(size + length);
			System.arraycopy(src, srcOffset, data, dstOffset, length);
		}
		testBuffer();
	}

	/**
	 * Append a complete buffer to the end of this buffer.
	 * @param skbuf
	 */
	public void append(SocketBuffer skbuf) {
		if (next != null) {
			next.append(skbuf);
		} else {
			next = skbuf;
		}
		testBuffer();
	}

	/**
	 * Append a buffer to the end of this buffer starting at the given offset
	 * in the appended buffer.
	 * @param skbufOffset
	 * @param skbuf
	 */
	public void append(int skbufOffset, SocketBuffer skbuf) {
		final byte[] src = skbuf.toByteArray();
		append(src, skbufOffset, src.length - skbufOffset);
	}

	/**
	 * Append a buffer to the end of this buffer with only a given amount
	 * of bytes. 
	 * The given buffer must not contain a next buffer and must have a size 
	 * greater or equal to length
	 * @param skbuf
	 */
	public void append(SocketBuffer skbuf, int length) throws IllegalArgumentException {
		if (length == 0) {
			return;
		}
		if (next != null) {
			next.append(skbuf, length);
		} else {
			if (length < 0) {
				throw new IllegalArgumentException("Length < 0");
			}
			if (skbuf.next != null) {
				throw new IllegalArgumentException("skbuf.next != null");
			}
			if (skbuf.size < length) {
				throw new IllegalArgumentException("skbuf.size < length");
			}
			next = skbuf;
			skbuf.size = length;
		}
		testBuffer();
	}

	/**
	 * Gets a byte in the buffer
	 * @param index
	 */
	public int get(int index) {
		if (index >= size) {
			if (next != null) {
				return next.get(index - size);
			} else {
				throw new IndexOutOfBoundsException("at index " + index);
			}
		} else {
			return data[start + index] & 0xFF;
		}

⌨️ 快捷键说明

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