Statistics
| Branch: | Revision:

pstreamer / src / net_helper-udp.c @ 662a3ab9

History | View | Annotate | Download (7.24 KB)

1
/*
2
 *  Copyright (c) 2010 Luca Abeni
3
 *  Copyright (c) 2010 Csaba Kiraly
4
 *  Copyright (c) 2010 Alessandro Russo
5
 *  Copyright (c) 2017 Luca Baldesi
6
 *
7
 *  This is free software; see lgpl-2.1.txt
8
 */
9

    
10
#include <sys/types.h>
11
#include <unistd.h>
12
#include <errno.h>
13
#include <stdlib.h>
14
#include <stdint.h>
15
#include <stdio.h>
16
#include <string.h>
17
#include <pstreamer_event.h>
18

    
19
#ifndef _WIN32
20
#include <sys/socket.h>
21
#include <netinet/in.h>
22
#include <netdb.h>
23
#include <arpa/inet.h>
24
#else
25
#define _WIN32_WINNT 0x0501 /* WINNT>=0x501 (WindowsXP) for supporting getaddrinfo/freeaddrinfo.*/
26
#include "win32-net.h"
27
#endif
28

    
29
#include "net_helper.h"
30

    
31
struct nodeID {
32
        struct sockaddr_storage addr;
33
        uint16_t occurrences;
34
        int fd;
35
};
36

    
37
int wait4data(const struct nodeID *s, struct timeval *tout, int *user_fds)
38
/* returns 0 if timeout expires 
39
 * returns -1 in case of error of the select function
40
 * retruns 1 if the nodeID file descriptor is ready to be read
41
 *                                         (i.e., some data is ready from the network socket)
42
 * returns 2 if some of the user_fds file descriptors is ready
43
 */
44
{
45
        fd_set fds;
46
        int i, res, max_fd;
47

    
48
        FD_ZERO(&fds);
49
        if (s && s->fd >= 0) {
50
                max_fd = s->fd;
51
                FD_SET(s->fd, &fds);
52
        } else {
53
                max_fd = -1;
54
        }
55
        if (user_fds) {
56
                for (i = 0; user_fds[i] != -1; i++) {
57
                        FD_SET(user_fds[i], &fds);
58
                        if (user_fds[i] > max_fd) {
59
                                max_fd = user_fds[i];
60
                        }
61
                }
62
        }
63
        res = select(max_fd + 1, &fds, NULL, NULL, tout);
64
        if (res <= 0) {
65
                return res;
66
        }
67
        if (s && FD_ISSET(s->fd, &fds)) {
68
                return 1;
69
        }
70

    
71
        /* If execution arrives here, user_fds cannot be 0
72
        (an FD is ready, and it's not s->fd) */
73
        for (i = 0; user_fds[i] != -1; i++) {
74
                if (!FD_ISSET(user_fds[i], &fds)) {
75
                        user_fds[i] = -2;
76
                }
77
        }
78

    
79
        return 2;
80
}
81

    
82
int register_network_fds(const struct nodeID *s, fd_register_f func, void *handler)
83
{
84
        if (s) 
85
                func(handler, s->fd, 'r');
86
        return 0;
87
}
88

    
89
struct nodeID *create_node(const char *IPaddr, int port)
90
{
91
        struct nodeID *s = NULL;
92
        int error = 0;
93
        struct addrinfo hints, *result = NULL;
94

    
95
        if (IPaddr && port > 0)
96
        {
97
                memset(&hints, 0, sizeof(hints));
98
                hints.ai_family = AF_UNSPEC;
99
                hints.ai_flags = AI_NUMERICHOST;
100

    
101
                s = malloc(sizeof(struct nodeID));
102
                memset(s, 0, sizeof(struct nodeID));
103
                s->occurrences = 1;
104
                s->fd = -1;
105

    
106
                if ((error = getaddrinfo(IPaddr, NULL, &hints, &result)) == 0)
107
                {
108
                        s->addr.ss_family = result->ai_family;
109
                        switch (result->ai_family) {
110
                                case (AF_INET):
111
                                        ((struct sockaddr_in *)&s->addr)->sin_port = htons(port);
112
                                        error = inet_pton (result->ai_family, IPaddr, &((struct sockaddr_in *)&s->addr)->sin_addr);
113
                                        if (error > 0)
114
                                                error = 0;
115
                                        break;
116
                                case (AF_INET6):
117
                                        ((struct sockaddr_in6 *)&s->addr)->sin6_port = htons(port);
118
                                        error = inet_pton (result->ai_family, IPaddr, &(((struct sockaddr_in6 *) &s->addr)->sin6_addr));
119
                                        if (error > 0)
120
                                                error = 0;
121
                                        break;
122
                                default:
123
                                        fprintf(stderr, "Cannot resolve address family %d for '%s'\n", result->ai_family, IPaddr);
124
                                        error = -1;
125
                        } 
126
                }
127
        }
128
        if (error)
129
        {
130
                fprintf(stderr, "Cannot resolve hostname '%s'\n", IPaddr);
131
                nodeid_free(s);
132
                s = NULL;
133
        }
134
        if (result)
135
                freeaddrinfo(result);
136

    
137
        return s;
138
}
139

    
140
struct nodeID *net_helper_init(const char *my_addr, int port, const char *config)
141
{
142
        int res;
143
        struct nodeID *myself = NULL;;
144

    
145
        if (my_addr && port > 0)
146
        {
147
                myself = create_node(my_addr, port);
148
                if (myself)
149
                        myself->fd =  socket(myself->addr.ss_family, SOCK_DGRAM, 0);
150
                if (myself && myself->fd >= 0)
151
                        switch (myself->addr.ss_family)
152
                        {
153
                                case (AF_INET):
154
                                        res = bind(myself->fd, (struct sockaddr *)&myself->addr, sizeof(struct sockaddr_in));
155
                                        break;
156
                                case (AF_INET6):
157
                                        res = bind(myself->fd, (struct sockaddr *)&myself->addr, sizeof(struct sockaddr_in6));
158
                                        break;
159
                                default:
160
                                        fprintf(stderr, "Cannot resolve address family %d in bind\n", myself->addr.ss_family);
161
                                        res = -1;
162
                                        break;
163
                        }
164
                if (myself && (myself->fd < 0 || res < 0))
165
                {
166
                        nodeid_free(myself);
167
                        myself = NULL;
168
                }
169

    
170
        }
171
        return myself;
172
}
173

    
174
void bind_msg_type (uint8_t msgtype)
175
{
176
}
177

    
178
int send_to_peer(const struct nodeID *from, const struct nodeID *to, const uint8_t *buffer_ptr, int buffer_size)
179
{
180
        return sendto(from->fd, buffer_ptr, buffer_size, MSG_CONFIRM, (const struct sockaddr *)&(to->addr), sizeof(struct sockaddr_storage));
181
}
182

    
183
int recv_from_peer(const struct nodeID *local, struct nodeID **remote, uint8_t *buffer_ptr, int buffer_size)
184
{
185
        struct nodeID * node;
186
        int res;
187
        socklen_t len;
188

    
189
        node = malloc(sizeof(struct nodeID));
190
        memset(node, 0, sizeof(struct nodeID));
191
        node->occurrences = 1;
192
        node->fd = -1;
193
        len = sizeof(struct nodeID);
194

    
195
        res = recvfrom(local->fd, buffer_ptr, buffer_size, 0, (struct sockaddr *)&(node->addr), &len);
196

    
197
        if (res <=0 )
198
        {
199
                nodeid_free(node);
200
                node = NULL;
201
        }
202
        *remote = node;
203

    
204
        return res;
205
}
206

    
207
int node_addr(const struct nodeID *s, char *addr, int len)
208
{
209
        int n = -1;
210

    
211
        if (addr && len > 0)
212
        {
213
                if (s)
214
                {
215
                        n = nodeid_dump((uint8_t *) addr, s, len);
216
                        if (n>0)
217
                                addr[n-1] = '\0';
218
                } else
219
                        n = snprintf(addr, len , "None");
220
        }
221
        return n;
222
}
223

    
224
struct nodeID *nodeid_dup(const struct nodeID *s)
225
{
226
        struct nodeID * n;
227

    
228
        n = (struct nodeID *) s;
229
        if (n)
230
                n->occurrences++;
231
  return n;
232
}
233

    
234
int nodeid_equal(const struct nodeID *s1, const struct nodeID *s2)
235
{
236
        if (s1 && s2)
237
                return (nodeid_cmp(s1, s2) == 0) ? 1 : 0;
238
        return 0;
239
}
240

    
241
int nodeid_cmp(const struct nodeID *s1, const struct nodeID *s2)
242
{
243
        char ip1[INET6_ADDRSTRLEN], ip2[INET6_ADDRSTRLEN];
244
        int res = 0;
245

    
246
        if (s1 && s2 && (s1 != s2))
247
        {
248
                node_ip(s1, ip1, INET6_ADDRSTRLEN);
249
                node_ip(s2, ip2, INET6_ADDRSTRLEN);
250
                res = strcmp(ip1, ip2);
251
                if (res == 0)
252
                        res = node_port(s1) - node_port(s2);
253
        } else {
254
                if (s1 && !s2)
255
                        res = 1;
256
                if (s2 && !s1)
257
                        res = -1;
258
        }
259
        return res;
260
}
261

    
262
int nodeid_dump(uint8_t *b, const struct nodeID *s, size_t max_write_size)
263
{
264
        char ip[INET6_ADDRSTRLEN];
265
        int port;
266
        int res = -1;
267

    
268
        if (s && b)
269
        {
270
                node_ip(s, ip, INET6_ADDRSTRLEN);
271
                port = node_port(s);
272
                if (max_write_size >= strlen(ip) + 1 + 5)
273
                        res = sprintf((char *)b, "%s:%d-", ip, port);
274
        }
275
        return res;
276
}
277

    
278
struct nodeID *nodeid_undump(const uint8_t *b, int *len)
279
{
280
        char * ptr;
281
        char * socket;
282
        int port;
283
        struct nodeID *res = NULL;
284

    
285
        if (b && len)
286
        {
287
                ptr = strchr((const char *) b, '-');
288
                *len = ptr-(char *)b + 1;
289
                socket = malloc(sizeof(char) * (*len));
290
                memmove(socket, b, sizeof(char) * (*len));
291
                socket[(*len)-1] = '\0';
292

    
293
                ptr = strrchr(socket, ':');
294
                port = atoi(ptr+1);
295

    
296
                *ptr = '\0';
297

    
298
                res = create_node(socket, port);
299
                free(socket);
300
        }
301
        return res;
302
}
303

    
304
void nodeid_free(struct nodeID *s)
305
{
306
        if (s)
307
        {
308
                s->occurrences--;
309
                if (s->occurrences == 0)
310
                {
311
                        if (s->fd >= 0)
312
                                close(s->fd);
313
                        free(s);
314
                }
315
        }
316
}
317

    
318
int node_ip(const struct nodeID *s, char *ip, int len)
319
{
320
        const char *res = NULL;
321

    
322
        switch (s->addr.ss_family)
323
        {
324
                case AF_INET:
325
                        res = inet_ntop(s->addr.ss_family, &((const struct sockaddr_in *)&s->addr)->sin_addr, ip, len);
326
                        break;
327
                case AF_INET6:
328
                        res = inet_ntop(s->addr.ss_family, &((const struct sockaddr_in6 *)&s->addr)->sin6_addr, ip, len);
329
                        break;
330
        }
331
        if (!res && len)
332
                ip[0] = '\0';
333

    
334
        return res ? 0 : -1;
335
}
336

    
337
int node_port(const struct nodeID *s)
338
{
339
        int res = -1;
340

    
341
        switch (s->addr.ss_family) {
342
                case AF_INET:
343
                        res = ntohs(((const struct sockaddr_in *) &s->addr)->sin_port);
344
                        break;
345
                case AF_INET6:
346
                        res = ntohs(((const struct sockaddr_in6 *)&s->addr)->sin6_port);
347
                        break;
348
        }
349
        return res;
350
}