Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed
Fork of EasyWebCR by
tcpip.c
00001 /****************************************************************** 00002 ***** ***** 00003 ***** Name: tcpip.c ***** 00004 ***** Ver.: 1.0 ***** 00005 ***** Date: 07/05/2001 ***** 00006 ***** Auth: Andreas Dannenberg ***** 00007 ***** HTWK Leipzig ***** 00008 ***** university of applied sciences ***** 00009 ***** Germany ***** 00010 ***** adannenb@et.htwk-leipzig.de ***** 00011 ***** Func: implements the TCP/IP-stack and provides a ***** 00012 ***** simple API to the user ***** 00013 ***** ***** 00014 ******************************************************************/ 00015 00016 // Modifications by Code Red Technologies for NXP LPC1768 00017 // Throughout file, functions of form xxx8900() renamed xxx_EthMAC() 00018 // Other changes commented in place 00019 00020 #include "tcpip.h" 00021 00022 //CodeRed - added header for LPC ethernet controller 00023 #include "ethmac.h" 00024 // CodeRed - added library string handling header 00025 #include <string.h> 00026 00027 // CodeRed - added NXP LPC register definitions header 00028 //#include "LPC17xx.h" 00029 00030 #include "mbed.h" 00031 00032 unsigned short MyIP[] = // "MYIP1.MYIP2.MYIP3.MYIP4" 00033 { 00034 MYIP_1 + (MYIP_2 << 8), 00035 MYIP_3 + (MYIP_4 << 8) 00036 }; 00037 00038 unsigned short SubnetMask[] = // "SUBMASK1.SUBMASK2.SUBMASK3.SUBMASK4" 00039 { 00040 SUBMASK_1 + (SUBMASK_2 << 8), 00041 SUBMASK_3 + (SUBMASK_4 << 8) 00042 }; 00043 00044 unsigned short GatewayIP[] = // "GWIP1.GWIP2.GWIP3.GWIP4" 00045 { 00046 GWIP_1 + (GWIP_2 << 8), 00047 GWIP_3 + (GWIP_4 << 8) 00048 }; 00049 00050 // the next 3 buffers must be word-aligned! 00051 // (here the 'RecdIPFrameLength' above does that) 00052 unsigned short _TxFrame1[(ETH_HEADER_SIZE + IP_HEADER_SIZE + TCP_HEADER_SIZE + MAX_TCP_TX_DATA_SIZE)/2]; 00053 unsigned short _TxFrame2[(ETH_HEADER_SIZE + MAX_ETH_TX_DATA_SIZE)/2]; 00054 unsigned short _RxTCPBuffer[MAX_TCP_RX_DATA_SIZE/2]; // space for incoming TCP-data 00055 00056 unsigned short TxFrame1Size; // bytes to send in TxFrame1 00057 unsigned char TxFrame2Size; // bytes to send in TxFrame2 00058 00059 unsigned char TransmitControl; 00060 #define SEND_FRAME1 0x01 00061 #define SEND_FRAME2 0x02 00062 00063 unsigned char TCPFlags; 00064 #define TCP_ACTIVE_OPEN 0x01 // easyWEB shall initiate a connection 00065 #define IP_ADDR_RESOLVED 0x02 // IP sucessfully resolved to MAC 00066 #define TCP_TIMER_RUNNING 0x04 00067 #define TIMER_TYPE_RETRY 0x08 00068 #define TCP_CLOSE_REQUESTED 0x10 00069 00070 // easyWEB's internal variables 00071 TTCPStateMachine TCPStateMachine; // perhaps the most important var at all ;-) 00072 TLastFrameSent LastFrameSent; // retransmission type 00073 00074 unsigned short ISNGenHigh; // upper word of our Initial Sequence Number 00075 unsigned long TCPSeqNr; // next sequence number to send 00076 unsigned long TCPUNASeqNr; // last unaknowledged sequence number 00077 // incremented AFTER sending data 00078 unsigned long TCPAckNr; // next seq to receive and ack to send 00079 // incremented AFTER receiving data 00080 unsigned char TCPTimer; // inc'd each 262ms 00081 unsigned char RetryCounter; // nr. of retransmissions 00082 00083 // properties of the just received frame 00084 unsigned short RecdFrameLength; // EMAC reported frame length 00085 unsigned short RecdFrameMAC[3]; // 48 bit MAC 00086 unsigned short RecdFrameIP[2]; // 32 bit IP 00087 unsigned short RecdIPFrameLength; // 16 bit IP packet length 00088 00089 // easyWEB-API global vars and flags 00090 unsigned short TCPRxDataCount; // nr. of bytes rec'd 00091 unsigned short TCPTxDataCount; // nr. of bytes to send 00092 00093 unsigned short TCPLocalPort; // TCP ports 00094 unsigned short TCPRemotePort; 00095 00096 unsigned short RemoteMAC[3]; // MAC and IP of current TCP-session 00097 unsigned short RemoteIP[2]; 00098 00099 unsigned char SocketStatus; 00100 00101 void Start_SysTick10ms(void); 00102 00103 // Code Red - moved myMAC definition in from original cs8900.h 00104 unsigned char MyMAC[6] = // "M1-M2-M3-M4-M5-M6" 00105 { 00106 MYMAC_6, MYMAC_5, MYMAC_4, 00107 MYMAC_3, MYMAC_2, MYMAC_1 00108 }; 00109 00110 // easyWEB-API function 00111 // initalizes the LAN-controller, reset flags, starts timer-ISR 00112 00113 void TCPLowLevelInit(void) 00114 { 00115 // CodeRed - comment out original 8900 specific code 00116 /* 00117 BCSCTL1 &= ~DIVA0; // ACLK = XT1 / 4 = 2 MHz 00118 BCSCTL1 |= DIVA1; 00119 TACTL = ID1 | ID0 | TASSEL0 | TAIE; // stop timer, use ACLK / 8 = 250 kHz, gen. int. 00120 TACTL |= MC1; // start timer in continuous up-mode 00121 _EINT(); // enable interrupts 00122 00123 Init8900(); 00124 */ 00125 LPC_GPIO1->FIODIR = 1 << 25; // P1.25 defined as Output (LED) 00126 00127 Start_SysTick10ms(); // Start SysTick timer running (10ms ticks) 00128 00129 Init_EthMAC(); 00130 00131 TransmitControl = 0; 00132 TCPFlags = 0; 00133 TCPStateMachine = CLOSED; 00134 SocketStatus = 0; 00135 } 00136 00137 // easyWEB-API function 00138 // does a passive open (listen on 'MyIP:TCPLocalPort' for an incoming 00139 // connection) 00140 00141 void TCPPassiveOpen(void) 00142 { 00143 if (TCPStateMachine == CLOSED) 00144 { 00145 TCPFlags &= ~TCP_ACTIVE_OPEN; // let's do a passive open! 00146 TCPStateMachine = LISTENING; 00147 SocketStatus = SOCK_ACTIVE; // reset, socket now active 00148 } 00149 } 00150 00151 // easyWEB-API function 00152 // does an active open (tries to establish a connection between 00153 // 'MyIP:TCPLocalPort' and 'RemoteIP:TCPRemotePort') 00154 00155 void TCPActiveOpen(void) 00156 { 00157 if ((TCPStateMachine == CLOSED) || (TCPStateMachine == LISTENING)) 00158 { 00159 TCPFlags |= TCP_ACTIVE_OPEN; // let's do an active open! 00160 TCPFlags &= ~IP_ADDR_RESOLVED; // we haven't opponents MAC yet 00161 00162 PrepareARP_REQUEST(); // ask for MAC by sending a broadcast 00163 LastFrameSent = ARP_REQUEST; 00164 TCPStartRetryTimer(); 00165 SocketStatus = SOCK_ACTIVE; // reset, socket now active 00166 } 00167 } 00168 00169 // easyWEB-API function 00170 // closes an open connection 00171 00172 void TCPClose(void) 00173 { 00174 switch (TCPStateMachine) 00175 { 00176 case LISTENING : 00177 case SYN_SENT : 00178 { 00179 TCPStateMachine = CLOSED; 00180 TCPFlags = 0; 00181 SocketStatus = 0; 00182 break; 00183 } 00184 case SYN_RECD : 00185 case ESTABLISHED : 00186 { 00187 TCPFlags |= TCP_CLOSE_REQUESTED; 00188 break; 00189 } 00190 } 00191 } 00192 00193 // easyWEB-API function 00194 // releases the receive-buffer and allows easyWEB to store new data 00195 // NOTE: rx-buffer MUST be released periodically, else the other TCP 00196 // get no ACKs for the data it sent 00197 00198 void TCPReleaseRxBuffer(void) 00199 { 00200 SocketStatus &= ~SOCK_DATA_AVAILABLE; 00201 } 00202 00203 // easyWEB-API function 00204 // transmitts data stored in 'TCP_TX_BUF' 00205 // NOTE: * number of bytes to transmit must have been written to 'TCPTxDataCount' 00206 // * data-count MUST NOT exceed 'MAX_TCP_TX_DATA_SIZE' 00207 00208 void TCPTransmitTxBuffer(void) 00209 { 00210 if ((TCPStateMachine == ESTABLISHED) || (TCPStateMachine == CLOSE_WAIT)) 00211 if (SocketStatus & SOCK_TX_BUF_RELEASED) 00212 { 00213 SocketStatus &= ~SOCK_TX_BUF_RELEASED; // occupy tx-buffer 00214 TCPUNASeqNr += TCPTxDataCount; // advance UNA 00215 00216 TxFrame1Size = ETH_HEADER_SIZE + IP_HEADER_SIZE + TCP_HEADER_SIZE + TCPTxDataCount; 00217 TransmitControl |= SEND_FRAME1; 00218 00219 LastFrameSent = TCP_DATA_FRAME; 00220 TCPStartRetryTimer(); 00221 } 00222 } 00223 00224 // CodeRed - New function to check if received frame 00225 // was a broadcast message 00226 00227 // Reads the length of the received ethernet frame and checks if the 00228 // destination address is a broadcast message or not 00229 unsigned int BroadcastMessage(void) 00230 { 00231 unsigned short FrameDestination[3]; // to hold 48 bit MAC address 00232 00233 RecdFrameLength = StartReadingFrame(); 00234 00235 // Read destination address 00236 CopyFromFrame_EthMAC(&FrameDestination, 6); 00237 // Save it for reply 00238 CopyFromFrame_EthMAC(&RecdFrameMAC, 6); 00239 00240 if ((FrameDestination[0] == 0xFFFF) && 00241 (FrameDestination[1] == 0xFFFF) && 00242 (FrameDestination[2] == 0xFFFF)) { 00243 return(1); // Broadcast message 00244 } else { 00245 return (0); 00246 } 00247 } 00248 00249 00250 // easyWEB's 'main()'-function 00251 // must be called from user program periodically (the often - the better) 00252 // handles network, TCP/IP-stack and user events 00253 00254 void DoNetworkStuff(void) 00255 { 00256 // CodeRed - comment out original cs8900 code 00257 /* 00258 unsigned int ActRxEvent; // copy of cs8900's RxEvent-Register 00259 00260 Write8900(ADD_PORT, PP_RxEvent); // point to RxEvent 00261 ActRxEvent = Read8900(DATA_PORT); // read, implied skip the last frame 00262 00263 if (ActRxEvent & RX_OK) 00264 { 00265 if (ActRxEvent & RX_IA) ProcessEthIAFrame(); 00266 if (ActRxEvent & RX_BROADCAST) ProcessEthBroadcastFrame(); 00267 } 00268 */ 00269 00270 // Check to see if packet received 00271 if (CheckIfFrameReceived()) 00272 { 00273 // Was it a broadcast message? 00274 if (BroadcastMessage()) { 00275 ProcessEthBroadcastFrame(); 00276 } 00277 else { 00278 ProcessEthIAFrame(); 00279 } 00280 // now release ethernet controller buffer 00281 StopReadingFrame(); 00282 } 00283 00284 00285 // CodeRed - now back to original code 00286 00287 if (TCPFlags & TCP_TIMER_RUNNING) 00288 if (TCPFlags & TIMER_TYPE_RETRY) 00289 { 00290 if (TCPTimer > RETRY_TIMEOUT) 00291 { 00292 TCPRestartTimer(); // set a new timeout 00293 00294 if (RetryCounter) 00295 { 00296 TCPHandleRetransmission(); // resend last frame 00297 RetryCounter--; 00298 } 00299 else 00300 { 00301 TCPStopTimer(); 00302 TCPHandleTimeout(); 00303 } 00304 } 00305 } 00306 else if (TCPTimer > FIN_TIMEOUT) 00307 { 00308 TCPStateMachine = CLOSED; 00309 TCPFlags = 0; // reset all flags, stop retransmission... 00310 SocketStatus &= SOCK_DATA_AVAILABLE; // clear all flags but data available 00311 } 00312 00313 switch (TCPStateMachine) 00314 { 00315 case CLOSED : 00316 case LISTENING : 00317 { 00318 if (TCPFlags & TCP_ACTIVE_OPEN) // stack has to open a connection? 00319 if (TCPFlags & IP_ADDR_RESOLVED) // IP resolved? 00320 if (!(TransmitControl & SEND_FRAME2)) // buffer free? 00321 { 00322 // CodeRed - change TAR -> TOTC to use LPC1768 clock 00323 // TCPSeqNr = ((unsigned long)ISNGenHigh << 16) | TAR; // set local ISN 00324 TCPSeqNr = ((unsigned long)ISNGenHigh << 16) | (LPC_TIM0->TC & 0xFFFF); // set local ISN 00325 TCPUNASeqNr = TCPSeqNr; 00326 TCPAckNr = 0; // we don't know what to ACK! 00327 TCPUNASeqNr++; // count SYN as a byte 00328 PrepareTCP_FRAME(TCP_CODE_SYN); // send SYN frame 00329 LastFrameSent = TCP_SYN_FRAME; 00330 TCPStartRetryTimer(); // we NEED a retry-timeout 00331 TCPStateMachine = SYN_SENT; 00332 } 00333 break; 00334 } 00335 case SYN_RECD : 00336 case ESTABLISHED : 00337 { 00338 if (TCPFlags & TCP_CLOSE_REQUESTED) // user has user initated a close? 00339 if (!(TransmitControl & (SEND_FRAME2 | SEND_FRAME1))) // buffers free? 00340 if (TCPSeqNr == TCPUNASeqNr) // all data ACKed? 00341 { 00342 TCPUNASeqNr++; 00343 PrepareTCP_FRAME(TCP_CODE_FIN | TCP_CODE_ACK); 00344 LastFrameSent = TCP_FIN_FRAME; 00345 TCPStartRetryTimer(); 00346 TCPStateMachine = FIN_WAIT_1; 00347 } 00348 break; 00349 } 00350 case CLOSE_WAIT : 00351 { 00352 if (!(TransmitControl & (SEND_FRAME2 | SEND_FRAME1))) // buffers free? 00353 if (TCPSeqNr == TCPUNASeqNr) // all data ACKed? 00354 { 00355 TCPUNASeqNr++; // count FIN as a byte 00356 PrepareTCP_FRAME(TCP_CODE_FIN | TCP_CODE_ACK); // we NEED a retry-timeout 00357 LastFrameSent = TCP_FIN_FRAME; // time to say goodbye... 00358 TCPStartRetryTimer(); 00359 TCPStateMachine = LAST_ACK; 00360 } 00361 break; 00362 } 00363 } 00364 00365 if (TransmitControl & SEND_FRAME2) 00366 { 00367 RequestSend(TxFrame2Size); 00368 00369 if (Rdy4Tx()) // NOTE: when using a very fast MCU, maybe 00370 SendFrame2(); // the CS8900 isn't ready yet, include 00371 else { // a kind of timer or counter here 00372 TCPStateMachine = CLOSED; 00373 SocketStatus = SOCK_ERR_ETHERNET; // indicate an error to user 00374 TCPFlags = 0; // clear all flags, stop timers etc. 00375 } 00376 00377 TransmitControl &= ~SEND_FRAME2; // clear tx-flag 00378 } 00379 00380 if (TransmitControl & SEND_FRAME1) 00381 { 00382 PrepareTCP_DATA_FRAME(); // build frame w/ actual SEQ, ACK.... 00383 RequestSend(TxFrame1Size); 00384 00385 if (Rdy4Tx()) // CS8900 ready to accept our frame? 00386 SendFrame1(); // (see note above) 00387 else { 00388 TCPStateMachine = CLOSED; 00389 SocketStatus = SOCK_ERR_ETHERNET; // indicate an error to user 00390 TCPFlags = 0; // clear all flags, stop timers etc. 00391 } 00392 00393 TransmitControl &= ~SEND_FRAME1; // clear tx-flag 00394 } 00395 } 00396 00397 // easyWEB internal function 00398 // handles an incoming broadcast frame 00399 00400 void ProcessEthBroadcastFrame(void) 00401 { 00402 // CodeRed - change from int to short 00403 // unsigned int TargetIP[2]; 00404 unsigned short TargetIP[2]; 00405 00406 // CodeRed - remove CS8900 specific code block 00407 /* 00408 // next two words MUST be read with High-Byte 1st (CS8900 AN181 Page 2) 00409 ReadHB1ST8900(RX_FRAME_PORT); // ignore RxStatus Word 00410 RecdFrameLength = ReadHB1ST8900(RX_FRAME_PORT);// get real length of frame 00411 00412 DummyReadFrame8900(6); // ignore DA (FF-FF-FF-FF-FF-FF) 00413 CopyFromFrame8900(&RecdFrameMAC, 6); // store SA (for our answer) 00414 // Code Red - end of CS8900 specific block 00415 */ 00416 00417 if (ReadFrameBE_EthMAC() == FRAME_ARP) // get frame type, check for ARP 00418 if (ReadFrameBE_EthMAC() == HARDW_ETH10) // Ethernet frame 00419 if (ReadFrameBE_EthMAC() == FRAME_IP) // check protocol 00420 if (ReadFrameBE_EthMAC() == IP_HLEN_PLEN) // check HLEN, PLEN 00421 if (ReadFrameBE_EthMAC() == OP_ARP_REQUEST) 00422 { 00423 DummyReadFrame_EthMAC(6); // ignore sender's hardware address 00424 CopyFromFrame_EthMAC(&RecdFrameIP, 4); // read sender's protocol address 00425 DummyReadFrame_EthMAC(6); // ignore target's hardware address 00426 CopyFromFrame_EthMAC(&TargetIP, 4); // read target's protocol address 00427 if (!memcmp(&MyIP, &TargetIP, 4)) // is it for us? 00428 PrepareARP_ANSWER(); // yes->create ARP_ANSWER frame 00429 } 00430 } 00431 00432 // easyWEB internal function 00433 // handles an incoming frame that passed CS8900's address filter 00434 // (individual addressed = IA) 00435 00436 void ProcessEthIAFrame(void) 00437 { 00438 // CodeRed - change from int to short 00439 //unsigned int TargetIP[2]; 00440 unsigned short TargetIP[2]; 00441 unsigned char ProtocolType; 00442 // CodeRed - next few lines not needed for LPC1768 port 00443 /* 00444 // next two words MUST be read with High-Byte 1st (CS8900 AN181 Page 2) 00445 ReadHB1ST_EthMAC(RX_FRAME_PORT); // ignore RxStatus Word 00446 RecdFrameLength = ReadHB1ST_EthMAC(RX_FRAME_PORT);// get real length of frame 00447 00448 DummyReadFrame_EthMAC(6); // ignore DA 00449 CopyFromFrame_EthMAC(&RecdFrameMAC, 6); // store SA (for our answer) 00450 */ 00451 switch (ReadFrameBE_EthMAC()) // get frame type 00452 { 00453 case FRAME_ARP : // check for ARP 00454 { 00455 if ((TCPFlags & (TCP_ACTIVE_OPEN | IP_ADDR_RESOLVED)) == TCP_ACTIVE_OPEN) 00456 if (ReadFrameBE_EthMAC() == HARDW_ETH10) // check for the right prot. etc. 00457 if (ReadFrameBE_EthMAC() == FRAME_IP) 00458 if (ReadFrameBE_EthMAC() == IP_HLEN_PLEN) 00459 if (ReadFrameBE_EthMAC() == OP_ARP_ANSWER) 00460 { 00461 TCPStopTimer(); // OK, now we've the MAC we wanted ;-) 00462 CopyFromFrame_EthMAC(&RemoteMAC, 6); // extract opponents MAC 00463 TCPFlags |= IP_ADDR_RESOLVED; 00464 } 00465 break; 00466 } 00467 case FRAME_IP : // check for IP-type 00468 { 00469 if ((ReadFrameBE_EthMAC() & 0xFF00 ) == IP_VER_IHL) // IPv4, IHL=5 (20 Bytes Header) 00470 { // ignore Type Of Service 00471 RecdIPFrameLength = ReadFrameBE_EthMAC(); // get IP frame's length 00472 ReadFrameBE_EthMAC(); // ignore identification 00473 00474 if (!(ReadFrameBE_EthMAC() & (IP_FLAG_MOREFRAG | IP_FRAGOFS_MASK))) // only unfragm. frames 00475 { 00476 // CodeRed - add mask 00477 // ProtocolType = ReadFrameBE_EthMAC() ; // get protocol, ignore TTL 00478 ProtocolType = ReadFrameBE_EthMAC() & 0xFF ; // get protocol, ignore TTL 00479 ReadFrameBE_EthMAC(); // ignore checksum 00480 CopyFromFrame_EthMAC(&RecdFrameIP, 4); // get source IP 00481 CopyFromFrame_EthMAC(&TargetIP, 4); // get destination IP 00482 00483 if (!memcmp(&MyIP, &TargetIP, 4)) // is it for us? 00484 switch (ProtocolType) { 00485 case PROT_ICMP : { ProcessICMPFrame(); break; } 00486 case PROT_TCP : { ProcessTCPFrame(); break; } 00487 case PROT_UDP : break; // not implemented! 00488 } 00489 } 00490 } 00491 break; 00492 } 00493 } 00494 } 00495 00496 // easyWEB internal function 00497 // we've just rec'd an ICMP-frame (Internet Control Message Protocol) 00498 // check what to do and branch to the appropriate sub-function 00499 00500 void ProcessICMPFrame(void) 00501 { 00502 // CodeRed - change from int to short 00503 //unsigned int ICMPTypeAndCode; 00504 unsigned short ICMPTypeAndCode; 00505 00506 ICMPTypeAndCode = ReadFrameBE_EthMAC(); // get Message Type and Code 00507 ReadFrameBE_EthMAC(); // ignore ICMP checksum 00508 00509 switch (ICMPTypeAndCode >> 8) { // check type 00510 case ICMP_ECHO : // is echo request? 00511 { 00512 PrepareICMP_ECHO_REPLY(); // echo as much as we can... 00513 break; 00514 } 00515 } 00516 } 00517 00518 // easyWEB internal function 00519 // we've just rec'd an TCP-frame (Transmission Control Protocol) 00520 // this function mainly implements the TCP state machine according to RFC793 00521 00522 void ProcessTCPFrame(void) 00523 { 00524 // CodeRed - change from int to short 00525 /* unsigned int TCPSegSourcePort; // segment's source port 00526 unsigned int TCPSegDestPort; // segment's destination port 00527 unsigned long TCPSegSeq; // segment's sequence number 00528 unsigned long TCPSegAck; // segment's acknowledge number 00529 unsigned int TCPCode; // TCP code and header length 00530 unsigned char TCPHeaderSize; // real TCP header length 00531 unsigned int NrOfDataBytes; // real number of data 00532 */ 00533 unsigned short TCPSegSourcePort; // segment's source port 00534 unsigned short TCPSegDestPort; // segment's destination port 00535 unsigned long TCPSegSeq; // segment's sequence number 00536 unsigned long TCPSegAck; // segment's acknowledge number 00537 unsigned short TCPCode; // TCP code and header length 00538 unsigned char TCPHeaderSize; // real TCP header length 00539 unsigned short NrOfDataBytes; // real number of data 00540 00541 00542 TCPSegSourcePort = ReadFrameBE_EthMAC(); // get ports 00543 TCPSegDestPort = ReadFrameBE_EthMAC(); 00544 00545 if (TCPSegDestPort != TCPLocalPort) return; // drop segment if port doesn't match 00546 00547 TCPSegSeq = (unsigned long)ReadFrameBE_EthMAC() << 16; // get segment sequence nr. 00548 TCPSegSeq |= ReadFrameBE_EthMAC(); 00549 00550 TCPSegAck = (unsigned long)ReadFrameBE_EthMAC() << 16; // get segment acknowledge nr. 00551 TCPSegAck |= ReadFrameBE_EthMAC(); 00552 00553 TCPCode = ReadFrameBE_EthMAC(); // get control bits, header length... 00554 00555 TCPHeaderSize = (TCPCode & DATA_OFS_MASK) >> 10; // header length in bytes 00556 NrOfDataBytes = RecdIPFrameLength - IP_HEADER_SIZE - TCPHeaderSize; // seg. text length 00557 00558 if (NrOfDataBytes > MAX_TCP_RX_DATA_SIZE) return; // packet too large for us :...-( 00559 00560 if (TCPHeaderSize > TCP_HEADER_SIZE) // ignore options if any 00561 DummyReadFrame_EthMAC(TCPHeaderSize - TCP_HEADER_SIZE); 00562 00563 switch (TCPStateMachine) // implement the TCP state machine 00564 { 00565 case CLOSED : 00566 { 00567 if (!(TCPCode & TCP_CODE_RST)) 00568 { 00569 TCPRemotePort = TCPSegSourcePort; 00570 memcpy(&RemoteMAC, &RecdFrameMAC, 6); // save opponents MAC and IP 00571 memcpy(&RemoteIP, &RecdFrameIP, 4); // for later use 00572 00573 if (TCPCode & TCP_CODE_ACK) // make the reset sequence 00574 { // acceptable to the other 00575 TCPSeqNr = TCPSegAck; // TCP 00576 PrepareTCP_FRAME(TCP_CODE_RST); 00577 } 00578 else 00579 { 00580 TCPSeqNr = 0; 00581 TCPAckNr = TCPSegSeq + NrOfDataBytes; 00582 if (TCPCode & (TCP_CODE_SYN | TCP_CODE_FIN)) TCPAckNr++; 00583 PrepareTCP_FRAME(TCP_CODE_RST | TCP_CODE_ACK); 00584 } 00585 } 00586 break; 00587 } 00588 case LISTENING : 00589 { 00590 if (!(TCPCode & TCP_CODE_RST)) // ignore segment containing RST 00591 { 00592 TCPRemotePort = TCPSegSourcePort; 00593 memcpy(&RemoteMAC, &RecdFrameMAC, 6); // save opponents MAC and IP 00594 memcpy(&RemoteIP, &RecdFrameIP, 4); // for later use 00595 00596 if (TCPCode & TCP_CODE_ACK) // reset a bad 00597 { // acknowledgement 00598 TCPSeqNr = TCPSegAck; 00599 PrepareTCP_FRAME(TCP_CODE_RST); 00600 } 00601 else if (TCPCode & TCP_CODE_SYN) 00602 { 00603 TCPAckNr = TCPSegSeq + 1; // get remote ISN, next byte we expect 00604 // CodeRed - change TAR -> TOTC to use LPC1768 clock 00605 // TCPSeqNr = ((unsigned long)ISNGenHigh << 16) | TAR; // set local ISN 00606 TCPSeqNr = ((unsigned long)ISNGenHigh << 16) | (LPC_TIM0->TC & 0xFFFF); // set local ISN 00607 TCPUNASeqNr = TCPSeqNr + 1; // one byte out -> increase by one 00608 PrepareTCP_FRAME(TCP_CODE_SYN | TCP_CODE_ACK); 00609 LastFrameSent = TCP_SYN_ACK_FRAME; 00610 TCPStartRetryTimer(); 00611 TCPStateMachine = SYN_RECD; 00612 } 00613 } 00614 break; 00615 } 00616 case SYN_SENT : 00617 { 00618 if (memcmp(&RemoteIP, &RecdFrameIP, 4)) break; // drop segment if its IP doesn't belong 00619 // to current session 00620 00621 if (TCPSegSourcePort != TCPRemotePort) break; // drop segment if port doesn't match 00622 00623 if (TCPCode & TCP_CODE_ACK) // ACK field significant? 00624 if (TCPSegAck != TCPUNASeqNr) // is our ISN ACKed? 00625 { 00626 if (!(TCPCode & TCP_CODE_RST)) 00627 { 00628 TCPSeqNr = TCPSegAck; 00629 PrepareTCP_FRAME(TCP_CODE_RST); 00630 } 00631 break; // drop segment 00632 } 00633 00634 if (TCPCode & TCP_CODE_RST) // RST?? 00635 { 00636 if (TCPCode & TCP_CODE_ACK) // if ACK was acceptable, reset 00637 { // connection 00638 TCPStateMachine = CLOSED; 00639 TCPFlags = 0; // reset all flags, stop retransmission... 00640 SocketStatus = SOCK_ERR_CONN_RESET; 00641 } 00642 break; // drop segment 00643 } 00644 00645 if (TCPCode & TCP_CODE_SYN) // SYN?? 00646 { 00647 TCPAckNr = TCPSegSeq; // get opponents ISN 00648 TCPAckNr++; // inc. by one... 00649 00650 if (TCPCode & TCP_CODE_ACK) 00651 { 00652 TCPStopTimer(); // stop retransmission, other TCP got our SYN 00653 TCPSeqNr = TCPUNASeqNr; // advance our sequence number 00654 00655 PrepareTCP_FRAME(TCP_CODE_ACK); // ACK this ISN 00656 TCPStateMachine = ESTABLISHED; 00657 SocketStatus |= SOCK_CONNECTED; 00658 SocketStatus |= SOCK_TX_BUF_RELEASED; // user may send data now :-) 00659 } 00660 else 00661 { 00662 TCPStopTimer(); 00663 PrepareTCP_FRAME(TCP_CODE_SYN | TCP_CODE_ACK); // our SYN isn't ACKed yet, 00664 LastFrameSent = TCP_SYN_ACK_FRAME; // now continue with sending 00665 TCPStartRetryTimer(); // SYN_ACK frames 00666 TCPStateMachine = SYN_RECD; 00667 } 00668 } 00669 break; 00670 } 00671 default : 00672 { 00673 if (memcmp(&RemoteIP, &RecdFrameIP, 4)) break; // drop segment if IP doesn't belong 00674 // to current session 00675 00676 if (TCPSegSourcePort != TCPRemotePort) break; // drop segment if port doesn't match 00677 00678 if (TCPSegSeq != TCPAckNr) break; // drop if it's not the segment we expect 00679 00680 if (TCPCode & TCP_CODE_RST) // RST?? 00681 { 00682 TCPStateMachine = CLOSED; // close the state machine 00683 TCPFlags = 0; // reset all flags, stop retransmission... 00684 SocketStatus = SOCK_ERR_CONN_RESET; // indicate an error to user 00685 break; 00686 } 00687 00688 if (TCPCode & TCP_CODE_SYN) // SYN?? 00689 { 00690 PrepareTCP_FRAME(TCP_CODE_RST); // is NOT allowed here! send a reset, 00691 TCPStateMachine = CLOSED; // close connection... 00692 TCPFlags = 0; // reset all flags, stop retransmission... 00693 SocketStatus = SOCK_ERR_REMOTE; // fatal error! 00694 break; // ...and drop the frame 00695 } 00696 00697 if (!(TCPCode & TCP_CODE_ACK)) break; // drop segment if the ACK bit is off 00698 00699 if (TCPSegAck == TCPUNASeqNr) // is our last data sent ACKed? 00700 { 00701 TCPStopTimer(); // stop retransmission 00702 TCPSeqNr = TCPUNASeqNr; // advance our sequence number 00703 00704 switch (TCPStateMachine) // change state if necessary 00705 { 00706 case SYN_RECD : // ACK of our SYN? 00707 { 00708 TCPStateMachine = ESTABLISHED; // user may send data now :-) 00709 SocketStatus |= SOCK_CONNECTED; 00710 break; 00711 } 00712 case FIN_WAIT_1 : { TCPStateMachine = FIN_WAIT_2; break; } // ACK of our FIN? 00713 case CLOSING : { TCPStateMachine = TIME_WAIT; break; } // ACK of our FIN? 00714 case LAST_ACK : // ACK of our FIN? 00715 { 00716 TCPStateMachine = CLOSED; 00717 TCPFlags = 0; // reset all flags, stop retransmission... 00718 SocketStatus &= SOCK_DATA_AVAILABLE; // clear all flags but data available 00719 break; 00720 } 00721 case TIME_WAIT : 00722 { 00723 PrepareTCP_FRAME(TCP_CODE_ACK); // ACK a retransmission of remote FIN 00724 TCPRestartTimer(); // restart TIME_WAIT timeout 00725 break; 00726 } 00727 } 00728 00729 if (TCPStateMachine == ESTABLISHED) // if true, give the frame buffer back 00730 SocketStatus |= SOCK_TX_BUF_RELEASED; // to user 00731 } 00732 00733 if ((TCPStateMachine == ESTABLISHED) || (TCPStateMachine == FIN_WAIT_1) || (TCPStateMachine == FIN_WAIT_2)) 00734 if (NrOfDataBytes) // data available? 00735 if (!(SocketStatus & SOCK_DATA_AVAILABLE)) // rx data-buffer empty? 00736 { 00737 DummyReadFrame_EthMAC(6); // ignore window, checksum, urgent pointer 00738 // CodeRed - removed unrequired & 00739 // CopyFromFrame_EthMAC(&RxTCPBuffer, NrOfDataBytes);// fetch data and 00740 CopyFromFrame_EthMAC(RxTCPBuffer, NrOfDataBytes);// fetch data and 00741 00742 TCPRxDataCount = NrOfDataBytes; // ...tell the user... 00743 SocketStatus |= SOCK_DATA_AVAILABLE; // indicate the new data to user 00744 TCPAckNr += NrOfDataBytes; 00745 PrepareTCP_FRAME(TCP_CODE_ACK); // ACK rec'd data 00746 } 00747 00748 if (TCPCode & TCP_CODE_FIN) // FIN?? 00749 { 00750 switch (TCPStateMachine) 00751 { 00752 case SYN_RECD : 00753 case ESTABLISHED : 00754 { 00755 TCPStateMachine = CLOSE_WAIT; 00756 break; 00757 } 00758 case FIN_WAIT_1 : 00759 { // if our FIN was ACKed, we automatically 00760 TCPStateMachine = CLOSING; // enter FIN_WAIT_2 (look above) and therefore 00761 SocketStatus &= ~SOCK_CONNECTED; // TIME_WAIT 00762 break; 00763 } 00764 case FIN_WAIT_2 : 00765 { 00766 TCPStartTimeWaitTimer(); 00767 TCPStateMachine = TIME_WAIT; 00768 SocketStatus &= ~SOCK_CONNECTED; 00769 break; 00770 } 00771 case TIME_WAIT : 00772 { 00773 TCPRestartTimer(); 00774 break; 00775 } 00776 } 00777 TCPAckNr++; // ACK remote's FIN flag 00778 PrepareTCP_FRAME(TCP_CODE_ACK); 00779 } 00780 } 00781 } 00782 } 00783 00784 // easyWEB internal function 00785 // prepares the TxFrame2-buffer to send an ARP-request 00786 00787 void PrepareARP_REQUEST(void) 00788 { 00789 // Ethernet 00790 00791 // CodeRed - added char cast 00792 // memset(&TxFrame2[ETH_DA_OFS], 0xFF, 6); 00793 memset(&TxFrame2[ETH_DA_OFS], (char)0xFF, 6); // we don't know opposites MAC! 00794 memcpy(&TxFrame2[ETH_SA_OFS], &MyMAC, 6); 00795 // Code Red - int-> short 00796 // *(unsigned int *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_ARP); 00797 *(unsigned short *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_ARP); 00798 00799 // ARP 00800 00801 // CodeRed - int-> short 00802 /* *(unsigned int *)&TxFrame2[ARP_HARDW_OFS] = SWAPB(HARDW_ETH10); 00803 *(unsigned int *)&TxFrame2[ARP_PROT_OFS] = SWAPB(FRAME_IP); 00804 *(unsigned int *)&TxFrame2[ARP_HLEN_PLEN_OFS] = SWAPB(IP_HLEN_PLEN); 00805 *(unsigned int *)&TxFrame2[ARP_OPCODE_OFS] = SWAPB(OP_ARP_REQUEST); 00806 */ 00807 *(unsigned short *)&TxFrame2[ARP_HARDW_OFS] = SWAPB(HARDW_ETH10); 00808 *(unsigned short *)&TxFrame2[ARP_PROT_OFS] = SWAPB(FRAME_IP); 00809 *(unsigned short *)&TxFrame2[ARP_HLEN_PLEN_OFS] = SWAPB(IP_HLEN_PLEN); 00810 *(unsigned short *)&TxFrame2[ARP_OPCODE_OFS] = SWAPB(OP_ARP_REQUEST); 00811 00812 memcpy(&TxFrame2[ARP_SENDER_HA_OFS], &MyMAC, 6); 00813 memcpy(&TxFrame2[ARP_SENDER_IP_OFS], &MyIP, 4); 00814 memset(&TxFrame2[ARP_TARGET_HA_OFS], 0x00, 6); // we don't know opposites MAC! 00815 00816 if (((RemoteIP[0] ^ MyIP[0]) & SubnetMask[0]) || ((RemoteIP[1] ^ MyIP[1]) & SubnetMask[1])) 00817 memcpy(&TxFrame2[ARP_TARGET_IP_OFS], &GatewayIP, 4); // IP not in subnet, use gateway 00818 else 00819 memcpy(&TxFrame2[ARP_TARGET_IP_OFS], &RemoteIP, 4); // other IP is next to us... 00820 00821 TxFrame2Size = ETH_HEADER_SIZE + ARP_FRAME_SIZE; 00822 TransmitControl |= SEND_FRAME2; 00823 } 00824 00825 // easyWEB internal function 00826 // prepares the TxFrame2-buffer to send an ARP-answer (reply) 00827 00828 void PrepareARP_ANSWER(void) 00829 { 00830 // Ethernet 00831 memcpy(&TxFrame2[ETH_DA_OFS], &RecdFrameMAC, 6); 00832 memcpy(&TxFrame2[ETH_SA_OFS], &MyMAC, 6); 00833 // CodeRed - int-> short 00834 // *(unsigned int *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_ARP); 00835 *(unsigned short *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_ARP); 00836 00837 // ARP 00838 00839 // CodeRed - int-> short 00840 /* *(unsigned int *)&TxFrame2[ARP_HARDW_OFS] = SWAPB(HARDW_ETH10); 00841 *(unsigned int *)&TxFrame2[ARP_PROT_OFS] = SWAPB(FRAME_IP); 00842 *(unsigned int *)&TxFrame2[ARP_HLEN_PLEN_OFS] = SWAPB(IP_HLEN_PLEN); 00843 *(unsigned int *)&TxFrame2[ARP_OPCODE_OFS] = SWAPB(OP_ARP_ANSWER); 00844 */ 00845 *(unsigned short *)&TxFrame2[ARP_HARDW_OFS] = SWAPB(HARDW_ETH10); 00846 *(unsigned short *)&TxFrame2[ARP_PROT_OFS] = SWAPB(FRAME_IP); 00847 *(unsigned short *)&TxFrame2[ARP_HLEN_PLEN_OFS] = SWAPB(IP_HLEN_PLEN); 00848 *(unsigned short *)&TxFrame2[ARP_OPCODE_OFS] = SWAPB(OP_ARP_ANSWER); 00849 memcpy(&TxFrame2[ARP_SENDER_HA_OFS], &MyMAC, 6); 00850 memcpy(&TxFrame2[ARP_SENDER_IP_OFS], &MyIP, 4); 00851 memcpy(&TxFrame2[ARP_TARGET_HA_OFS], &RecdFrameMAC, 6); 00852 memcpy(&TxFrame2[ARP_TARGET_IP_OFS], &RecdFrameIP, 4); 00853 00854 TxFrame2Size = ETH_HEADER_SIZE + ARP_FRAME_SIZE; 00855 TransmitControl |= SEND_FRAME2; 00856 } 00857 00858 // easyWEB internal function 00859 // prepares the TxFrame2-buffer to send an ICMP-echo-reply 00860 00861 void PrepareICMP_ECHO_REPLY(void) 00862 { 00863 // CodeRed - int-> short 00864 // unsigned int ICMPDataCount; 00865 unsigned short ICMPDataCount; 00866 00867 if (RecdIPFrameLength > MAX_ETH_TX_DATA_SIZE) // don't overload TX-buffer 00868 ICMPDataCount = MAX_ETH_TX_DATA_SIZE - IP_HEADER_SIZE - ICMP_HEADER_SIZE; 00869 else 00870 ICMPDataCount = RecdIPFrameLength - IP_HEADER_SIZE - ICMP_HEADER_SIZE; 00871 00872 // Ethernet 00873 memcpy(&TxFrame2[ETH_DA_OFS], &RecdFrameMAC, 6); 00874 memcpy(&TxFrame2[ETH_SA_OFS], &MyMAC, 6); 00875 00876 // CodeRed - int-> short 00877 // *(unsigned int *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_IP); 00878 *(unsigned short *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_IP); 00879 00880 // IP 00881 00882 // CodeRed - int-> short 00883 /* *(unsigned int *)&TxFrame2[IP_VER_IHL_TOS_OFS] = SWAPB(IP_VER_IHL); 00884 WriteWBE(&TxFrame2[IP_TOTAL_LENGTH_OFS], IP_HEADER_SIZE + ICMP_HEADER_SIZE + ICMPDataCount); 00885 *(unsigned int *)&TxFrame2[IP_IDENT_OFS] = 0; 00886 *(unsigned int *)&TxFrame2[IP_FLAGS_FRAG_OFS] = 0; 00887 *(unsigned int *)&TxFrame2[IP_TTL_PROT_OFS] = SWAPB((DEFAULT_TTL << 8) | PROT_ICMP); 00888 *(unsigned int *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = 0; 00889 memcpy(&TxFrame2[IP_SOURCE_OFS], &MyIP, 4); 00890 memcpy(&TxFrame2[IP_DESTINATION_OFS], &RecdFrameIP, 4); 00891 *(unsigned int *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = CalcChecksum(&TxFrame2[IP_VER_IHL_TOS_OFS], IP_HEADER_SIZE, 0); 00892 */ 00893 *(unsigned short *)&TxFrame2[IP_VER_IHL_TOS_OFS] = SWAPB(IP_VER_IHL); 00894 WriteWBE(&TxFrame2[IP_TOTAL_LENGTH_OFS], IP_HEADER_SIZE + ICMP_HEADER_SIZE + ICMPDataCount); 00895 *(unsigned short *)&TxFrame2[IP_IDENT_OFS] = 0; 00896 *(unsigned short *)&TxFrame2[IP_FLAGS_FRAG_OFS] = 0; 00897 *(unsigned short *)&TxFrame2[IP_TTL_PROT_OFS] = SWAPB((DEFAULT_TTL << 8) | PROT_ICMP); 00898 *(unsigned short *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = 0; 00899 memcpy(&TxFrame2[IP_SOURCE_OFS], &MyIP, 4); 00900 memcpy(&TxFrame2[IP_DESTINATION_OFS], &RecdFrameIP, 4); 00901 *(unsigned short *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = CalcChecksum(&TxFrame2[IP_VER_IHL_TOS_OFS], IP_HEADER_SIZE, 0); 00902 00903 // ICMP 00904 00905 // CodeRed - int-> short 00906 /* *(unsigned int *)&TxFrame2[ICMP_TYPE_CODE_OFS] = SWAPB(ICMP_ECHO_REPLY << 8); 00907 *(unsigned int *)&TxFrame2[ICMP_CHKSUM_OFS] = 0; // initialize checksum field 00908 00909 CopyFromFrame8900(&TxFrame2[ICMP_DATA_OFS], ICMPDataCount); // get data to echo... 00910 *(unsigned int *)&TxFrame2[ICMP_CHKSUM_OFS] = CalcChecksum(&TxFrame2[IP_DATA_OFS], ICMPDataCount + ICMP_HEADER_SIZE, 0); 00911 */ 00912 *(unsigned short *)&TxFrame2[ICMP_TYPE_CODE_OFS] = SWAPB(ICMP_ECHO_REPLY << 8); 00913 *(unsigned short *)&TxFrame2[ICMP_CHKSUM_OFS] = 0; // initialize checksum field 00914 00915 CopyFromFrame_EthMAC(&TxFrame2[ICMP_DATA_OFS], ICMPDataCount); // get data to echo... 00916 *(unsigned short *)&TxFrame2[ICMP_CHKSUM_OFS] = CalcChecksum(&TxFrame2[IP_DATA_OFS], ICMPDataCount + ICMP_HEADER_SIZE, 0); 00917 00918 00919 // ICMP 00920 00921 // Code Red - int-> short 00922 /* *(unsigned int *)&TxFrame2[ICMP_TYPE_CODE_OFS] = SWAPB(ICMP_ECHO_REPLY << 8); 00923 *(unsigned int *)&TxFrame2[ICMP_CHKSUM_OFS] = 0; // initialize checksum field 00924 00925 CopyFromFrame8900(&TxFrame2[ICMP_DATA_OFS], ICMPDataCount); // get data to echo... 00926 *(unsigned int *)&TxFrame2[ICMP_CHKSUM_OFS] = CalcChecksum(&TxFrame2[IP_DATA_OFS], ICMPDataCount + ICMP_HEADER_SIZE, 0); 00927 */ 00928 *(unsigned short *)&TxFrame2[ICMP_TYPE_CODE_OFS] = SWAPB(ICMP_ECHO_REPLY << 8); 00929 *(unsigned short *)&TxFrame2[ICMP_CHKSUM_OFS] = 0; // initialize checksum field 00930 00931 CopyFromFrame_EthMAC(&TxFrame2[ICMP_DATA_OFS], ICMPDataCount); // get data to echo... 00932 *(unsigned short *)&TxFrame2[ICMP_CHKSUM_OFS] = CalcChecksum(&TxFrame2[IP_DATA_OFS], ICMPDataCount + ICMP_HEADER_SIZE, 0); 00933 00934 00935 TxFrame2Size = ETH_HEADER_SIZE + IP_HEADER_SIZE + ICMP_HEADER_SIZE + ICMPDataCount; 00936 TransmitControl |= SEND_FRAME2; 00937 } 00938 00939 // easyWEB internal function 00940 // prepares the TxFrame2-buffer to send a general TCP frame 00941 // the TCPCode-field is passed as an argument 00942 00943 // CodeRed - int-> short 00944 //void PrepareTCP_FRAME(unsigned int TCPCode) 00945 void PrepareTCP_FRAME(unsigned short TCPCode) 00946 { 00947 // Ethernet 00948 memcpy(&TxFrame2[ETH_DA_OFS], &RemoteMAC, 6); 00949 memcpy(&TxFrame2[ETH_SA_OFS], &MyMAC, 6); 00950 00951 // CodeRed - int-> short 00952 // *(unsigned int *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_IP); 00953 *(unsigned short *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_IP); 00954 00955 // IP 00956 00957 // Code Red - int-> short 00958 /* *(unsigned int *)&TxFrame2[IP_VER_IHL_TOS_OFS] = SWAPB(IP_VER_IHL | IP_TOS_D); 00959 00960 if (TCPCode & TCP_CODE_SYN) // if SYN, we want to use the MSS option 00961 *(unsigned int *)&TxFrame2[IP_TOTAL_LENGTH_OFS] = SWAPB(IP_HEADER_SIZE + TCP_HEADER_SIZE + TCP_OPT_MSS_SIZE); 00962 else 00963 *(unsigned int *)&TxFrame2[IP_TOTAL_LENGTH_OFS] = SWAPB(IP_HEADER_SIZE + TCP_HEADER_SIZE); 00964 00965 *(unsigned int *)&TxFrame2[IP_IDENT_OFS] = 0; 00966 *(unsigned int *)&TxFrame2[IP_FLAGS_FRAG_OFS] = 0; 00967 *(unsigned int *)&TxFrame2[IP_TTL_PROT_OFS] = SWAPB((DEFAULT_TTL << 8) | PROT_TCP); 00968 *(unsigned int *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = 0; 00969 memcpy(&TxFrame2[IP_SOURCE_OFS], &MyIP, 4); 00970 memcpy(&TxFrame2[IP_DESTINATION_OFS], &RemoteIP, 4); 00971 *(unsigned int *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = CalcChecksum(&TxFrame2[IP_VER_IHL_TOS_OFS], IP_HEADER_SIZE, 0); 00972 */ 00973 *(unsigned short *)&TxFrame2[IP_VER_IHL_TOS_OFS] = SWAPB(IP_VER_IHL | IP_TOS_D); 00974 00975 if (TCPCode & TCP_CODE_SYN) // if SYN, we want to use the MSS option 00976 *(unsigned short *)&TxFrame2[IP_TOTAL_LENGTH_OFS] = SWAPB(IP_HEADER_SIZE + TCP_HEADER_SIZE + TCP_OPT_MSS_SIZE); 00977 else 00978 *(unsigned short *)&TxFrame2[IP_TOTAL_LENGTH_OFS] = SWAPB(IP_HEADER_SIZE + TCP_HEADER_SIZE); 00979 00980 *(unsigned short *)&TxFrame2[IP_IDENT_OFS] = 0; 00981 *(unsigned short *)&TxFrame2[IP_FLAGS_FRAG_OFS] = 0; 00982 *(unsigned short *)&TxFrame2[IP_TTL_PROT_OFS] = SWAPB((DEFAULT_TTL << 8) | PROT_TCP); 00983 *(unsigned short *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = 0; 00984 memcpy(&TxFrame2[IP_SOURCE_OFS], &MyIP, 4); 00985 memcpy(&TxFrame2[IP_DESTINATION_OFS], &RemoteIP, 4); 00986 *(unsigned short *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = CalcChecksum(&TxFrame2[IP_VER_IHL_TOS_OFS], IP_HEADER_SIZE, 0); 00987 00988 // TCP 00989 WriteWBE(&TxFrame2[TCP_SRCPORT_OFS], TCPLocalPort); 00990 WriteWBE(&TxFrame2[TCP_DESTPORT_OFS], TCPRemotePort); 00991 00992 WriteDWBE(&TxFrame2[TCP_SEQNR_OFS], TCPSeqNr); 00993 WriteDWBE(&TxFrame2[TCP_ACKNR_OFS], TCPAckNr); 00994 00995 // CodeRed - int-> short 00996 /* *(unsigned int *)&TxFrame2[TCP_WINDOW_OFS] = SWAPB(MAX_TCP_RX_DATA_SIZE); // data bytes to accept 00997 *(unsigned int *)&TxFrame2[TCP_CHKSUM_OFS] = 0; // initalize checksum 00998 *(unsigned int *)&TxFrame2[TCP_URGENT_OFS] = 0; 00999 01000 if (TCPCode & TCP_CODE_SYN) // if SYN, we want to use the MSS option 01001 { 01002 *(unsigned int *)&TxFrame2[TCP_DATA_CODE_OFS] = SWAPB(0x6000 | TCPCode); // TCP header length = 24 01003 *(unsigned int *)&TxFrame2[TCP_DATA_OFS] = SWAPB(TCP_OPT_MSS); // MSS option 01004 *(unsigned int *)&TxFrame2[TCP_DATA_OFS + 2] = SWAPB(MAX_TCP_RX_DATA_SIZE);// max. length of TCP-data we accept 01005 *(unsigned int *)&TxFrame2[TCP_CHKSUM_OFS] = CalcChecksum(&TxFrame2[TCP_SRCPORT_OFS], TCP_HEADER_SIZE + TCP_OPT_MSS_SIZE, 1); 01006 TxFrame2Size = ETH_HEADER_SIZE + IP_HEADER_SIZE + TCP_HEADER_SIZE + TCP_OPT_MSS_SIZE; 01007 } 01008 else 01009 { 01010 *(unsigned int *)&TxFrame2[TCP_DATA_CODE_OFS] = SWAPB(0x5000 | TCPCode); // TCP header length = 20 01011 *(unsigned int *)&TxFrame2[TCP_CHKSUM_OFS] = CalcChecksum(&TxFrame2[TCP_SRCPORT_OFS], TCP_HEADER_SIZE, 1); 01012 TxFrame2Size = ETH_HEADER_SIZE + IP_HEADER_SIZE + TCP_HEADER_SIZE; 01013 } 01014 */ 01015 *(unsigned short *)&TxFrame2[TCP_WINDOW_OFS] = SWAPB(MAX_TCP_RX_DATA_SIZE); // data bytes to accept 01016 *(unsigned short *)&TxFrame2[TCP_CHKSUM_OFS] = 0; // initalize checksum 01017 *(unsigned short *)&TxFrame2[TCP_URGENT_OFS] = 0; 01018 01019 if (TCPCode & TCP_CODE_SYN) // if SYN, we want to use the MSS option 01020 { 01021 *(unsigned short *)&TxFrame2[TCP_DATA_CODE_OFS] = SWAPB(0x6000 | TCPCode); // TCP header length = 24 01022 *(unsigned short *)&TxFrame2[TCP_DATA_OFS] = SWAPB(TCP_OPT_MSS); // MSS option 01023 *(unsigned short *)&TxFrame2[TCP_DATA_OFS + 2] = SWAPB(MAX_TCP_RX_DATA_SIZE);// max. length of TCP-data we accept 01024 *(unsigned short *)&TxFrame2[TCP_CHKSUM_OFS] = CalcChecksum(&TxFrame2[TCP_SRCPORT_OFS], TCP_HEADER_SIZE + TCP_OPT_MSS_SIZE, 1); 01025 TxFrame2Size = ETH_HEADER_SIZE + IP_HEADER_SIZE + TCP_HEADER_SIZE + TCP_OPT_MSS_SIZE; 01026 } 01027 else 01028 { 01029 *(unsigned short *)&TxFrame2[TCP_DATA_CODE_OFS] = SWAPB(0x5000 | TCPCode); // TCP header length = 20 01030 *(unsigned short *)&TxFrame2[TCP_CHKSUM_OFS] = CalcChecksum(&TxFrame2[TCP_SRCPORT_OFS], TCP_HEADER_SIZE, 1); 01031 TxFrame2Size = ETH_HEADER_SIZE + IP_HEADER_SIZE + TCP_HEADER_SIZE; 01032 } 01033 TransmitControl |= SEND_FRAME2; 01034 } 01035 01036 // easyWEB internal function 01037 // prepares the TxFrame1-buffer to send a payload-packet 01038 01039 void PrepareTCP_DATA_FRAME(void) 01040 { 01041 // Ethernet 01042 memcpy(&TxFrame1[ETH_DA_OFS], &RemoteMAC, 6); 01043 memcpy(&TxFrame1[ETH_SA_OFS], &MyMAC, 6); 01044 // Code Red - int-> short 01045 // *(unsigned int *)&TxFrame1[ETH_TYPE_OFS] = SWAPB(FRAME_IP); 01046 *(unsigned short *)&TxFrame1[ETH_TYPE_OFS] = SWAPB(FRAME_IP); 01047 01048 // IP 01049 01050 // CodeRed - int-> short 01051 /* *(unsigned int *)&TxFrame1[IP_VER_IHL_TOS_OFS] = SWAPB(IP_VER_IHL | IP_TOS_D); 01052 WriteWBE(&TxFrame1[IP_TOTAL_LENGTH_OFS], IP_HEADER_SIZE + TCP_HEADER_SIZE + TCPTxDataCount); 01053 *(unsigned int *)&TxFrame1[IP_IDENT_OFS] = 0; 01054 *(unsigned int *)&TxFrame1[IP_FLAGS_FRAG_OFS] = 0; 01055 *(unsigned int *)&TxFrame1[IP_TTL_PROT_OFS] = SWAPB((DEFAULT_TTL << 8) | PROT_TCP); 01056 *(unsigned int *)&TxFrame1[IP_HEAD_CHKSUM_OFS] = 0; 01057 memcpy(&TxFrame1[IP_SOURCE_OFS], &MyIP, 4); 01058 memcpy(&TxFrame1[IP_DESTINATION_OFS], &RemoteIP, 4); 01059 *(unsigned int *)&TxFrame1[IP_HEAD_CHKSUM_OFS] = CalcChecksum(&TxFrame1[IP_VER_IHL_TOS_OFS], IP_HEADER_SIZE, 0); 01060 */ 01061 *(unsigned short *)&TxFrame1[IP_VER_IHL_TOS_OFS] = SWAPB(IP_VER_IHL | IP_TOS_D); 01062 WriteWBE(&TxFrame1[IP_TOTAL_LENGTH_OFS], IP_HEADER_SIZE + TCP_HEADER_SIZE + TCPTxDataCount); 01063 *(unsigned short *)&TxFrame1[IP_IDENT_OFS] = 0; 01064 *(unsigned short *)&TxFrame1[IP_FLAGS_FRAG_OFS] = 0; 01065 *(unsigned short *)&TxFrame1[IP_TTL_PROT_OFS] = SWAPB((DEFAULT_TTL << 8) | PROT_TCP); 01066 *(unsigned short *)&TxFrame1[IP_HEAD_CHKSUM_OFS] = 0; 01067 memcpy(&TxFrame1[IP_SOURCE_OFS], &MyIP, 4); 01068 memcpy(&TxFrame1[IP_DESTINATION_OFS], &RemoteIP, 4); 01069 *(unsigned short *)&TxFrame1[IP_HEAD_CHKSUM_OFS] = CalcChecksum(&TxFrame1[IP_VER_IHL_TOS_OFS], IP_HEADER_SIZE, 0); 01070 01071 01072 // TCP 01073 WriteWBE(&TxFrame1[TCP_SRCPORT_OFS], TCPLocalPort); 01074 WriteWBE(&TxFrame1[TCP_DESTPORT_OFS], TCPRemotePort); 01075 01076 WriteDWBE(&TxFrame1[TCP_SEQNR_OFS], TCPSeqNr); 01077 WriteDWBE(&TxFrame1[TCP_ACKNR_OFS], TCPAckNr); 01078 // CodeRed - int-> short 01079 /* *(unsigned int *)&TxFrame1[TCP_DATA_CODE_OFS] = SWAPB(0x5000 | TCP_CODE_ACK); // TCP header length = 20 01080 *(unsigned int *)&TxFrame1[TCP_WINDOW_OFS] = SWAPB(MAX_TCP_RX_DATA_SIZE); // data bytes to accept 01081 *(unsigned int *)&TxFrame1[TCP_CHKSUM_OFS] = 0; 01082 *(unsigned int *)&TxFrame1[TCP_URGENT_OFS] = 0; 01083 *(unsigned int *)&TxFrame1[TCP_CHKSUM_OFS] = CalcChecksum(&TxFrame1[TCP_SRCPORT_OFS], TCP_HEADER_SIZE + TCPTxDataCount, 1); 01084 */ 01085 *(unsigned short *)&TxFrame1[TCP_DATA_CODE_OFS] = SWAPB(0x5000 | TCP_CODE_ACK); // TCP header length = 20 01086 *(unsigned short *)&TxFrame1[TCP_WINDOW_OFS] = SWAPB(MAX_TCP_RX_DATA_SIZE); // data bytes to accept 01087 *(unsigned short *)&TxFrame1[TCP_CHKSUM_OFS] = 0; 01088 *(unsigned short *)&TxFrame1[TCP_URGENT_OFS] = 0; 01089 *(unsigned short *)&TxFrame1[TCP_CHKSUM_OFS] = CalcChecksum(&TxFrame1[TCP_SRCPORT_OFS], TCP_HEADER_SIZE + TCPTxDataCount, 1); 01090 01091 } 01092 01093 // easyWEB internal function 01094 // calculates the TCP/IP checksum. if 'IsTCP != 0', the TCP pseudo-header 01095 // will be included. 01096 01097 // CodeRed - int-> short 01098 //unsigned int CalcChecksum(void *Start, unsigned int Count, unsigned char IsTCP) 01099 unsigned short CalcChecksum(void *Start, unsigned short Count, unsigned char IsTCP) 01100 { 01101 // Code Red - added pStart 01102 unsigned short *pStart; 01103 unsigned long Sum = 0; 01104 01105 if (IsTCP) { // if we've a TCP frame... 01106 Sum += MyIP[0]; // ...include TCP pseudo-header 01107 Sum += MyIP[1]; 01108 Sum += RemoteIP[0]; 01109 Sum += RemoteIP[1]; 01110 Sum += SwapBytes(Count); // TCP header length plus data length 01111 Sum += SWAPB(PROT_TCP); 01112 } 01113 01114 // Code Red - modified to correct expression 01115 /* while (Count > 1) { // sum words 01116 Sum += *((unsigned int *)Start)++; 01117 Count -= 2; 01118 } 01119 01120 if (Count) // add left-over byte, if any 01121 Sum += *(unsigned char *)Start; 01122 */ 01123 01124 pStart = (unsigned short *)Start; 01125 while (Count > 1) { // sum words 01126 Sum += *pStart++; 01127 Count -= 2; 01128 } 01129 01130 if (Count) // add left-over byte, if any 01131 Sum += *(unsigned char *)pStart; 01132 01133 01134 while (Sum >> 16) // fold 32-bit sum to 16 bits 01135 Sum = (Sum & 0xFFFF) + (Sum >> 16); 01136 01137 return ~Sum; 01138 } 01139 01140 // easyWEB internal function 01141 // starts the timer as a retry-timer (used for retransmission-timeout) 01142 01143 void TCPStartRetryTimer(void) 01144 { 01145 TCPTimer = 0; 01146 RetryCounter = MAX_RETRYS; 01147 TCPFlags |= TCP_TIMER_RUNNING; 01148 TCPFlags |= TIMER_TYPE_RETRY; 01149 } 01150 01151 // easyWEB internal function 01152 // starts the timer as a 'TIME_WAIT'-timer (used to finish a TCP-session) 01153 01154 void TCPStartTimeWaitTimer(void) 01155 { 01156 TCPTimer = 0; 01157 TCPFlags |= TCP_TIMER_RUNNING; 01158 TCPFlags &= ~TIMER_TYPE_RETRY; 01159 } 01160 01161 // easyWEB internal function 01162 // restarts the timer 01163 01164 void TCPRestartTimer(void) 01165 { 01166 TCPTimer = 0; 01167 } 01168 01169 // easyWEB internal function 01170 // stopps the timer 01171 01172 void TCPStopTimer(void) 01173 { 01174 TCPFlags &= ~TCP_TIMER_RUNNING; 01175 } 01176 01177 // easyWEB internal function 01178 // if a retransmission-timeout occured, check which packet 01179 // to resend. 01180 01181 void TCPHandleRetransmission(void) 01182 { 01183 switch (LastFrameSent) 01184 { 01185 case ARP_REQUEST : { PrepareARP_REQUEST(); break; } 01186 case TCP_SYN_FRAME : { PrepareTCP_FRAME(TCP_CODE_SYN); break; } 01187 case TCP_SYN_ACK_FRAME : { PrepareTCP_FRAME(TCP_CODE_SYN | TCP_CODE_ACK); break; } 01188 case TCP_FIN_FRAME : { PrepareTCP_FRAME(TCP_CODE_FIN | TCP_CODE_ACK); break; } 01189 case TCP_DATA_FRAME : { TransmitControl |= SEND_FRAME1; break; } 01190 } 01191 } 01192 01193 // easyWEB internal function 01194 // if all retransmissions failed, close connection and indicate an error 01195 01196 void TCPHandleTimeout(void) 01197 { 01198 TCPStateMachine = CLOSED; 01199 01200 if ((TCPFlags & (TCP_ACTIVE_OPEN | IP_ADDR_RESOLVED)) == TCP_ACTIVE_OPEN) 01201 SocketStatus = SOCK_ERR_ARP_TIMEOUT; // indicate an error to user 01202 else 01203 SocketStatus = SOCK_ERR_TCP_TIMEOUT; 01204 01205 TCPFlags = 0; // clear all flags 01206 } 01207 01208 01209 // CodeRed - TCPClockHandler() replaced 01210 /* 01211 // easyWEB internal function 01212 // function executed every 0.262s by the MCU. used for the 01213 // inital sequence number generator (ISN) and the TCP-timer 01214 01215 interrupt [TIMERA1_VECTOR] void TCPClockHandler(void) 01216 { 01217 if (TAIV == 10) // check for timer overflow, reset int.-flag 01218 { 01219 ISNGenHigh++; // upper 16 bits of initial sequence number 01220 TCPTimer++; // timer for retransmissions 01221 } 01222 } 01223 */ 01224 01225 // easyWEB internal function 01226 // function executed every 0.210s by the MCU. used for the 01227 // inital sequence number generator (ISN) and the TCP-timer 01228 01229 void TCPClockHandler(void) 01230 { 01231 ISNGenHigh++; // upper 16 bits of initial sequence number 01232 TCPTimer++; // timer for retransmissions 01233 } 01234 01235 01236 // easyWEB internal function 01237 // transfers the contents of 'TxFrame1'-Buffer to the CS8900A 01238 01239 void SendFrame1(void) 01240 { 01241 // CodeRed - updated for LPC1768 port 01242 // CopyToFrame8900(&TxFrame1, TxFrame1Size); 01243 CopyToFrame_EthMAC(TxFrame1, TxFrame1Size); 01244 } 01245 01246 // easyWEB internal function 01247 // transfers the contents of 'TxFrame2'-Buffer to the CS8900A 01248 01249 void SendFrame2(void) 01250 { 01251 // CodeRed - updated for LPC1768 port 01252 // CopyToFrame8900(&TxFrame2, TxFrame2Size); 01253 CopyToFrame_EthMAC(TxFrame2, TxFrame2Size); 01254 } 01255 01256 // easyWEB internal function 01257 // help function to write a WORD in big-endian byte-order 01258 // to MCU-memory 01259 01260 // CodeRed - int->short 01261 //void WriteWBE(unsigned char *Add, unsigned int Data) 01262 void WriteWBE(unsigned char *Add, unsigned short Data) 01263 { 01264 *Add++ = Data >> 8; 01265 // Code Red - added cast 01266 // *Add = Data; 01267 *Add = (char)Data; 01268 } 01269 01270 // easyWEB internal function 01271 // help function to write a DWORD in big-endian byte-order 01272 // to MCU-memory 01273 01274 void WriteDWBE(unsigned char *Add, unsigned long Data) 01275 { 01276 *Add++ = Data >> 24; 01277 *Add++ = Data >> 16; 01278 *Add++ = Data >> 8; 01279 *Add = Data; 01280 } 01281 01282 // easyWEB internal function 01283 // help function to swap the byte order of a WORD 01284 01285 // CodeRed - int->short 01286 //unsigned int SwapBytes(unsigned int Data) 01287 unsigned short SwapBytes(unsigned short Data) 01288 { 01289 return (Data >> 8) | (Data << 8); 01290 } 01291
Generated on Tue Jul 12 2022 18:57:49 by
1.7.2
