?? tcpip.c
字號:
if (TCPCode & TCP_CODE_RST) // RST??
{
if (TCPCode & TCP_CODE_ACK) // if ACK was acceptable, reset
{ // connection
TCPStateMachine = CLOSED;
TCPFlags = 0; // reset all flags, stop retransmission...
SocketStatus = SOCK_ERR_CONN_RESET;
}
break; // drop segment
}
if (TCPCode & TCP_CODE_SYN) // SYN??
{
TCPAckNr = TCPSegSeq; // get opponents ISN
TCPAckNr++; // inc. by one...
if (TCPCode & TCP_CODE_ACK)
{
TCPStopTimer(); // stop retransmission, other TCP got our SYN
TCPSeqNr = TCPUNASeqNr; // advance our sequence number
PrepareTCP_FRAME(TCPSeqNr, TCPAckNr, TCP_CODE_ACK); // ACK this ISN
TCPStateMachine = ESTABLISHED;
SocketStatus |= SOCK_CONNECTED;
SocketStatus |= SOCK_TX_BUF_RELEASED; // user may send data now :-)
}
else
{
TCPStopTimer();
PrepareTCP_FRAME(TCPSeqNr, TCPAckNr, TCP_CODE_SYN | TCP_CODE_ACK); // our SYN isn't ACKed yet,
LastFrameSent = TCP_SYN_ACK_FRAME; // now continue with sending
TCPStartRetryTimer(); // SYN_ACK frames
TCPStateMachine = SYN_RECD;
}
}
break;
default :
// drop segment if IP doesn't belong to current session
if ((RemoteIP[0] != RecdFrameIP[0]) || (RemoteIP[1] != RecdFrameIP[1]))
break;
// drop segment if port doesn't match
if (TCPSegSourcePort != TCPRemotePort)
break;
// drop segment if it doesn't fall into the receive window
if ((TCPSegSeq < TCPAckNr) || (TCPSegSeq >= TCPAckNr + MAX_TCP_RX_DATA_SIZE))
break;
if (TCPCode & TCP_CODE_RST) // RST??
{
TCPStateMachine = CLOSED; // close the state machine
TCPFlags = 0; // reset all flags, stop retransmission...
SocketStatus = SOCK_ERR_CONN_RESET; // indicate an error to user
break;
}
if (TCPCode & TCP_CODE_SYN) // SYN??
{
PrepareTCP_FRAME(TCPSegAck, 0, TCP_CODE_RST); // is NOT allowed here! send a reset,
TCPStateMachine = CLOSED; // close connection...
TCPFlags = 0; // reset all flags, stop retransmission...
SocketStatus = SOCK_ERR_REMOTE; // fatal error!
break; // ...and drop the frame
}
if (TCPSegSeq != TCPAckNr) // drop if it's not the segment we expect,
{ // and send an ACK
PrepareTCP_FRAME(TCPUNASeqNr, TCPAckNr, TCP_CODE_ACK);
break;
}
if (!(TCPCode & TCP_CODE_ACK)) break; // drop segment if the ACK bit is off
if (TCPSegAck == TCPUNASeqNr) // is our last data sent ACKed?
{
TCPStopTimer(); // stop retransmission
TCPSeqNr = TCPUNASeqNr; // advance our sequence number
switch (TCPStateMachine) // change state if necessary
{
case SYN_RECD : // ACK of our SYN?
TCPStateMachine = ESTABLISHED; // user may send data now :-)
SocketStatus |= SOCK_CONNECTED;
break;
case ESTABLISHED :
SocketStatus |= SOCK_TX_BUF_RELEASED; // give TX buffer back
break;
case FIN_WAIT_1 : // ACK of our FIN?
TCPStateMachine = FIN_WAIT_2;
/*
The following code lines are not according to RFC793, but prevent from
being stuck in the FIN_WAIT_2 state when no FIN packet within a certain
timeframe will be received (RFC793 says there are two ways to leave this
state: 1. FIN is received or 2. user closes/resets the connection)
*/
TCPStartFinTimer(); // start TIME_WAIT timeout
break;
case CLOSING : // ACK of our FIN?
TCPStateMachine = TIME_WAIT;
TCPStartFinTimer(); // start TIME_WAIT timeout
break;
case LAST_ACK : // ACK of our FIN?
TCPStateMachine = CLOSED;
TCPFlags = 0; // reset all flags, stop retransmission...
SocketStatus &= SOCK_DATA_AVAILABLE; // clear all flags but data available
break;
case TIME_WAIT :
// ACK a retransmission of remote FIN
PrepareTCP_FRAME(TCPSegAck, TCPAckNr, TCP_CODE_ACK);
TCPRestartTimer(); // restart TIME_WAIT timeout
break;
}
}
if ((TCPStateMachine == ESTABLISHED) ||
(TCPStateMachine == FIN_WAIT_1) ||
(TCPStateMachine == FIN_WAIT_2))
if (NrOfDataBytes) // data available?
if (!(SocketStatus & SOCK_DATA_AVAILABLE)) // rx data-buffer empty?
{
DummyReadFrame8900(6); // ignore window, checksum, urgent pointer
CopyFromFrame8900(RxTCPBufferMem, NrOfDataBytes); // fetch data and
TCPRxDataCount = NrOfDataBytes; // ...tell the user...
SocketStatus |= SOCK_DATA_AVAILABLE; // indicate the new data to user
TCPAckNr += NrOfDataBytes;
PrepareTCP_FRAME(TCPSegAck, TCPAckNr, TCP_CODE_ACK); // ACK rec'd data
}
else
break; // stop processing here, we cannot send an
// acknowledge packet as the received data
// could not be passed to the app layer
if (TCPCode & TCP_CODE_FIN) // FIN??
{
switch (TCPStateMachine)
{
case SYN_RECD :
case ESTABLISHED :
TCPStateMachine = CLOSE_WAIT;
break;
case FIN_WAIT_1 :
TCPStateMachine = CLOSING; // enter FIN_WAIT_2 (look above) and therefore
SocketStatus &= ~SOCK_CONNECTED; // TIME_WAIT
break;
case FIN_WAIT_2 :
TCPStateMachine = TIME_WAIT;
SocketStatus &= ~SOCK_CONNECTED;
TCPStartFinTimer(); // start TIME_WAIT timeout
break;
case TIME_WAIT :
TCPRestartTimer(); // restart TIME_WAIT timeout
break;
}
TCPAckNr++; // ACK remote's FIN flag
PrepareTCP_FRAME(TCPSegAck, TCPAckNr, TCP_CODE_ACK);
}
}
}
//------------------------------------------------------------------------------
// easyWEB internal function
// prepares the TxFrame2-buffer to send an ARP-request
//------------------------------------------------------------------------------
static void PrepareARP_REQUEST(void)
{
// Ethernet
ACCESS_UINT(TxFrame2Mem, ETH_DA_OFS) = 0xffff; // we don't know opposites MAC!
ACCESS_UINT(TxFrame2Mem, ETH_DA_OFS + 2) = 0xffff;
ACCESS_UINT(TxFrame2Mem, ETH_DA_OFS + 4) = 0xffff;
ACCESS_UINT(TxFrame2Mem, ETH_SA_OFS) = MyMAC[0];
ACCESS_UINT(TxFrame2Mem, ETH_SA_OFS + 2) = MyMAC[1];
ACCESS_UINT(TxFrame2Mem, ETH_SA_OFS + 4) = MyMAC[2];
ACCESS_UINT(TxFrame2Mem, ETH_TYPE_OFS) = SWAPB(FRAME_ARP);
// ARP
ACCESS_UINT(TxFrame2Mem, ARP_HARDW_OFS) = SWAPB(HARDW_ETH10);
ACCESS_UINT(TxFrame2Mem, ARP_PROT_OFS) = SWAPB(FRAME_IP);
ACCESS_UINT(TxFrame2Mem, ARP_HLEN_PLEN_OFS) = SWAPB(IP_HLEN_PLEN);
ACCESS_UINT(TxFrame2Mem, ARP_OPCODE_OFS) = SWAPB(OP_ARP_REQUEST);
ACCESS_UINT(TxFrame2Mem, ARP_SENDER_HA_OFS) = MyMAC[0];
ACCESS_UINT(TxFrame2Mem, ARP_SENDER_HA_OFS + 2) = MyMAC[1];
ACCESS_UINT(TxFrame2Mem, ARP_SENDER_HA_OFS + 4) = MyMAC[2];
ACCESS_UINT(TxFrame2Mem, ARP_SENDER_IP_OFS) = MyIP[0];
ACCESS_UINT(TxFrame2Mem, ARP_SENDER_IP_OFS + 2) = MyIP[1];
ACCESS_UINT(TxFrame2Mem, ARP_TARGET_HA_OFS) = 0;
ACCESS_UINT(TxFrame2Mem, ARP_TARGET_HA_OFS + 2) = 0;
ACCESS_UINT(TxFrame2Mem, ARP_TARGET_HA_OFS + 4) = 0;
ACCESS_UINT(TxFrame2Mem, ARP_TARGET_IP_OFS) = 0;
ACCESS_UINT(TxFrame2Mem, ARP_TARGET_IP_OFS + 2) = 0;
if (((RemoteIP[0] ^ MyIP[0]) & SubnetMask[0]) ||
((RemoteIP[1] ^ MyIP[1]) & SubnetMask[1]))
{
ACCESS_UINT(TxFrame2Mem, ARP_TARGET_IP_OFS) = GatewayIP[0];
ACCESS_UINT(TxFrame2Mem, ARP_TARGET_IP_OFS + 2) = GatewayIP[1];
}
else
{
ACCESS_UINT(TxFrame2Mem, ARP_TARGET_IP_OFS) = RemoteIP[0];
ACCESS_UINT(TxFrame2Mem, ARP_TARGET_IP_OFS + 2) = RemoteIP[1];
}
TxFrame2Size = ETH_HEADER_SIZE + ARP_FRAME_SIZE;
TransmitControl |= SEND_FRAME2;
}
//------------------------------------------------------------------------------
// easyWEB internal function
// prepares the TxFrame2-buffer to send an ARP-answer (reply)
//------------------------------------------------------------------------------
static void PrepareARP_ANSWER(void)
{
// Ethernet
ACCESS_UINT(TxFrame2Mem, ETH_DA_OFS) = RecdFrameMAC[0];
ACCESS_UINT(TxFrame2Mem, ETH_DA_OFS + 2) = RecdFrameMAC[1];
ACCESS_UINT(TxFrame2Mem, ETH_DA_OFS + 4) = RecdFrameMAC[2];
ACCESS_UINT(TxFrame2Mem, ETH_SA_OFS) = MyMAC[0];
ACCESS_UINT(TxFrame2Mem, ETH_SA_OFS + 2) = MyMAC[1];
ACCESS_UINT(TxFrame2Mem, ETH_SA_OFS + 4) = MyMAC[2];
ACCESS_UINT(TxFrame2Mem, ETH_TYPE_OFS) = SWAPB(FRAME_ARP);
// ARP
ACCESS_UINT(TxFrame2Mem, ARP_HARDW_OFS) = SWAPB(HARDW_ETH10);
ACCESS_UINT(TxFrame2Mem, ARP_PROT_OFS) = SWAPB(FRAME_IP);
ACCESS_UINT(TxFrame2Mem, ARP_HLEN_PLEN_OFS) = SWAPB(IP_HLEN_PLEN);
ACCESS_UINT(TxFrame2Mem, ARP_OPCODE_OFS) = SWAPB(OP_ARP_ANSWER);
ACCESS_UINT(TxFrame2Mem, ARP_SENDER_HA_OFS) = MyMAC[0];
ACCESS_UINT(TxFrame2Mem, ARP_SENDER_HA_OFS + 2) = MyMAC[1];
ACCESS_UINT(TxFrame2Mem, ARP_SENDER_HA_OFS + 4) = MyMAC[2];
ACCESS_UINT(TxFrame2Mem, ARP_SENDER_IP_OFS) = MyIP[0];
ACCESS_UINT(TxFrame2Mem, ARP_SENDER_IP_OFS + 2) = MyIP[1];
ACCESS_UINT(TxFrame2Mem, ARP_TARGET_HA_OFS) = RecdFrameMAC[0];
ACCESS_UINT(TxFrame2Mem, ARP_TARGET_HA_OFS + 2) = RecdFrameMAC[1];
ACCESS_UINT(TxFrame2Mem, ARP_TARGET_HA_OFS + 4) = RecdFrameMAC[2];
ACCESS_UINT(TxFrame2Mem, ARP_TARGET_IP_OFS) = RecdFrameIP[0];
ACCESS_UINT(TxFrame2Mem, ARP_TARGET_IP_OFS + 2) = RecdFrameIP[1];
TxFrame2Size = ETH_HEADER_SIZE + ARP_FRAME_SIZE;
TransmitControl |= SEND_FRAME2;
}
//------------------------------------------------------------------------------
// easyWEB internal function
// prepares the TxFrame2-buffer to send an ICMP-echo-reply
//------------------------------------------------------------------------------
static void PrepareICMP_ECHO_REPLY(void)
{
unsigned int ICMPDataCount;
if (RecdIPFrameLength > MAX_ETH_TX_DATA_SIZE) // don't overload TX-buffer
ICMPDataCount = MAX_ETH_TX_DATA_SIZE - IP_HEADER_SIZE - ICMP_HEADER_SIZE;
else
ICMPDataCount = RecdIPFrameLength - IP_HEADER_SIZE - ICMP_HEADER_SIZE;
// Ethernet
ACCESS_UINT(TxFrame2Mem, ETH_DA_OFS) = RecdFrameMAC[0];
ACCESS_UINT(TxFrame2Mem, ETH_DA_OFS + 2) = RecdFrameMAC[1];
ACCESS_UINT(TxFrame2Mem, ETH_DA_OFS + 4) = RecdFrameMAC[2];
ACCESS_UINT(TxFrame2Mem, ETH_SA_OFS) = MyMAC[0];
ACCESS_UINT(TxFrame2Mem, ETH_SA_OFS + 2) = MyMAC[1];
ACCESS_UINT(TxFrame2Mem, ETH_SA_OFS + 4) = MyMAC[2];
ACCESS_UINT(TxFrame2Mem, ETH_TYPE_OFS) = SWAPB(FRAME_IP);
// IP
ACCESS_UINT(TxFrame2Mem, IP_VER_IHL_TOS_OFS) = SWAPB(IP_VER_IHL);
ACCESS_UINT(TxFrame2Mem, IP_TOTAL_LENGTH_OFS) =
__swap_bytes(IP_HEADER_SIZE + ICMP_HEADER_SIZE + ICMPDataCount);
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -