source: roaraudio/libroar/nnode.c @ 3437:4289f31e687f

Last change on this file since 3437:4289f31e687f was 2811:3d2f0ab1b673, checked in by phi, 15 years ago

added nnode.[ch], added nnode support to ctl.c

File size: 8.2 KB
Line 
1//nnode.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2009
5 *
6 *  This file is part of libroar a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  libroar is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 *  NOTE for everyone want's to change something and send patches:
24 *  read README and HACKING! There a addition information on
25 *  the license of this document you need to read before you send
26 *  any patches.
27 *
28 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
29 *  or libpulse*:
30 *  The libs libroaresd, libroararts and libroarpulse link this lib
31 *  and are therefore GPL. Because of this it may be illigal to use
32 *  them with any software that uses libesd, libartsc or libpulse*.
33 */
34
35#include "libroar.h"
36
37#define _CHECK(x) if ( (x) == NULL ) return -1
38
39int roar_nnode_new        (struct roar_nnode * nnode, int socktype) {
40 _CHECK(nnode);
41
42 memset(nnode, 0, sizeof(struct roar_nnode));
43
44 nnode->socktype = socktype;
45
46 return 0;
47}
48
49int roar_nnode_new_from_af(struct roar_nnode * nnode, int af) {
50 int socktype;
51
52 _CHECK(nnode);
53
54 switch (af) {
55#ifdef ROAR_HAVE_IPV4
56  case AF_INET:   socktype = ROAR_SOCKET_TYPE_INET;   break;
57#endif
58#ifdef ROAR_HAVE_IPV6
59  case AF_INET6:  socktype = ROAR_SOCKET_TYPE_INET6;  break;
60#endif
61#ifdef ROAR_HAVE_UNIX
62  case AF_UNIX:   socktype = ROAR_SOCKET_TYPE_UNIX;   break;
63#endif
64#ifdef ROAR_HAVE_LIBDNET
65  case AF_DECnet: socktype = ROAR_SOCKET_TYPE_DECNET; break;
66#endif
67#ifdef ROAR_HAVE_IPX
68  case AF_IPX:    socktype = ROAR_SOCKET_TYPE_IPX;    break;
69#endif
70  default:
71    return -1;
72   break;
73 }
74
75 if ( roar_nnode_new(nnode, socktype) == -1 )
76  return -1;
77
78 return 0;
79}
80
81int roar_nnode_new_from_sockaddr(struct roar_nnode * nnode, struct sockaddr * addr, socklen_t len) {
82 _CHECK(nnode);
83 _CHECK(addr);
84
85 ROAR_DBG("roar_nnode_new_from_sockaddr(nnode=%p, addr=%p, len=%lu) = ?", nnode, addr, (unsigned long)len);
86
87 if ( len < sizeof(addr->sa_family) )
88  return -1;
89
90 ROAR_DBG("roar_nnode_new_from_sockaddr(nnode=%p, addr=%p, len=%lu) = ?", nnode, addr, (unsigned long)len);
91
92 if ( roar_nnode_new_from_af(nnode, addr->sa_family) == -1 )
93  return -1;
94
95 ROAR_DBG("roar_nnode_new_from_sockaddr(nnode=%p, addr=%p, len=%lu) = ?", nnode, addr, (unsigned long)len);
96
97 switch (addr->sa_family) {
98#ifdef ROAR_HAVE_IPV4
99  case AF_INET:
100    if ( len < sizeof(struct sockaddr_in) )
101     return -1;
102
103    memcpy(nnode->addr.inet4, &(((struct sockaddr_in*)addr)->sin_addr), sizeof(nnode->addr.inet4));
104   break;
105#endif
106#ifdef ROAR_HAVE_IPV6
107  case AF_INET6:
108    if ( len < sizeof(struct sockaddr_in6) )
109     return -1;
110
111    memcpy(nnode->addr.inet6, ((struct sockaddr_in6*)addr)->sin6_addr.s6_addr, sizeof(nnode->addr.inet6));
112   break;
113#endif
114#ifdef ROAR_HAVE_UNIX
115  case AF_UNIX:
116    // nothing to do/save here.
117   break;
118#endif
119#ifdef ROAR_HAVE_LIBDNET
120  case AF_DECnet:
121    if ( len < sizeof(struct sockaddr_dn) )
122     return -1;
123
124    nnode->addr.decnet.node  =  ((struct sockaddr_dn*)addr)->sdn_add.a_addr[0];
125    nnode->addr.decnet.node |= (((struct sockaddr_dn*)addr)->sdn_add.a_addr[1] & 0x03) << 8;
126    nnode->addr.decnet.area  =  ((struct sockaddr_dn*)addr)->sdn_add.a_addr[1] >> 2;
127   break;
128#endif
129#ifdef ROAR_HAVE_IPX
130  case AF_IPX:
131    return -1;
132   break;
133#endif
134  default:
135    return -1;
136   break;
137 }
138
139 ROAR_DBG("roar_nnode_new_from_sockaddr(nnode=%p, addr=%p, len=%lu) = 0", nnode, addr, (unsigned long)len);
140 return 0;
141}
142
143int roar_nnode_free       (struct roar_nnode * nnode) {
144 _CHECK(nnode);
145
146 return 0;
147}
148
149int roar_nnode_get_socktype (struct roar_nnode * nnode) {
150 _CHECK(nnode);
151
152 return nnode->socktype;
153}
154
155int roar_nnode_to_str     (struct roar_nnode * nnode, char * str, size_t len) {
156 // Format: PROTO: nodename[nodeaddr]
157 char proto[7]    = "???";
158 char nodename[4] = "";
159 char nodeaddr[48 /* IPv6 */] = "???";
160
161 _CHECK(nnode);
162
163 if ( len == 0 )
164  return 0;
165
166 _CHECK(str);
167
168 if ( len == 1 ) {
169  *str = 0;
170  return 0;
171 }
172
173 switch (nnode->socktype) {
174  case ROAR_SOCKET_TYPE_UNIX:
175    strcpy(proto,     "UNIX");
176    strcpy(nodeaddr, "LOCAL");
177   break;
178  case ROAR_SOCKET_TYPE_INET:
179    strcpy(proto,     "IPv4");
180    sprintf(nodeaddr, "%i.%i.%i.%i",
181                 nnode->addr.inet4[0], nnode->addr.inet4[1],
182                 nnode->addr.inet4[2], nnode->addr.inet4[3]
183           );
184   break;
185  case ROAR_SOCKET_TYPE_DECNET:
186    strcpy(proto,     "DECnet");
187    sprintf(nodeaddr, "%i.%i", nnode->addr.decnet.area, nnode->addr.decnet.node);
188   break;
189  case ROAR_SOCKET_TYPE_INET6:
190    strcpy(proto,     "IPv6");
191   break;
192  case ROAR_SOCKET_TYPE_IPX:
193    strcpy(proto,     "IPX");
194   break;
195  default:
196    sprintf(proto, "P#%i", nnode->socktype);
197   break;
198 }
199
200 if ( *nodename ) {
201  snprintf(str, len, "%s: %s[%s]", proto, nodename, nodeaddr);
202 } else {
203  snprintf(str, len, "%s: %s", proto, nodeaddr);
204 }
205
206 str[len-1] = 0;
207
208 return 0;
209}
210
211int roar_nnode_from_blob  (struct roar_nnode * nnode, void * blob, size_t * len) {
212 uint16_t socktype;
213
214 _CHECK(nnode);
215 _CHECK(blob);
216 _CHECK(len);
217
218 if ( *len < 2 )
219  return -1;
220
221 memcpy(&socktype, blob, 2);
222
223 socktype = ROAR_NET2HOST16(socktype);
224
225 if ( roar_nnode_new(nnode, socktype) == -1 )
226  return -1;
227
228 switch (socktype) {
229  case ROAR_SOCKET_TYPE_UNIX:
230    *len = 2;
231   break;
232  case ROAR_SOCKET_TYPE_INET:
233    if ( *len < 6 )
234     return -1;
235
236    memcpy(nnode->addr.inet4, blob+2, 4);
237
238    *len = 6;
239   break;
240  case ROAR_SOCKET_TYPE_DECNET:
241    if ( *len < 4 )
242     return -1;
243
244    nnode->addr.decnet.node   =  ((unsigned char*)blob)[2];
245    nnode->addr.decnet.node   = (((unsigned char*)blob)[3] & 0x03) << 8;
246    nnode->addr.decnet.area   =  ((unsigned char*)blob)[3] >> 2;
247
248    *len = 4;
249   break;
250  case ROAR_SOCKET_TYPE_INET6:
251    if ( *len < 18 )
252     return -1;
253
254    memcpy(nnode->addr.inet4, blob+2, 16);
255
256    *len = 18;
257   break;
258  case ROAR_SOCKET_TYPE_IPX:
259  default:
260    return -1;
261   break;
262 }
263
264 return 0;
265}
266
267int roar_nnode_to_blob    (struct roar_nnode * nnode, void * blob, size_t * len) {
268 uint16_t socktype_net;
269
270 _CHECK(nnode);
271 _CHECK(blob);
272 _CHECK(len);
273
274 if ( *len < 2 )
275  return -1;
276
277 socktype_net = ROAR_HOST2NET16(nnode->socktype);
278
279 memcpy(blob, &socktype_net, 2);
280
281 switch (nnode->socktype) {
282  case ROAR_SOCKET_TYPE_UNIX:
283    // all UNIX sockets allways match.
284    *len = 2;
285   break;
286  case ROAR_SOCKET_TYPE_INET:
287    if ( *len < 6 )
288     return -1;
289
290    memcpy(blob+2, nnode->addr.inet4, 4);
291    *len = 6;
292
293   break;
294  case ROAR_SOCKET_TYPE_DECNET:
295    if ( *len < 4 )
296     return -1;
297
298    ((unsigned char*)blob)[2] =   nnode->addr.decnet.node & 0x00FF;
299    ((unsigned char*)blob)[3] = ((nnode->addr.decnet.node & 0x0300) >> 8) | (nnode->addr.decnet.area << 2);
300    *len = 4;
301
302    return -1;
303   break;
304  case ROAR_SOCKET_TYPE_INET6:
305    if ( *len < 18 )
306     return -1;
307
308    memcpy(blob+2, nnode->addr.inet4, 16);
309    *len = 18;
310
311   break;
312  case ROAR_SOCKET_TYPE_IPX:
313  default:
314    return -1;
315   break;
316 }
317
318 return 0;
319}
320
321int roar_nnode_cmp        (struct roar_nnode * n0, struct roar_nnode * n1) {
322 _CHECK(n0);
323 _CHECK(n1);
324
325 if ( n0->socktype != n1->socktype )
326  return 1;
327
328 switch (n0->socktype) {
329  case ROAR_SOCKET_TYPE_UNIX:
330    // all UNIX sockets allways match.
331   break;
332  case ROAR_SOCKET_TYPE_INET:
333    if ( memcmp(n0->addr.inet4, n1->addr.inet4, sizeof(n0->addr.inet4)) != 0 )
334     return 1;
335   break;
336  case ROAR_SOCKET_TYPE_DECNET:
337    if ( n0->addr.decnet.area != n1->addr.decnet.area ||
338         n0->addr.decnet.node != n1->addr.decnet.node   )
339     return 1;
340   break;
341  case ROAR_SOCKET_TYPE_INET6:
342    if ( memcmp(n0->addr.inet6, n1->addr.inet6, sizeof(n0->addr.inet6)) != 0 )
343     return 1;
344   break;
345  case ROAR_SOCKET_TYPE_IPX:
346  default:
347    return -1;
348   break;
349 }
350
351 return 0;
352}
353
354//ll
Note: See TracBrowser for help on using the repository browser.