source: roaraudio/libroar/serverinfo.c @ 5432:956f6af25715

Last change on this file since 5432:956f6af25715 was 5387:ec00c0a72024, checked in by phi, 12 years ago

added function to get serverinfo for library as well as libinfo command for roarctl to list those infos

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