130 lines
3.5 KiB
C
130 lines
3.5 KiB
C
/* $Id: testasyncsendto.c,v 1.5 2018/03/13 10:25:52 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 <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <netinet/in.h>
|
|
#include <arpa/inet.h>
|
|
#include <sys/time.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <syslog.h>
|
|
#include <errno.h>
|
|
|
|
#include "miniupnpdtypes.h"
|
|
#include "upnputils.h"
|
|
#include "asyncsendto.h"
|
|
|
|
struct lan_addr_list lan_addrs;
|
|
int runtime_flags = 0;
|
|
time_t startup_time = 0;
|
|
|
|
#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;
|
|
}
|
|
|