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.
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 22:58:15 by
1.7.2