?? tcpip.c
字號:
break;
case CLOSE_WAIT :
if (!(TransmitControl & (SEND_FRAME2 | SEND_FRAME1))) // buffers free?
if (TCPSeqNr == TCPUNASeqNr) // all data ACKed?
{
TCPUNASeqNr++; // count FIN as a byte
PrepareTCP_FRAME(TCPSeqNr, TCPAckNr, TCP_CODE_FIN | TCP_CODE_ACK); // we NEED a retry-timeout
LastFrameSent = TCP_FIN_FRAME; // time to say goodbye...
TCPStartRetryTimer();
TCPStateMachine = LAST_ACK;
}
break;
}
if (TransmitControl & SEND_FRAME2)
{
RequestSend(TxFrame2Size);
if (Rdy4Tx()) // NOTE: when using a very fast MCU,
{ // maybe the CS8900 isn't ready yet
CopyToFrame8900((unsigned char *)TxFrame2Mem, TxFrame2Size);
}
else
{
TCPStateMachine = CLOSED;
SocketStatus = SOCK_ERR_ETHERNET; // indicate an error to user
TCPFlags = 0; // clear all flags, stop timers etc.
}
TransmitControl &= ~SEND_FRAME2; // clear tx-flag
}
if (TransmitControl & SEND_FRAME1)
{
PrepareTCP_DATA_FRAME(); // build frame w/ actual SEQ, ACK....
RequestSend(TxFrame1Size);
if (Rdy4Tx()) // CS8900 ready to accept our frame?
{ // (see note above)
CopyToFrame8900((unsigned char *)TxFrame1Mem, TxFrame1Size);
}
else
{
TCPStateMachine = CLOSED;
SocketStatus = SOCK_ERR_ETHERNET; // indicate an error to user
TCPFlags = 0; // clear all flags, stop timers etc.
}
TransmitControl &= ~SEND_FRAME1; // clear tx-flag
}
}
//------------------------------------------------------------------------------
// easyWEB internal function
// handles an incoming broadcast frame
//------------------------------------------------------------------------------
static void ProcessEthBroadcastFrame(void)
{
unsigned int TargetIP[2];
// next two words MUST be read with High-Byte 1st (CS8900 AN181 Page 2)
ReadHB1ST8900(RX_FRAME_PORT); // ignore RxStatus Word
RecdFrameLength = ReadHB1ST8900(RX_FRAME_PORT);// get real length of frame
DummyReadFrame8900(6); // ignore DA (FF-FF-FF-FF-FF-FF)
CopyFromFrame8900(&RecdFrameMAC, 6); // store SA (for our answer)
if (ReadFrameBE8900() == FRAME_ARP) // get frame type, check for ARP
if (ReadFrameBE8900() == HARDW_ETH10) // Ethernet frame
if (ReadFrameBE8900() == FRAME_IP) // check protocol
if (ReadFrameBE8900() == IP_HLEN_PLEN) // check HLEN, PLEN
if (ReadFrameBE8900() == OP_ARP_REQUEST)
{
DummyReadFrame8900(6); // ignore sender's hardware address
CopyFromFrame8900(&RecdFrameIP, 4); // read sender's protocol address
DummyReadFrame8900(6); // ignore target's hardware address
CopyFromFrame8900(&TargetIP, 4); // read target's protocol address
if ((MyIP[0] == TargetIP[0]) && (MyIP[1] == TargetIP[1])) // is it for us?
PrepareARP_ANSWER(); // yes->create ARP_ANSWER frame
}
}
//------------------------------------------------------------------------------
// easyWEB internal function
// handles an incoming frame that passed CS8900's address filter
// (individual addressed = IA)
//------------------------------------------------------------------------------
static void ProcessEthIAFrame(void)
{
unsigned int TargetIP[2];
unsigned char ProtocolType;
// next two words MUST be read with High-Byte 1st (CS8900 AN181 Page 2)
ReadHB1ST8900(RX_FRAME_PORT); // ignore RxStatus Word
RecdFrameLength = ReadHB1ST8900(RX_FRAME_PORT);// get real length of frame
DummyReadFrame8900(6); // ignore DA
CopyFromFrame8900(&RecdFrameMAC, 6); // store SA (for our answer)
switch (ReadFrameBE8900()) // get frame type
{
case FRAME_ARP : // check for ARP
if ((TCPFlags & (TCP_ACTIVE_OPEN | IP_ADDR_RESOLVED)) == TCP_ACTIVE_OPEN)
if (ReadFrameBE8900() == HARDW_ETH10) // check for the right prot. etc.
if (ReadFrameBE8900() == FRAME_IP)
if (ReadFrameBE8900() == IP_HLEN_PLEN)
if (ReadFrameBE8900() == OP_ARP_ANSWER)
{
TCPStopTimer(); // OK, now we've the MAC we wanted ;-)
CopyFromFrame8900(&RemoteMAC, 6); // extract opponents MAC
TCPFlags |= IP_ADDR_RESOLVED;
}
break;
case FRAME_IP : // check for IP-type
if ((ReadFrameBE8900() & 0xff00 ) == IP_VER_IHL) // IPv4, IHL=5 (20 Bytes Header)
{ // ignore Type Of Service
RecdIPFrameLength = ReadFrameBE8900(); // get IP frame's length
ReadFrameBE8900(); // ignore identification
if (!(ReadFrameBE8900() & (IP_FLAG_MOREFRAG | IP_FRAGOFS_MASK))) // only unfragm. frames
{
ProtocolType = ReadFrameBE8900(); // get protocol, ignore TTL
ReadFrameBE8900(); // ignore checksum
RecdFrameIP[0] = ReadFrame8900(); // get source IP
RecdFrameIP[1] = ReadFrame8900();
TargetIP[0] = ReadFrame8900(); // get destination IP
TargetIP[1] = ReadFrame8900();
if ((MyIP[0] == TargetIP[0]) && (MyIP[1] == TargetIP[1])) // is it for us?
switch (ProtocolType)
{
case PROT_ICMP :
ProcessICMPFrame();
break;
case PROT_TCP :
ProcessTCPFrame();
break;
case PROT_UDP : // not implemented!
break;
}
}
break;
}
}
}
//------------------------------------------------------------------------------
// easyWEB internal function
// we've just rec'd an ICMP-frame (Internet Control Message Protocol)
// check what to do and branch to the appropriate sub-function
//------------------------------------------------------------------------------
static void ProcessICMPFrame(void)
{
unsigned int ICMPTypeAndCode;
ICMPTypeAndCode = ReadFrameBE8900(); // get Message Type and Code
ReadFrameBE8900(); // ignore ICMP checksum
switch (ICMPTypeAndCode >> 8) // check type
{
case ICMP_ECHO : // is echo request?
PrepareICMP_ECHO_REPLY(); // echo as much as we can...
break;
}
}
//------------------------------------------------------------------------------
// easyWEB internal function
// we've just rec'd an TCP-frame (Transmission Control Protocol)
// this function mainly implements the TCP state machine according to RFC793
//------------------------------------------------------------------------------
static void ProcessTCPFrame(void)
{
unsigned int TCPSegSourcePort; // segment's source port
unsigned int TCPSegDestPort; // segment's destination port
unsigned long TCPSegSeq; // segment's sequence number
unsigned long TCPSegAck; // segment's acknowledge number
unsigned int TCPCode; // TCP code and header length
unsigned char TCPHeaderSize; // real TCP header length
unsigned int NrOfDataBytes; // real number of data
TCPSegSourcePort = ReadFrameBE8900(); // get ports
TCPSegDestPort = ReadFrameBE8900();
if (TCPSegDestPort != TCPLocalPort) return; // drop segment if port doesn't match
TCPSegSeq = (unsigned long)ReadFrameBE8900() << 16; // get segment sequence nr.
TCPSegSeq |= ReadFrameBE8900();
TCPSegAck = (unsigned long)ReadFrameBE8900() << 16; // get segment acknowledge nr.
TCPSegAck |= ReadFrameBE8900();
TCPCode = ReadFrameBE8900(); // get control bits, header length...
TCPHeaderSize = (TCPCode & DATA_OFS_MASK) >> 10; // header length in bytes
NrOfDataBytes = RecdIPFrameLength - IP_HEADER_SIZE - TCPHeaderSize; // seg. text length
if (NrOfDataBytes > MAX_TCP_RX_DATA_SIZE) return; // drop, packet too large for us :'(
if (TCPHeaderSize > TCP_HEADER_SIZE) // ignore options if any
DummyReadFrame8900(TCPHeaderSize - TCP_HEADER_SIZE);
switch (TCPStateMachine) // implement the TCP state machine
{ // RFC793
case CLOSED :
if (!(TCPCode & TCP_CODE_RST))
{
TCPRemotePort = TCPSegSourcePort; // get remote TCP port
RemoteMAC[0] = RecdFrameMAC[0]; // save opponents MAC and IP
RemoteMAC[1] = RecdFrameMAC[1]; // for later use
RemoteMAC[2] = RecdFrameMAC[2];
RemoteIP[0] = RecdFrameIP[0];
RemoteIP[1] = RecdFrameIP[1];
if (TCPCode & TCP_CODE_ACK) // make the reset sequence
{ // acceptable to the other
PrepareTCP_FRAME(TCPSegAck, 0, TCP_CODE_RST); // TCP
}
else
{
TCPAckNr = TCPSegSeq + NrOfDataBytes;
if (TCPCode & (TCP_CODE_SYN | TCP_CODE_FIN)) TCPAckNr++;
PrepareTCP_FRAME(0, TCPAckNr, TCP_CODE_RST | TCP_CODE_ACK);
}
}
break;
case LISTENING :
if (!(TCPCode & TCP_CODE_RST)) // ignore segment containing RST
{
TCPRemotePort = TCPSegSourcePort; // get remote TCP port
RemoteMAC[0] = RecdFrameMAC[0]; // save opponents MAC and IP
RemoteMAC[1] = RecdFrameMAC[1]; // for later use
RemoteMAC[2] = RecdFrameMAC[2];
RemoteIP[0] = RecdFrameIP[0];
RemoteIP[1] = RecdFrameIP[1];
if (TCPCode & TCP_CODE_ACK) // reset a bad
{ // acknowledgement
PrepareTCP_FRAME(TCPSegAck, 0, TCP_CODE_RST);
}
else if (TCPCode & TCP_CODE_SYN)
{
// initialize global connection variables
TCPAckNr = TCPSegSeq + 1; // get remote ISN, next byte we expect
TCPSeqNr = ((unsigned long)ISNGenHigh << 16) | TAR; // set local ISN
TCPUNASeqNr = TCPSeqNr + 1; // one byte out -> increase by one
PrepareTCP_FRAME(TCPSeqNr, TCPAckNr, TCP_CODE_SYN | TCP_CODE_ACK); // acknowledge connection request
LastFrameSent = TCP_SYN_ACK_FRAME;
TCPStartRetryTimer();
TCPStateMachine = SYN_RECD;
}
}
break;
case SYN_SENT :
// drop segment if its 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;
if (TCPCode & TCP_CODE_ACK) // ACK field significant?
if (TCPSegAck != TCPUNASeqNr) // is our ISN ACKed?
{
if (!(TCPCode & TCP_CODE_RST))
{
PrepareTCP_FRAME(TCPSegAck, 0, TCP_CODE_RST);
}
break; // drop segment
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -