tcpprotocol.java

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

JAVA
198
字号
/*
 * $Id: TCPProtocol.java,v 1.1 2003/11/25 11:52:23 epr Exp $
 */
package org.jnode.net.ipv4.tcp;

import java.io.IOException;
import java.net.BindException;
import java.net.DatagramSocketImplFactory;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketImplFactory;

import org.apache.log4j.Logger;
import org.jnode.driver.net.NetworkException;
import org.jnode.net.SocketBuffer;
import org.jnode.net.ipv4.IPv4Address;
import org.jnode.net.ipv4.IPv4Constants;
import org.jnode.net.ipv4.IPv4Header;
import org.jnode.net.ipv4.IPv4Protocol;
import org.jnode.net.ipv4.IPv4Service;
import org.jnode.util.Statistics;

/**
 * @author epr
 */
public class TCPProtocol implements IPv4Protocol, IPv4Constants, TCPConstants {

	/** The IP service I'm a part of */
	private final IPv4Service ipService;
	/** The ICMP service */
	//private final ICMPUtils icmp;
	/** My statistics */
	private final TCPStatistics stat = new TCPStatistics();
	/** The SocketImpl factory for TCP */
	private final TCPSocketImplFactory socketImplFactory;
	/** My control blocks */
	private final TCPControlBlockList controlBlocks;
	/** The timer */
	private final TCPTimer timer;
	/** My logger */
	private final Logger log = Logger.getLogger(getClass());

	/**
	 * Initialize a new instance
	 * 
	 * @param ipService
	 */
	public TCPProtocol(IPv4Service ipService) throws NetworkException {
		this.ipService = ipService;
		//this.icmp = new ICMPUtils(ipService);
		this.controlBlocks = new TCPControlBlockList(this);
		this.timer = new TCPTimer(controlBlocks);
		try {
			socketImplFactory = new TCPSocketImplFactory(this);
			Socket.setSocketImplFactory(socketImplFactory);
			ServerSocket.setSocketFactory(socketImplFactory);
		} catch (IOException ex) {
			throw new NetworkException(ex);
		}
		timer.start();
	}

	/**
	 * @see org.jnode.net.TransportLayer#getDatagramSocketImplFactory()
	 */
	public DatagramSocketImplFactory getDatagramSocketImplFactory() throws SocketException {
		throw new SocketException("TCP is socket based");
	}

	/**
	 * @see org.jnode.net.TransportLayer#getName()
	 */
	public String getName() {
		return "tcp";
	}

	/**
	 * @see org.jnode.net.TransportLayer#getProtocolID()
	 */
	public int getProtocolID() {
		return IPPROTO_TCP;
	}

	/**
	 * @see org.jnode.net.TransportLayer#getSocketImplFactory()
	 */
	public SocketImplFactory getSocketImplFactory() throws SocketException {
		return socketImplFactory;
	}

	/**
	 * @see org.jnode.net.TransportLayer#getStatistics()
	 */
	public Statistics getStatistics() {
		return stat;
	}

	/**
	 * @see org.jnode.net.TransportLayer#receive(org.jnode.net.SocketBuffer)
	 */
	public void receive(SocketBuffer skbuf) throws SocketException {

		// Increment stats
		stat.ipackets.inc();

		// Get the IP header
		final IPv4Header ipHdr = (IPv4Header) skbuf.getNetworkLayerHeader();

		// Read the TCP header
		final TCPHeader hdr = new TCPHeader(skbuf);

		// Set the TCP header in the buffer-field
		skbuf.setTransportLayerHeader(hdr);
		// Remove the TCP header from the head of the buffer
		skbuf.pull(hdr.getLength());
		// Trim the buffer up to the length in the TCP header
		skbuf.trim(hdr.getDataLength());

		if (!hdr.isChecksumOk()) {
			if (log.isDebugEnabled()) {
				log.debug("Receive: badsum: " + hdr);
			}
			stat.badsum.inc();
		} else {
			if (log.isDebugEnabled()) {
				log.debug("Receive: " + hdr);
			}

			// Find the corresponding control block
			final TCPControlBlock cb = (TCPControlBlock) controlBlocks.lookup(ipHdr.getSource(), hdr.getSrcPort(), ipHdr.getDestination(), hdr.getDstPort(), true);
			if (cb == null) {
				// Port unreachable
				log.debug("Port unreachable");
				stat.noport.inc();
				processPortUnreachable(ipHdr, hdr);
			} else {
				// Let the cb handle the receive
				cb.receive(hdr, skbuf);
			}
		}
	}

	/**
	 * @see org.jnode.net.ipv4.IPv4Protocol#receiveError(org.jnode.net.SocketBuffer)
	 */
	public void receiveError(SocketBuffer skbuf) throws SocketException {
		// TODO Auto-generated method stub

	}

	/**
	 * Process a segment whose destination port is unreachable
	 * 
	 * @param hdr
	 */
	private void processPortUnreachable(IPv4Header ipHdr, TCPHeader hdr) throws SocketException {
		final TCPHeader replyHdr = new TCPHeader(hdr.getDstPort(), hdr.getSrcPort(), 0, 0, hdr.getSequenceNr() + 1, 0, 0);
		replyHdr.setFlags(TCPF_ACK | TCPF_RST);
		final IPv4Header replyIpHdr = new IPv4Header(ipHdr);
		replyIpHdr.swapAddresses();
		send(replyIpHdr, replyHdr, new SocketBuffer());
	}

	/**
	 * Create a binding for a local address
	 * 
	 * @param lAddr
	 * @param lPort
	 */
	public TCPControlBlock bind(IPv4Address lAddr, int lPort) throws BindException {
		return (TCPControlBlock) controlBlocks.bind(lAddr, lPort);
	}

	/**
	 * Send an TCP packet
	 * 
	 * @param skbuf
	 */
	protected void send(IPv4Header ipHdr, TCPHeader tcpHdr, SocketBuffer skbuf) throws SocketException {
		if (log.isDebugEnabled()) {
			log.debug("send(ipHdr, " + tcpHdr + ")");
		}
		skbuf.setTransportLayerHeader(tcpHdr);
		tcpHdr.prefixTo(skbuf);
		ipHdr.setDataLength(skbuf.getSize());
		ipService.transmit(ipHdr, skbuf);
		stat.opackets.inc();
	}

	/**
	 * Get the current time counter
	 */
	protected long getTimeCounter() {
		return timer.getCounter();
	}
}

⌨️ 快捷键说明

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