/* $Id: testasyncsendto.c,v 1.4 2018/01/16 00:50:49 nanard Exp $ */ /* vim: tabstop=4 shiftwidth=4 noexpandtab * MiniUPnP project * http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ * (c) 2006-2018 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ #include #include #include #include #include #include #include #include #include #include "miniupnpdtypes.h" #include "upnputils.h" #include "asyncsendto.h" struct lan_addr_list lan_addrs; #define DEST_IP "239.255.255.250" #define DEST_PORT 1900 /* ssize_t sendto_schedule(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen, unsigned int delay) */ int test(void) { int s; ssize_t n; int i; struct sockaddr_in addr; struct sockaddr_in dest_addr; struct timeval next_send; if( (s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { syslog(LOG_ERR, "socket(): %m"); return 1; } set_non_blocking(s); memset(&addr, 0, sizeof(struct sockaddr_in)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; if(bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { syslog(LOG_ERR, "bind(): %m"); close(s); return 1; } memset(&dest_addr, 0, sizeof(struct sockaddr_in)); dest_addr.sin_family = AF_INET; dest_addr.sin_addr.s_addr = inet_addr(DEST_IP); dest_addr.sin_port = htons(DEST_PORT); n = sendto_or_schedule(s, "1234", 4, 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr)); syslog(LOG_DEBUG, "sendto_or_schedule : %d", (int)n); n = sendto_schedule(s, "1234", 4, 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr), 4400); syslog(LOG_DEBUG, "sendto_schedule : %d", (int)n); n = sendto_schedule(s, "1234", 4, 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr), 3000); syslog(LOG_DEBUG, "sendto_schedule : %d", (int)n); while ((i = get_next_scheduled_send(&next_send)) > 0) { fd_set writefds; int max_fd; struct timeval timeout; struct timeval now; syslog(LOG_DEBUG, "get_next_scheduled_send : %d next_send=%ld.%06ld", i, (long)next_send.tv_sec, (long)next_send.tv_usec); FD_ZERO(&writefds); max_fd = 0; gettimeofday(&now, NULL); i = get_sendto_fds(&writefds, &max_fd, &now); if(now.tv_sec > next_send.tv_sec || (now.tv_sec == next_send.tv_sec && now.tv_usec >= next_send.tv_usec)) { if(i > 0) { /* don't wait */ timeout.tv_sec = 0; } else { /* wait 10sec :) */ timeout.tv_sec = 10; } timeout.tv_usec = 0; } else { /* ... */ timeout.tv_sec = (next_send.tv_sec - now.tv_sec); timeout.tv_usec = (next_send.tv_usec - now.tv_usec); if(timeout.tv_usec < 0) { timeout.tv_usec += 1000000; timeout.tv_sec--; } } syslog(LOG_DEBUG, "get_sendto_fds() returned %d", i); syslog(LOG_DEBUG, "select(%d, NULL, xx, NULL, %ld.%06ld)", max_fd, (long)timeout.tv_sec, (long)timeout.tv_usec); i = select(max_fd, NULL, &writefds, NULL, &timeout); if(i < 0) { syslog(LOG_ERR, "select: %m"); if(errno != EINTR) break; } else if(try_sendto(&writefds) < 0) { syslog(LOG_ERR, "try_sendto: %m"); break; } } close(s); return 0; } int main(int argc, char * * argv) { int r; (void)argc; (void)argv; openlog("testasyncsendto", LOG_CONS|LOG_PERROR, LOG_USER); r = test(); closelog(); return r; }