Add basic testing code.
[radsecproxy.git] / lib / tests / udp.c
1 #include <stdlib.h>
2 #include <string.h>
3 #include <unistd.h>
4 #include <assert.h>
5 #include <stdio.h>
6 #include <event2/event.h>
7 #include <sys/socket.h>
8 #include <netinet/in.h>
9 #include <sys/types.h>
10 #include <netdb.h>
11 #include <sys/select.h>
12 #include <sys/time.h>
13 #include "udp.h"
14
15 static struct addrinfo *
16 _resolve (const char *str)
17 {
18   static int first = 1;
19   static struct addrinfo hints, *result = NULL;
20   struct addrinfo *rp = NULL;
21   int r;
22
23   if (first)
24     {
25       first = 0;
26       memset (&hints, 0, sizeof (hints));
27       hints.ai_family = AF_INET; /* AF_UNSPEC */
28       hints.ai_socktype = SOCK_DGRAM;
29       r = getaddrinfo (NULL, str, &hints, &result);
30       if (r)
31         fprintf (stderr, "getaddrinfo: %s\n", gai_strerror (r));
32     }
33
34   if (result)
35     {
36       rp = result;
37       result = result->ai_next;
38     }
39
40   return rp;
41 }
42
43 ssize_t
44 poll (struct polldata *data)
45 {
46   int r;
47   long timeout;
48   fd_set rfds;
49   ssize_t len;
50   uint8_t buf[4096];
51
52   FD_ZERO (&rfds);
53   FD_SET (data->s, &rfds);
54   if (data->timeout)
55     timeout = data->timeout->tv_sec; /* Save from destruction (Linux).  */
56   //fprintf (stderr, "calling select with timeout %ld\n", timeout);
57   r = select (data->s + 1, &rfds, NULL, NULL, data->timeout);
58   if (data->timeout)
59     data->timeout->tv_sec = timeout; /* Restore.  */
60   //fprintf (stderr, "select returning %d\n", r);
61   if (r > 0)
62     {
63       len = recv (data->s, buf, sizeof (buf), 0);
64       if (len > 0)
65         return data->cb (buf, len);
66     }
67   return r;
68 }
69
70 struct polldata *
71 server (const char *bindto, struct timeval *timeout, data_cb cb)
72 {
73   struct addrinfo *res;
74   int s = -1;
75
76   for (res = _resolve (bindto); res; res = _resolve (bindto))
77     {
78       s = socket (res->ai_family, res->ai_socktype, res->ai_protocol);
79       if (s >= 0)
80         {
81           if (bind (s, res->ai_addr, res->ai_addrlen) == 0)
82             break;              /* Done.  */
83           else
84             {
85               close (s);
86               s = -1;
87             }
88         }
89     }
90
91   if (s >= 0)
92     {
93       struct polldata *data = malloc (sizeof (struct polldata));
94       assert (data);
95       memset (data, 0, sizeof (struct polldata));
96       data->s = s;
97       data->cb = cb;
98       if (timeout)
99         {
100           data->timeout = malloc (sizeof (struct timeval));
101           assert (data->timeout);
102           memcpy (data->timeout, timeout, sizeof (struct timeval));
103         }
104       return data;
105     }
106
107   return NULL;
108 }