📄 tcpip.c
字号:
else memcpy(&TxFrame2[ARP_TARGET_IP_OFS], &RemoteIP, 4); // other IP is next to us... TxFrame2Size = ETH_HEADER_SIZE + ARP_FRAME_SIZE; TransmitControl |= SEND_FRAME2;}// 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 short *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_ARP); // ARP *(unsigned short *)&TxFrame2[ARP_HARDW_OFS] = SWAPB(HARDW_ETH10); *(unsigned short *)&TxFrame2[ARP_PROT_OFS] = SWAPB(FRAME_IP); *(unsigned short *)&TxFrame2[ARP_HLEN_PLEN_OFS] = SWAPB(IP_HLEN_PLEN); *(unsigned short *)&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 short 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 short *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_IP); // IP *(unsigned short *)&TxFrame2[IP_VER_IHL_TOS_OFS] = SWAPB(IP_VER_IHL); WriteWBE(&TxFrame2[IP_TOTAL_LENGTH_OFS], IP_HEADER_SIZE + ICMP_HEADER_SIZE + ICMPDataCount); *(unsigned short *)&TxFrame2[IP_IDENT_OFS] = 0; *(unsigned short *)&TxFrame2[IP_FLAGS_FRAG_OFS] = 0; *(unsigned short *)&TxFrame2[IP_TTL_PROT_OFS] = SWAPB((DEFAULT_TTL << 8) | PROT_ICMP); *(unsigned short *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = 0; memcpy(&TxFrame2[IP_SOURCE_OFS], &MyIP, 4); memcpy(&TxFrame2[IP_DESTINATION_OFS], &RecdFrameIP, 4); *(unsigned short *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = CalcChecksum(&TxFrame2[IP_VER_IHL_TOS_OFS], IP_HEADER_SIZE, 0); // ICMP *(unsigned short *)&TxFrame2[ICMP_TYPE_CODE_OFS] = SWAPB(ICMP_ECHO_REPLY << 8); *(unsigned short *)&TxFrame2[ICMP_CHKSUM_OFS] = 0; // initialize checksum field CopyFromFrame_EMAC(&TxFrame2[ICMP_DATA_OFS], ICMPDataCount); // get data to echo... *(unsigned short *)&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 short TCPCode){ // Ethernet memcpy(&TxFrame2[ETH_DA_OFS], &RemoteMAC, 6); memcpy(&TxFrame2[ETH_SA_OFS], &MyMAC, 6); *(unsigned short *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_IP); // IP *(unsigned short *)&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 short *)&TxFrame2[IP_TOTAL_LENGTH_OFS] = SWAPB(IP_HEADER_SIZE + TCP_HEADER_SIZE + TCP_OPT_MSS_SIZE); else *(unsigned short *)&TxFrame2[IP_TOTAL_LENGTH_OFS] = SWAPB(IP_HEADER_SIZE + TCP_HEADER_SIZE); *(unsigned short *)&TxFrame2[IP_IDENT_OFS] = 0; *(unsigned short *)&TxFrame2[IP_FLAGS_FRAG_OFS] = 0; *(unsigned short *)&TxFrame2[IP_TTL_PROT_OFS] = SWAPB((DEFAULT_TTL << 8) | PROT_TCP); *(unsigned short *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = 0; memcpy(&TxFrame2[IP_SOURCE_OFS], &MyIP, 4); memcpy(&TxFrame2[IP_DESTINATION_OFS], &RemoteIP, 4); *(unsigned short *)&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 short *)&TxFrame2[TCP_WINDOW_OFS] = SWAPB(MAX_TCP_RX_DATA_SIZE); // data bytes to accept *(unsigned short *)&TxFrame2[TCP_CHKSUM_OFS] = 0; // initalize checksum *(unsigned short *)&TxFrame2[TCP_URGENT_OFS] = 0; if (TCPCode & TCP_CODE_SYN) // if SYN, we want to use the MSS option { *(unsigned short *)&TxFrame2[TCP_DATA_CODE_OFS] = SWAPB(0x6000 | TCPCode); // TCP header length = 24 *(unsigned short *)&TxFrame2[TCP_DATA_OFS] = SWAPB(TCP_OPT_MSS); // MSS option *(unsigned short *)&TxFrame2[TCP_DATA_OFS + 2] = SWAPB(MAX_TCP_RX_DATA_SIZE);// max. length of TCP-data we accept *(unsigned short *)&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 short *)&TxFrame2[TCP_DATA_CODE_OFS] = SWAPB(0x5000 | TCPCode); // TCP header length = 20 *(unsigned short *)&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 short *)&TxFrame1[ETH_TYPE_OFS] = SWAPB(FRAME_IP); // IP *(unsigned short *)&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 short *)&TxFrame1[IP_IDENT_OFS] = 0; *(unsigned short *)&TxFrame1[IP_FLAGS_FRAG_OFS] = 0; *(unsigned short *)&TxFrame1[IP_TTL_PROT_OFS] = SWAPB((DEFAULT_TTL << 8) | PROT_TCP); *(unsigned short *)&TxFrame1[IP_HEAD_CHKSUM_OFS] = 0; memcpy(&TxFrame1[IP_SOURCE_OFS], &MyIP, 4); memcpy(&TxFrame1[IP_DESTINATION_OFS], &RemoteIP, 4); *(unsigned short *)&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 short *)&TxFrame1[TCP_DATA_CODE_OFS] = SWAPB(0x5000 | TCP_CODE_ACK); // TCP header length = 20 *(unsigned short *)&TxFrame1[TCP_WINDOW_OFS] = SWAPB(MAX_TCP_RX_DATA_SIZE); // data bytes to accept *(unsigned short *)&TxFrame1[TCP_CHKSUM_OFS] = 0; *(unsigned short *)&TxFrame1[TCP_URGENT_OFS] = 0; *(unsigned short *)&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 short CalcChecksum(void *Start, unsigned short Count, unsigned char IsTCP){ unsigned long Sum = 0; unsigned short * piStart; // Keil: Pointer added to correct expression 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); } piStart = Start; // Keil: Line added while (Count > 1) { // sum words// Sum += *((unsigned short *)Start)++; // Keil: Line replaced with following line Sum += *piStart++; Count -= 2; } if (Count) // add left-over byte, if any// Sum += *(unsigned char *)Start; // Keil: Line replaced with following line Sum += *(unsigned char *)piStart; 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.210s by the CPU. used for the// inital sequence number generator (ISN) and the TCP-timervoid TCPClockHandler(void) __irq // Keil: interrupt service routine for timer 0{ ISNGenHigh++; // upper 16 bits of initial sequence number TCPTimer++; // timer for retransmissions
T0IR = 1; // Clear interrupt flag
VICVectAddr = 0; // Acknowledge Interrupt
}// easyWEB internal function// transfers the contents of 'TxFrame1'-Buffer to the EMACvoid SendFrame1(void){ CopyToFrame_EMAC(TxFrame1, TxFrame1Size);}// easyWEB internal function// transfers the contents of 'TxFrame2'-Buffer to the EMACvoid SendFrame2(void){ CopyToFrame_EMAC(TxFrame2, TxFrame2Size);}// easyWEB internal function// help function to write a WORD in big-endian byte-order// to MCU-memoryvoid WriteWBE(unsigned char *Add, unsigned short Data){ *Add++ = Data >> 8; *Add = (char)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 = (char)Data;}// easyWEB internal function// help function to swap the byte order of a WORDunsigned short SwapBytes(unsigned short Data){ return (Data >> 8) | (Data << 8);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -