📄 udp.c
字号:
{ break; } } } /*-----------------------------------------------------------------*/ /* If no match, accept port number match if address is wildcard. */ /*-----------------------------------------------------------------*/ if ((sock == NULL) && port_match) { if (port_match->local.sin_addr.s_addr == INADDR_ANY) sock = port_match; } } /*-------------------------------------------------------------------*/ /* If no match, update statistics and send ICMP "port unreachable". */ /*-------------------------------------------------------------------*/ if (sock == NULL) { ++Stats.UdpNoPorts; IcmpDestUR(ICC_PORTUR, RxBuf, src_addr, dst_addr); } /*-------------------------------------------------------------------*/ /* Else, deliver datagram to selected socket. */ /*-------------------------------------------------------------------*/ else { /*-----------------------------------------------------------------*/ /* Ignore buffer if receive queue is full. */ /*-----------------------------------------------------------------*/ if (sock->q_count >= UDP_MAX_QUEUE) ++Stats.UdpInErrors; /*-----------------------------------------------------------------*/ /* Else accept if not shutdown for receiving. */ /*-----------------------------------------------------------------*/ else if ((sock->flags & SF_RCV_SHUT) == FALSE) { /*---------------------------------------------------------------*/ /* Append to socket queue and reserve buffer. */ /*---------------------------------------------------------------*/ ++sock->q_count; RxBuf->next = NULL; if (sock->rq_head == NULL) sock->rq_head = RxBuf; else sock->rq_tail->next = RxBuf; sock->rq_tail = RxBuf; RxBuf = NULL; /*---------------------------------------------------------------*/ /* Unblock any waiting readers by posting "data received" event. */ /*---------------------------------------------------------------*/ NetPostEvent(sock, SE_DATA_RCVD); ++Stats.UdpInDatagrams; /*---------------------------------------------------------------*/ /* If not already there, move socket to head of UDP list. */ /*---------------------------------------------------------------*/ link = (CircLink *)sock; if (link != UdpLruList.next_bck) { /*-------------------------------------------------------------*/ /* Remove from socket list. */ /*-------------------------------------------------------------*/ link->next_bck->next_fwd = link->next_fwd; link->next_fwd->next_bck = link->next_bck; /*-------------------------------------------------------------*/ /* Append to head of socket list. */ /*-------------------------------------------------------------*/ link->next_bck = UdpLruList.next_bck; link->next_fwd = &UdpLruList; UdpLruList.next_bck->next_fwd = link; UdpLruList.next_bck = link; } } }}/***********************************************************************//* UdpSend: Send UDP datagram to specified IP address *//* *//* Inputs: sock = pointer to SOCKET structure *//* dst = destination SockAddr *//* buf = pointer to NetBuf containing datagram *//* len = amount of data to send *//* rt = route to destination or gateway *//* *//***********************************************************************/void UdpSend(CSOCKET sock, const SockAddr *dst, NetBuf *buf, int len, Route *rt){ Ip *ip = (Ip *)buf->ip_pkt; Udp *udp = buf->ip_data; /*-------------------------------------------------------------------*/ /* Start IP header field initialization. */ /*-------------------------------------------------------------------*/ ip->protocol = IPT_UDP; ip->dst_ip = dst->sin_addr.s_addr; ip->src_ip = rt->ni->ip_addr; /*-------------------------------------------------------------------*/ /* Assign buffer length. */ /*-------------------------------------------------------------------*/ buf->length = UDP_HLEN + len; /*-------------------------------------------------------------------*/ /* Complete UDP header field initialization (in network order). */ /*-------------------------------------------------------------------*/ udp->src_port = sock->local.sin_port; udp->dst_port = dst->sin_port; udp->length = htons((ui16)buf->length); /*-------------------------------------------------------------------*/ /* Calculate checksum. Use all ones representation for zero. */ /*-------------------------------------------------------------------*/ udp->checksum = 0; if ((sock->flags & SF_NOCHECKSUM) == 0) { udp->checksum = checksum(buf); if (udp->checksum == 0) udp->checksum = ~0; } /*-------------------------------------------------------------------*/ /* Pass packet to IP layer for delivery and update statistics. */ /*-------------------------------------------------------------------*/ IpSend(rt, buf, buf->length, sock->ip_tos); ++Stats.UdpOutDatagrams;}/***********************************************************************//* UdpConnect: Ensure local port is assigned and check remote address *//* *//* Input: sock = pointer to socket to add *//* *//* Returns: 0 if no errors, else -1 with errno set to error code *//* *//***********************************************************************/int UdpConnect(SOCKET sock){ /*-------------------------------------------------------------------*/ /* If local port is not specified, pick one. */ /*-------------------------------------------------------------------*/ if (sock->local.sin_port == 0) { sock->local.sin_port = UdpNextPort(); if (sock->local.sin_port == 0) { NetError(sock, EMFILE); return -1; } } /*-------------------------------------------------------------------*/ /* Else, verify that the address is not already used. */ /*-------------------------------------------------------------------*/ else { CircLink *link = UdpLruList.next_bck; for (; link != &UdpLruList; link = link->next_bck) { SOCKET next = (SOCKET)link; /*---------------------------------------------------------------*/ /* Have match if unconnected socket matches local address or if */ /* connected socket matches local and remote addresses. */ /*---------------------------------------------------------------*/ if ((sock->local.sin_port == next->local.sin_port) && (sock->local.sin_addr.s_addr == next->local.sin_addr.s_addr)) { if (!(next->flags & SF_CONNECTED) || ((sock->remote.sin_port == next->remote.sin_port) && (sock->remote.sin_addr.s_addr == next->remote.sin_addr.s_addr))) { if (sock != next) { NetError(sock, EADDRINUSE); return -1; } } } } } /*-------------------------------------------------------------------*/ /* Set "connected" flag and return 0 for no errors. */ /*-------------------------------------------------------------------*/ sock->flags |= SF_CONNECTED; return 0;}/***********************************************************************//* UdpQuerySock: Loop through UDP socket list, reporting status *//* *//***********************************************************************/void UdpQuerySock(void){ CircLink *link = UdpLruList.next_bck; /*-------------------------------------------------------------------*/ /* Sweep through LRU-sorted UDP socket list. */ /*-------------------------------------------------------------------*/ for (; link != &UdpLruList; link = link->next_bck) printf(" %2u UDP\n", ((SOCKET)link - &Socks[0]) + 1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -