tcpcontrolblock.java
来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 751 行 · 第 1/2 页
JAVA
751 行
/*
* $Id: TCPControlBlock.java,v 1.1 2003/11/25 11:52:23 epr Exp $
*/
package org.jnode.net.ipv4.tcp;
import java.net.ConnectException;
import java.net.SocketException;
import java.util.LinkedList;
import org.apache.log4j.Logger;
import org.jnode.net.SocketBuffer;
import org.jnode.net.ipv4.IPv4Address;
import org.jnode.net.ipv4.IPv4Constants;
import org.jnode.net.ipv4.IPv4ControlBlock;
import org.jnode.net.ipv4.IPv4Header;
import org.jnode.util.NumberUtils;
import org.jnode.util.TimeoutException;
/**
* @author Ewout Prangsma (epr@users.sourceforge.net)
*/
public class TCPControlBlock extends IPv4ControlBlock implements TCPConstants {
/** My logger */
private final Logger log = Logger.getLogger(getClass());
/** The outgoing channel */
private final TCPOutChannel outChannel;
/** The incoming channel */
private final TCPInChannel inChannel;
/** Last incoming sequence number */
//private int lastInSeqNr;
/** Window size of the outgoing connection */
private int outWindowSize;
/** The current state */
private int curState;
/** My listening parent */
private final TCPControlBlock parent;
/** List of connections that are established, but have not been "accepted" */
private LinkedList readyToAcceptList = new LinkedList();
/** Has this connection be reset? */
private boolean reset;
/** Has this connection been refused? */
private boolean refused;
/** Timeout for blocking operations */
private int timeout = TCP_DEFAULT_TIMEOUT;
/**
* Create a new instance
*
* @param list
* @param parent
* @param tcp
* @param isn
* The initial outgoing sequence number
*/
public TCPControlBlock(TCPControlBlockList list, TCPControlBlock parent, TCPProtocol tcp, int isn) {
super(list, IPv4Constants.IPPROTO_TCP, TCP_DEFAULT_TTL);
this.parent = parent;
this.outChannel = new TCPOutChannel(tcp, this, isn);
this.inChannel = new TCPInChannel(this);
//this.tcp = tcp;
this.curState = TCPS_CLOSED;
this.outWindowSize = TCP_MAXWIN;
this.reset = false;
this.refused = false;
}
// ------------------------------------------
// Receive (input) methods
// ------------------------------------------
/**
* Handle a received segment for this connection
*
* @param hdr
* @param skbuf
*/
public synchronized void receive(TCPHeader hdr, SocketBuffer skbuf) throws SocketException {
if (log.isDebugEnabled()) {
log.debug("receive: me=[" + this +"], hdr=[" + hdr + "]");
}
final IPv4Header ipHdr = (IPv4Header) skbuf.getNetworkLayerHeader();
final boolean ack = hdr.isFlagAcknowledgeSet();
final boolean rst = hdr.isFlagResetSet();
if (rst) {
receiveProcessReset(ipHdr, hdr, skbuf);
return;
}
if (ack) {
outChannel.processAck(hdr.getAckNr());
}
switch (curState) {
case TCPS_LISTEN :
receiveListen(ipHdr, hdr, skbuf);
break;
case TCPS_SYN_RECV :
receiveSynRecv(ipHdr, hdr, skbuf);
break;
case TCPS_SYN_SENT :
receiveSynSend(ipHdr, hdr, skbuf);
break;
case TCPS_ESTABLISHED :
receiveEstablished(ipHdr, hdr, skbuf);
break;
case TCPS_FIN_WAIT_1 :
receiveFinWait1(ipHdr, hdr, skbuf);
break;
case TCPS_FIN_WAIT_2 :
receiveFinWait2(ipHdr, hdr, skbuf);
break;
case TCPS_LAST_ACK :
receiveLastAck(ipHdr, hdr, skbuf);
break;
case TCPS_CLOSING :
receiveClosing(ipHdr, hdr, skbuf);
break;
case TCPS_TIME_WAIT :
receiveTimeWait(ipHdr, hdr, skbuf);
break;
default :
log.debug("Unhandled state in receive (" + getStateName() + ")");
break;
}
}
/**
* Process a reset segment
*
* @param ipHdr
* @param hdr
* @param skbuf
*/
private final void receiveProcessReset(IPv4Header ipHdr, TCPHeader hdr, SocketBuffer skbuf) throws SocketException {
final boolean ack = hdr.isFlagAcknowledgeSet();
final boolean syn = hdr.isFlagSynchronizeSet();
switch (curState) {
case TCPS_SYN_RECV :
case TCPS_SYN_SENT :
notifyConnectionRefused();
setState(TCPS_CLOSED);
drop(ipHdr, hdr, "connection refused");
break;
case TCPS_ESTABLISHED :
case TCPS_FIN_WAIT_1 :
case TCPS_FIN_WAIT_2 :
case TCPS_CLOSE_WAIT :
notifyConnectionReset();
setState(TCPS_CLOSED);
drop(ipHdr, hdr, "connection reset");
break;
case TCPS_CLOSING :
case TCPS_LAST_ACK :
case TCPS_TIME_WAIT :
setState(TCPS_CLOSED);
drop(ipHdr, hdr, "connection reset");
break;
}
if (syn) {
notifyConnectionReset();
sendRST();
drop(ipHdr, hdr, "connection reset");
}
if (!ack) {
drop(ipHdr, hdr, "ACK expected together with RST");
}
}
/**
* Current state is LISTEN. If a SYN segment is received, send a SYN&ACK, and set the state to
* SYN_RECV
*
* @param hdr
* @param skbuf
*/
private final void receiveListen(IPv4Header ipHdr, TCPHeader hdr, SocketBuffer skbuf) throws SocketException {
log.debug("receiveListen");
final boolean ack = hdr.isFlagAcknowledgeSet();
final boolean syn = hdr.isFlagSynchronizeSet();
if (ack) {
// Drop this segment with a RST reply
sendRST();
drop(ipHdr, hdr, "unexpected ACK segment");
} else if (syn) {
// Drop if broadcast or multicast
final IPv4Address dst = ipHdr.getDestination();
if (dst.isBroadcast() || dst.isMulticast()) {
// Drop this segment
drop(ipHdr, hdr, "broadcast or multicast destination");
} else {
// Process the SYN request
final TCPControlBlock copy = (TCPControlBlock) copyAndConnect(dst, ipHdr.getSource(), hdr.getSrcPort());
copy.listenSynReceivedOnCopy(hdr, skbuf);
}
} else {
// Invalid segment
drop(ipHdr, hdr, "unexpected segment; SYN expected");
}
}
/**
* Current state is 0, SYN segment received. This method is called on a copy of the listening
* control block. Send a SYN&ACK, and set the state to SYN_RECV
*
* @param hdr
* @param skbuf
*/
private final void listenSynReceivedOnCopy(TCPHeader hdr, SocketBuffer skbuf) throws SocketException {
log.debug("listenSynReceivedOnCopy");
// Save the foreign seq nr
inChannel.initISN(hdr);
// Send the SYN&ACK TCP reply
sendACK(TCPF_SYN, hdr.getSequenceNr() + 1);
// Update the state
setState(TCPS_SYN_RECV);
}
/**
* Current state is SYN_RECV.
*/
private final void receiveSynRecv(IPv4Header ipHdr, TCPHeader hdr, SocketBuffer skbuf) throws SocketException {
final boolean ack = hdr.isFlagAcknowledgeSet();
if (ack) {
setState(TCPS_ESTABLISHED);
parent.notifyChildEstablished(this);
} else {
// Invalid segment
drop(ipHdr, hdr, "ACK expected");
}
}
/**
* Current state is SYN_SEND.
*/
private final void receiveSynSend(IPv4Header ipHdr, TCPHeader hdr, SocketBuffer skbuf) throws SocketException {
final boolean syn = hdr.isFlagSynchronizeSet();
if (!syn) {
// Invalid segment
drop(ipHdr, hdr, "SYN expected");
} else {
// Active open , go to ESTABLISHED
inChannel.initISN(hdr);
sendACK(0, hdr.getSequenceNr() + 1);
setState(TCPS_ESTABLISHED);
//Syslog.debug("go to ESTABLISHED not implemented yet");
}
}
/**
* Current state is ESTABLISHED, FIN segment received. Send a ACK, and set the state to
* CLOSE_WAIT
*
* @param hdr
* @param skbuf
*/
private final void receiveEstablished(IPv4Header ipHdr, TCPHeader hdr, SocketBuffer skbuf) throws SocketException {
final boolean fin = hdr.isFlagFinishedSet();
// Process the data
inChannel.processData(ipHdr, hdr, skbuf);
// FIN received, then change state
if (fin) {
setState(TCPS_CLOSE_WAIT);
}
}
/**
* State is FIN_WAIT_1, any segment received
*
* @param hdr
* @param skbuf
*/
private final void receiveFinWait1(IPv4Header ipHdr, TCPHeader hdr, SocketBuffer skbuf) throws SocketException {
final boolean fin = hdr.isFlagFinishedSet();
final boolean ack = hdr.isFlagAcknowledgeSet();
// Process the data
inChannel.processData(ipHdr, hdr, skbuf);
// Update state (if required)
if (fin && ack) {
setState(TCPS_TIME_WAIT);
} else if (fin) {
setState(TCPS_CLOSING);
} else if (ack) {
setState(TCPS_FIN_WAIT_2);
} else {
// Invalid segment
drop(ipHdr, hdr, "FIN and/or ACK expected");
}
}
/**
* State is FIN_WAIT_2, any segment received
*
* @param hdr
* @param skbuf
*/
private final void receiveFinWait2(IPv4Header ipHdr, TCPHeader hdr, SocketBuffer skbuf) throws SocketException {
final boolean fin = hdr.isFlagFinishedSet();
// Process the data
inChannel.processData(ipHdr, hdr, skbuf);
// Update state
if (fin) {
setState(TCPS_TIME_WAIT);
} else {
// Invalid segment
drop(ipHdr, hdr, "FIN expected");
}
}
/**
* State is LAST_ACK, any segment received
*
* @param hdr
* @param skbuf
*/
private final void receiveLastAck(IPv4Header ipHdr, TCPHeader hdr, SocketBuffer skbuf) throws SocketException {
final boolean ack = hdr.isFlagAcknowledgeSet();
if (ack) {
setState(TCPS_CLOSED);
} else {
// Invalid segment
drop(ipHdr, hdr, "ACK expected");
}
}
/**
* State is CLOSING, any segment received
*
* @param hdr
* @param skbuf
*/
private final void receiveClosing(IPv4Header ipHdr, TCPHeader hdr, SocketBuffer skbuf) throws SocketException {
final boolean ack = hdr.isFlagAcknowledgeSet();
if (ack) {
setState(TCPS_TIME_WAIT);
} else {
// Invalid segment
drop(ipHdr, hdr, "ACK expected");
}
}
/**
* State is TIME_WAIT, discard any segments
*
* @param hdr
* @param skbuf
*/
private final void receiveTimeWait(IPv4Header ipHdr, TCPHeader hdr, SocketBuffer skbuf) throws SocketException {
drop(ipHdr, hdr, "discard all in TIME_WAIT state");
}
// ------------------------------------------
// Timeout methods
// ------------------------------------------
/**
* Process timeout handling
*/
public void timeout() {
try {
outChannel.timeout();
} catch (SocketException ex) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?