source: roaraudio/libroar/serverinfo.c @ 6052:d48765b2475e

Last change on this file since 6052:d48765b2475e was 6052:d48765b2475e, checked in by phi, 9 years ago

updated copyright headers

File size: 9.9 KB
Line 
1//serverinfo.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2015
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// include for uname() used by roar_library_info()
39#ifdef ROAR_HAVE_UNAME
40#include <sys/utsname.h>
41#endif
42
43struct ie {
44 int type;
45 size_t len;
46 const char * buf;
47};
48
49struct roar_server_info * roar_server_info(struct roar_connection * con) {
50 struct roar_server_info * ret;
51 struct roar_message mes;
52 uint16_t * d16;
53 char * data = NULL;
54
55 memset(&mes, 0, sizeof(mes));
56
57 mes.cmd = ROAR_CMD_SERVER_INFO;
58 mes.datalen = 2*2;
59 d16 = (uint16_t*)mes.data;
60
61 d16[0] = ROAR_HOST2NET16(0); // version
62 d16[1] = ROAR_HOST2NET16(ROAR_IT_SERVER);
63
64 if ( roar_req(con, &mes, &data) != 0 )
65  return NULL;
66
67 if ( mes.cmd != ROAR_CMD_OK )
68  return NULL;
69
70 ret = roar_server_info_from_mes(&mes, data);
71
72 if ( data != NULL )
73  roar_mm_free(data);
74
75 return ret;
76}
77
78#ifdef ROAR_HAVE_GETHOSTID
79#define _HOSTID_BUFLEN 64
80#else
81#define _HOSTID_BUFLEN 0
82#endif
83struct roar_server_info * roar_library_info(void) {
84 struct roar_server_info * ret = roar_mm_malloc(sizeof(struct roar_server_info) + _HOSTID_BUFLEN);
85#ifdef ROAR_HAVE_UNAME
86 static struct utsname utsname;
87 static int utsname_inited = 0;
88#endif
89#ifdef ROAR_HAVE_GETHOSTID
90 long hostid;
91 char * hostidbuf = ((void*)ret) + sizeof(*ret);
92#endif
93
94 if ( ret == NULL )
95  return NULL;
96
97 memset(ret, 0, sizeof(struct roar_server_info));
98
99#if 0
100+ const char * version;
101X const char * location;
102X const char * description;
103X const char * contact;
104X const char * serial;
105X const char * address;
106X const char * uiurl;
107 const char * hostid;
108+ const char * license;
109+ const char * build;
110+ struct {
111+  const char * sysname;
112+  const char * release;
113+  const char * nodename;
114+  const char * machine;
115+ } un;
116#endif
117
118 if ( ROAR_VERSION_DISTRIBUTION_STRING[0] == 0 ) {
119  ret->version = "libroar/" ROAR_VERSION_STRING " <" ROAR_DEV_VENDOR_STRING ">";
120 } else {
121  ret->version = "libroar/" ROAR_VERSION_STRING " <" ROAR_DEV_VENDOR_STRING "> (" ROAR_VERSION_DISTRIBUTION_STRING ")";
122 }
123#ifdef ROAR_HAVE_GETHOSTID
124 hostid = gethostid();
125 roar_random_salt_nonce(&hostid, sizeof(hostid));
126 snprintf(hostidbuf, _HOSTID_BUFLEN, sizeof(long) == 8 ? "0x%.16lx" : "0x%.8lx", hostid);
127 ret->hostid = hostidbuf;
128#endif
129 ret->license = ROAR_LICENSE_GPLv3_0;
130 ret->build   = ROAR_BUILD_STAMP;
131
132#ifdef ROAR_HAVE_UNAME
133 if ( !utsname_inited )
134  if ( uname(&utsname) == 0 ) {
135   utsname_inited = 1;
136   roar_random_salt_nonce(&utsname, sizeof(utsname));
137  }
138
139 if ( utsname_inited ) {
140  ret->un.sysname  = utsname.sysname;
141  ret->un.release  = utsname.release;
142  ret->un.nodename = utsname.nodename;
143  ret->un.machine  = utsname.machine;
144 }
145#endif
146#ifdef ROAR_HAVE_GETVERSIONEX
147 ret->un.sysname = "Windows";
148#endif
149
150 return ret;
151}
152
153int roar_server_info_free(struct roar_server_info * info) {
154 if ( info == NULL ) {
155  roar_err_set(ROAR_ERROR_FAULT);
156  return -1;
157 }
158
159 roar_mm_free(info);
160
161 return 0;
162}
163
164#define _add(t, m) do { if ( info->m != NULL && (sl = strlen(info->m)) != 0 ) { iebuf[idx].type = (t); iebuf[idx].len = sl; iebuf[idx].buf = (info->m); idx++; needlen += 4 + sl; } } while (0)
165
166int roar_server_info_to_mes(struct roar_message * mes, struct roar_server_info * info, void ** data) {
167 size_t needlen = 4;
168 size_t sl;
169 int idx = 0;
170 struct ie iebuf[sizeof(struct roar_server_info)/sizeof(char*)];
171 uint16_t * d16, * dptr;
172 char * textpart;
173 int i;
174 char * mesdata;
175
176 if ( mes == NULL || info == NULL ) {
177  roar_err_set(ROAR_ERROR_FAULT);
178  return -1;
179 }
180
181 _add(ROAR_ITST_VERSION, version);
182 _add(ROAR_ITST_LOCATION, location);
183 _add(ROAR_ITST_DESCRIPTION, description);
184 _add(ROAR_ITST_CONTACT, contact);
185 _add(ROAR_ITST_SERIAL, serial);
186 _add(ROAR_ITST_ADDRESS, address);
187 _add(ROAR_ITST_UIURL, uiurl);
188 _add(ROAR_ITST_LICENSE, license);
189 _add(ROAR_ITST_HOSTID, hostid);
190 _add(ROAR_ITST_BUILD, build);
191 _add(ROAR_ITST_UN_SYSNAME, un.sysname);
192 _add(ROAR_ITST_UN_RELEASE, un.release);
193 _add(ROAR_ITST_UN_NODENAME, un.nodename);
194 _add(ROAR_ITST_UN_MACHINE, un.machine);
195
196 if ( needlen > LIBROAR_BUFFER_MSGDATA ) {
197  if ( data == NULL ) {
198   roar_err_set(ROAR_ERROR_MSGSIZE);
199   return -1;
200  }
201
202  mesdata = roar_mm_malloc(needlen);
203
204  if ( mesdata == NULL )
205   return -1;
206
207  *data = mesdata;
208 } else {
209  mesdata = mes->data;
210 }
211
212 memset(mes, 0, sizeof(struct roar_message));
213
214 mes->datalen = needlen;
215
216 d16 = (uint16_t*)mesdata;
217
218 mesdata[0] = 0; // version
219 mesdata[1] = 0; // reserved
220
221 d16[1] = ROAR_HOST2NET16(idx);
222
223 dptr = &(d16[2]);
224
225 for (i = 0; i < idx; i++) {
226  dptr[0] = ROAR_HOST2NET16(iebuf[i].type & 0xFF);
227  dptr[1] = ROAR_HOST2NET16(iebuf[i].len);
228  dptr += 2;
229 }
230
231 textpart = mesdata + (4 + 4*idx);
232
233 for (i = 0; i < idx; i++) {
234  memcpy(textpart, iebuf[i].buf, iebuf[i].len);
235  textpart += iebuf[i].len;
236 }
237
238 return 0;
239}
240
241struct roar_server_info * roar_server_info_from_mes(struct roar_message * mes, void * data) {
242 struct ie iebuf[sizeof(struct roar_server_info)/sizeof(char*)];
243 struct ie * ieptr;
244 struct roar_server_info * ret = NULL;
245 uint16_t * d16, * dptr;
246 size_t idx;
247 size_t i;
248 size_t needlen = 4;
249 char * textpart;
250 char * textbuf;
251 const char ** tptr;
252 char * mesdata;
253
254 ROAR_DBG("roar_server_info(mes=%p{.datalen=%llu) = ?", mes, (long long unsigned int)mes->datalen);
255
256 if ( mes == NULL ) {
257  roar_err_set(ROAR_ERROR_FAULT);
258  return NULL;
259 }
260
261 if ( data == NULL ) {
262  mesdata = mes->data;
263 } else {
264  mesdata = data;
265 }
266
267 memset(iebuf, 0, sizeof(iebuf));
268
269 ROAR_DBG("roar_server_info(mes=%p) = ?", mes);
270
271 // some basic texts like version:
272 if ( mes->datalen < needlen ) {
273  roar_err_set(ROAR_ERROR_PROTO);
274  return NULL;
275 }
276
277 ROAR_DBG("roar_server_info(mes=%p) = ?", mes);
278
279 if ( mesdata[0] != 0 ) { /* version */
280  roar_err_set(ROAR_ERROR_NSVERSION);
281  return NULL;
282 }
283
284 ROAR_DBG("roar_server_info(mes=%p) = ?", mes);
285
286 if ( mesdata[1] != 0 ) { /* reserved */
287  roar_err_set(ROAR_ERROR_PROTO);
288  return NULL;
289 }
290
291 ROAR_DBG("roar_server_info(mes=%p) = ?", mes);
292
293 d16 = (uint16_t*)mesdata;
294
295 idx = ROAR_NET2HOST16(d16[1]);
296
297 ROAR_DBG("roar_server_info(mes=%p): idx=%i", mes, idx);
298
299 // return error if our index buffer is too short.
300 if ( idx > (sizeof(iebuf)/sizeof(*iebuf)) ) {
301  roar_err_set(ROAR_ERROR_MSGSIZE);
302  return NULL;
303 }
304
305 ROAR_DBG("roar_server_info(mes=%p) = ?", mes);
306
307 ROAR_DBG("roar_server_info(mes=%p): needlen=%llu", mes, (long long unsigned int)needlen);
308
309 needlen += 4*idx;
310
311 // recheck if we have a complet index.
312 if ( mes->datalen < needlen ) {
313  roar_err_set(ROAR_ERROR_PROTO);
314  return NULL;
315 }
316
317 ROAR_DBG("roar_server_info(mes=%p) = ?", mes);
318
319 d16 = (uint16_t*)mesdata;
320 dptr = &(d16[2]);
321
322 textpart = mesdata + (4 + 4*idx);
323
324 ROAR_DBG("roar_server_info(mes=%p): needlen=%llu", mes, (long long unsigned int)needlen);
325
326 for (i = 0; i < idx; i++) {
327  iebuf[i].type = ROAR_NET2HOST16(dptr[0]) & 0xFF;
328  iebuf[i].len  = ROAR_NET2HOST16(dptr[1]);
329  iebuf[i].buf  = textpart;
330  needlen  += iebuf[i].len;
331  textpart += iebuf[i].len;
332  dptr += 2;
333  ROAR_DBG("roar_server_info(mes=%p): iebuf[i]={.len=%llu,...}", mes, (long long unsigned int)iebuf[i].len);
334 }
335
336 ROAR_DBG("roar_server_info(mes=%p): needlen=%llu", mes, (long long unsigned int)needlen);
337
338 // recheck if we have all the data...
339 if ( mes->datalen < needlen ) {
340  roar_err_set(ROAR_ERROR_PROTO);
341  return NULL;
342 }
343
344 ROAR_DBG("roar_server_info(mes=%p) = ?", mes);
345
346 // alloc the needed space. this can be reduced in future to the actual needed value.
347 ret = roar_mm_malloc(2*sizeof(struct roar_server_info) + mes->datalen);
348
349 if ( ret == NULL )
350  return NULL;
351
352 ROAR_DBG("roar_server_info(mes=%p) = ?", mes);
353
354 // for the size see the alloc call above.
355 memset(ret, 0, 2*sizeof(struct roar_server_info) + mes->datalen);
356
357 textbuf = (char*)ret + sizeof(struct roar_server_info);
358
359 for (i = 0; i < idx; i++) {
360  ieptr = &(iebuf[i]);
361
362   // ignore empty fields
363  if ( ieptr->len == 0 )
364   continue;
365  if ( ieptr->len == 1 && ieptr->buf[0] == 0 )
366   continue;
367
368#define _ck(TYPE,member) case TYPE: tptr = &(ret->member); break;
369  switch (ieptr->type) {
370   _ck(ROAR_ITST_VERSION, version);
371   _ck(ROAR_ITST_LOCATION, location);
372   _ck(ROAR_ITST_DESCRIPTION, description);
373   _ck(ROAR_ITST_CONTACT, contact);
374   _ck(ROAR_ITST_SERIAL, serial);
375   _ck(ROAR_ITST_ADDRESS, address);
376   _ck(ROAR_ITST_UIURL, uiurl);
377   _ck(ROAR_ITST_HOSTID, hostid);
378   _ck(ROAR_ITST_LICENSE, license);
379   _ck(ROAR_ITST_BUILD, build);
380   _ck(ROAR_ITST_UN_SYSNAME, un.sysname);
381   _ck(ROAR_ITST_UN_RELEASE, un.release);
382   _ck(ROAR_ITST_UN_NODENAME, un.nodename);
383   _ck(ROAR_ITST_UN_MACHINE, un.machine);
384   default:
385     continue;
386    break;
387  }
388#undef _ck
389
390  *tptr = textbuf;
391   memcpy(textbuf, ieptr->buf, ieptr->len);
392   textbuf += ieptr->len;
393   *textbuf = 0; // set \0
394   textbuf++;
395 }
396
397 ROAR_DBG("roar_server_info(mes=%p) = %p", mes, ret);
398
399 return ret;
400}
401
402
403//ll
Note: See TracBrowser for help on using the repository browser.