source: roaraudio/libroar/serverinfo.c @ 5959:b568f7b84e08

Last change on this file since 5959:b568f7b84e08 was 5959:b568f7b84e08, checked in by phi, 10 years ago

Also use uname() and hostid for seeding nonce generator.

File size: 9.5 KB
Line 
1//serverinfo.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2013
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  return -1;
178
179 _add(ROAR_ITST_VERSION, version);
180 _add(ROAR_ITST_LOCATION, location);
181 _add(ROAR_ITST_DESCRIPTION, description);
182 _add(ROAR_ITST_CONTACT, contact);
183 _add(ROAR_ITST_SERIAL, serial);
184 _add(ROAR_ITST_ADDRESS, address);
185 _add(ROAR_ITST_UIURL, uiurl);
186 _add(ROAR_ITST_LICENSE, license);
187 _add(ROAR_ITST_HOSTID, hostid);
188 _add(ROAR_ITST_BUILD, build);
189 _add(ROAR_ITST_UN_SYSNAME, un.sysname);
190 _add(ROAR_ITST_UN_RELEASE, un.release);
191 _add(ROAR_ITST_UN_NODENAME, un.nodename);
192 _add(ROAR_ITST_UN_MACHINE, un.machine);
193
194 if ( needlen > LIBROAR_BUFFER_MSGDATA ) {
195  if ( data == NULL )
196   return -1;
197
198  mesdata = roar_mm_malloc(needlen);
199
200  if ( mesdata == NULL )
201   return -1;
202
203  *data = mesdata;
204 } else {
205  mesdata = mes->data;
206 }
207
208 memset(mes, 0, sizeof(struct roar_message));
209
210 mes->datalen = needlen;
211
212 d16 = (uint16_t*)mesdata;
213
214 mesdata[0] = 0; // version
215 mesdata[1] = 0; // reserved
216
217 d16[1] = ROAR_HOST2NET16(idx);
218
219 dptr = &(d16[2]);
220
221 for (i = 0; i < idx; i++) {
222  dptr[0] = ROAR_HOST2NET16(iebuf[i].type & 0xFF);
223  dptr[1] = ROAR_HOST2NET16(iebuf[i].len);
224  dptr += 2;
225 }
226
227 textpart = mesdata + (4 + 4*idx);
228
229 for (i = 0; i < idx; i++) {
230  memcpy(textpart, iebuf[i].buf, iebuf[i].len);
231  textpart += iebuf[i].len;
232 }
233
234 return 0;
235}
236
237struct roar_server_info * roar_server_info_from_mes(struct roar_message * mes, void * data) {
238 struct ie iebuf[sizeof(struct roar_server_info)/sizeof(char*)];
239 struct ie * ieptr;
240 struct roar_server_info * ret = NULL;
241 uint16_t * d16, * dptr;
242 size_t idx;
243 size_t i;
244 size_t needlen = 4;
245 char * textpart;
246 char * textbuf;
247 const char ** tptr;
248 char * mesdata;
249
250 ROAR_DBG("roar_server_info(mes=%p{.datalen=%llu) = ?", mes, (long long unsigned int)mes->datalen);
251
252 if ( mes == NULL )
253  return NULL;
254
255 if ( data == NULL ) {
256  mesdata = mes->data;
257 } else {
258  mesdata = data;
259 }
260
261 memset(iebuf, 0, sizeof(iebuf));
262
263 ROAR_DBG("roar_server_info(mes=%p) = ?", mes);
264
265 // some basic texts like version:
266 if ( mes->datalen < needlen )
267  return NULL;
268
269 ROAR_DBG("roar_server_info(mes=%p) = ?", mes);
270
271 if ( mesdata[0] != 0 ) /* version */
272  return NULL;
273
274 ROAR_DBG("roar_server_info(mes=%p) = ?", mes);
275
276 if ( mesdata[1] != 0 ) /* reserved */
277  return NULL;
278
279 ROAR_DBG("roar_server_info(mes=%p) = ?", mes);
280
281 d16 = (uint16_t*)mesdata;
282
283 idx = ROAR_NET2HOST16(d16[1]);
284
285 ROAR_DBG("roar_server_info(mes=%p): idx=%i", mes, idx);
286
287 // return error if our index buffer is too short.
288 if ( idx > (sizeof(iebuf)/sizeof(*iebuf)) )
289  return NULL;
290
291 ROAR_DBG("roar_server_info(mes=%p) = ?", mes);
292
293 ROAR_DBG("roar_server_info(mes=%p): needlen=%llu", mes, (long long unsigned int)needlen);
294
295 needlen += 4*idx;
296
297 // recheck if we have a complet index.
298 if ( mes->datalen < needlen )
299  return NULL;
300
301 ROAR_DBG("roar_server_info(mes=%p) = ?", mes);
302
303 d16 = (uint16_t*)mesdata;
304 dptr = &(d16[2]);
305
306 textpart = mesdata + (4 + 4*idx);
307
308 ROAR_DBG("roar_server_info(mes=%p): needlen=%llu", mes, (long long unsigned int)needlen);
309
310 for (i = 0; i < idx; i++) {
311  iebuf[i].type = ROAR_NET2HOST16(dptr[0]) & 0xFF;
312  iebuf[i].len  = ROAR_NET2HOST16(dptr[1]);
313  iebuf[i].buf  = textpart;
314  needlen  += iebuf[i].len;
315  textpart += iebuf[i].len;
316  dptr += 2;
317  ROAR_DBG("roar_server_info(mes=%p): iebuf[i]={.len=%llu,...}", mes, (long long unsigned int)iebuf[i].len);
318 }
319
320 ROAR_DBG("roar_server_info(mes=%p): needlen=%llu", mes, (long long unsigned int)needlen);
321
322 // recheck if we have all the data...
323 if ( mes->datalen < needlen )
324  return NULL;
325
326 ROAR_DBG("roar_server_info(mes=%p) = ?", mes);
327
328 // alloc the needed space. this can be reduced in future to the actual needed value.
329 ret = roar_mm_malloc(2*sizeof(struct roar_server_info) + mes->datalen);
330
331 if ( ret == NULL )
332  return NULL;
333
334 ROAR_DBG("roar_server_info(mes=%p) = ?", mes);
335
336 // for the size see the alloc call above.
337 memset(ret, 0, 2*sizeof(struct roar_server_info) + mes->datalen);
338
339 textbuf = (char*)ret + sizeof(struct roar_server_info);
340
341 for (i = 0; i < idx; i++) {
342  ieptr = &(iebuf[i]);
343
344   // ignore empty fields
345  if ( ieptr->len == 0 )
346   continue;
347  if ( ieptr->len == 1 && ieptr->buf[0] == 0 )
348   continue;
349
350#define _ck(TYPE,member) case TYPE: tptr = &(ret->member); break;
351  switch (ieptr->type) {
352   _ck(ROAR_ITST_VERSION, version);
353   _ck(ROAR_ITST_LOCATION, location);
354   _ck(ROAR_ITST_DESCRIPTION, description);
355   _ck(ROAR_ITST_CONTACT, contact);
356   _ck(ROAR_ITST_SERIAL, serial);
357   _ck(ROAR_ITST_ADDRESS, address);
358   _ck(ROAR_ITST_UIURL, uiurl);
359   _ck(ROAR_ITST_HOSTID, hostid);
360   _ck(ROAR_ITST_LICENSE, license);
361   _ck(ROAR_ITST_BUILD, build);
362   _ck(ROAR_ITST_UN_SYSNAME, un.sysname);
363   _ck(ROAR_ITST_UN_RELEASE, un.release);
364   _ck(ROAR_ITST_UN_NODENAME, un.nodename);
365   _ck(ROAR_ITST_UN_MACHINE, un.machine);
366   default:
367     continue;
368    break;
369  }
370#undef _ck
371
372  *tptr = textbuf;
373   memcpy(textbuf, ieptr->buf, ieptr->len);
374   textbuf += ieptr->len;
375   *textbuf = 0; // set \0
376   textbuf++;
377 }
378
379 ROAR_DBG("roar_server_info(mes=%p) = %p", mes, ret);
380
381 return ret;
382}
383
384
385//ll
Note: See TracBrowser for help on using the repository browser.