source: roaraudio/libroar/nnode.c @ 3728:b2f45541bb6a

Last change on this file since 3728:b2f45541bb6a was 3728:b2f45541bb6a, checked in by phi, 14 years ago

added roar_nnode_new_from_fh()

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