Move lib to the root.
[libradsec.git] / tests / udp.c
1 /* Copyright 2011,2013, NORDUnet A/S. All rights reserved. */
2 /* See LICENSE for licensing information. */
3
4 #include <stdlib.h>
5 #include <string.h>
6 #include <unistd.h>
7 #include <assert.h>
8 #include <stdio.h>
9 #include <event2/event.h>
10 #include <sys/socket.h>
11 #include <netinet/in.h>
12 #include <sys/types.h>
13 #include <netdb.h>
14 #include <sys/select.h>
15 #include <sys/time.h>
16 #include "radius/client.h"
17 #include "udp.h"
18
19 static struct addrinfo *
20 _resolve (const char *str)
21 {
22   static int first = 1;
23   static struct addrinfo hints, *result = NULL;
24   struct addrinfo *rp = NULL;
25   int r;
26
27   if (first)
28     {
29       first = 0;
30       memset (&hints, 0, sizeof (hints));
31       hints.ai_family = AF_INET; /* AF_UNSPEC */
32       hints.ai_socktype = SOCK_DGRAM;
33       r = getaddrinfo (NULL, str, &hints, &result);
34       if (r)
35         fprintf (stderr, "getaddrinfo: %s\n", gai_strerror (r));
36     }
37
38   if (result)
39     {
40       rp = result;
41       result = result->ai_next;
42     }
43
44   return rp;
45 }
46
47 void
48 udp_free_polldata (struct polldata *data)
49 {
50   if (data)
51     {
52       if (data->timeout)
53         free (data->timeout);
54       free (data);
55     }
56 }
57
58 /* @return if select() returns error or timeout, return select()
59    else return value from invoked callback function */
60 ssize_t
61 udp_poll (struct polldata *data)
62 {
63   int r;
64   long timeout = 0;
65   fd_set rfds;
66   ssize_t len;
67   uint8_t buf[RS_MAX_PACKET_LEN];
68
69   FD_ZERO (&rfds);
70   FD_SET (data->s, &rfds);
71   if (data->timeout)
72     timeout = data->timeout->tv_sec; /* Save from destruction (Linux).  */
73   //fprintf (stderr, "calling select with timeout %ld\n", timeout);
74   r = select (data->s + 1, &rfds, NULL, NULL, data->timeout);
75   if (data->timeout)
76     data->timeout->tv_sec = timeout; /* Restore.  */
77   //fprintf (stderr, "select returning %d\n", r);
78   if (r > 0)
79     {
80       len = recv (data->s, buf, sizeof (buf), 0);
81       if (len > 0)
82         return data->cb (buf, len);
83     }
84   return r;
85 }
86
87 struct polldata *
88 udp_server (const char *bindto, struct timeval *timeout, data_cb cb)
89 {
90   struct addrinfo *res;
91   int s = -1;
92
93   for (res = _resolve (bindto); res; res = _resolve (bindto))
94     {
95       s = socket (res->ai_family, res->ai_socktype, res->ai_protocol);
96       if (s >= 0)
97         {
98           if (bind (s, res->ai_addr, res->ai_addrlen) == 0)
99             break;              /* Done.  */
100           else
101             {
102               close (s);
103               s = -1;
104             }
105         }
106     }
107
108   if (s >= 0)
109     {
110       struct polldata *data = malloc (sizeof (struct polldata));
111       assert (data);
112       memset (data, 0, sizeof (struct polldata));
113       data->s = s;
114       data->cb = cb;
115       if (timeout)
116         {
117           data->timeout = malloc (sizeof (struct timeval));
118           assert (data->timeout);
119           memcpy (data->timeout, timeout, sizeof (struct timeval));
120         }
121       return data;
122     }
123
124   return NULL;
125 }
126
127 ssize_t
128 hd (const uint8_t *buf, ssize_t len)
129 {
130   int i;
131
132   printf ("# len: %ld\n", len);
133   for (i = 0; i < len; i++)
134     {
135       printf ("%02x%s", buf[i], (i+1) % 8 ? " " : "   ");
136       if ((i + 1) % 16 == 0)
137         printf ("\n");
138     }
139   printf ("\n");
140   return len;
141 }