📄 tcpip.c
字号:
/****************************************************************** ***** ***** ***** Name: tcpip.c ***** ***** Ver.: 1.0 ***** ***** Date: 07/05/2001 ***** ***** Auth: Andreas Dannenberg ***** ***** HTWK Leipzig ***** ***** university of applied sciences ***** ***** Germany ***** ***** Func: implements the TCP/IP-stack and provides a ***** ***** simple API to the user ***** ***** ***** ******************************************************************/#include "tcpip.h"#include "EMAC.h" // Keil: Line added#include <string.h> // Keil: Line added#include <LPC23xx.h> // Keil: Register definition file for LPC2378const unsigned char MyMAC[6] = // "M1-M2-M3-M4-M5-M6"{ MYMAC_1, MYMAC_2, MYMAC_3, MYMAC_4, MYMAC_5, MYMAC_6};// easyWEB-API function// initalizes the LAN-controller, reset flags, starts timer-ISRvoid TCPLowLevelInit(void){// Keil: Timer 0 is used for TCP retransmission control T0MR0 = 3144000; // 262mSec
T0MCR = 3; // Interrupt and Reset on MR0
T0TCR = 1; // Timer0 Enable
VICVectAddr4 = (unsigned int)TCPClockHandler;// set interrupt vector in 4
VICIntEnable = 0x00000010; // Enable Timer0 Interrupt
PCONP |= (1<<12); // Deliver clock to AD
PINSEL1 = 0x00014000; // Enable AD0 and AD1 inputs
Init_EMAC(); TransmitControl = 0; TCPFlags = 0; TCPStateMachine = CLOSED; SocketStatus = 0;}// easyWEB-API function// does a passive open (listen on 'MyIP:TCPLocalPort' for an incoming// connection)void TCPPassiveOpen(void){ if (TCPStateMachine == CLOSED) { TCPFlags &= ~TCP_ACTIVE_OPEN; // let's do a passive open! TCPStateMachine = LISTENING; SocketStatus = SOCK_ACTIVE; // reset, socket now active }}// easyWEB-API function// does an active open (tries to establish a connection between// 'MyIP:TCPLocalPort' and 'RemoteIP:TCPRemotePort')void TCPActiveOpen(void){ if ((TCPStateMachine == CLOSED) || (TCPStateMachine == LISTENING)) { TCPFlags |= TCP_ACTIVE_OPEN; // let's do an active open! TCPFlags &= ~IP_ADDR_RESOLVED; // we haven't opponents MAC yet PrepareARP_REQUEST(); // ask for MAC by sending a broadcast LastFrameSent = ARP_REQUEST; TCPStartRetryTimer(); SocketStatus = SOCK_ACTIVE; // reset, socket now active }}// easyWEB-API function// closes an open connectionvoid TCPClose(void){ switch (TCPStateMachine) { case LISTENING : case SYN_SENT : { TCPStateMachine = CLOSED; TCPFlags = 0; SocketStatus = 0; break; } case SYN_RECD : case ESTABLISHED : { TCPFlags |= TCP_CLOSE_REQUESTED; break; } }}// easyWEB-API function// releases the receive-buffer and allows easyWEB to store new data// NOTE: rx-buffer MUST be released periodically, else the other TCP// get no ACKs for the data it sentvoid TCPReleaseRxBuffer(void){ SocketStatus &= ~SOCK_DATA_AVAILABLE;}// easyWEB-API function// transmitts data stored in 'TCP_TX_BUF'// NOTE: * number of bytes to transmit must have been written to 'TCPTxDataCount'// * data-count MUST NOT exceed 'MAX_TCP_TX_DATA_SIZE'void TCPTransmitTxBuffer(void){ if ((TCPStateMachine == ESTABLISHED) || (TCPStateMachine == CLOSE_WAIT)) if (SocketStatus & SOCK_TX_BUF_RELEASED) { SocketStatus &= ~SOCK_TX_BUF_RELEASED; // occupy tx-buffer TCPUNASeqNr += TCPTxDataCount; // advance UNA TxFrame1Size = ETH_HEADER_SIZE + IP_HEADER_SIZE + TCP_HEADER_SIZE + TCPTxDataCount; TransmitControl |= SEND_FRAME1; LastFrameSent = TCP_DATA_FRAME; TCPStartRetryTimer(); }}// Reads the length of the received ethernet frame and checks if the // destination address is a broadcast message or notunsigned int IsBroadcast(void) { unsigned short RecdDestMAC[3]; // 48 bit MAC RecdFrameLength = StartReadFrame(); CopyFromFrame_EMAC(&RecdDestMAC, 6); // receive DA to see if it was a broadcast CopyFromFrame_EMAC(&RecdFrameMAC, 6); // store SA (for our answer) if ((RecdDestMAC[0] == 0xFFFF) && (RecdDestMAC[1] == 0xFFFF) && (RecdDestMAC[2] == 0xFFFF)) { return(1); } else { return (0); }}// easyWEB's 'main()'-function// must be called from user program periodically (the often - the better)// handles network, TCP/IP-stack and user eventsvoid DoNetworkStuff(void){ if (CheckFrameReceived()) // Packet received { if (IsBroadcast()) { ProcessEthBroadcastFrame(); } else { ProcessEthIAFrame(); } EndReadFrame(); // release buffer in ethernet controller } if (TCPFlags & TCP_TIMER_RUNNING) if (TCPFlags & TIMER_TYPE_RETRY) { if (TCPTimer > RETRY_TIMEOUT) { TCPRestartTimer(); // set a new timeout if (RetryCounter) { TCPHandleRetransmission(); // resend last frame RetryCounter--; } else { TCPStopTimer(); TCPHandleTimeout(); } } } else if (TCPTimer > FIN_TIMEOUT) { TCPStateMachine = CLOSED; TCPFlags = 0; // reset all flags, stop retransmission... SocketStatus &= SOCK_DATA_AVAILABLE; // clear all flags but data available } switch (TCPStateMachine) { case CLOSED : case LISTENING : { if (TCPFlags & TCP_ACTIVE_OPEN) // stack has to open a connection? if (TCPFlags & IP_ADDR_RESOLVED) // IP resolved? if (!(TransmitControl & SEND_FRAME2)) // buffer free? { TCPSeqNr = ((unsigned long)ISNGenHigh << 16) | (T0TC & 0xFFFF); // Keil: changed from TAR to T0TC;
// set local ISN TCPUNASeqNr = TCPSeqNr; TCPAckNr = 0; // we don't know what to ACK! TCPUNASeqNr++; // count SYN as a byte PrepareTCP_FRAME(TCP_CODE_SYN); // send SYN frame LastFrameSent = TCP_SYN_FRAME; TCPStartRetryTimer(); // we NEED a retry-timeout TCPStateMachine = SYN_SENT; } break; } case SYN_RECD : case ESTABLISHED : { if (TCPFlags & TCP_CLOSE_REQUESTED) // user has user initated a close? if (!(TransmitControl & (SEND_FRAME2 | SEND_FRAME1))) // buffers free? if (TCPSeqNr == TCPUNASeqNr) // all data ACKed? { TCPUNASeqNr++; PrepareTCP_FRAME(TCP_CODE_FIN | TCP_CODE_ACK); LastFrameSent = TCP_FIN_FRAME; TCPStartRetryTimer(); TCPStateMachine = FIN_WAIT_1; } 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(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 SendFrame2(); // the EMAC isn't ready yet, include else { // a kind of timer or counter here 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()) // EMAC ready to accept our frame? SendFrame1(); // (see note above) 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 framevoid ProcessEthBroadcastFrame(void){ unsigned short TargetIP[2]; if (ReadFrameBE_EMAC() == FRAME_ARP) // get frame type, check for ARP if (ReadFrameBE_EMAC() == HARDW_ETH10) // Ethernet frame if (ReadFrameBE_EMAC() == FRAME_IP) // check protocol if (ReadFrameBE_EMAC() == IP_HLEN_PLEN) // check HLEN, PLEN if (ReadFrameBE_EMAC() == OP_ARP_REQUEST) { DummyReadFrame_EMAC(6); // ignore sender's hardware address CopyFromFrame_EMAC(&RecdFrameIP, 4); // read sender's protocol address DummyReadFrame_EMAC(6); // ignore target's hardware address CopyFromFrame_EMAC(&TargetIP, 4); // read target's protocol address if (!memcmp(&MyIP, &TargetIP, 4)) // is it for us? PrepareARP_ANSWER(); // yes->create ARP_ANSWER frame }}// easyWEB internal function// handles an incoming frame that passed EMAC's address filter// (individual addressed = IA)void ProcessEthIAFrame(void){ unsigned short TargetIP[2]; unsigned char ProtocolType; switch (ReadFrameBE_EMAC()) // get frame type { case FRAME_ARP : // check for ARP { if ((TCPFlags & (TCP_ACTIVE_OPEN | IP_ADDR_RESOLVED)) == TCP_ACTIVE_OPEN) if (ReadFrameBE_EMAC() == HARDW_ETH10) // check for the right prot. etc. if (ReadFrameBE_EMAC() == FRAME_IP) if (ReadFrameBE_EMAC() == IP_HLEN_PLEN) if (ReadFrameBE_EMAC() == OP_ARP_ANSWER) { TCPStopTimer(); // OK, now we've the MAC we wanted ;-) CopyFromFrame_EMAC(&RemoteMAC, 6); // extract opponents MAC TCPFlags |= IP_ADDR_RESOLVED;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -