THREAD(DiscoveryResponder, arg) { UDPSOCKET *sock; DISCOVERY_TELE *dist; u_long raddr; u_short rport; int len; /* Insist on allocating a datagram buffer. */ while ((dist = malloc(sizeof(DISCOVERY_TELE))) == NULL) { NutSleep(1000); } /* Insist on creating a socket. */ while ((sock = NutUdpCreateSocket(disopt.disopt_port)) == NULL) { NutSleep(1000); } /* Nut/Net doesn't provide UDP datagram buffering by default. */ { u_short max_ms = sizeof(DISCOVERY_TELE) * 3; NutUdpSetSockOpt(sock, SO_RCVBUF, &max_ms, sizeof(max_ms)); } /* Create a pseudo random telegram identifier. */ memcpy(&xid, &confnet.cdn_mac[2], sizeof(xid)); xid += NutGetTickCount(); /* Optionally send initial announce datagram. */ if (disopt.disopt_flags & DISF_INITAL_ANN) { /* Variable sleep avoids broadcast storms in large installations. */ NutSleep(500 + (xid & 0x7FF)); if ((len = NutDiscoveryAnnTele(dist)) > 0) { NutUdpSendTo(sock, INADDR_BROADCAST, disopt.disopt_port, dist, len); } } /* Handle discovery telegrams in an endless loop. */ for (;;) { len = NutUdpReceiveFrom(sock, &raddr, &rport, dist, sizeof(DISCOVERY_TELE), 0); /* Updates may be filtered by an IP mask. */ if ((raddr & disopt.disopt_ipmask) == raddr && len > 0 && discovery_callback) { if ((len = discovery_callback(raddr, rport, dist, len)) > 0) { /* Broadcast response if destination is unreachable. */ if ((raddr & confnet.cdn_ip_mask) != (confnet.cdn_ip_addr & confnet.cdn_ip_mask)) { raddr = INADDR_BROADCAST; } NutUdpSendTo(sock, raddr, disopt.disopt_port, dist, len); } } /* Avoid system blocking by datagram storms. */ NutSleep(100); } }
/* * Main application routine. * */ int main(void) { uint32_t baud = 115200; UDPSOCKET *socket; uint32_t ip_addr; uint32_t ip_udp_echo; int rc; int error; int packet_nr; uint16_t length; /* * Initialize the uart device. */ NutRegisterDevice(&DEV_DEBUG, 0, 0); freopen(DEV_DEBUG_NAME, "w", stdout); _ioctl(_fileno(stdout), UART_SETSPEED, &baud); puts("Demo for ICMP support in UDP sockets...\r\n"); #ifdef DEV_ETHER #ifndef NUT_UDP_ICMP_SUPPORT #warning ICMP support for UDP sockets not enabled in the configurator, please enable NUT_UDP_ICMP_SUPPORT puts("ICMP support for UDP sockets not enabled in the configurator\r\n"); puts("Please enable NUT_UDP_ICMP_SUPPORT\r\n"); #endif /* * Register the network device. */ puts("Configuring Ethernet interface"); NutRegisterDevice(&DEV_ETHER, 0, 0); ip_addr = inet_addr(MY_IP); NutNetIfConfig("eth0", my_mac, ip_addr, inet_addr(MY_MASK)); NutIpRouteAdd(0, 0, inet_addr(MY_GATE), &DEV_ETHER); printf("%s ready\r\n", inet_ntoa(ip_addr)); socket = NutUdpCreateSocket(UDP_ECHO_PORT); if (socket == 0) { printf("Could not create UDP socket in port '%d'\r\n", UDP_ECHO_PORT); puts("Demo halted...\r\n"); while (1); } else { printf("Successfully created UDP socket on port '%d'\r\n", UDP_ECHO_PORT); length = UDP_BUFF_SIZE; if (NutUdpSetSockOpt(socket, SO_RCVBUF, &length, sizeof(length))) {; printf("Could not set UDP receive buffer size (%d)\r\n", length); puts("Demo halted...\r\n"); while (1); } } if (NutThreadCreate("RCV", UDPReceiver, (void*)socket, 1024) == 0) { puts("Could not start receiver thread\r\n"); puts("Demo halted...\r\n"); while (1); } else { puts("Receiver thread started\r\n"); } puts("Starting echo test (1 packet / second)\r\n"); ip_udp_echo = inet_addr(UDP_ECHO_IP); packet_nr = 0; while (1) { packet_nr ++; sprintf(send_buffer, "Packet: %d", packet_nr); rc = NutUdpSendTo(socket, ip_udp_echo, UDP_ECHO_PORT, send_buffer, length); printf("--> Sended packet: \"%s\", to %s, rc: %d\r\n", send_buffer, inet_ntoa(ip_udp_echo), rc); if (rc < 0) { uint32_t remote_ip; uint16_t remote_port; error = NutUdpError(socket, &remote_ip, &remote_port); print_udp_icmp_error(remote_ip, remote_port, error); } NutSleep(1000); } #endif /* DEV_ETHER */ return 0; }