📄 tcpip.c
字号:
}// easyWEB internal function// prepares the TxFrame2-buffer to send an ARP-answer (reply)void PrepareARP_ANSWER(void){ // Ethernet memcpy(&TxFrame2[ETH_DA_OFS], &RecdFrameMAC, 6); memcpy(&TxFrame2[ETH_SA_OFS], &MyMAC, 6); *(unsigned int *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_ARP); // ARP *(unsigned int *)&TxFrame2[ARP_HARDW_OFS] = SWAPB(HARDW_ETH10); *(unsigned int *)&TxFrame2[ARP_PROT_OFS] = SWAPB(FRAME_IP); *(unsigned int *)&TxFrame2[ARP_HLEN_PLEN_OFS] = SWAPB(IP_HLEN_PLEN); *(unsigned int *)&TxFrame2[ARP_OPCODE_OFS] = SWAPB(OP_ARP_ANSWER); memcpy(&TxFrame2[ARP_SENDER_HA_OFS], &MyMAC, 6); memcpy(&TxFrame2[ARP_SENDER_IP_OFS], &MyIP, 4); memcpy(&TxFrame2[ARP_TARGET_HA_OFS], &RecdFrameMAC, 6); memcpy(&TxFrame2[ARP_TARGET_IP_OFS], &RecdFrameIP, 4); TxFrame2Size = ETH_HEADER_SIZE + ARP_FRAME_SIZE; TransmitControl |= SEND_FRAME2;}// easyWEB internal function// prepares the TxFrame2-buffer to send an ICMP-echo-replyvoid PrepareICMP_ECHO_REPLY(void){ unsigned int ICMPDataCount; if (RecdIPFrameLength > MAX_ETH_TX_DATA_SIZE) // don't overload TX-buffer ICMPDataCount = MAX_ETH_TX_DATA_SIZE - IP_HEADER_SIZE - ICMP_HEADER_SIZE; else ICMPDataCount = RecdIPFrameLength - IP_HEADER_SIZE - ICMP_HEADER_SIZE; // Ethernet memcpy(&TxFrame2[ETH_DA_OFS], &RecdFrameMAC, 6); memcpy(&TxFrame2[ETH_SA_OFS], &MyMAC, 6); *(unsigned int *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_IP); // IP *(unsigned int *)&TxFrame2[IP_VER_IHL_TOS_OFS] = SWAPB(IP_VER_IHL); WriteWBE(&TxFrame2[IP_TOTAL_LENGTH_OFS], IP_HEADER_SIZE + ICMP_HEADER_SIZE + ICMPDataCount); *(unsigned int *)&TxFrame2[IP_IDENT_OFS] = 0; *(unsigned int *)&TxFrame2[IP_FLAGS_FRAG_OFS] = 0; *(unsigned int *)&TxFrame2[IP_TTL_PROT_OFS] = SWAPB((DEFAULT_TTL << 8) | PROT_ICMP); *(unsigned int *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = 0; memcpy(&TxFrame2[IP_SOURCE_OFS], &MyIP, 4); memcpy(&TxFrame2[IP_DESTINATION_OFS], &RecdFrameIP, 4); *(unsigned int *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = CalcChecksum(&TxFrame2[IP_VER_IHL_TOS_OFS], IP_HEADER_SIZE, 0); // ICMP *(unsigned int *)&TxFrame2[ICMP_TYPE_CODE_OFS] = SWAPB(ICMP_ECHO_REPLY << 8); *(unsigned int *)&TxFrame2[ICMP_CHKSUM_OFS] = 0; // initialize checksum field CopyFromFrame8900(&TxFrame2[ICMP_DATA_OFS], ICMPDataCount); // get data to echo... *(unsigned int *)&TxFrame2[ICMP_CHKSUM_OFS] = CalcChecksum(&TxFrame2[IP_DATA_OFS], ICMPDataCount + ICMP_HEADER_SIZE, 0); TxFrame2Size = ETH_HEADER_SIZE + IP_HEADER_SIZE + ICMP_HEADER_SIZE + ICMPDataCount; TransmitControl |= SEND_FRAME2;}// easyWEB internal function// prepares the TxFrame2-buffer to send a general TCP frame// the TCPCode-field is passed as an argumentvoid PrepareTCP_FRAME(unsigned int TCPCode){ // Ethernet memcpy(&TxFrame2[ETH_DA_OFS], &RemoteMAC, 6); memcpy(&TxFrame2[ETH_SA_OFS], &MyMAC, 6); *(unsigned int *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_IP); // IP *(unsigned int *)&TxFrame2[IP_VER_IHL_TOS_OFS] = SWAPB(IP_VER_IHL | IP_TOS_D); if (TCPCode & TCP_CODE_SYN) // if SYN, we want to use the MSS option *(unsigned int *)&TxFrame2[IP_TOTAL_LENGTH_OFS] = SWAPB(IP_HEADER_SIZE + TCP_HEADER_SIZE + TCP_OPT_MSS_SIZE); else *(unsigned int *)&TxFrame2[IP_TOTAL_LENGTH_OFS] = SWAPB(IP_HEADER_SIZE + TCP_HEADER_SIZE); *(unsigned int *)&TxFrame2[IP_IDENT_OFS] = 0; *(unsigned int *)&TxFrame2[IP_FLAGS_FRAG_OFS] = 0; *(unsigned int *)&TxFrame2[IP_TTL_PROT_OFS] = SWAPB((DEFAULT_TTL << 8) | PROT_TCP); *(unsigned int *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = 0; memcpy(&TxFrame2[IP_SOURCE_OFS], &MyIP, 4); memcpy(&TxFrame2[IP_DESTINATION_OFS], &RemoteIP, 4); *(unsigned int *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = CalcChecksum(&TxFrame2[IP_VER_IHL_TOS_OFS], IP_HEADER_SIZE, 0); // TCP WriteWBE(&TxFrame2[TCP_SRCPORT_OFS], TCPLocalPort); WriteWBE(&TxFrame2[TCP_DESTPORT_OFS], TCPRemotePort); WriteDWBE(&TxFrame2[TCP_SEQNR_OFS], TCPSeqNr); WriteDWBE(&TxFrame2[TCP_ACKNR_OFS], TCPAckNr); *(unsigned int *)&TxFrame2[TCP_WINDOW_OFS] = SWAPB(MAX_TCP_RX_DATA_SIZE); // data bytes to accept *(unsigned int *)&TxFrame2[TCP_CHKSUM_OFS] = 0; // initalize checksum *(unsigned int *)&TxFrame2[TCP_URGENT_OFS] = 0; if (TCPCode & TCP_CODE_SYN) // if SYN, we want to use the MSS option { *(unsigned int *)&TxFrame2[TCP_DATA_CODE_OFS] = SWAPB(0x6000 | TCPCode); // TCP header length = 24 *(unsigned int *)&TxFrame2[TCP_DATA_OFS] = SWAPB(TCP_OPT_MSS); // MSS option *(unsigned int *)&TxFrame2[TCP_DATA_OFS + 2] = SWAPB(MAX_TCP_RX_DATA_SIZE);// max. length of TCP-data we accept *(unsigned int *)&TxFrame2[TCP_CHKSUM_OFS] = CalcChecksum(&TxFrame2[TCP_SRCPORT_OFS], TCP_HEADER_SIZE + TCP_OPT_MSS_SIZE, 1); TxFrame2Size = ETH_HEADER_SIZE + IP_HEADER_SIZE + TCP_HEADER_SIZE + TCP_OPT_MSS_SIZE; } else { *(unsigned int *)&TxFrame2[TCP_DATA_CODE_OFS] = SWAPB(0x5000 | TCPCode); // TCP header length = 20 *(unsigned int *)&TxFrame2[TCP_CHKSUM_OFS] = CalcChecksum(&TxFrame2[TCP_SRCPORT_OFS], TCP_HEADER_SIZE, 1); TxFrame2Size = ETH_HEADER_SIZE + IP_HEADER_SIZE + TCP_HEADER_SIZE; } TransmitControl |= SEND_FRAME2;}// easyWEB internal function// prepares the TxFrame1-buffer to send a payload-packetvoid PrepareTCP_DATA_FRAME(void){ // Ethernet memcpy(&TxFrame1[ETH_DA_OFS], &RemoteMAC, 6); memcpy(&TxFrame1[ETH_SA_OFS], &MyMAC, 6); *(unsigned int *)&TxFrame1[ETH_TYPE_OFS] = SWAPB(FRAME_IP); // IP *(unsigned int *)&TxFrame1[IP_VER_IHL_TOS_OFS] = SWAPB(IP_VER_IHL | IP_TOS_D); WriteWBE(&TxFrame1[IP_TOTAL_LENGTH_OFS], IP_HEADER_SIZE + TCP_HEADER_SIZE + TCPTxDataCount); *(unsigned int *)&TxFrame1[IP_IDENT_OFS] = 0; *(unsigned int *)&TxFrame1[IP_FLAGS_FRAG_OFS] = 0; *(unsigned int *)&TxFrame1[IP_TTL_PROT_OFS] = SWAPB((DEFAULT_TTL << 8) | PROT_TCP); *(unsigned int *)&TxFrame1[IP_HEAD_CHKSUM_OFS] = 0; memcpy(&TxFrame1[IP_SOURCE_OFS], &MyIP, 4); memcpy(&TxFrame1[IP_DESTINATION_OFS], &RemoteIP, 4); *(unsigned int *)&TxFrame1[IP_HEAD_CHKSUM_OFS] = CalcChecksum(&TxFrame1[IP_VER_IHL_TOS_OFS], IP_HEADER_SIZE, 0); // TCP WriteWBE(&TxFrame1[TCP_SRCPORT_OFS], TCPLocalPort); WriteWBE(&TxFrame1[TCP_DESTPORT_OFS], TCPRemotePort); WriteDWBE(&TxFrame1[TCP_SEQNR_OFS], TCPSeqNr); WriteDWBE(&TxFrame1[TCP_ACKNR_OFS], TCPAckNr); *(unsigned int *)&TxFrame1[TCP_DATA_CODE_OFS] = SWAPB(0x5000 | TCP_CODE_ACK); // TCP header length = 20 *(unsigned int *)&TxFrame1[TCP_WINDOW_OFS] = SWAPB(MAX_TCP_RX_DATA_SIZE); // data bytes to accept *(unsigned int *)&TxFrame1[TCP_CHKSUM_OFS] = 0; *(unsigned int *)&TxFrame1[TCP_URGENT_OFS] = 0; *(unsigned int *)&TxFrame1[TCP_CHKSUM_OFS] = CalcChecksum(&TxFrame1[TCP_SRCPORT_OFS], TCP_HEADER_SIZE + TCPTxDataCount, 1);}// easyWEB internal function// calculates the TCP/IP checksum. if 'IsTCP != 0', the TCP pseudo-header// will be included.unsigned int CalcChecksum(void *Start, unsigned int Count, unsigned char IsTCP){ unsigned long Sum = 0; if (IsTCP) { // if we've a TCP frame... Sum += MyIP[0]; // ...include TCP pseudo-header Sum += MyIP[1]; Sum += RemoteIP[0]; Sum += RemoteIP[1]; Sum += SwapBytes(Count); // TCP header length plus data length Sum += SWAPB(PROT_TCP); } while (Count > 1) { // sum words Sum += *((unsigned int *)Start)++; Count -= 2; } if (Count) // add left-over byte, if any Sum += *(unsigned char *)Start; while (Sum >> 16) // fold 32-bit sum to 16 bits Sum = (Sum & 0xFFFF) + (Sum >> 16); return ~Sum;}// easyWEB internal function// starts the timer as a retry-timer (used for retransmission-timeout)void TCPStartRetryTimer(void){ TCPTimer = 0; RetryCounter = MAX_RETRYS; TCPFlags |= TCP_TIMER_RUNNING; TCPFlags |= TIMER_TYPE_RETRY;}// easyWEB internal function// starts the timer as a 'TIME_WAIT'-timer (used to finish a TCP-session)void TCPStartTimeWaitTimer(void){ TCPTimer = 0; TCPFlags |= TCP_TIMER_RUNNING; TCPFlags &= ~TIMER_TYPE_RETRY; }// easyWEB internal function// restarts the timervoid TCPRestartTimer(void){ TCPTimer = 0;}// easyWEB internal function// stopps the timervoid TCPStopTimer(void){ TCPFlags &= ~TCP_TIMER_RUNNING;}// easyWEB internal function// if a retransmission-timeout occured, check which packet// to resend.void TCPHandleRetransmission(void){ switch (LastFrameSent) { case ARP_REQUEST : { PrepareARP_REQUEST(); break; } case TCP_SYN_FRAME : { PrepareTCP_FRAME(TCP_CODE_SYN); break; } case TCP_SYN_ACK_FRAME : { PrepareTCP_FRAME(TCP_CODE_SYN | TCP_CODE_ACK); break; } case TCP_FIN_FRAME : { PrepareTCP_FRAME(TCP_CODE_FIN | TCP_CODE_ACK); break; } case TCP_DATA_FRAME : { TransmitControl |= SEND_FRAME1; break; } }}// easyWEB internal function// if all retransmissions failed, close connection and indicate an errorvoid TCPHandleTimeout(void){ TCPStateMachine = CLOSED; if ((TCPFlags & (TCP_ACTIVE_OPEN | IP_ADDR_RESOLVED)) == TCP_ACTIVE_OPEN) SocketStatus = SOCK_ERR_ARP_TIMEOUT; // indicate an error to user else SocketStatus = SOCK_ERR_TCP_TIMEOUT; TCPFlags = 0; // clear all flags}// easyWEB internal function// function executed every 0.262s by the MCU. used for the// inital sequence number generator (ISN) and the TCP-timerinterrupt [TIMERA1_VECTOR] void TCPClockHandler(void){ if (TAIV == 10) // check for timer overflow, reset int.-flag { ISNGenHigh++; // upper 16 bits of initial sequence number TCPTimer++; // timer for retransmissions }}// easyWEB internal function// transfers the contents of 'TxFrame1'-Buffer to the CS8900Avoid SendFrame1(void){ CopyToFrame8900(&TxFrame1, TxFrame1Size);}// easyWEB internal function// transfers the contents of 'TxFrame2'-Buffer to the CS8900Avoid SendFrame2(void){ CopyToFrame8900(&TxFrame2, TxFrame2Size);}// easyWEB internal function// help function to write a WORD in big-endian byte-order// to MCU-memoryvoid WriteWBE(unsigned char *Add, unsigned int Data){ *Add++ = Data >> 8; *Add = Data;}// easyWEB internal function// help function to write a DWORD in big-endian byte-order// to MCU-memoryvoid WriteDWBE(unsigned char *Add, unsigned long Data){ *Add++ = Data >> 24; *Add++ = Data >> 16; *Add++ = Data >> 8; *Add = Data;}// easyWEB internal function// help function to swap the byte order of a WORDunsigned int SwapBytes(unsigned int Data){ return (Data >> 8) | (Data << 8);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -