diff options
author | linus <linus@nordu.net> | 2011-01-19 16:47:37 +0100 |
---|---|---|
committer | linus <linus@nordu.net> | 2011-01-19 16:47:37 +0100 |
commit | 75732c2f1247725bf512b152450306157b56d78f (patch) | |
tree | 065948ef3a95b016d0921ba0e06ce5631484fa99 /lib/tests/udp.c | |
parent | 54eeaa8284b754879f02ee1b76094e377c00ab7b (diff) |
Add basic testing code.
Diffstat (limited to 'lib/tests/udp.c')
-rw-r--r-- | lib/tests/udp.c | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/lib/tests/udp.c b/lib/tests/udp.c new file mode 100644 index 0000000..6c43a2f --- /dev/null +++ b/lib/tests/udp.c @@ -0,0 +1,108 @@ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <assert.h> +#include <stdio.h> +#include <event2/event.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <sys/types.h> +#include <netdb.h> +#include <sys/select.h> +#include <sys/time.h> +#include "udp.h" + +static struct addrinfo * +_resolve (const char *str) +{ + static int first = 1; + static struct addrinfo hints, *result = NULL; + struct addrinfo *rp = NULL; + int r; + + if (first) + { + first = 0; + memset (&hints, 0, sizeof (hints)); + hints.ai_family = AF_INET; /* AF_UNSPEC */ + hints.ai_socktype = SOCK_DGRAM; + r = getaddrinfo (NULL, str, &hints, &result); + if (r) + fprintf (stderr, "getaddrinfo: %s\n", gai_strerror (r)); + } + + if (result) + { + rp = result; + result = result->ai_next; + } + + return rp; +} + +ssize_t +poll (struct polldata *data) +{ + int r; + long timeout; + fd_set rfds; + ssize_t len; + uint8_t buf[4096]; + + FD_ZERO (&rfds); + FD_SET (data->s, &rfds); + if (data->timeout) + timeout = data->timeout->tv_sec; /* Save from destruction (Linux). */ + //fprintf (stderr, "calling select with timeout %ld\n", timeout); + r = select (data->s + 1, &rfds, NULL, NULL, data->timeout); + if (data->timeout) + data->timeout->tv_sec = timeout; /* Restore. */ + //fprintf (stderr, "select returning %d\n", r); + if (r > 0) + { + len = recv (data->s, buf, sizeof (buf), 0); + if (len > 0) + return data->cb (buf, len); + } + return r; +} + +struct polldata * +server (const char *bindto, struct timeval *timeout, data_cb cb) +{ + struct addrinfo *res; + int s = -1; + + for (res = _resolve (bindto); res; res = _resolve (bindto)) + { + s = socket (res->ai_family, res->ai_socktype, res->ai_protocol); + if (s >= 0) + { + if (bind (s, res->ai_addr, res->ai_addrlen) == 0) + break; /* Done. */ + else + { + close (s); + s = -1; + } + } + } + + if (s >= 0) + { + struct polldata *data = malloc (sizeof (struct polldata)); + assert (data); + memset (data, 0, sizeof (struct polldata)); + data->s = s; + data->cb = cb; + if (timeout) + { + data->timeout = malloc (sizeof (struct timeval)); + assert (data->timeout); + memcpy (data->timeout, timeout, sizeof (struct timeval)); + } + return data; + } + + return NULL; +} |