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

📄 udp.c

📁 STR912 arm9实现的以太网通信程序
💻 C
字号:
#include "udp.h"
#include <string.h>

u8_t uip_buf[UIP_BUFSIZE+2];

volatile u8_t *uip_appdata;

u16_t uip_len, uip_slen;

volatile u8_t uip_flags;  

struct uip_udp_conn *uip_udp_conn;
struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
struct uip_eth_addr uip_ethaddr = {{UIP_ETHADDR0,
				    UIP_ETHADDR1,
				    UIP_ETHADDR2,
				    UIP_ETHADDR3,
				    UIP_ETHADDR4,
				    UIP_ETHADDR5}};
static u16_t lastport=1024;                        
static u16_t ipid;
static u8_t i, c; 
static u16_t tmp16;
static struct arp_entry arp_table[UIP_ARPTAB_SIZE];
static u16_t ipaddr[2];

static u8_t arptime;
static u8_t tmpage;


#define BUF   ((struct arp_hdr *)&uip_buf[0])
#define IPBUF ((struct ethip_hdr *)&uip_buf[0])
#define UDPBUF ((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])
#define ICMPBUF ((struct uip_icmpip_hdr *)&uip_buf[UIP_LLH_LEN])

#define ARP_REQUEST 1
#define ARP_REPLY   2
#define ICMP_ECHO_REPLY 0
#define ICMP_ECHO       8
#define ARP_HWTYPE_ETH 1
				
const u16_t uip_hostaddr[2] =
	{HTONS((UIP_IPADDR0 << 8) | UIP_IPADDR1),
	HTONS((UIP_IPADDR2 << 8) | UIP_IPADDR3)};
const u16_t uip_arp_draddr[2] =
	{HTONS((UIP_DRIPADDR0 << 8) | UIP_DRIPADDR1),
	HTONS((UIP_DRIPADDR2 << 8) | UIP_DRIPADDR3)};
const u16_t uip_arp_netmask[2] =
	{HTONS((UIP_NETMASK0 << 8) | UIP_NETMASK1),
	HTONS((UIP_NETMASK2 << 8) | UIP_NETMASK3)};

void udp_init(void)
{
  for(c = 0; c < UIP_UDP_CONNS; ++c) {
    uip_udp_conns[c].lport = 0;
  }
  for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
    memset(arp_table[i].ipaddr, 0, 4);
  }
}

void uip_arp_timer(void)
{
  struct arp_entry *tabptr;

  ++arptime;
  for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
    tabptr = &arp_table[i];
    if((tabptr->ipaddr[0] | tabptr->ipaddr[1]) != 0 &&
       arptime - tabptr->time >= UIP_ARP_MAXAGE) {
      memset(tabptr->ipaddr, 0, 4);
    }
  }

}


static void uip_arp_update(u16_t *ipaddr, struct uip_eth_addr *ethaddr)
{
  register struct arp_entry *tabptr;

  for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {

    tabptr = &arp_table[i];

    if(tabptr->ipaddr[0] != 0 &&tabptr->ipaddr[1] != 0) {

      if(ipaddr[0] == tabptr->ipaddr[0] &&ipaddr[1] == tabptr->ipaddr[1]) {
	
	memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6);
	tabptr->time = arptime;

	return;
      }
    }
  }

  for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
    tabptr = &arp_table[i];
    if(tabptr->ipaddr[0] == 0 &&tabptr->ipaddr[1] == 0) {
      break;
    }
  }

  if(i == UIP_ARPTAB_SIZE) {
    tmpage = 0;
    c = 0;
    for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
      tabptr = &arp_table[i];
      if(arptime - tabptr->time > tmpage) {
	tmpage = arptime - tabptr->time;
	c = i;
      }
    }
	tabptr=&arp_table[c];
  }

  memcpy(tabptr->ipaddr, ipaddr, 4);
  memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6);
  tabptr->time = arptime;
}
void uip_arp_ipin(void)
{
  uip_len -= sizeof(struct uip_eth_hdr);
	
  if((IPBUF->srcipaddr[0] & uip_arp_netmask[0]) !=
     (uip_hostaddr[0] & uip_arp_netmask[0])) {
    return;
  }
  if((IPBUF->srcipaddr[1] & uip_arp_netmask[1]) !=
     (uip_hostaddr[1] & uip_arp_netmask[1])) {
    return;
  }
  uip_arp_update(IPBUF->srcipaddr, &(IPBUF->ethhdr.src));

  return;
}

typedef struct arp_hdr aht;

void uip_arp_arpin(void)
{

  if(uip_len < 60){
         uip_len = 0;
         return;
  }
  if((BUF->sipaddr[0] == uip_hostaddr[0]) &&
		(BUF->sipaddr[1] == uip_hostaddr[1])){
		uip_len = 0;
    	return;
  }

  if((BUF->dipaddr[0] != uip_hostaddr[0]) || 
		(BUF->dipaddr[1] != uip_hostaddr[1])){
		uip_len = 0;
    	return;
  }
  uip_len = 0;

  	switch(BUF->opcode) {

  		case HTONS(ARP_REQUEST):

      			BUF->opcode = HTONS(2);

      			memcpy(BUF->dhwaddr.addr, BUF->shwaddr.addr, 6);
      			memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6);
      			memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6);
      			memcpy(BUF->ethhdr.dest.addr, BUF->dhwaddr.addr, 6);

      			BUF->dipaddr[0] = BUF->sipaddr[0];
     			BUF->dipaddr[1] = BUF->sipaddr[1];
      			BUF->sipaddr[0] = uip_hostaddr[0];
      			BUF->sipaddr[1] = uip_hostaddr[1];
      			BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP);
      			uip_len = 60;
    		break;
  		case HTONS(ARP_REPLY):
    	
      			uip_arp_update(BUF->sipaddr, &BUF->shwaddr);
    		break;
  	}
}

void uip_arp_out(void)
{
  struct arp_entry *tabptr;

    ipaddr[0] = IPBUF->destipaddr[0];
    ipaddr[1] = IPBUF->destipaddr[1];

  for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
    tabptr = &arp_table[i];
    if(ipaddr[0] == tabptr->ipaddr[0] &&
       ipaddr[1] == tabptr->ipaddr[1])
      break;
  }

  if(i == UIP_ARPTAB_SIZE) {

    memset(BUF->ethhdr.dest.addr, 0xff, 6);
    memset(BUF->dhwaddr.addr, 0x00, 6);
    memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6);
    memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6);

    BUF->dipaddr[0] = ipaddr[0];
    BUF->dipaddr[1] = ipaddr[1];
    BUF->sipaddr[0] = uip_hostaddr[0];
    BUF->sipaddr[1] = uip_hostaddr[1];
    BUF->opcode = HTONS(ARP_REQUEST); 
    BUF->hwtype = HTONS(ARP_HWTYPE_ETH);
    BUF->protocol = HTONS(UIP_ETHTYPE_IP);
    BUF->hwlen = 6;
    BUF->protolen = 4;
    BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP);
	uip_appdata = &uip_buf[UIP_LLH_LEN];
    uip_len = 60;
    return;
  }

  memcpy(IPBUF->ethhdr.dest.addr, tabptr->ethaddr.addr, 6);
  memcpy(IPBUF->ethhdr.src.addr, uip_ethaddr.addr, 6);

  IPBUF->ethhdr.type = HTONS(UIP_ETHTYPE_IP);

  uip_len += sizeof(struct uip_eth_hdr);
}

struct uip_udp_conn * uip_udp_new(u16_t *ripaddr, u16_t rport)
{
  register struct uip_udp_conn *conn;
  u8_t c;

 again:
  ++lastport;

  if(lastport >= 32000) {
    lastport = 1024;
  }

  for(c = 0; c < UIP_UDP_CONNS; ++c) {
    if(uip_udp_conns[c].lport == lastport) {
      goto again;
    }
  }

  conn = 0;
  for(c = 0; c < UIP_UDP_CONNS; ++c) {
    if(uip_udp_conns[c].lport == 0) {
      conn = &uip_udp_conns[c];
      break;
    }
  }

  if(conn == 0) {
    return 0;
  }

  conn->lport = HTONS(lastport);
  conn->rport = HTONS(rport);
  conn->ripaddr[0] = ripaddr[0];
  conn->ripaddr[1] = ripaddr[1];

  return conn;
}

void udp_process(void)
{
	u16_t j;

	if(UDPBUF->vhl != 0x45){ 
		goto drop;
	}
		
	if((UDPBUF->destipaddr[0] != uip_hostaddr[0]) ||
	   (UDPBUF->destipaddr[1] != uip_hostaddr[1])){
		goto drop;
	}
		
	if((UDPBUF->srcipaddr[0] == uip_hostaddr[0]) &&
		(UDPBUF->srcipaddr[1] == uip_hostaddr[1])){
		goto drop;
	}

	if (uip_ipchksum() != 0xffff){
		goto drop;
	}
	switch(UDPBUF->proto){
		case UIP_PROTO_ICMP:			
			goto icmp_input;
		case UIP_PROTO_UDP:				
			goto udp_input;
		default:						
			goto drop;
		}
icmp_input:
		if (ICMPBUF->type != ICMP_ECHO){
			goto drop;
		}
		j = (((ICMPBUF->len[0])<<8)+(ICMPBUF->len[1]) - 20);
		if (uip_chksum((u16_t *)&uip_buf[UIP_LLH_LEN+20],j) != 0xffff){
		goto drop;
		}
	
		ICMPBUF->type = ICMP_ECHO_REPLY;
	
		if(ICMPBUF->icmpchksum >= HTONS(0xffff - (ICMP_ECHO << 8))) {
    	ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8) + 1;
  		} else {
    	ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8);
  		}

  		tmp16 = IPBUF->destipaddr[0];
  		UDPBUF->destipaddr[0] = UDPBUF->srcipaddr[0];
 		UDPBUF->srcipaddr[0] = tmp16;
 		tmp16 = UDPBUF->destipaddr[1];
    	UDPBUF->destipaddr[1] = UDPBUF->srcipaddr[1];
  		UDPBUF->srcipaddr[1] = tmp16;
		return;	
udp_input:
		for(uip_udp_conn = &uip_udp_conns[0]; uip_udp_conn < &uip_udp_conns[UIP_UDP_CONNS]; ++uip_udp_conn) {
    	if(uip_udp_conn->lport != 0 &&UDPBUF->destport == uip_udp_conn->lport &&
       		(uip_udp_conn->rport == 0 ||UDPBUF->srcport == uip_udp_conn->rport) &&
       		UDPBUF->srcipaddr[0] == uip_udp_conn->ripaddr[0] &&
       		UDPBUF->srcipaddr[1] == uip_udp_conn->ripaddr[1]) {
       				uip_appdata = &uip_buf[UIP_LLH_LEN + 28];
      				uip_len = uip_slen = 0;
				  uip_flags = UIP_NEWDATA;
      			UIP_UDP_APPCALL();
				break;
			}
	  		else 
	  			goto drop;
    	}

	 if(uip_slen == 0) 
	 {
			goto drop;
     }
	uip_len = uip_slen + 8 + 20;
  	
	UDPBUF->vhl = 0x45;
  	UDPBUF->tos = 0;
	UDPBUF->len[0] = (uip_len >> 8);
  	UDPBUF->len[1] = (uip_len & 0xff);

  	UDPBUF->ipoffset[0] = UDPBUF->ipoffset[1] = 0;
  	UDPBUF->ttl  = UIP_TTL;
  	++ipid;
  	UDPBUF->ipid[0] = ipid >> 8;
  	UDPBUF->ipid[1] = ipid & 0xff;
	UDPBUF->proto = UIP_PROTO_UDP;
  	UDPBUF->ipchksum = ~(uip_ipchksum());
	UDPBUF->srcipaddr[0] = uip_hostaddr[0];
  	UDPBUF->srcipaddr[1] = uip_hostaddr[1];
  	UDPBUF->destipaddr[0] = uip_udp_conn->ripaddr[0];
  	UDPBUF->destipaddr[1] = uip_udp_conn->ripaddr[1];
	UDPBUF->srcport  = uip_udp_conn->lport;
  	UDPBUF->destport = uip_udp_conn->rport;
	UDPBUF->udplen = HTONS(uip_slen + 8);
  	UDPBUF->udpchksum = 0;
	return;
drop:
	  		uip_len = 0;
  			return;
}

void uip_udp_periodic(void)
{
   if(uip_udp_conn->lport != 0) {
      uip_appdata = &uip_buf[UIP_LLH_LEN + 28];
      uip_len = uip_slen = 0;
      uip_flags = UIP_POLL;
      UIP_UDP_APPCALL();
	}
	if(uip_slen == 0) 
	 {
			uip_len = 0;
  			return;
     }
	uip_len = uip_slen + 8 + 20;
  	
	UDPBUF->vhl = 0x45;
  	UDPBUF->tos = 0;
	UDPBUF->len[0] = (uip_len >> 8);
  	UDPBUF->len[1] = (uip_len & 0xff);

  	UDPBUF->ipoffset[0] = UDPBUF->ipoffset[1] = 0;
  	UDPBUF->ttl  = UIP_TTL;
  	++ipid;
  	UDPBUF->ipid[0] = ipid >> 8;
  	UDPBUF->ipid[1] = ipid & 0xff;
	UDPBUF->proto = UIP_PROTO_UDP;
  	UDPBUF->ipchksum = ~(uip_ipchksum());
	UDPBUF->srcipaddr[0] = uip_hostaddr[0];
  	UDPBUF->srcipaddr[1] = uip_hostaddr[1];
  	UDPBUF->destipaddr[0] = uip_udp_conn->ripaddr[0];
  	UDPBUF->destipaddr[1] = uip_udp_conn->ripaddr[1];
	UDPBUF->srcport  = uip_udp_conn->lport;
  	UDPBUF->destport = uip_udp_conn->rport;
	UDPBUF->udplen = HTONS(uip_slen + 8);
  	UDPBUF->udpchksum = 0;
}
u16_t uip_chksum(u16_t *sdata, u16_t len)
{
  u16_t acc;

  for (acc = 0; len > 1; len -= 2) {
    u16_t u = ((unsigned char *)sdata)[0] + (((unsigned char *)sdata)[1] << 8);
    if ((acc += u) < u) {

      ++acc;
    }
    ++sdata;
  }

  if(len == 1) {
    acc += htons(((u16_t)(*(u8_t *)sdata)) << 8);
    if(acc < htons(((u16_t)(*(u8_t *)sdata)) << 8)) {
      ++acc;
    }
  }

  return acc;
}

u16_t uip_ipchksum(void)
{
  return uip_chksum((u16_t *)&uip_buf[UIP_LLH_LEN], 20);
}
	
u16_t htons(u16_t val)
{
  return HTONS(val);
}

⌨️ 快捷键说明

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