void
udp_input(struct pbuf *p, struct netif *inp)
{
struct udp_hdr *udphdr;
struct udp_pcb *pcb, *prev;
struct udp_pcb *uncon_pcb;
u16_t src, dest;
u8_t broadcast;
u8_t for_us = 0;
/* Check minimum length (UDP header) 检查最小长度,不能小于UDP首部*/
if (p->len < UDP_HLEN) {
/* drop short packets */
pbuf_free(p);
goto end;
}
//指向UDP报文首部,并且强制转换成udp_hdr类型,方便操作
udphdr = (struct udp_hdr *)p->payload;
/* is broadcast packet ? 判断是不是广播包*/
broadcast = ip_addr_isbroadcast(ip_current_dest_addr(), ip_current_netif());
/* convert src and dest ports to host byte order 得到UDP首部中的源地址和目标主机端口号*/
src = lwip_ntohs(udphdr->src);
dest = lwip_ntohs(udphdr->dest);
pcb = NULL;
prev = NULL;
uncon_pcb = NULL;
/* Iterate through the UDP pcb list for a matching pcb.遍历UDP链表,找到对应的端口号,如果找不到,
* 'Perfect match' pcbs (connected to the remote port & ip address) are就用链表的第一个未使用的UDP控制块
* preferred. If no perfect match is found, the first unconnected pcb that
* matches the local port and ip address gets the datagram. */
for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
/* compare PCB local addr+port to UDP destination addr+port */
if ((pcb->local_port == dest) && //将UDP控制块本地地址+端口与UDP首部目标地址+端口进行比较
(udp_input_local_match(pcb, inp, broadcast) != 0)) {
if (((pcb->flags & UDP_FLAGS_CONNECTED) == 0) &&
((uncon_pcb == NULL))) {
/* the first unconnected matching PCB 如果未找到则使用第一个UDP控制块*/
uncon_pcb = pcb;
}
/* compare PCB remote addr+port to UDP source addr+port将UDP控制块的目标地址+端口号与UDP首部控制块源地址+端口进行比较*/
if ((pcb->remote_port == src) &&
(ip_addr_isany_val(pcb->remote_ip) ||
ip_addr_cmp(&pcb->remote_ip, ip_current_src_addr()))) {
/* the first fully matching PCB */
if (prev != NULL) {
/* move the pcb to the front of udp_pcbs so that is
found faster next time */
prev->next = pcb->next;
pcb->next = udp_pcbs;
udp_pcbs = pcb;
} else {
UDP_STATS_INC(udp.cachehit);
}
break;
}
}
prev = pcb;
}
/* no fully matching pcb found? then look for an unconnected pcb */
if (pcb == NULL) {
pcb = uncon_pcb;
}
/* Check checksum if this is a match or if it was directed at us. */
if (pcb != NULL) {
for_us = 1;
} else {
if (!ip_current_is_v6()) {
for_us = ip4_addr_cmp(netif_ip4_addr(inp), ip4_current_dest_addr());
}
}
if (for_us) {
IF__NETIF_CHECKSUM_ENABLED(inp, CHECKSUM_CHECK_UDP) {
if (ip_current_header_proto() == IP_PROTO_UDPLITE) {
/* Do the UDP Lite checksum */
u16_t chklen = lwip_ntohs(udphdr->len);
if (chklen < sizeof(struct udp_hdr)) {
if (chklen == 0) {
/* For UDP-Lite, checksum length of 0 means checksum
over the complete packet (See RFC 3828 chap. 3.1) */
chklen = p->tot_len;
} else {
/* At least the UDP-Lite header must be covered by the
checksum! (Again, see RFC 3828 chap. 3.1) */
goto chkerr;
}
}
if (ip_chksum_pseudo_partial(p, IP_PROTO_UDPLITE,
p->tot_len, chklen,
ip_current_src_addr(), ip_current_dest_addr()) != 0) {
goto chkerr;
}
} else
//校验和通过,则将报文中的数据递交给用户程序处理,先调整 payload 指针
if (pbuf_header(p, -UDP_HLEN)) { //指向报文中的数据区
/* Can we cope with this failing? Just assert for now */
pbuf_free(p); //调整失败,则删除整个数据报
goto end;
}
if (pcb != NULL) {
MIB2_STATS_INC(mib2.udpindatagrams);
/* callback */
if (pcb->recv != NULL) {
/* now the recv function is responsible for freeing p */
pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr(), src);
} else {
/* no recv function registered? then we have to free the pbuf! */
pbuf_free(p);
goto end;
}
} else {
#if LWIP_ICMP || LWIP_ICMP6
/* No match was found, send ICMP destination port unreachable unless
destination address was broadcast/multicast. */
if (!broadcast && !ip_addr_ismulticast(ip_current_dest_addr())) {
/* move payload pointer back to ip header */
pbuf_header_force(p, (s16_t)(ip_current_header_tot_len() + UDP_HLEN));
icmp_port_unreach(ip_current_is_v6(), p);
}
#endif /* LWIP_ICMP || LWIP_ICMP6 */
pbuf_free(p);
}
} else {
pbuf_free(p);
}
end:
PERF_STOP("udp_input");
return;
#if CHECKSUM_CHECK_UDP
chkerr:
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
("udp_input: UDP (or UDP Lite) datagram discarded due to failing checksum\n"));
UDP_STATS_INC(udp.chkerr);
UDP_STATS_INC(udp.drop);
MIB2_STATS_INC(mib2.udpinerrors);
pbuf_free(p);
PERF_STOP("udp_input");
#endif /* CHECKSUM_CHECK_UDP */
}
LwIP 接收函数udp_input精简版
最新推荐文章于 2023-03-29 19:30:30 发布