⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcpip.c

📁 IARSOURCECODE是基于LPC2478嵌入式软件IAR EWARM V4.42的应用实例代码
💻 C
📖 第 1 页 / 共 3 页
字号:
  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-reply

void 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 argument

void 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-packet

void 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 timer

void TCPRestartTimer(void)
{
  TCPTimer = 0;
}

// easyWEB internal function
// stopps the timer

void 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 error

void 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-timer
 __irq void TCPClockHandler(void)                // 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 EMAC

void SendFrame1(void)
{
  CopyToFrame_EMAC(TxFrame1, TxFrame1Size);
}

// easyWEB internal function
// transfers the contents of 'TxFrame2'-Buffer to the EMAC

void SendFrame2(void)
{
  CopyToFrame_EMAC(TxFrame2, TxFrame2Size);
}

// easyWEB internal function
// help function to write a WORD in big-endian byte-order
// to MCU-memory

void 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-memory

void 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 WORD

unsigned short SwapBytes(unsigned short Data)
{
  return (Data >> 8) | (Data << 8);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -