#include #include #include #ifndef WIN32 #include #include #include #include #include #include #endif #ifndef __USE_GNU #define __USE_GNU #endif #ifdef WIN32 #define gethostbyname2(a, b) gethostbyname(a) #else #include #endif #define BUFLEN 65535 void diep(char *s) { perror(s); exit(1); } int split_host_port(char *input, int default_port, char **host, int *port) { char *p; *host = strdup(input); if ((p = strchr(*host, ':'))) { *port = strtol(p+1, NULL, 0); *p = 0; } else { *port = default_port; } return 1; } int open_udp_socket(int port) { struct sockaddr_in si_me; int s; int reuse = 1; if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) return(-1); // diep("socket"); if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse)) != 0) return(-1); //diep("setsockaopt"); memset((char *) &si_me, 0, sizeof(si_me)); si_me.sin_family = AF_INET; si_me.sin_port = htons(port); si_me.sin_addr.s_addr = htonl(INADDR_ANY); if (::bind(s, (struct sockaddr *) &si_me, sizeof(si_me)) != 0) return(-1); //diep("bind"); return s; } void send_udp_datagram(void *buf, int len, int socket, char *target_host, int target_port) { struct sockaddr_in target_si; struct addrinfo hints, *res = NULL, *p; int errcode; memset(&target_si, 0, sizeof(target_si)); memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET; /* IPv4 */ // hints.ai_socktype = SOCK_STREAM; // hints.ai_flags |= AI_CANONNAME; if((errcode = getaddrinfo(target_host, NULL, &hints, &res)) || !res) return; for (p = res; p != NULL; p = p->ai_next) { memcpy(&target_si, res->ai_addr, res->ai_addrlen); break; } freeaddrinfo(res); target_si.sin_port = htons(target_port); if (sendto(socket, (const char*)buf, len, 0, (struct sockaddr *) &target_si, sizeof(target_si)) == -1) return; //diep("sendto"); } int receive_udp_datagram(void *buf, int max, int socket, char **sender_host, int *sender_port) { struct sockaddr_in sender_si; int slen = sizeof(sender_si); int nr; nr = recvfrom(socket, (char*)buf, BUFLEN, #ifdef WIN32 0, #else MSG_DONTWAIT, // TODO: add select() to avoid waiting forever #endif (struct sockaddr *) &sender_si, (socklen_t*)&slen); if (nr == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK) return 0; return(-1); //diep("recvfrom"); } if (sender_host) *sender_host = inet_ntoa(sender_si.sin_addr); if (sender_port) *sender_port = ntohs(sender_si.sin_port); return nr; } /* Borrowed from the GNU libc manual. */ int input_timeout(int filedes, unsigned int seconds) { fd_set set; struct timeval timeout; /* Initialize the file descriptor set. */ FD_ZERO(&set); FD_SET(filedes, &set); /* Initialize the timeout data structure. */ timeout.tv_sec = seconds; timeout.tv_usec = 0; /* `select' returns 0 if timeout, 1 if input available, -1 if error. */ return /* TEMP_FAILURE_RETRY*/(select(FD_SETSIZE, &set, NULL, NULL, &timeout)); }