?? tcpip.c
字號:
/****************************************************************** ***** ***** ***** Name: tcpip.c ***** ***** Ver.: 1.0 ***** ***** Date: 07/05/2001 ***** ***** Auth: Andreas Dannenberg ***** ***** HTWK Leipzig ***** ***** university of applied sciences ***** ***** Germany ***** ***** adannenb@et.htwk-leipzig.de ***** ***** Func: implements the TCP/IP-stack and provides a ***** ***** simple API to the user ***** ***** ***** ******************************************************************/#include "tcpip.h"// easyWEB-API function// initalizes the LAN-controller, reset flags, starts timer-ISRvoid TCPLowLevelInit(void){ BCSCTL1 &= ~DIVA0; // ACLK = XT1 / 4 = 2 MHz BCSCTL1 |= DIVA1; TACTL = ID1 | ID0 | TASSEL0 | TAIE; // stop timer, use ACLK / 8 = 250 kHz, gen. int. TACTL |= MC1; // start timer in continuous up-mode _EINT(); // enable interrupts Init8900(); 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(); }}// 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){ unsigned int ActRxEvent; // copy of cs8900's RxEvent-Register Write8900(ADD_PORT, PP_RxEvent); // point to RxEvent ActRxEvent = Read8900(DATA_PORT); // read, implied skip the last frame if (ActRxEvent & RX_OK) { if (ActRxEvent & RX_IA) ProcessEthIAFrame(); if (ActRxEvent & RX_BROADCAST) ProcessEthBroadcastFrame(); } 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) | TAR; // 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 CS8900 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()) // CS8900 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 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 (!memcmp(&MyIP, &TargetIP, 4)) // 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)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
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -