LPC1768 Mini-DK EasyWeb application with SPI TFT output. Started from EasyWebCR and modified for DM9161 PHY support.

Dependencies:   Mini-DK mbed

This is a very basic EasyWeb application.

No error checking is performed during initialisation.

Information

If the webpage is not reachable or the 'Webserver running' message does not appear, press the reset button on the Mini-DK and wait until the message 'Webserver running' appears.
This happens sometimes when powering up the Mini-DK because the DM9161 reset pin is NOT controlled by the LPC1768, it is directly connected to the reset button.

IP adress/mask/gateway in tcpip.h : 192.168.0.200 / 255.255.255.0 / 192.168.0.1

MAC address in ethmac.h : 6-5-4-3-2-1

Committer:
frankvnk
Date:
Tue Jan 15 06:43:51 2013 +0000
Revision:
8:4c3db9231e3f
Parent:
3:342aa2cf54e8
DM9161_BMSR - bit 13 define modified

Who changed what in which revision?

UserRevisionLine numberNew contents of line
frankvnk 0:636056c0b5e1 1 /******************************************************************
frankvnk 0:636056c0b5e1 2 ***** *****
frankvnk 0:636056c0b5e1 3 ***** Name: tcpip.c *****
frankvnk 0:636056c0b5e1 4 ***** Ver.: 1.0 *****
frankvnk 0:636056c0b5e1 5 ***** Date: 17/12/2012 *****
frankvnk 0:636056c0b5e1 6 ***** Func: implements the TCP/IP-stack and provides a *****
frankvnk 0:636056c0b5e1 7 ***** simple API to the user *****
frankvnk 0:636056c0b5e1 8 ***** Rewrite from Andreas Dannenberg *****
frankvnk 0:636056c0b5e1 9 ***** HTWK Leipzig *****
frankvnk 0:636056c0b5e1 10 ***** university of applied sciences *****
frankvnk 0:636056c0b5e1 11 ***** Germany *****
frankvnk 0:636056c0b5e1 12 ***** adannenb@et.htwk-leipzig.de *****
frankvnk 0:636056c0b5e1 13 ***** *****
frankvnk 0:636056c0b5e1 14 ******************************************************************/
frankvnk 0:636056c0b5e1 15
frankvnk 0:636056c0b5e1 16
frankvnk 0:636056c0b5e1 17 #include "tcpip.h"
frankvnk 0:636056c0b5e1 18 #include "ethmac.h"
frankvnk 0:636056c0b5e1 19 #include "string.h"
frankvnk 0:636056c0b5e1 20 #include "mbed.h"
frankvnk 0:636056c0b5e1 21
frankvnk 0:636056c0b5e1 22 unsigned short MyIP[] = // "MYIP1.MYIP2.MYIP3.MYIP4"
frankvnk 0:636056c0b5e1 23 {
frankvnk 0:636056c0b5e1 24 MYIP_1 + (MYIP_2 << 8),
frankvnk 0:636056c0b5e1 25 MYIP_3 + (MYIP_4 << 8)
frankvnk 0:636056c0b5e1 26 };
frankvnk 0:636056c0b5e1 27
frankvnk 0:636056c0b5e1 28 unsigned short SubnetMask[] = // "SUBMASK1.SUBMASK2.SUBMASK3.SUBMASK4"
frankvnk 0:636056c0b5e1 29 {
frankvnk 0:636056c0b5e1 30 SUBMASK_1 + (SUBMASK_2 << 8),
frankvnk 0:636056c0b5e1 31 SUBMASK_3 + (SUBMASK_4 << 8)
frankvnk 0:636056c0b5e1 32 };
frankvnk 0:636056c0b5e1 33
frankvnk 0:636056c0b5e1 34 unsigned short GatewayIP[] = // "GWIP1.GWIP2.GWIP3.GWIP4"
frankvnk 0:636056c0b5e1 35 {
frankvnk 0:636056c0b5e1 36 GWIP_1 + (GWIP_2 << 8),
frankvnk 0:636056c0b5e1 37 GWIP_3 + (GWIP_4 << 8)
frankvnk 0:636056c0b5e1 38 };
frankvnk 0:636056c0b5e1 39
frankvnk 0:636056c0b5e1 40 // easyWEB's internal variables
frankvnk 0:636056c0b5e1 41 TTCPStateMachine TCPStateMachine; // perhaps the most important var at all ;-)
frankvnk 0:636056c0b5e1 42 TLastFrameSent LastFrameSent; // retransmission type
frankvnk 0:636056c0b5e1 43
frankvnk 0:636056c0b5e1 44 unsigned short ISNGenHigh; // upper word of our Initial Sequence Number
frankvnk 0:636056c0b5e1 45 unsigned long TCPSeqNr; // next sequence number to send
frankvnk 0:636056c0b5e1 46 unsigned long TCPUNASeqNr; // last unaknowledged sequence number
frankvnk 0:636056c0b5e1 47 // incremented AFTER sending data
frankvnk 0:636056c0b5e1 48 unsigned long TCPAckNr; // next seq to receive and ack to send
frankvnk 0:636056c0b5e1 49 // incremented AFTER receiving data
frankvnk 0:636056c0b5e1 50 unsigned char TCPTimer; // inc'd each 262ms
frankvnk 0:636056c0b5e1 51 unsigned char RetryCounter; // nr. of retransmissions
frankvnk 0:636056c0b5e1 52
frankvnk 0:636056c0b5e1 53 // properties of the just received frame
frankvnk 0:636056c0b5e1 54 unsigned short RecdFrameLength; // EMAC reported frame length
frankvnk 0:636056c0b5e1 55 unsigned short RecdFrameMAC[3]; // 48 bit MAC
frankvnk 0:636056c0b5e1 56 unsigned short RecdFrameIP[2]; // 32 bit IP
frankvnk 0:636056c0b5e1 57 unsigned short RecdIPFrameLength; // 16 bit IP packet length
frankvnk 0:636056c0b5e1 58
frankvnk 0:636056c0b5e1 59 // the next 3 buffers must be word-aligned!
frankvnk 0:636056c0b5e1 60 // (here the 'RecdIPFrameLength' above does that)
frankvnk 0:636056c0b5e1 61 unsigned short _TxFrame1[(ETH_HEADER_SIZE + IP_HEADER_SIZE + TCP_HEADER_SIZE + MAX_TCP_TX_DATA_SIZE)/2];
frankvnk 0:636056c0b5e1 62 unsigned short _TxFrame2[(ETH_HEADER_SIZE + MAX_ETH_TX_DATA_SIZE)/2];
frankvnk 0:636056c0b5e1 63 unsigned short _RxTCPBuffer[MAX_TCP_RX_DATA_SIZE/2]; // space for incoming TCP-data
frankvnk 0:636056c0b5e1 64
frankvnk 0:636056c0b5e1 65 unsigned short TxFrame1Size; // bytes to send in TxFrame1
frankvnk 0:636056c0b5e1 66 unsigned char TxFrame2Size; // bytes to send in TxFrame2
frankvnk 0:636056c0b5e1 67
frankvnk 0:636056c0b5e1 68 unsigned char TransmitControl;
frankvnk 0:636056c0b5e1 69 #define SEND_FRAME1 0x01
frankvnk 0:636056c0b5e1 70 #define SEND_FRAME2 0x02
frankvnk 0:636056c0b5e1 71
frankvnk 0:636056c0b5e1 72 unsigned char TCPFlags;
frankvnk 0:636056c0b5e1 73 #define TCP_ACTIVE_OPEN 0x01 // easyWEB shall initiate a connection
frankvnk 0:636056c0b5e1 74 #define IP_ADDR_RESOLVED 0x02 // IP sucessfully resolved to MAC
frankvnk 0:636056c0b5e1 75 #define TCP_TIMER_RUNNING 0x04
frankvnk 0:636056c0b5e1 76 #define TIMER_TYPE_RETRY 0x08
frankvnk 0:636056c0b5e1 77 #define TCP_CLOSE_REQUESTED 0x10
frankvnk 0:636056c0b5e1 78
frankvnk 0:636056c0b5e1 79
frankvnk 0:636056c0b5e1 80 // easyWEB-API global vars and flags
frankvnk 0:636056c0b5e1 81 unsigned short TCPRxDataCount; // nr. of bytes rec'd
frankvnk 0:636056c0b5e1 82 unsigned short TCPTxDataCount; // nr. of bytes to send
frankvnk 0:636056c0b5e1 83
frankvnk 0:636056c0b5e1 84 unsigned short TCPLocalPort; // TCP ports
frankvnk 0:636056c0b5e1 85 unsigned short TCPRemotePort;
frankvnk 0:636056c0b5e1 86
frankvnk 0:636056c0b5e1 87 unsigned short RemoteMAC[3]; // MAC and IP of current TCP-session
frankvnk 0:636056c0b5e1 88 unsigned short RemoteIP[2];
frankvnk 0:636056c0b5e1 89
frankvnk 0:636056c0b5e1 90 unsigned char SocketStatus;
frankvnk 0:636056c0b5e1 91
frankvnk 0:636056c0b5e1 92 void Start_SysTick10ms(void);
frankvnk 0:636056c0b5e1 93
frankvnk 0:636056c0b5e1 94 unsigned char MyMAC[6] = // "M1-M2-M3-M4-M5-M6"
frankvnk 0:636056c0b5e1 95 {
frankvnk 0:636056c0b5e1 96 MYMAC_6, MYMAC_5, MYMAC_4,
frankvnk 0:636056c0b5e1 97 MYMAC_3, MYMAC_2, MYMAC_1
frankvnk 0:636056c0b5e1 98 };
frankvnk 0:636056c0b5e1 99
frankvnk 0:636056c0b5e1 100 // easyWEB-API function
frankvnk 0:636056c0b5e1 101 // initalizes the LAN-controller, reset flags, starts timer-ISR
frankvnk 0:636056c0b5e1 102
frankvnk 0:636056c0b5e1 103 void TCPLowLevelInit(void)
frankvnk 0:636056c0b5e1 104 {
frankvnk 0:636056c0b5e1 105 Start_SysTick10ms(); // Start SysTick timer running (10ms ticks)
frankvnk 0:636056c0b5e1 106 Init_EthMAC();
frankvnk 0:636056c0b5e1 107 TransmitControl = 0;
frankvnk 0:636056c0b5e1 108 TCPFlags = 0;
frankvnk 0:636056c0b5e1 109 TCPStateMachine = CLOSED;
frankvnk 0:636056c0b5e1 110 SocketStatus = 0;
frankvnk 0:636056c0b5e1 111 }
frankvnk 0:636056c0b5e1 112
frankvnk 0:636056c0b5e1 113 // easyWEB-API function
frankvnk 0:636056c0b5e1 114 // does a passive open (listen on 'MyIP:TCPLocalPort' for an incoming
frankvnk 0:636056c0b5e1 115 // connection)
frankvnk 0:636056c0b5e1 116
frankvnk 0:636056c0b5e1 117 void TCPPassiveOpen(void)
frankvnk 0:636056c0b5e1 118 {
frankvnk 0:636056c0b5e1 119 if (TCPStateMachine == CLOSED)
frankvnk 0:636056c0b5e1 120 {
frankvnk 0:636056c0b5e1 121 TCPFlags &= ~TCP_ACTIVE_OPEN; // let's do a passive open!
frankvnk 0:636056c0b5e1 122 TCPStateMachine = LISTENING;
frankvnk 0:636056c0b5e1 123 SocketStatus = SOCK_ACTIVE; // reset, socket now active
frankvnk 0:636056c0b5e1 124 }
frankvnk 0:636056c0b5e1 125 }
frankvnk 0:636056c0b5e1 126
frankvnk 0:636056c0b5e1 127 // easyWEB-API function
frankvnk 0:636056c0b5e1 128 // does an active open (tries to establish a connection between
frankvnk 0:636056c0b5e1 129 // 'MyIP:TCPLocalPort' and 'RemoteIP:TCPRemotePort')
frankvnk 0:636056c0b5e1 130
frankvnk 0:636056c0b5e1 131 void TCPActiveOpen(void)
frankvnk 0:636056c0b5e1 132 {
frankvnk 0:636056c0b5e1 133 if ((TCPStateMachine == CLOSED) || (TCPStateMachine == LISTENING))
frankvnk 0:636056c0b5e1 134 {
frankvnk 0:636056c0b5e1 135 TCPFlags |= TCP_ACTIVE_OPEN; // let's do an active open!
frankvnk 0:636056c0b5e1 136 TCPFlags &= ~IP_ADDR_RESOLVED; // we haven't opponents MAC yet
frankvnk 0:636056c0b5e1 137
frankvnk 0:636056c0b5e1 138 PrepareARP_REQUEST(); // ask for MAC by sending a broadcast
frankvnk 0:636056c0b5e1 139 LastFrameSent = ARP_REQUEST;
frankvnk 0:636056c0b5e1 140 TCPStartRetryTimer();
frankvnk 0:636056c0b5e1 141 SocketStatus = SOCK_ACTIVE; // reset, socket now active
frankvnk 0:636056c0b5e1 142 }
frankvnk 0:636056c0b5e1 143 }
frankvnk 0:636056c0b5e1 144
frankvnk 0:636056c0b5e1 145 // easyWEB-API function
frankvnk 0:636056c0b5e1 146 // closes an open connection
frankvnk 0:636056c0b5e1 147
frankvnk 0:636056c0b5e1 148 void TCPClose(void)
frankvnk 0:636056c0b5e1 149 {
frankvnk 0:636056c0b5e1 150 switch (TCPStateMachine)
frankvnk 0:636056c0b5e1 151 {
frankvnk 0:636056c0b5e1 152 case LISTENING :
frankvnk 0:636056c0b5e1 153 case SYN_SENT :
frankvnk 0:636056c0b5e1 154 {
frankvnk 0:636056c0b5e1 155 TCPStateMachine = CLOSED;
frankvnk 0:636056c0b5e1 156 TCPFlags = 0;
frankvnk 0:636056c0b5e1 157 SocketStatus = 0;
frankvnk 0:636056c0b5e1 158 break;
frankvnk 0:636056c0b5e1 159 }
frankvnk 0:636056c0b5e1 160 case SYN_RECD :
frankvnk 0:636056c0b5e1 161 case ESTABLISHED :
frankvnk 0:636056c0b5e1 162 {
frankvnk 0:636056c0b5e1 163 TCPFlags |= TCP_CLOSE_REQUESTED;
frankvnk 0:636056c0b5e1 164 break;
frankvnk 0:636056c0b5e1 165 }
frankvnk 0:636056c0b5e1 166 }
frankvnk 0:636056c0b5e1 167 }
frankvnk 0:636056c0b5e1 168
frankvnk 0:636056c0b5e1 169 // easyWEB-API function
frankvnk 0:636056c0b5e1 170 // releases the receive-buffer and allows easyWEB to store new data
frankvnk 0:636056c0b5e1 171 // NOTE: rx-buffer MUST be released periodically, else the other TCP
frankvnk 0:636056c0b5e1 172 // get no ACKs for the data it sent
frankvnk 0:636056c0b5e1 173
frankvnk 0:636056c0b5e1 174 void TCPReleaseRxBuffer(void)
frankvnk 0:636056c0b5e1 175 {
frankvnk 0:636056c0b5e1 176 SocketStatus &= ~SOCK_DATA_AVAILABLE;
frankvnk 0:636056c0b5e1 177 }
frankvnk 0:636056c0b5e1 178
frankvnk 0:636056c0b5e1 179 // easyWEB-API function
frankvnk 0:636056c0b5e1 180 // transmitts data stored in 'TCP_TX_BUF'
frankvnk 0:636056c0b5e1 181 // NOTE: * number of bytes to transmit must have been written to 'TCPTxDataCount'
frankvnk 0:636056c0b5e1 182 // * data-count MUST NOT exceed 'MAX_TCP_TX_DATA_SIZE'
frankvnk 0:636056c0b5e1 183
frankvnk 0:636056c0b5e1 184 void TCPTransmitTxBuffer(void)
frankvnk 0:636056c0b5e1 185 {
frankvnk 0:636056c0b5e1 186 if ((TCPStateMachine == ESTABLISHED) || (TCPStateMachine == CLOSE_WAIT))
frankvnk 0:636056c0b5e1 187 if (SocketStatus & SOCK_TX_BUF_RELEASED)
frankvnk 0:636056c0b5e1 188 {
frankvnk 0:636056c0b5e1 189 SocketStatus &= ~SOCK_TX_BUF_RELEASED; // occupy tx-buffer
frankvnk 0:636056c0b5e1 190 TCPUNASeqNr += TCPTxDataCount; // advance UNA
frankvnk 0:636056c0b5e1 191
frankvnk 0:636056c0b5e1 192 TxFrame1Size = ETH_HEADER_SIZE + IP_HEADER_SIZE + TCP_HEADER_SIZE + TCPTxDataCount;
frankvnk 0:636056c0b5e1 193 TransmitControl |= SEND_FRAME1;
frankvnk 0:636056c0b5e1 194
frankvnk 0:636056c0b5e1 195 LastFrameSent = TCP_DATA_FRAME;
frankvnk 0:636056c0b5e1 196 TCPStartRetryTimer();
frankvnk 0:636056c0b5e1 197 }
frankvnk 0:636056c0b5e1 198 }
frankvnk 0:636056c0b5e1 199
frankvnk 0:636056c0b5e1 200 // Reads the length of the received ethernet frame and checks if the
frankvnk 0:636056c0b5e1 201 // destination address is a broadcast message or not
frankvnk 0:636056c0b5e1 202 unsigned int BroadcastMessage(void)
frankvnk 0:636056c0b5e1 203 {
frankvnk 0:636056c0b5e1 204 unsigned short FrameDestination[3]; // to hold 48 bit MAC address
frankvnk 0:636056c0b5e1 205
frankvnk 0:636056c0b5e1 206 RecdFrameLength = StartReadingFrame();
frankvnk 0:636056c0b5e1 207
frankvnk 0:636056c0b5e1 208 // Read destination address
frankvnk 0:636056c0b5e1 209 CopyFromFrame_EthMAC(&FrameDestination, 6);
frankvnk 0:636056c0b5e1 210 // Save it for reply
frankvnk 0:636056c0b5e1 211 CopyFromFrame_EthMAC(&RecdFrameMAC, 6);
frankvnk 0:636056c0b5e1 212
frankvnk 0:636056c0b5e1 213 if ((FrameDestination[0] == 0xFFFF) &&
frankvnk 0:636056c0b5e1 214 (FrameDestination[1] == 0xFFFF) &&
frankvnk 0:636056c0b5e1 215 (FrameDestination[2] == 0xFFFF)) {
frankvnk 0:636056c0b5e1 216 return(1); // Broadcast message
frankvnk 0:636056c0b5e1 217 } else {
frankvnk 0:636056c0b5e1 218 return (0);
frankvnk 0:636056c0b5e1 219 }
frankvnk 0:636056c0b5e1 220 }
frankvnk 0:636056c0b5e1 221
frankvnk 0:636056c0b5e1 222
frankvnk 0:636056c0b5e1 223 // easyWEB's 'main()'-function
frankvnk 0:636056c0b5e1 224 // must be called from user program periodically (the often - the better)
frankvnk 0:636056c0b5e1 225 // handles network, TCP/IP-stack and user events
frankvnk 0:636056c0b5e1 226
frankvnk 0:636056c0b5e1 227 void DoNetworkStuff(void)
frankvnk 0:636056c0b5e1 228 {
frankvnk 0:636056c0b5e1 229 // Check to see if packet received
frankvnk 0:636056c0b5e1 230 if (CheckIfFrameReceived())
frankvnk 0:636056c0b5e1 231 {
frankvnk 0:636056c0b5e1 232 // Was it a broadcast message?
frankvnk 0:636056c0b5e1 233 if (BroadcastMessage()) {
frankvnk 0:636056c0b5e1 234 ProcessEthBroadcastFrame();
frankvnk 0:636056c0b5e1 235 }
frankvnk 0:636056c0b5e1 236 else {
frankvnk 0:636056c0b5e1 237 ProcessEthIAFrame();
frankvnk 0:636056c0b5e1 238 }
frankvnk 0:636056c0b5e1 239 // now release ethernet controller buffer
frankvnk 0:636056c0b5e1 240 StopReadingFrame();
frankvnk 0:636056c0b5e1 241 }
frankvnk 0:636056c0b5e1 242 if (TCPFlags & TCP_TIMER_RUNNING)
frankvnk 0:636056c0b5e1 243 if (TCPFlags & TIMER_TYPE_RETRY)
frankvnk 0:636056c0b5e1 244 {
frankvnk 0:636056c0b5e1 245 if (TCPTimer > RETRY_TIMEOUT)
frankvnk 0:636056c0b5e1 246 {
frankvnk 0:636056c0b5e1 247 TCPRestartTimer(); // set a new timeout
frankvnk 0:636056c0b5e1 248
frankvnk 0:636056c0b5e1 249 if (RetryCounter)
frankvnk 0:636056c0b5e1 250 {
frankvnk 0:636056c0b5e1 251 TCPHandleRetransmission(); // resend last frame
frankvnk 0:636056c0b5e1 252 RetryCounter--;
frankvnk 0:636056c0b5e1 253 }
frankvnk 0:636056c0b5e1 254 else
frankvnk 0:636056c0b5e1 255 {
frankvnk 0:636056c0b5e1 256 TCPStopTimer();
frankvnk 0:636056c0b5e1 257 TCPHandleTimeout();
frankvnk 0:636056c0b5e1 258 }
frankvnk 0:636056c0b5e1 259 }
frankvnk 0:636056c0b5e1 260 }
frankvnk 0:636056c0b5e1 261 else if (TCPTimer > FIN_TIMEOUT)
frankvnk 0:636056c0b5e1 262 {
frankvnk 0:636056c0b5e1 263 TCPStateMachine = CLOSED;
frankvnk 0:636056c0b5e1 264 TCPFlags = 0; // reset all flags, stop retransmission...
frankvnk 0:636056c0b5e1 265 SocketStatus &= SOCK_DATA_AVAILABLE; // clear all flags but data available
frankvnk 0:636056c0b5e1 266 }
frankvnk 0:636056c0b5e1 267
frankvnk 0:636056c0b5e1 268 switch (TCPStateMachine)
frankvnk 0:636056c0b5e1 269 {
frankvnk 0:636056c0b5e1 270 case CLOSED :
frankvnk 0:636056c0b5e1 271 case LISTENING :
frankvnk 0:636056c0b5e1 272 {
frankvnk 0:636056c0b5e1 273 if (TCPFlags & TCP_ACTIVE_OPEN) // stack has to open a connection?
frankvnk 0:636056c0b5e1 274 if (TCPFlags & IP_ADDR_RESOLVED) // IP resolved?
frankvnk 0:636056c0b5e1 275 if (!(TransmitControl & SEND_FRAME2)) // buffer free?
frankvnk 0:636056c0b5e1 276 {
frankvnk 0:636056c0b5e1 277 TCPSeqNr = ((unsigned long)ISNGenHigh << 16) | (LPC_TIM0->TC & 0xFFFF); // set local ISN
frankvnk 0:636056c0b5e1 278 TCPUNASeqNr = TCPSeqNr;
frankvnk 0:636056c0b5e1 279 TCPAckNr = 0; // we don't know what to ACK!
frankvnk 0:636056c0b5e1 280 TCPUNASeqNr++; // count SYN as a byte
frankvnk 0:636056c0b5e1 281 PrepareTCP_FRAME(TCP_CODE_SYN); // send SYN frame
frankvnk 0:636056c0b5e1 282 LastFrameSent = TCP_SYN_FRAME;
frankvnk 0:636056c0b5e1 283 TCPStartRetryTimer(); // we NEED a retry-timeout
frankvnk 0:636056c0b5e1 284 TCPStateMachine = SYN_SENT;
frankvnk 0:636056c0b5e1 285 }
frankvnk 0:636056c0b5e1 286 break;
frankvnk 0:636056c0b5e1 287 }
frankvnk 0:636056c0b5e1 288 case SYN_RECD :
frankvnk 0:636056c0b5e1 289 case ESTABLISHED :
frankvnk 0:636056c0b5e1 290 {
frankvnk 0:636056c0b5e1 291 if (TCPFlags & TCP_CLOSE_REQUESTED) // user has user initated a close?
frankvnk 0:636056c0b5e1 292 if (!(TransmitControl & (SEND_FRAME2 | SEND_FRAME1))) // buffers free?
frankvnk 0:636056c0b5e1 293 if (TCPSeqNr == TCPUNASeqNr) // all data ACKed?
frankvnk 0:636056c0b5e1 294 {
frankvnk 0:636056c0b5e1 295 TCPUNASeqNr++;
frankvnk 0:636056c0b5e1 296 PrepareTCP_FRAME(TCP_CODE_FIN | TCP_CODE_ACK);
frankvnk 0:636056c0b5e1 297 LastFrameSent = TCP_FIN_FRAME;
frankvnk 0:636056c0b5e1 298 TCPStartRetryTimer();
frankvnk 0:636056c0b5e1 299 TCPStateMachine = FIN_WAIT_1;
frankvnk 0:636056c0b5e1 300 }
frankvnk 0:636056c0b5e1 301 break;
frankvnk 0:636056c0b5e1 302 }
frankvnk 0:636056c0b5e1 303 case CLOSE_WAIT :
frankvnk 0:636056c0b5e1 304 {
frankvnk 0:636056c0b5e1 305 if (!(TransmitControl & (SEND_FRAME2 | SEND_FRAME1))) // buffers free?
frankvnk 0:636056c0b5e1 306 if (TCPSeqNr == TCPUNASeqNr) // all data ACKed?
frankvnk 0:636056c0b5e1 307 {
frankvnk 0:636056c0b5e1 308 TCPUNASeqNr++; // count FIN as a byte
frankvnk 0:636056c0b5e1 309 PrepareTCP_FRAME(TCP_CODE_FIN | TCP_CODE_ACK); // we NEED a retry-timeout
frankvnk 0:636056c0b5e1 310 LastFrameSent = TCP_FIN_FRAME; // time to say goodbye...
frankvnk 0:636056c0b5e1 311 TCPStartRetryTimer();
frankvnk 0:636056c0b5e1 312 TCPStateMachine = LAST_ACK;
frankvnk 0:636056c0b5e1 313 }
frankvnk 0:636056c0b5e1 314 break;
frankvnk 0:636056c0b5e1 315 }
frankvnk 0:636056c0b5e1 316 }
frankvnk 0:636056c0b5e1 317
frankvnk 0:636056c0b5e1 318 if (TransmitControl & SEND_FRAME2)
frankvnk 0:636056c0b5e1 319 {
frankvnk 0:636056c0b5e1 320 RequestSend(TxFrame2Size);
frankvnk 0:636056c0b5e1 321
frankvnk 0:636056c0b5e1 322 if (Rdy4Tx()) // NOTE: when using a very fast MCU, maybe
frankvnk 0:636056c0b5e1 323 SendFrame2(); // the CS8900 isn't ready yet, include
frankvnk 0:636056c0b5e1 324 else { // a kind of timer or counter here
frankvnk 0:636056c0b5e1 325 TCPStateMachine = CLOSED;
frankvnk 0:636056c0b5e1 326 SocketStatus = SOCK_ERR_ETHERNET; // indicate an error to user
frankvnk 0:636056c0b5e1 327 TCPFlags = 0; // clear all flags, stop timers etc.
frankvnk 0:636056c0b5e1 328 }
frankvnk 0:636056c0b5e1 329
frankvnk 0:636056c0b5e1 330 TransmitControl &= ~SEND_FRAME2; // clear tx-flag
frankvnk 0:636056c0b5e1 331 }
frankvnk 0:636056c0b5e1 332
frankvnk 0:636056c0b5e1 333 if (TransmitControl & SEND_FRAME1)
frankvnk 0:636056c0b5e1 334 {
frankvnk 0:636056c0b5e1 335 PrepareTCP_DATA_FRAME(); // build frame w/ actual SEQ, ACK....
frankvnk 0:636056c0b5e1 336 RequestSend(TxFrame1Size);
frankvnk 0:636056c0b5e1 337
frankvnk 0:636056c0b5e1 338 if (Rdy4Tx()) // CS8900 ready to accept our frame?
frankvnk 0:636056c0b5e1 339 SendFrame1(); // (see note above)
frankvnk 0:636056c0b5e1 340 else {
frankvnk 0:636056c0b5e1 341 TCPStateMachine = CLOSED;
frankvnk 0:636056c0b5e1 342 SocketStatus = SOCK_ERR_ETHERNET; // indicate an error to user
frankvnk 0:636056c0b5e1 343 TCPFlags = 0; // clear all flags, stop timers etc.
frankvnk 0:636056c0b5e1 344 }
frankvnk 0:636056c0b5e1 345
frankvnk 0:636056c0b5e1 346 TransmitControl &= ~SEND_FRAME1; // clear tx-flag
frankvnk 0:636056c0b5e1 347 }
frankvnk 0:636056c0b5e1 348 }
frankvnk 0:636056c0b5e1 349
frankvnk 0:636056c0b5e1 350 // easyWEB internal function
frankvnk 0:636056c0b5e1 351 // handles an incoming broadcast frame
frankvnk 0:636056c0b5e1 352
frankvnk 0:636056c0b5e1 353 void ProcessEthBroadcastFrame(void)
frankvnk 0:636056c0b5e1 354 {
frankvnk 0:636056c0b5e1 355 unsigned short TargetIP[2];
frankvnk 0:636056c0b5e1 356 if (ReadFrameBE_EthMAC() == FRAME_ARP) // get frame type, check for ARP
frankvnk 0:636056c0b5e1 357 if (ReadFrameBE_EthMAC() == HARDW_ETH10) // Ethernet frame
frankvnk 0:636056c0b5e1 358 if (ReadFrameBE_EthMAC() == FRAME_IP) // check protocol
frankvnk 0:636056c0b5e1 359 if (ReadFrameBE_EthMAC() == IP_HLEN_PLEN) // check HLEN, PLEN
frankvnk 0:636056c0b5e1 360 if (ReadFrameBE_EthMAC() == OP_ARP_REQUEST)
frankvnk 0:636056c0b5e1 361 {
frankvnk 0:636056c0b5e1 362 DummyReadFrame_EthMAC(6); // ignore sender's hardware address
frankvnk 0:636056c0b5e1 363 CopyFromFrame_EthMAC(&RecdFrameIP, 4); // read sender's protocol address
frankvnk 0:636056c0b5e1 364 DummyReadFrame_EthMAC(6); // ignore target's hardware address
frankvnk 0:636056c0b5e1 365 CopyFromFrame_EthMAC(&TargetIP, 4); // read target's protocol address
frankvnk 0:636056c0b5e1 366 if (!memcmp(&MyIP, &TargetIP, 4)) // is it for us?
frankvnk 0:636056c0b5e1 367 PrepareARP_ANSWER(); // yes->create ARP_ANSWER frame
frankvnk 0:636056c0b5e1 368 }
frankvnk 0:636056c0b5e1 369 }
frankvnk 0:636056c0b5e1 370
frankvnk 0:636056c0b5e1 371 // easyWEB internal function
frankvnk 0:636056c0b5e1 372 // handles an incoming frame that passed CS8900's address filter
frankvnk 0:636056c0b5e1 373 // (individual addressed = IA)
frankvnk 0:636056c0b5e1 374
frankvnk 0:636056c0b5e1 375 void ProcessEthIAFrame(void)
frankvnk 0:636056c0b5e1 376 {
frankvnk 0:636056c0b5e1 377 unsigned short TargetIP[2];
frankvnk 0:636056c0b5e1 378 unsigned char ProtocolType;
frankvnk 0:636056c0b5e1 379 switch (ReadFrameBE_EthMAC()) // get frame type
frankvnk 0:636056c0b5e1 380 {
frankvnk 0:636056c0b5e1 381 case FRAME_ARP : // check for ARP
frankvnk 0:636056c0b5e1 382 {
frankvnk 0:636056c0b5e1 383 if ((TCPFlags & (TCP_ACTIVE_OPEN | IP_ADDR_RESOLVED)) == TCP_ACTIVE_OPEN)
frankvnk 0:636056c0b5e1 384 if (ReadFrameBE_EthMAC() == HARDW_ETH10) // check for the right prot. etc.
frankvnk 0:636056c0b5e1 385 if (ReadFrameBE_EthMAC() == FRAME_IP)
frankvnk 0:636056c0b5e1 386 if (ReadFrameBE_EthMAC() == IP_HLEN_PLEN)
frankvnk 0:636056c0b5e1 387 if (ReadFrameBE_EthMAC() == OP_ARP_ANSWER)
frankvnk 0:636056c0b5e1 388 {
frankvnk 0:636056c0b5e1 389 TCPStopTimer(); // OK, now we've the MAC we wanted ;-)
frankvnk 0:636056c0b5e1 390 CopyFromFrame_EthMAC(&RemoteMAC, 6); // extract opponents MAC
frankvnk 0:636056c0b5e1 391 TCPFlags |= IP_ADDR_RESOLVED;
frankvnk 0:636056c0b5e1 392 }
frankvnk 0:636056c0b5e1 393 break;
frankvnk 0:636056c0b5e1 394 }
frankvnk 0:636056c0b5e1 395 case FRAME_IP : // check for IP-type
frankvnk 0:636056c0b5e1 396 {
frankvnk 0:636056c0b5e1 397 if ((ReadFrameBE_EthMAC() & 0xFF00 ) == IP_VER_IHL) // IPv4, IHL=5 (20 Bytes Header)
frankvnk 0:636056c0b5e1 398 { // ignore Type Of Service
frankvnk 0:636056c0b5e1 399 RecdIPFrameLength = ReadFrameBE_EthMAC(); // get IP frame's length
frankvnk 0:636056c0b5e1 400 ReadFrameBE_EthMAC(); // ignore identification
frankvnk 0:636056c0b5e1 401
frankvnk 0:636056c0b5e1 402 if (!(ReadFrameBE_EthMAC() & (IP_FLAG_MOREFRAG | IP_FRAGOFS_MASK))) // only unfragm. frames
frankvnk 0:636056c0b5e1 403 {
frankvnk 0:636056c0b5e1 404 ProtocolType = ReadFrameBE_EthMAC() & 0xFF ; // get protocol, ignore TTL
frankvnk 0:636056c0b5e1 405 ReadFrameBE_EthMAC(); // ignore checksum
frankvnk 0:636056c0b5e1 406 CopyFromFrame_EthMAC(&RecdFrameIP, 4); // get source IP
frankvnk 0:636056c0b5e1 407 CopyFromFrame_EthMAC(&TargetIP, 4); // get destination IP
frankvnk 0:636056c0b5e1 408
frankvnk 0:636056c0b5e1 409 if (!memcmp(&MyIP, &TargetIP, 4)) // is it for us?
frankvnk 0:636056c0b5e1 410 switch (ProtocolType) {
frankvnk 0:636056c0b5e1 411 case PROT_ICMP : { ProcessICMPFrame(); break; }
frankvnk 0:636056c0b5e1 412 case PROT_TCP : { ProcessTCPFrame(); break; }
frankvnk 0:636056c0b5e1 413 case PROT_UDP : break; // not implemented!
frankvnk 0:636056c0b5e1 414 }
frankvnk 0:636056c0b5e1 415 }
frankvnk 0:636056c0b5e1 416 }
frankvnk 0:636056c0b5e1 417 break;
frankvnk 0:636056c0b5e1 418 }
frankvnk 0:636056c0b5e1 419 }
frankvnk 0:636056c0b5e1 420 }
frankvnk 0:636056c0b5e1 421
frankvnk 0:636056c0b5e1 422 // easyWEB internal function
frankvnk 0:636056c0b5e1 423 // we've just rec'd an ICMP-frame (Internet Control Message Protocol)
frankvnk 0:636056c0b5e1 424 // check what to do and branch to the appropriate sub-function
frankvnk 0:636056c0b5e1 425
frankvnk 0:636056c0b5e1 426 void ProcessICMPFrame(void)
frankvnk 0:636056c0b5e1 427 {
frankvnk 0:636056c0b5e1 428 unsigned short ICMPTypeAndCode;
frankvnk 0:636056c0b5e1 429
frankvnk 0:636056c0b5e1 430 ICMPTypeAndCode = ReadFrameBE_EthMAC(); // get Message Type and Code
frankvnk 0:636056c0b5e1 431 ReadFrameBE_EthMAC(); // ignore ICMP checksum
frankvnk 0:636056c0b5e1 432
frankvnk 0:636056c0b5e1 433 switch (ICMPTypeAndCode >> 8) { // check type
frankvnk 0:636056c0b5e1 434 case ICMP_ECHO : // is echo request?
frankvnk 0:636056c0b5e1 435 {
frankvnk 0:636056c0b5e1 436 PrepareICMP_ECHO_REPLY(); // echo as much as we can...
frankvnk 0:636056c0b5e1 437 break;
frankvnk 0:636056c0b5e1 438 }
frankvnk 0:636056c0b5e1 439 }
frankvnk 0:636056c0b5e1 440 }
frankvnk 0:636056c0b5e1 441
frankvnk 0:636056c0b5e1 442 // easyWEB internal function
frankvnk 0:636056c0b5e1 443 // we've just rec'd an TCP-frame (Transmission Control Protocol)
frankvnk 0:636056c0b5e1 444 // this function mainly implements the TCP state machine according to RFC793
frankvnk 0:636056c0b5e1 445
frankvnk 0:636056c0b5e1 446 void ProcessTCPFrame(void)
frankvnk 0:636056c0b5e1 447 {
frankvnk 0:636056c0b5e1 448 unsigned short TCPSegSourcePort; // segment's source port
frankvnk 0:636056c0b5e1 449 unsigned short TCPSegDestPort; // segment's destination port
frankvnk 0:636056c0b5e1 450 unsigned long TCPSegSeq; // segment's sequence number
frankvnk 0:636056c0b5e1 451 unsigned long TCPSegAck; // segment's acknowledge number
frankvnk 0:636056c0b5e1 452 unsigned short TCPCode; // TCP code and header length
frankvnk 0:636056c0b5e1 453 unsigned char TCPHeaderSize; // real TCP header length
frankvnk 0:636056c0b5e1 454 unsigned short NrOfDataBytes; // real number of data
frankvnk 0:636056c0b5e1 455
frankvnk 0:636056c0b5e1 456
frankvnk 0:636056c0b5e1 457 TCPSegSourcePort = ReadFrameBE_EthMAC(); // get ports
frankvnk 0:636056c0b5e1 458 TCPSegDestPort = ReadFrameBE_EthMAC();
frankvnk 0:636056c0b5e1 459
frankvnk 0:636056c0b5e1 460 if (TCPSegDestPort != TCPLocalPort) return; // drop segment if port doesn't match
frankvnk 0:636056c0b5e1 461
frankvnk 0:636056c0b5e1 462 TCPSegSeq = (unsigned long)ReadFrameBE_EthMAC() << 16; // get segment sequence nr.
frankvnk 0:636056c0b5e1 463 TCPSegSeq |= ReadFrameBE_EthMAC();
frankvnk 0:636056c0b5e1 464
frankvnk 0:636056c0b5e1 465 TCPSegAck = (unsigned long)ReadFrameBE_EthMAC() << 16; // get segment acknowledge nr.
frankvnk 0:636056c0b5e1 466 TCPSegAck |= ReadFrameBE_EthMAC();
frankvnk 0:636056c0b5e1 467
frankvnk 0:636056c0b5e1 468 TCPCode = ReadFrameBE_EthMAC(); // get control bits, header length...
frankvnk 0:636056c0b5e1 469
frankvnk 0:636056c0b5e1 470 TCPHeaderSize = (TCPCode & DATA_OFS_MASK) >> 10; // header length in bytes
frankvnk 0:636056c0b5e1 471 NrOfDataBytes = RecdIPFrameLength - IP_HEADER_SIZE - TCPHeaderSize; // seg. text length
frankvnk 0:636056c0b5e1 472
frankvnk 0:636056c0b5e1 473 if (NrOfDataBytes > MAX_TCP_RX_DATA_SIZE) return; // packet too large for us :...-(
frankvnk 0:636056c0b5e1 474
frankvnk 0:636056c0b5e1 475 if (TCPHeaderSize > TCP_HEADER_SIZE) // ignore options if any
frankvnk 0:636056c0b5e1 476 DummyReadFrame_EthMAC(TCPHeaderSize - TCP_HEADER_SIZE);
frankvnk 0:636056c0b5e1 477
frankvnk 0:636056c0b5e1 478 switch (TCPStateMachine) // implement the TCP state machine
frankvnk 0:636056c0b5e1 479 {
frankvnk 0:636056c0b5e1 480 case CLOSED :
frankvnk 0:636056c0b5e1 481 {
frankvnk 0:636056c0b5e1 482 if (!(TCPCode & TCP_CODE_RST))
frankvnk 0:636056c0b5e1 483 {
frankvnk 0:636056c0b5e1 484 TCPRemotePort = TCPSegSourcePort;
frankvnk 0:636056c0b5e1 485 memcpy(&RemoteMAC, &RecdFrameMAC, 6); // save opponents MAC and IP
frankvnk 0:636056c0b5e1 486 memcpy(&RemoteIP, &RecdFrameIP, 4); // for later use
frankvnk 0:636056c0b5e1 487
frankvnk 0:636056c0b5e1 488 if (TCPCode & TCP_CODE_ACK) // make the reset sequence
frankvnk 0:636056c0b5e1 489 { // acceptable to the other
frankvnk 0:636056c0b5e1 490 TCPSeqNr = TCPSegAck; // TCP
frankvnk 0:636056c0b5e1 491 PrepareTCP_FRAME(TCP_CODE_RST);
frankvnk 0:636056c0b5e1 492 }
frankvnk 0:636056c0b5e1 493 else
frankvnk 0:636056c0b5e1 494 {
frankvnk 0:636056c0b5e1 495 TCPSeqNr = 0;
frankvnk 0:636056c0b5e1 496 TCPAckNr = TCPSegSeq + NrOfDataBytes;
frankvnk 0:636056c0b5e1 497 if (TCPCode & (TCP_CODE_SYN | TCP_CODE_FIN)) TCPAckNr++;
frankvnk 0:636056c0b5e1 498 PrepareTCP_FRAME(TCP_CODE_RST | TCP_CODE_ACK);
frankvnk 0:636056c0b5e1 499 }
frankvnk 0:636056c0b5e1 500 }
frankvnk 0:636056c0b5e1 501 break;
frankvnk 0:636056c0b5e1 502 }
frankvnk 0:636056c0b5e1 503 case LISTENING :
frankvnk 0:636056c0b5e1 504 {
frankvnk 0:636056c0b5e1 505 if (!(TCPCode & TCP_CODE_RST)) // ignore segment containing RST
frankvnk 0:636056c0b5e1 506 {
frankvnk 0:636056c0b5e1 507 TCPRemotePort = TCPSegSourcePort;
frankvnk 0:636056c0b5e1 508 memcpy(&RemoteMAC, &RecdFrameMAC, 6); // save opponents MAC and IP
frankvnk 0:636056c0b5e1 509 memcpy(&RemoteIP, &RecdFrameIP, 4); // for later use
frankvnk 0:636056c0b5e1 510
frankvnk 0:636056c0b5e1 511 if (TCPCode & TCP_CODE_ACK) // reset a bad
frankvnk 0:636056c0b5e1 512 { // acknowledgement
frankvnk 0:636056c0b5e1 513 TCPSeqNr = TCPSegAck;
frankvnk 0:636056c0b5e1 514 PrepareTCP_FRAME(TCP_CODE_RST);
frankvnk 0:636056c0b5e1 515 }
frankvnk 0:636056c0b5e1 516 else if (TCPCode & TCP_CODE_SYN)
frankvnk 0:636056c0b5e1 517 {
frankvnk 0:636056c0b5e1 518 TCPAckNr = TCPSegSeq + 1; // get remote ISN, next byte we expect
frankvnk 0:636056c0b5e1 519 TCPSeqNr = ((unsigned long)ISNGenHigh << 16) | (LPC_TIM0->TC & 0xFFFF); // set local ISN
frankvnk 0:636056c0b5e1 520 TCPUNASeqNr = TCPSeqNr + 1; // one byte out -> increase by one
frankvnk 0:636056c0b5e1 521 PrepareTCP_FRAME(TCP_CODE_SYN | TCP_CODE_ACK);
frankvnk 0:636056c0b5e1 522 LastFrameSent = TCP_SYN_ACK_FRAME;
frankvnk 0:636056c0b5e1 523 TCPStartRetryTimer();
frankvnk 0:636056c0b5e1 524 TCPStateMachine = SYN_RECD;
frankvnk 0:636056c0b5e1 525 }
frankvnk 0:636056c0b5e1 526 }
frankvnk 0:636056c0b5e1 527 break;
frankvnk 0:636056c0b5e1 528 }
frankvnk 0:636056c0b5e1 529 case SYN_SENT :
frankvnk 0:636056c0b5e1 530 {
frankvnk 0:636056c0b5e1 531 if (memcmp(&RemoteIP, &RecdFrameIP, 4)) break; // drop segment if its IP doesn't belong
frankvnk 0:636056c0b5e1 532 // to current session
frankvnk 0:636056c0b5e1 533
frankvnk 0:636056c0b5e1 534 if (TCPSegSourcePort != TCPRemotePort) break; // drop segment if port doesn't match
frankvnk 0:636056c0b5e1 535
frankvnk 0:636056c0b5e1 536 if (TCPCode & TCP_CODE_ACK) // ACK field significant?
frankvnk 0:636056c0b5e1 537 if (TCPSegAck != TCPUNASeqNr) // is our ISN ACKed?
frankvnk 0:636056c0b5e1 538 {
frankvnk 0:636056c0b5e1 539 if (!(TCPCode & TCP_CODE_RST))
frankvnk 0:636056c0b5e1 540 {
frankvnk 0:636056c0b5e1 541 TCPSeqNr = TCPSegAck;
frankvnk 0:636056c0b5e1 542 PrepareTCP_FRAME(TCP_CODE_RST);
frankvnk 0:636056c0b5e1 543 }
frankvnk 0:636056c0b5e1 544 break; // drop segment
frankvnk 0:636056c0b5e1 545 }
frankvnk 0:636056c0b5e1 546
frankvnk 0:636056c0b5e1 547 if (TCPCode & TCP_CODE_RST) // RST??
frankvnk 0:636056c0b5e1 548 {
frankvnk 0:636056c0b5e1 549 if (TCPCode & TCP_CODE_ACK) // if ACK was acceptable, reset
frankvnk 0:636056c0b5e1 550 { // connection
frankvnk 0:636056c0b5e1 551 TCPStateMachine = CLOSED;
frankvnk 0:636056c0b5e1 552 TCPFlags = 0; // reset all flags, stop retransmission...
frankvnk 0:636056c0b5e1 553 SocketStatus = SOCK_ERR_CONN_RESET;
frankvnk 0:636056c0b5e1 554 }
frankvnk 0:636056c0b5e1 555 break; // drop segment
frankvnk 0:636056c0b5e1 556 }
frankvnk 0:636056c0b5e1 557
frankvnk 0:636056c0b5e1 558 if (TCPCode & TCP_CODE_SYN) // SYN??
frankvnk 0:636056c0b5e1 559 {
frankvnk 0:636056c0b5e1 560 TCPAckNr = TCPSegSeq; // get opponents ISN
frankvnk 0:636056c0b5e1 561 TCPAckNr++; // inc. by one...
frankvnk 0:636056c0b5e1 562
frankvnk 0:636056c0b5e1 563 if (TCPCode & TCP_CODE_ACK)
frankvnk 0:636056c0b5e1 564 {
frankvnk 0:636056c0b5e1 565 TCPStopTimer(); // stop retransmission, other TCP got our SYN
frankvnk 0:636056c0b5e1 566 TCPSeqNr = TCPUNASeqNr; // advance our sequence number
frankvnk 0:636056c0b5e1 567
frankvnk 0:636056c0b5e1 568 PrepareTCP_FRAME(TCP_CODE_ACK); // ACK this ISN
frankvnk 0:636056c0b5e1 569 TCPStateMachine = ESTABLISHED;
frankvnk 0:636056c0b5e1 570 SocketStatus |= SOCK_CONNECTED;
frankvnk 0:636056c0b5e1 571 SocketStatus |= SOCK_TX_BUF_RELEASED; // user may send data now :-)
frankvnk 0:636056c0b5e1 572 }
frankvnk 0:636056c0b5e1 573 else
frankvnk 0:636056c0b5e1 574 {
frankvnk 0:636056c0b5e1 575 TCPStopTimer();
frankvnk 0:636056c0b5e1 576 PrepareTCP_FRAME(TCP_CODE_SYN | TCP_CODE_ACK); // our SYN isn't ACKed yet,
frankvnk 0:636056c0b5e1 577 LastFrameSent = TCP_SYN_ACK_FRAME; // now continue with sending
frankvnk 0:636056c0b5e1 578 TCPStartRetryTimer(); // SYN_ACK frames
frankvnk 0:636056c0b5e1 579 TCPStateMachine = SYN_RECD;
frankvnk 0:636056c0b5e1 580 }
frankvnk 0:636056c0b5e1 581 }
frankvnk 0:636056c0b5e1 582 break;
frankvnk 0:636056c0b5e1 583 }
frankvnk 0:636056c0b5e1 584 default :
frankvnk 0:636056c0b5e1 585 {
frankvnk 0:636056c0b5e1 586 if (memcmp(&RemoteIP, &RecdFrameIP, 4)) break; // drop segment if IP doesn't belong
frankvnk 0:636056c0b5e1 587 // to current session
frankvnk 0:636056c0b5e1 588
frankvnk 0:636056c0b5e1 589 if (TCPSegSourcePort != TCPRemotePort) break; // drop segment if port doesn't match
frankvnk 0:636056c0b5e1 590
frankvnk 0:636056c0b5e1 591 if (TCPSegSeq != TCPAckNr) break; // drop if it's not the segment we expect
frankvnk 0:636056c0b5e1 592
frankvnk 0:636056c0b5e1 593 if (TCPCode & TCP_CODE_RST) // RST??
frankvnk 0:636056c0b5e1 594 {
frankvnk 0:636056c0b5e1 595 TCPStateMachine = CLOSED; // close the state machine
frankvnk 0:636056c0b5e1 596 TCPFlags = 0; // reset all flags, stop retransmission...
frankvnk 0:636056c0b5e1 597 SocketStatus = SOCK_ERR_CONN_RESET; // indicate an error to user
frankvnk 0:636056c0b5e1 598 break;
frankvnk 0:636056c0b5e1 599 }
frankvnk 0:636056c0b5e1 600
frankvnk 0:636056c0b5e1 601 if (TCPCode & TCP_CODE_SYN) // SYN??
frankvnk 0:636056c0b5e1 602 {
frankvnk 0:636056c0b5e1 603 PrepareTCP_FRAME(TCP_CODE_RST); // is NOT allowed here! send a reset,
frankvnk 0:636056c0b5e1 604 TCPStateMachine = CLOSED; // close connection...
frankvnk 0:636056c0b5e1 605 TCPFlags = 0; // reset all flags, stop retransmission...
frankvnk 0:636056c0b5e1 606 SocketStatus = SOCK_ERR_REMOTE; // fatal error!
frankvnk 0:636056c0b5e1 607 break; // ...and drop the frame
frankvnk 0:636056c0b5e1 608 }
frankvnk 0:636056c0b5e1 609
frankvnk 0:636056c0b5e1 610 if (!(TCPCode & TCP_CODE_ACK)) break; // drop segment if the ACK bit is off
frankvnk 0:636056c0b5e1 611
frankvnk 0:636056c0b5e1 612 if (TCPSegAck == TCPUNASeqNr) // is our last data sent ACKed?
frankvnk 0:636056c0b5e1 613 {
frankvnk 0:636056c0b5e1 614 TCPStopTimer(); // stop retransmission
frankvnk 0:636056c0b5e1 615 TCPSeqNr = TCPUNASeqNr; // advance our sequence number
frankvnk 0:636056c0b5e1 616
frankvnk 0:636056c0b5e1 617 switch (TCPStateMachine) // change state if necessary
frankvnk 0:636056c0b5e1 618 {
frankvnk 0:636056c0b5e1 619 case SYN_RECD : // ACK of our SYN?
frankvnk 0:636056c0b5e1 620 {
frankvnk 0:636056c0b5e1 621 TCPStateMachine = ESTABLISHED; // user may send data now :-)
frankvnk 0:636056c0b5e1 622 SocketStatus |= SOCK_CONNECTED;
frankvnk 0:636056c0b5e1 623 break;
frankvnk 0:636056c0b5e1 624 }
frankvnk 0:636056c0b5e1 625 case FIN_WAIT_1 : { TCPStateMachine = FIN_WAIT_2; break; } // ACK of our FIN?
frankvnk 0:636056c0b5e1 626 case CLOSING : { TCPStateMachine = TIME_WAIT; break; } // ACK of our FIN?
frankvnk 0:636056c0b5e1 627 case LAST_ACK : // ACK of our FIN?
frankvnk 0:636056c0b5e1 628 {
frankvnk 0:636056c0b5e1 629 TCPStateMachine = CLOSED;
frankvnk 0:636056c0b5e1 630 TCPFlags = 0; // reset all flags, stop retransmission...
frankvnk 0:636056c0b5e1 631 SocketStatus &= SOCK_DATA_AVAILABLE; // clear all flags but data available
frankvnk 0:636056c0b5e1 632 break;
frankvnk 0:636056c0b5e1 633 }
frankvnk 0:636056c0b5e1 634 case TIME_WAIT :
frankvnk 0:636056c0b5e1 635 {
frankvnk 0:636056c0b5e1 636 PrepareTCP_FRAME(TCP_CODE_ACK); // ACK a retransmission of remote FIN
frankvnk 0:636056c0b5e1 637 TCPRestartTimer(); // restart TIME_WAIT timeout
frankvnk 0:636056c0b5e1 638 break;
frankvnk 0:636056c0b5e1 639 }
frankvnk 0:636056c0b5e1 640 }
frankvnk 0:636056c0b5e1 641
frankvnk 0:636056c0b5e1 642 if (TCPStateMachine == ESTABLISHED) // if true, give the frame buffer back
frankvnk 0:636056c0b5e1 643 SocketStatus |= SOCK_TX_BUF_RELEASED; // to user
frankvnk 0:636056c0b5e1 644 }
frankvnk 0:636056c0b5e1 645
frankvnk 0:636056c0b5e1 646 if ((TCPStateMachine == ESTABLISHED) || (TCPStateMachine == FIN_WAIT_1) || (TCPStateMachine == FIN_WAIT_2))
frankvnk 0:636056c0b5e1 647 if (NrOfDataBytes) // data available?
frankvnk 0:636056c0b5e1 648 if (!(SocketStatus & SOCK_DATA_AVAILABLE)) // rx data-buffer empty?
frankvnk 0:636056c0b5e1 649 {
frankvnk 0:636056c0b5e1 650 DummyReadFrame_EthMAC(6); // ignore window, checksum, urgent pointer
frankvnk 0:636056c0b5e1 651 CopyFromFrame_EthMAC(RxTCPBuffer, NrOfDataBytes);// fetch data and
frankvnk 0:636056c0b5e1 652
frankvnk 0:636056c0b5e1 653 TCPRxDataCount = NrOfDataBytes; // ...tell the user...
frankvnk 0:636056c0b5e1 654 SocketStatus |= SOCK_DATA_AVAILABLE; // indicate the new data to user
frankvnk 0:636056c0b5e1 655 TCPAckNr += NrOfDataBytes;
frankvnk 0:636056c0b5e1 656 PrepareTCP_FRAME(TCP_CODE_ACK); // ACK rec'd data
frankvnk 0:636056c0b5e1 657 }
frankvnk 0:636056c0b5e1 658
frankvnk 0:636056c0b5e1 659 if (TCPCode & TCP_CODE_FIN) // FIN??
frankvnk 0:636056c0b5e1 660 {
frankvnk 0:636056c0b5e1 661 switch (TCPStateMachine)
frankvnk 0:636056c0b5e1 662 {
frankvnk 0:636056c0b5e1 663 case SYN_RECD :
frankvnk 0:636056c0b5e1 664 case ESTABLISHED :
frankvnk 0:636056c0b5e1 665 {
frankvnk 0:636056c0b5e1 666 TCPStateMachine = CLOSE_WAIT;
frankvnk 0:636056c0b5e1 667 break;
frankvnk 0:636056c0b5e1 668 }
frankvnk 0:636056c0b5e1 669 case FIN_WAIT_1 :
frankvnk 0:636056c0b5e1 670 { // if our FIN was ACKed, we automatically
frankvnk 0:636056c0b5e1 671 TCPStateMachine = CLOSING; // enter FIN_WAIT_2 (look above) and therefore
frankvnk 0:636056c0b5e1 672 SocketStatus &= ~SOCK_CONNECTED; // TIME_WAIT
frankvnk 0:636056c0b5e1 673 break;
frankvnk 0:636056c0b5e1 674 }
frankvnk 0:636056c0b5e1 675 case FIN_WAIT_2 :
frankvnk 0:636056c0b5e1 676 {
frankvnk 0:636056c0b5e1 677 TCPStartTimeWaitTimer();
frankvnk 0:636056c0b5e1 678 TCPStateMachine = TIME_WAIT;
frankvnk 0:636056c0b5e1 679 SocketStatus &= ~SOCK_CONNECTED;
frankvnk 0:636056c0b5e1 680 break;
frankvnk 0:636056c0b5e1 681 }
frankvnk 0:636056c0b5e1 682 case TIME_WAIT :
frankvnk 0:636056c0b5e1 683 {
frankvnk 0:636056c0b5e1 684 TCPRestartTimer();
frankvnk 0:636056c0b5e1 685 break;
frankvnk 0:636056c0b5e1 686 }
frankvnk 0:636056c0b5e1 687 }
frankvnk 0:636056c0b5e1 688 TCPAckNr++; // ACK remote's FIN flag
frankvnk 0:636056c0b5e1 689 PrepareTCP_FRAME(TCP_CODE_ACK);
frankvnk 0:636056c0b5e1 690 }
frankvnk 0:636056c0b5e1 691 }
frankvnk 0:636056c0b5e1 692 }
frankvnk 0:636056c0b5e1 693 }
frankvnk 0:636056c0b5e1 694
frankvnk 0:636056c0b5e1 695 // easyWEB internal function
frankvnk 0:636056c0b5e1 696 // prepares the TxFrame2-buffer to send an ARP-request
frankvnk 0:636056c0b5e1 697 void PrepareARP_REQUEST(void)
frankvnk 0:636056c0b5e1 698 {
frankvnk 0:636056c0b5e1 699 // Ethernet
frankvnk 0:636056c0b5e1 700 memset(&TxFrame2[ETH_DA_OFS], (char)0xFF, 6); // we don't know opposites MAC!
frankvnk 0:636056c0b5e1 701 memcpy(&TxFrame2[ETH_SA_OFS], &MyMAC, 6);
frankvnk 0:636056c0b5e1 702 *(unsigned short *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_ARP);
frankvnk 0:636056c0b5e1 703
frankvnk 0:636056c0b5e1 704 // ARP
frankvnk 0:636056c0b5e1 705 *(unsigned short *)&TxFrame2[ARP_HARDW_OFS] = SWAPB(HARDW_ETH10);
frankvnk 0:636056c0b5e1 706 *(unsigned short *)&TxFrame2[ARP_PROT_OFS] = SWAPB(FRAME_IP);
frankvnk 0:636056c0b5e1 707 *(unsigned short *)&TxFrame2[ARP_HLEN_PLEN_OFS] = SWAPB(IP_HLEN_PLEN);
frankvnk 0:636056c0b5e1 708 *(unsigned short *)&TxFrame2[ARP_OPCODE_OFS] = SWAPB(OP_ARP_REQUEST);
frankvnk 0:636056c0b5e1 709
frankvnk 0:636056c0b5e1 710 memcpy(&TxFrame2[ARP_SENDER_HA_OFS], &MyMAC, 6);
frankvnk 0:636056c0b5e1 711 memcpy(&TxFrame2[ARP_SENDER_IP_OFS], &MyIP, 4);
frankvnk 0:636056c0b5e1 712 memset(&TxFrame2[ARP_TARGET_HA_OFS], 0x00, 6); // we don't know opposites MAC!
frankvnk 0:636056c0b5e1 713
frankvnk 0:636056c0b5e1 714 if (((RemoteIP[0] ^ MyIP[0]) & SubnetMask[0]) || ((RemoteIP[1] ^ MyIP[1]) & SubnetMask[1]))
frankvnk 0:636056c0b5e1 715 memcpy(&TxFrame2[ARP_TARGET_IP_OFS], &GatewayIP, 4); // IP not in subnet, use gateway
frankvnk 0:636056c0b5e1 716 else
frankvnk 0:636056c0b5e1 717 memcpy(&TxFrame2[ARP_TARGET_IP_OFS], &RemoteIP, 4); // other IP is next to us...
frankvnk 0:636056c0b5e1 718
frankvnk 0:636056c0b5e1 719 TxFrame2Size = ETH_HEADER_SIZE + ARP_FRAME_SIZE;
frankvnk 0:636056c0b5e1 720 TransmitControl |= SEND_FRAME2;
frankvnk 0:636056c0b5e1 721 }
frankvnk 0:636056c0b5e1 722
frankvnk 0:636056c0b5e1 723 // easyWEB internal function
frankvnk 0:636056c0b5e1 724 // prepares the TxFrame2-buffer to send an ARP-answer (reply)
frankvnk 0:636056c0b5e1 725
frankvnk 0:636056c0b5e1 726 void PrepareARP_ANSWER(void)
frankvnk 0:636056c0b5e1 727 {
frankvnk 0:636056c0b5e1 728 // Ethernet
frankvnk 0:636056c0b5e1 729 memcpy(&TxFrame2[ETH_DA_OFS], &RecdFrameMAC, 6);
frankvnk 0:636056c0b5e1 730 memcpy(&TxFrame2[ETH_SA_OFS], &MyMAC, 6);
frankvnk 0:636056c0b5e1 731 *(unsigned short *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_ARP);
frankvnk 0:636056c0b5e1 732
frankvnk 0:636056c0b5e1 733 // ARP
frankvnk 0:636056c0b5e1 734 *(unsigned short *)&TxFrame2[ARP_HARDW_OFS] = SWAPB(HARDW_ETH10);
frankvnk 0:636056c0b5e1 735 *(unsigned short *)&TxFrame2[ARP_PROT_OFS] = SWAPB(FRAME_IP);
frankvnk 0:636056c0b5e1 736 *(unsigned short *)&TxFrame2[ARP_HLEN_PLEN_OFS] = SWAPB(IP_HLEN_PLEN);
frankvnk 0:636056c0b5e1 737 *(unsigned short *)&TxFrame2[ARP_OPCODE_OFS] = SWAPB(OP_ARP_ANSWER);
frankvnk 0:636056c0b5e1 738 memcpy(&TxFrame2[ARP_SENDER_HA_OFS], &MyMAC, 6);
frankvnk 0:636056c0b5e1 739 memcpy(&TxFrame2[ARP_SENDER_IP_OFS], &MyIP, 4);
frankvnk 0:636056c0b5e1 740 memcpy(&TxFrame2[ARP_TARGET_HA_OFS], &RecdFrameMAC, 6);
frankvnk 0:636056c0b5e1 741 memcpy(&TxFrame2[ARP_TARGET_IP_OFS], &RecdFrameIP, 4);
frankvnk 0:636056c0b5e1 742
frankvnk 0:636056c0b5e1 743 TxFrame2Size = ETH_HEADER_SIZE + ARP_FRAME_SIZE;
frankvnk 0:636056c0b5e1 744 TransmitControl |= SEND_FRAME2;
frankvnk 0:636056c0b5e1 745 }
frankvnk 0:636056c0b5e1 746
frankvnk 0:636056c0b5e1 747 // easyWEB internal function
frankvnk 0:636056c0b5e1 748 // prepares the TxFrame2-buffer to send an ICMP-echo-reply
frankvnk 0:636056c0b5e1 749 void PrepareICMP_ECHO_REPLY(void)
frankvnk 0:636056c0b5e1 750 {
frankvnk 0:636056c0b5e1 751 unsigned short ICMPDataCount;
frankvnk 0:636056c0b5e1 752
frankvnk 0:636056c0b5e1 753 if (RecdIPFrameLength > MAX_ETH_TX_DATA_SIZE) // don't overload TX-buffer
frankvnk 0:636056c0b5e1 754 ICMPDataCount = MAX_ETH_TX_DATA_SIZE - IP_HEADER_SIZE - ICMP_HEADER_SIZE;
frankvnk 0:636056c0b5e1 755 else
frankvnk 0:636056c0b5e1 756 ICMPDataCount = RecdIPFrameLength - IP_HEADER_SIZE - ICMP_HEADER_SIZE;
frankvnk 0:636056c0b5e1 757
frankvnk 0:636056c0b5e1 758 // Ethernet
frankvnk 0:636056c0b5e1 759 memcpy(&TxFrame2[ETH_DA_OFS], &RecdFrameMAC, 6);
frankvnk 0:636056c0b5e1 760 memcpy(&TxFrame2[ETH_SA_OFS], &MyMAC, 6);
frankvnk 0:636056c0b5e1 761
frankvnk 0:636056c0b5e1 762 *(unsigned short *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_IP);
frankvnk 0:636056c0b5e1 763
frankvnk 0:636056c0b5e1 764 // IP
frankvnk 0:636056c0b5e1 765 *(unsigned short *)&TxFrame2[IP_VER_IHL_TOS_OFS] = SWAPB(IP_VER_IHL);
frankvnk 0:636056c0b5e1 766 WriteWBE(&TxFrame2[IP_TOTAL_LENGTH_OFS], IP_HEADER_SIZE + ICMP_HEADER_SIZE + ICMPDataCount);
frankvnk 0:636056c0b5e1 767 *(unsigned short *)&TxFrame2[IP_IDENT_OFS] = 0;
frankvnk 0:636056c0b5e1 768 *(unsigned short *)&TxFrame2[IP_FLAGS_FRAG_OFS] = 0;
frankvnk 0:636056c0b5e1 769 *(unsigned short *)&TxFrame2[IP_TTL_PROT_OFS] = SWAPB((DEFAULT_TTL << 8) | PROT_ICMP);
frankvnk 0:636056c0b5e1 770 *(unsigned short *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = 0;
frankvnk 0:636056c0b5e1 771 memcpy(&TxFrame2[IP_SOURCE_OFS], &MyIP, 4);
frankvnk 0:636056c0b5e1 772 memcpy(&TxFrame2[IP_DESTINATION_OFS], &RecdFrameIP, 4);
frankvnk 0:636056c0b5e1 773 *(unsigned short *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = CalcChecksum(&TxFrame2[IP_VER_IHL_TOS_OFS], IP_HEADER_SIZE, 0);
frankvnk 0:636056c0b5e1 774
frankvnk 0:636056c0b5e1 775 // ICMP
frankvnk 0:636056c0b5e1 776 *(unsigned short *)&TxFrame2[ICMP_TYPE_CODE_OFS] = SWAPB(ICMP_ECHO_REPLY << 8);
frankvnk 0:636056c0b5e1 777 *(unsigned short *)&TxFrame2[ICMP_CHKSUM_OFS] = 0; // initialize checksum field
frankvnk 0:636056c0b5e1 778
frankvnk 0:636056c0b5e1 779 CopyFromFrame_EthMAC(&TxFrame2[ICMP_DATA_OFS], ICMPDataCount); // get data to echo...
frankvnk 0:636056c0b5e1 780 *(unsigned short *)&TxFrame2[ICMP_CHKSUM_OFS] = CalcChecksum(&TxFrame2[IP_DATA_OFS], ICMPDataCount + ICMP_HEADER_SIZE, 0);
frankvnk 0:636056c0b5e1 781
frankvnk 0:636056c0b5e1 782 TxFrame2Size = ETH_HEADER_SIZE + IP_HEADER_SIZE + ICMP_HEADER_SIZE + ICMPDataCount;
frankvnk 0:636056c0b5e1 783 TransmitControl |= SEND_FRAME2;
frankvnk 0:636056c0b5e1 784 }
frankvnk 0:636056c0b5e1 785
frankvnk 0:636056c0b5e1 786
frankvnk 0:636056c0b5e1 787 // easyWEB internal function
frankvnk 0:636056c0b5e1 788 // prepares the TxFrame2-buffer to send a general TCP frame
frankvnk 0:636056c0b5e1 789 // the TCPCode-field is passed as an argument
frankvnk 0:636056c0b5e1 790 void PrepareTCP_FRAME(unsigned short TCPCode)
frankvnk 0:636056c0b5e1 791 {
frankvnk 0:636056c0b5e1 792 // Ethernet
frankvnk 0:636056c0b5e1 793 memcpy(&TxFrame2[ETH_DA_OFS], &RemoteMAC, 6);
frankvnk 0:636056c0b5e1 794 memcpy(&TxFrame2[ETH_SA_OFS], &MyMAC, 6);
frankvnk 0:636056c0b5e1 795
frankvnk 0:636056c0b5e1 796 *(unsigned short *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_IP);
frankvnk 0:636056c0b5e1 797
frankvnk 0:636056c0b5e1 798 // IP
frankvnk 0:636056c0b5e1 799 *(unsigned short *)&TxFrame2[IP_VER_IHL_TOS_OFS] = SWAPB(IP_VER_IHL | IP_TOS_D);
frankvnk 0:636056c0b5e1 800
frankvnk 0:636056c0b5e1 801 if (TCPCode & TCP_CODE_SYN) // if SYN, we want to use the MSS option
frankvnk 0:636056c0b5e1 802 *(unsigned short *)&TxFrame2[IP_TOTAL_LENGTH_OFS] = SWAPB(IP_HEADER_SIZE + TCP_HEADER_SIZE + TCP_OPT_MSS_SIZE);
frankvnk 0:636056c0b5e1 803 else
frankvnk 0:636056c0b5e1 804 *(unsigned short *)&TxFrame2[IP_TOTAL_LENGTH_OFS] = SWAPB(IP_HEADER_SIZE + TCP_HEADER_SIZE);
frankvnk 0:636056c0b5e1 805
frankvnk 0:636056c0b5e1 806 *(unsigned short *)&TxFrame2[IP_IDENT_OFS] = 0;
frankvnk 0:636056c0b5e1 807 *(unsigned short *)&TxFrame2[IP_FLAGS_FRAG_OFS] = 0;
frankvnk 0:636056c0b5e1 808 *(unsigned short *)&TxFrame2[IP_TTL_PROT_OFS] = SWAPB((DEFAULT_TTL << 8) | PROT_TCP);
frankvnk 0:636056c0b5e1 809 *(unsigned short *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = 0;
frankvnk 0:636056c0b5e1 810 memcpy(&TxFrame2[IP_SOURCE_OFS], &MyIP, 4);
frankvnk 0:636056c0b5e1 811 memcpy(&TxFrame2[IP_DESTINATION_OFS], &RemoteIP, 4);
frankvnk 0:636056c0b5e1 812 *(unsigned short *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = CalcChecksum(&TxFrame2[IP_VER_IHL_TOS_OFS], IP_HEADER_SIZE, 0);
frankvnk 0:636056c0b5e1 813
frankvnk 0:636056c0b5e1 814 // TCP
frankvnk 0:636056c0b5e1 815 WriteWBE(&TxFrame2[TCP_SRCPORT_OFS], TCPLocalPort);
frankvnk 0:636056c0b5e1 816 WriteWBE(&TxFrame2[TCP_DESTPORT_OFS], TCPRemotePort);
frankvnk 0:636056c0b5e1 817
frankvnk 0:636056c0b5e1 818 WriteDWBE(&TxFrame2[TCP_SEQNR_OFS], TCPSeqNr);
frankvnk 0:636056c0b5e1 819 WriteDWBE(&TxFrame2[TCP_ACKNR_OFS], TCPAckNr);
frankvnk 0:636056c0b5e1 820
frankvnk 0:636056c0b5e1 821 *(unsigned short *)&TxFrame2[TCP_WINDOW_OFS] = SWAPB(MAX_TCP_RX_DATA_SIZE); // data bytes to accept
frankvnk 0:636056c0b5e1 822 *(unsigned short *)&TxFrame2[TCP_CHKSUM_OFS] = 0; // initalize checksum
frankvnk 0:636056c0b5e1 823 *(unsigned short *)&TxFrame2[TCP_URGENT_OFS] = 0;
frankvnk 0:636056c0b5e1 824
frankvnk 0:636056c0b5e1 825 if (TCPCode & TCP_CODE_SYN) // if SYN, we want to use the MSS option
frankvnk 0:636056c0b5e1 826 {
frankvnk 0:636056c0b5e1 827 *(unsigned short *)&TxFrame2[TCP_DATA_CODE_OFS] = SWAPB(0x6000 | TCPCode); // TCP header length = 24
frankvnk 0:636056c0b5e1 828 *(unsigned short *)&TxFrame2[TCP_DATA_OFS] = SWAPB(TCP_OPT_MSS); // MSS option
frankvnk 0:636056c0b5e1 829 *(unsigned short *)&TxFrame2[TCP_DATA_OFS + 2] = SWAPB(MAX_TCP_RX_DATA_SIZE);// max. length of TCP-data we accept
frankvnk 0:636056c0b5e1 830 *(unsigned short *)&TxFrame2[TCP_CHKSUM_OFS] = CalcChecksum(&TxFrame2[TCP_SRCPORT_OFS], TCP_HEADER_SIZE + TCP_OPT_MSS_SIZE, 1);
frankvnk 0:636056c0b5e1 831 TxFrame2Size = ETH_HEADER_SIZE + IP_HEADER_SIZE + TCP_HEADER_SIZE + TCP_OPT_MSS_SIZE;
frankvnk 0:636056c0b5e1 832 }
frankvnk 0:636056c0b5e1 833 else
frankvnk 0:636056c0b5e1 834 {
frankvnk 0:636056c0b5e1 835 *(unsigned short *)&TxFrame2[TCP_DATA_CODE_OFS] = SWAPB(0x5000 | TCPCode); // TCP header length = 20
frankvnk 0:636056c0b5e1 836 *(unsigned short *)&TxFrame2[TCP_CHKSUM_OFS] = CalcChecksum(&TxFrame2[TCP_SRCPORT_OFS], TCP_HEADER_SIZE, 1);
frankvnk 0:636056c0b5e1 837 TxFrame2Size = ETH_HEADER_SIZE + IP_HEADER_SIZE + TCP_HEADER_SIZE;
frankvnk 0:636056c0b5e1 838 }
frankvnk 0:636056c0b5e1 839 TransmitControl |= SEND_FRAME2;
frankvnk 0:636056c0b5e1 840 }
frankvnk 0:636056c0b5e1 841
frankvnk 0:636056c0b5e1 842 // easyWEB internal function
frankvnk 0:636056c0b5e1 843 // prepares the TxFrame1-buffer to send a payload-packet
frankvnk 0:636056c0b5e1 844 void PrepareTCP_DATA_FRAME(void)
frankvnk 0:636056c0b5e1 845 {
frankvnk 0:636056c0b5e1 846 // Ethernet
frankvnk 0:636056c0b5e1 847 memcpy(&TxFrame1[ETH_DA_OFS], &RemoteMAC, 6);
frankvnk 0:636056c0b5e1 848 memcpy(&TxFrame1[ETH_SA_OFS], &MyMAC, 6);
frankvnk 0:636056c0b5e1 849 *(unsigned short *)&TxFrame1[ETH_TYPE_OFS] = SWAPB(FRAME_IP);
frankvnk 0:636056c0b5e1 850
frankvnk 0:636056c0b5e1 851 // IP
frankvnk 0:636056c0b5e1 852 *(unsigned short *)&TxFrame1[IP_VER_IHL_TOS_OFS] = SWAPB(IP_VER_IHL | IP_TOS_D);
frankvnk 0:636056c0b5e1 853 WriteWBE(&TxFrame1[IP_TOTAL_LENGTH_OFS], IP_HEADER_SIZE + TCP_HEADER_SIZE + TCPTxDataCount);
frankvnk 0:636056c0b5e1 854 *(unsigned short *)&TxFrame1[IP_IDENT_OFS] = 0;
frankvnk 0:636056c0b5e1 855 *(unsigned short *)&TxFrame1[IP_FLAGS_FRAG_OFS] = 0;
frankvnk 0:636056c0b5e1 856 *(unsigned short *)&TxFrame1[IP_TTL_PROT_OFS] = SWAPB((DEFAULT_TTL << 8) | PROT_TCP);
frankvnk 0:636056c0b5e1 857 *(unsigned short *)&TxFrame1[IP_HEAD_CHKSUM_OFS] = 0;
frankvnk 0:636056c0b5e1 858 memcpy(&TxFrame1[IP_SOURCE_OFS], &MyIP, 4);
frankvnk 0:636056c0b5e1 859 memcpy(&TxFrame1[IP_DESTINATION_OFS], &RemoteIP, 4);
frankvnk 0:636056c0b5e1 860 *(unsigned short *)&TxFrame1[IP_HEAD_CHKSUM_OFS] = CalcChecksum(&TxFrame1[IP_VER_IHL_TOS_OFS], IP_HEADER_SIZE, 0);
frankvnk 0:636056c0b5e1 861
frankvnk 0:636056c0b5e1 862
frankvnk 0:636056c0b5e1 863 // TCP
frankvnk 0:636056c0b5e1 864 WriteWBE(&TxFrame1[TCP_SRCPORT_OFS], TCPLocalPort);
frankvnk 0:636056c0b5e1 865 WriteWBE(&TxFrame1[TCP_DESTPORT_OFS], TCPRemotePort);
frankvnk 0:636056c0b5e1 866
frankvnk 0:636056c0b5e1 867 WriteDWBE(&TxFrame1[TCP_SEQNR_OFS], TCPSeqNr);
frankvnk 0:636056c0b5e1 868 WriteDWBE(&TxFrame1[TCP_ACKNR_OFS], TCPAckNr);
frankvnk 0:636056c0b5e1 869 *(unsigned short *)&TxFrame1[TCP_DATA_CODE_OFS] = SWAPB(0x5000 | TCP_CODE_ACK); // TCP header length = 20
frankvnk 0:636056c0b5e1 870 *(unsigned short *)&TxFrame1[TCP_WINDOW_OFS] = SWAPB(MAX_TCP_RX_DATA_SIZE); // data bytes to accept
frankvnk 0:636056c0b5e1 871 *(unsigned short *)&TxFrame1[TCP_CHKSUM_OFS] = 0;
frankvnk 0:636056c0b5e1 872 *(unsigned short *)&TxFrame1[TCP_URGENT_OFS] = 0;
frankvnk 0:636056c0b5e1 873 *(unsigned short *)&TxFrame1[TCP_CHKSUM_OFS] = CalcChecksum(&TxFrame1[TCP_SRCPORT_OFS], TCP_HEADER_SIZE + TCPTxDataCount, 1);
frankvnk 0:636056c0b5e1 874
frankvnk 0:636056c0b5e1 875 }
frankvnk 0:636056c0b5e1 876
frankvnk 0:636056c0b5e1 877 // easyWEB internal function
frankvnk 0:636056c0b5e1 878 // calculates the TCP/IP checksum. if 'IsTCP != 0', the TCP pseudo-header
frankvnk 0:636056c0b5e1 879 // will be included.
frankvnk 0:636056c0b5e1 880 unsigned short CalcChecksum(void *Start, unsigned short Count, unsigned char IsTCP)
frankvnk 0:636056c0b5e1 881 {
frankvnk 0:636056c0b5e1 882 // Code Red - added pStart
frankvnk 0:636056c0b5e1 883 unsigned short *pStart;
frankvnk 0:636056c0b5e1 884 unsigned long Sum = 0;
frankvnk 0:636056c0b5e1 885
frankvnk 0:636056c0b5e1 886 if (IsTCP) { // if we've a TCP frame...
frankvnk 0:636056c0b5e1 887 Sum += MyIP[0]; // ...include TCP pseudo-header
frankvnk 0:636056c0b5e1 888 Sum += MyIP[1];
frankvnk 0:636056c0b5e1 889 Sum += RemoteIP[0];
frankvnk 0:636056c0b5e1 890 Sum += RemoteIP[1];
frankvnk 0:636056c0b5e1 891 Sum += SwapBytes(Count); // TCP header length plus data length
frankvnk 0:636056c0b5e1 892 Sum += SWAPB(PROT_TCP);
frankvnk 0:636056c0b5e1 893 }
frankvnk 0:636056c0b5e1 894
frankvnk 0:636056c0b5e1 895 pStart = (unsigned short *)Start;
frankvnk 0:636056c0b5e1 896 while (Count > 1) { // sum words
frankvnk 0:636056c0b5e1 897 Sum += *pStart++;
frankvnk 0:636056c0b5e1 898 Count -= 2;
frankvnk 0:636056c0b5e1 899 }
frankvnk 0:636056c0b5e1 900
frankvnk 0:636056c0b5e1 901 if (Count) // add left-over byte, if any
frankvnk 0:636056c0b5e1 902 Sum += *(unsigned char *)pStart;
frankvnk 0:636056c0b5e1 903
frankvnk 0:636056c0b5e1 904
frankvnk 0:636056c0b5e1 905 while (Sum >> 16) // fold 32-bit sum to 16 bits
frankvnk 0:636056c0b5e1 906 Sum = (Sum & 0xFFFF) + (Sum >> 16);
frankvnk 0:636056c0b5e1 907
frankvnk 0:636056c0b5e1 908 return ~Sum;
frankvnk 0:636056c0b5e1 909 }
frankvnk 0:636056c0b5e1 910
frankvnk 0:636056c0b5e1 911 // easyWEB internal function
frankvnk 0:636056c0b5e1 912 // starts the timer as a retry-timer (used for retransmission-timeout)
frankvnk 0:636056c0b5e1 913 void TCPStartRetryTimer(void)
frankvnk 0:636056c0b5e1 914 {
frankvnk 0:636056c0b5e1 915 TCPTimer = 0;
frankvnk 0:636056c0b5e1 916 RetryCounter = MAX_RETRYS;
frankvnk 0:636056c0b5e1 917 TCPFlags |= TCP_TIMER_RUNNING;
frankvnk 0:636056c0b5e1 918 TCPFlags |= TIMER_TYPE_RETRY;
frankvnk 0:636056c0b5e1 919 }
frankvnk 0:636056c0b5e1 920
frankvnk 0:636056c0b5e1 921 // easyWEB internal function
frankvnk 0:636056c0b5e1 922 // starts the timer as a 'TIME_WAIT'-timer (used to finish a TCP-session)
frankvnk 0:636056c0b5e1 923
frankvnk 0:636056c0b5e1 924 void TCPStartTimeWaitTimer(void)
frankvnk 0:636056c0b5e1 925 {
frankvnk 0:636056c0b5e1 926 TCPTimer = 0;
frankvnk 0:636056c0b5e1 927 TCPFlags |= TCP_TIMER_RUNNING;
frankvnk 0:636056c0b5e1 928 TCPFlags &= ~TIMER_TYPE_RETRY;
frankvnk 0:636056c0b5e1 929 }
frankvnk 0:636056c0b5e1 930
frankvnk 0:636056c0b5e1 931 // easyWEB internal function
frankvnk 0:636056c0b5e1 932 // restarts the timer
frankvnk 0:636056c0b5e1 933
frankvnk 0:636056c0b5e1 934 void TCPRestartTimer(void)
frankvnk 0:636056c0b5e1 935 {
frankvnk 0:636056c0b5e1 936 TCPTimer = 0;
frankvnk 0:636056c0b5e1 937 }
frankvnk 0:636056c0b5e1 938
frankvnk 0:636056c0b5e1 939 // easyWEB internal function
frankvnk 0:636056c0b5e1 940 // stopps the timer
frankvnk 0:636056c0b5e1 941
frankvnk 0:636056c0b5e1 942 void TCPStopTimer(void)
frankvnk 0:636056c0b5e1 943 {
frankvnk 0:636056c0b5e1 944 TCPFlags &= ~TCP_TIMER_RUNNING;
frankvnk 0:636056c0b5e1 945 }
frankvnk 0:636056c0b5e1 946
frankvnk 0:636056c0b5e1 947 // easyWEB internal function
frankvnk 0:636056c0b5e1 948 // if a retransmission-timeout occured, check which packet
frankvnk 0:636056c0b5e1 949 // to resend.
frankvnk 0:636056c0b5e1 950
frankvnk 0:636056c0b5e1 951 void TCPHandleRetransmission(void)
frankvnk 0:636056c0b5e1 952 {
frankvnk 0:636056c0b5e1 953 switch (LastFrameSent)
frankvnk 0:636056c0b5e1 954 {
frankvnk 0:636056c0b5e1 955 case ARP_REQUEST : { PrepareARP_REQUEST(); break; }
frankvnk 0:636056c0b5e1 956 case TCP_SYN_FRAME : { PrepareTCP_FRAME(TCP_CODE_SYN); break; }
frankvnk 0:636056c0b5e1 957 case TCP_SYN_ACK_FRAME : { PrepareTCP_FRAME(TCP_CODE_SYN | TCP_CODE_ACK); break; }
frankvnk 0:636056c0b5e1 958 case TCP_FIN_FRAME : { PrepareTCP_FRAME(TCP_CODE_FIN | TCP_CODE_ACK); break; }
frankvnk 0:636056c0b5e1 959 case TCP_DATA_FRAME : { TransmitControl |= SEND_FRAME1; break; }
frankvnk 0:636056c0b5e1 960 }
frankvnk 0:636056c0b5e1 961 }
frankvnk 0:636056c0b5e1 962
frankvnk 0:636056c0b5e1 963 // easyWEB internal function
frankvnk 0:636056c0b5e1 964 // if all retransmissions failed, close connection and indicate an error
frankvnk 0:636056c0b5e1 965 void TCPHandleTimeout(void)
frankvnk 0:636056c0b5e1 966 {
frankvnk 0:636056c0b5e1 967 TCPStateMachine = CLOSED;
frankvnk 0:636056c0b5e1 968
frankvnk 0:636056c0b5e1 969 if ((TCPFlags & (TCP_ACTIVE_OPEN | IP_ADDR_RESOLVED)) == TCP_ACTIVE_OPEN)
frankvnk 0:636056c0b5e1 970 SocketStatus = SOCK_ERR_ARP_TIMEOUT; // indicate an error to user
frankvnk 0:636056c0b5e1 971 else
frankvnk 0:636056c0b5e1 972 SocketStatus = SOCK_ERR_TCP_TIMEOUT;
frankvnk 0:636056c0b5e1 973
frankvnk 0:636056c0b5e1 974 TCPFlags = 0; // clear all flags
frankvnk 0:636056c0b5e1 975 }
frankvnk 0:636056c0b5e1 976
frankvnk 0:636056c0b5e1 977
frankvnk 0:636056c0b5e1 978 // easyWEB internal function
frankvnk 0:636056c0b5e1 979 // function executed every 0.210s by the MCU. used for the
frankvnk 0:636056c0b5e1 980 // inital sequence number generator (ISN) and the TCP-timer
frankvnk 0:636056c0b5e1 981
frankvnk 0:636056c0b5e1 982 void TCPClockHandler(void)
frankvnk 0:636056c0b5e1 983 {
frankvnk 0:636056c0b5e1 984 ISNGenHigh++; // upper 16 bits of initial sequence number
frankvnk 0:636056c0b5e1 985 TCPTimer++; // timer for retransmissions
frankvnk 0:636056c0b5e1 986 }
frankvnk 0:636056c0b5e1 987
frankvnk 0:636056c0b5e1 988
frankvnk 0:636056c0b5e1 989 // easyWEB internal function
frankvnk 0:636056c0b5e1 990 // transfers the contents of 'TxFrame1'-Buffer to the CS8900A
frankvnk 0:636056c0b5e1 991 void SendFrame1(void)
frankvnk 0:636056c0b5e1 992 {
frankvnk 0:636056c0b5e1 993 CopyToFrame_EthMAC(TxFrame1, TxFrame1Size);
frankvnk 0:636056c0b5e1 994 }
frankvnk 0:636056c0b5e1 995
frankvnk 0:636056c0b5e1 996 // easyWEB internal function
frankvnk 0:636056c0b5e1 997 // transfers the contents of 'TxFrame2'-Buffer to the CS8900A
frankvnk 0:636056c0b5e1 998 void SendFrame2(void)
frankvnk 0:636056c0b5e1 999 {
frankvnk 0:636056c0b5e1 1000 CopyToFrame_EthMAC(TxFrame2, TxFrame2Size);
frankvnk 0:636056c0b5e1 1001 }
frankvnk 0:636056c0b5e1 1002
frankvnk 0:636056c0b5e1 1003 // easyWEB internal function
frankvnk 0:636056c0b5e1 1004 // help function to write a WORD in big-endian byte-order
frankvnk 0:636056c0b5e1 1005 // to MCU-memory
frankvnk 0:636056c0b5e1 1006 void WriteWBE(unsigned char *Add, unsigned short Data)
frankvnk 0:636056c0b5e1 1007 {
frankvnk 0:636056c0b5e1 1008 *Add++ = Data >> 8;
frankvnk 0:636056c0b5e1 1009 *Add = (char)Data;
frankvnk 0:636056c0b5e1 1010 }
frankvnk 0:636056c0b5e1 1011
frankvnk 0:636056c0b5e1 1012 // easyWEB internal function
frankvnk 0:636056c0b5e1 1013 // help function to write a DWORD in big-endian byte-order
frankvnk 0:636056c0b5e1 1014 // to MCU-memory
frankvnk 0:636056c0b5e1 1015 void WriteDWBE(unsigned char *Add, unsigned long Data)
frankvnk 0:636056c0b5e1 1016 {
frankvnk 0:636056c0b5e1 1017 *Add++ = Data >> 24;
frankvnk 0:636056c0b5e1 1018 *Add++ = Data >> 16;
frankvnk 0:636056c0b5e1 1019 *Add++ = Data >> 8;
frankvnk 0:636056c0b5e1 1020 *Add = Data;
frankvnk 0:636056c0b5e1 1021 }
frankvnk 0:636056c0b5e1 1022
frankvnk 0:636056c0b5e1 1023 // easyWEB internal function
frankvnk 0:636056c0b5e1 1024 // help function to swap the byte order of a WORD
frankvnk 0:636056c0b5e1 1025 unsigned short SwapBytes(unsigned short Data)
frankvnk 0:636056c0b5e1 1026 {
frankvnk 0:636056c0b5e1 1027 return (Data >> 8) | (Data << 8);
frankvnk 0:636056c0b5e1 1028 }
frankvnk 0:636056c0b5e1 1029