source: roaraudio/roard/req.c @ 6034:ac2a2a593b1f

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

creatively work around useless and wrong compiler warnings

File size: 47.5 KB
Line 
1//req.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2014
5 *
6 *  This file is part of roard 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 *  RoarAudio 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 */
25
26/* ckport options:
27 * massage <-> object converters:
28 * ckport: ignore-symbol: roar_stream_s2m of target libroar0
29 * ckport: ignore-symbol: roar_stream_m2s of target libroar0
30 * ckport: ignore-symbol: roar_ctl_c2m of target libroar0
31 * ckport: ignore-symbol: roar_ctl_ia2m of target libroar0
32 * ckport: ignore-symbol: roar_ctl_m2f of target libroar0
33 * Caps support:
34 * ckport: ignore-symbol: roar_caps_from_msg of target libroar0
35 * ckport: ignore-symbol: roar_caps_to_msg of target libroar0
36 * Server info:
37 * ckport: ignore-symbol: roar_server_info_to_mes of target libroar0
38 * PASSFH:
39 * ckport: ignore-symbol: roar_socket_recv_fh of target libroar0
40 * AUTH:
41 * ckport: ignore-symbol: roar_auth_from_mes of target libroar0
42 * ckport: ignore-symbol: roar_auth_to_mes of target libroar0
43 * Events:
44 * ckport: ignore-symbol: roar_event_from_blob of target libroar0
45 * Filter:
46 * ckport: ignore-symbol: roar_filter_match of target libroar0
47 */
48
49#include "roard.h"
50
51// include for uname() used by req_on_server_info()
52#ifdef ROAR_HAVE_UNAME
53#include <sys/utsname.h>
54#endif
55
56static void * _dataspace(struct roar_message * mes, char ** data, uint32_t flags[2], size_t len) {
57 if ( len <= LIBROAR_BUFFER_MSGDATA )
58  return mes->data;
59
60 if ( *data != NULL )
61  roar_mm_free(*data);
62
63 *data = roar_mm_malloc(len);
64
65 ROAR_DBG("_dataspace(mes=%p, data=%p, flags=%p, len=%llu): *data=%p", mes, data, flags, (long long unsigned int)len, *data);
66
67 if ( *data == NULL )
68  return NULL;
69
70 flags[1] |= COMMAND_FLAG_OUT_LONGDATA;
71
72 return *data;
73}
74
75int req_on_noop        (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
76 (void)client, (void)data, (void)flags;
77 mes->cmd     = ROAR_CMD_OK;
78 mes->pos     = g_pos;
79 mes->datalen = 0;
80 return 0;
81}
82
83int req_on_quit        (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
84 (void)client, (void)data;
85 mes->cmd     = ROAR_CMD_OK;
86 mes->pos     = g_pos;
87 mes->datalen = 0;
88 flags[1] |= COMMAND_FLAG_OUT_DELETE;
89 return 0;
90}
91
92int req_on_identify    (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
93 struct roar_client_server * cs;
94 struct roar_client        * c;
95 int max_len;
96
97 (void)data, (void)flags;
98
99 if ( mes->datalen < 1 )
100  return -1;
101
102 clients_get_server(client, &cs);
103
104 c = ROAR_CLIENT(cs);
105
106 if ( mes->data[0] == 1 ) {
107  if ( c->pid == -1 ) {
108   c->pid       = ROAR_NET2HOST32(*(uint32_t*)((mes->data)+1));
109   ROAR_DBG("req_on_identify(): new PID: c->pid = %i", c->pid);
110  }
111
112  ROAR_DBG("req_on_identify(): final PID: c->pid = %i", c->pid);
113
114  max_len = (mes->datalen - 5) < (ROAR_BUFFER_NAME-1) ? (mes->datalen - 5) : (ROAR_BUFFER_NAME-1);
115
116  strncpy(c->name, mes->data + 5, max_len);
117  c->name[max_len] = 0;
118
119  // we set the acclevel to IDENTED here.
120  // if it is alreay > IDENTED we reset it anyway
121  // as potential auth relevent data changed.
122  cs->acclev = ACCLEV_IDENTED;
123
124  mes->cmd     = ROAR_CMD_OK;
125  mes->pos     = g_pos;
126  mes->datalen = 0;
127
128  ROAR_DBG("req_on_identify(*): client=%i, pid=%i", client, c->pid);
129  ROAR_DBG("req_on_identify(*) = 0");
130  return 0;
131 }
132
133 return -1;
134}
135
136int req_on_auth        (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
137 struct roar_error_frame   error_frame;
138 void                    * error_data;
139 struct roar_message       error_mes;
140 struct roar_client_server * cs;
141 struct roar_auth_message    authmes;
142 int next = -1;
143 int ret;
144
145 (void)flags;
146
147 clients_get_server(client, &cs);
148
149 // TODO: add code to support some auth.
150
151 if ( roar_auth_from_mes(&authmes, mes, *data) == -1 )
152  return -1;
153
154 ROAR_INFO("req_on_auth(client=%i,...): authtype=%s(%i), len=%llu bytes", ROAR_DBG_INFO_VERBOSE,
155                           client, roar_autht2str(authmes.type), authmes.type, (long long unsigned int)authmes.len);
156
157 ROAR_DBG("req_on_auth(client=%i,...): CALL auth_client_ckeck(cs=%p, &authmes=%p, &next=%p)", client, cs, &authmes, &next);
158 ret = auth_client_ckeck(cs, &authmes, &next);
159 ROAR_DBG("req_on_auth(client=%i,...): RET %i // next=%s(%i)", client, ret, roar_autht2str(next), next);
160
161 if ( ret != 1 ) {
162  ROAR_DBG("req_on_auth(client=%i,...) = ?", client);
163
164  if ( next != -1 ) {
165   ROAR_DBG("req_on_auth(client=%i,...) = ?", client);
166   memset(&authmes, 0, sizeof(authmes));
167
168   authmes.type = next;
169
170   if ( roar_auth_to_mes(&error_mes, NULL, &authmes) == -1 )
171    return -1;
172
173   ROAR_DBG("req_on_auth(client=%i,...) = ?", client);
174
175   if ( roar_err_init(&error_frame) == -1 )
176    return -1;
177
178   ROAR_DBG("req_on_auth(client=%i,...) = ?", client);
179
180   error_frame.ra_errno = ROAR_ERROR_PERM;
181   error_frame.datalen  = error_mes.datalen;
182
183   error_data   = roar_err_buildmsg(mes, NULL, &error_frame);
184   ROAR_DBG("req_on_auth(client=%i,...): error_data=%p", client, error_data);
185
186   memcpy(error_data, error_mes.data, error_mes.datalen);
187
188   mes->cmd     = ROAR_CMD_ERROR;
189   mes->pos     = g_pos;
190
191   ROAR_DBG("req_on_auth(client=%i,...): mes=%p{.datalen=%i}", client, mes, (int)mes->datalen);
192   ROAR_DBG("req_on_auth(client=%i,...) = 0 // cmd=ERROR", client);
193   return 0;
194  }
195
196  ROAR_DBG("req_on_auth(client=%i,...) = 0", client);
197  return -1;
198 }
199
200 mes->cmd     = ROAR_CMD_OK;
201 mes->pos     = g_pos;
202 mes->datalen = 0;
203
204 ROAR_DBG("req_on_auth(client=%i,...) = 0", client);
205 return 0;
206}
207
208
209int req_on_whoami      (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
210 (void)data, (void)flags;
211
212 mes->cmd     = ROAR_CMD_OK;
213 mes->pos     = g_pos;
214 mes->datalen = 1;
215 mes->data[0] = client;
216 return 0;
217}
218
219
220int req_on_new_stream  (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
221 int stream;
222 struct roar_stream_server * ss;
223 struct roar_stream        * s;
224 struct roar_stream * source_stream;
225 struct roar_audio_info * info;
226 struct roar_audio_info * source_info;
227
228 ROAR_DBG("req_on_new_stream(client=%i, ...): creating stream...", client);
229 if ((stream = streams_new()) == -1 )
230  return -1;
231
232 ROAR_DBG("req_on_new_stream(client=%i, ...): stream=%i", client, stream);
233
234 ROAR_DBG("req_on_new_stream(client=%i, ...): getting stream...", client);
235 if ( streams_get(stream, &ss) == -1 ) {
236  streams_delete(stream);
237  return -1;
238 }
239
240 s = ROAR_STREAM(ss);
241
242 ROAR_DBG("req_on_new_stream(client=%i, ...): set client of stream...", client);
243 if ( client_stream_add(client, stream) == -1 ) {
244  streams_delete(stream);
245  return -1;
246 }
247
248 ROAR_DBG("req_on_new_stream(client=%i, ...): loading stream from message...", client);
249 if ( roar_stream_m2s(s, mes) == -1 ) {
250  streams_delete(stream);
251  return -1;
252 }
253
254 ROAR_DBG("req_on_new_stream(client=%i, ...): setting id and codec of stream...", client);
255 ROAR_STREAM(s)->id = stream; // roar_stream_m2s() resets this
256 ROAR_STREAM_SERVER(s)->codec_orgi = ROAR_STREAM(s)->info.codec;
257
258 ROAR_DBG("req_on_new_stream(client=%i, ...): setting direction stream...", client);
259 // int streams_set_dir    (int id, int dir, int defaults)
260 if ( streams_set_dir(stream, ROAR_STREAM(s)->dir, 1) == -1 ) {
261  streams_delete(stream);
262  return -1;
263 }
264
265 ROAR_DBG("req_on_new_stream(client=%i, ...): checking mixer settings...", client);
266 if ( mes->stream != -1 && mes->stream != ss->mixer_stream ) {
267  streams_delete(stream);
268  return -1;
269 }
270
271 ROAR_DBG("req_on_new_stream(client=%i, ...): setting up direction specific stream settings...", client);
272 switch (ROAR_STREAM(s)->dir) {
273  case ROAR_DIR_LIGHT_IN:
274  case ROAR_DIR_LIGHT_OUT:
275#ifndef ROAR_WITHOUT_DCOMP_LIGHT
276    info = &(ROAR_STREAM(s)->info);
277
278    info->channels = 0;
279    info->bits     = 0;
280    info->rate     = 0;
281#else
282    streams_delete(stream);
283    return -1;
284#endif
285
286   break;
287  case ROAR_DIR_MIDI_IN:
288  case ROAR_DIR_MIDI_OUT:
289#ifndef ROAR_WITHOUT_DCOMP_MIDI
290    info = &(ROAR_STREAM(s)->info);
291
292    info->channels = ROAR_MIDI_CHANNELS_DEFAULT;
293    info->bits     = ROAR_MIDI_BITS;
294    info->rate     = 0;
295#else
296    streams_delete(stream);
297    return -1;
298#endif
299
300   break;
301
302  case ROAR_DIR_RAW_IN:
303#ifndef ROAR_WITHOUT_DCOMP_RAW
304    if ( ROAR_STREAM(s)->pos_rel_id == -1     ||
305         ROAR_STREAM(s)->pos_rel_id == stream ||
306         streams_get_dir(ROAR_STREAM(s)->pos_rel_id) != ROAR_DIR_RAW_OUT
307       ) {
308     ROAR_STREAM(s)->pos_rel_id = -1; // force this here as it will try to delete itself while deleting
309                                      // in case rel_id == stream
310     streams_delete(stream);
311     return -1;
312    }
313#else
314  case ROAR_DIR_RAW_OUT:
315    streams_delete(stream);
316    return -1;
317#endif
318
319   break;
320  case ROAR_DIR_THRU:
321
322    if ( ROAR_STREAM(s)->pos_rel_id == -1 || ROAR_STREAM(s)->pos_rel_id == stream ) {
323     ROAR_STREAM(s)->pos_rel_id = -1; // force this here as it will try to delete itself while deleting
324                                      // in case rel_id == stream
325     streams_delete(stream);
326     return -1;
327    }
328
329    if ( streams_get_clientobj(ROAR_STREAM(s)->pos_rel_id, &source_stream) == -1 ) {
330     streams_delete(stream);
331     return -1;
332    }
333
334    info        = &(ROAR_STREAM(s)->info);
335    source_info = &(ROAR_STREAM(source_stream)->info);
336
337    info->channels = source_info->channels;
338    info->bits     = source_info->bits;
339    info->rate     = source_info->rate;
340    info->codec    = source_info->codec;
341    ROAR_STREAM_SERVER(s)->codec_orgi = ROAR_STREAM_SERVER(source_stream)->codec_orgi;
342
343   break;
344  case ROAR_DIR_FILTER:
345    info        = &(ROAR_STREAM(s)->info);
346
347    if ( ROAR_STREAM(s)->pos_rel_id == -1 ) {
348     source_info = g_sa;
349    } else {
350     if ( streams_get_clientobj(ROAR_STREAM(s)->pos_rel_id, &source_stream) == -1 ) {
351      streams_delete(stream);
352      return -1;
353     }
354     source_info = &(ROAR_STREAM(source_stream)->info);
355    }
356
357    if ( info->channels != source_info->channels || info->bits != source_info->bits ||
358         info->codec    != source_info->codec    || info->rate != source_info->rate ) {
359     // the stream parameters don't match the one of the stream being filtered.
360     // -> delete and reject the stream.
361     streams_delete(stream);
362     return -1;
363    }
364   break;
365 }
366
367 ROAR_DBG("req_on_new_stream(client=%i, ...): returning (OK, stream=%i)...", client, stream);
368
369 mes->cmd     = ROAR_CMD_OK;
370 mes->stream  = stream;
371 mes->datalen = 0;
372
373 return 0;
374}
375
376int req_on_exec_stream (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
377 struct roar_message    m;
378 struct roar_client   * c;
379 struct roar_connection con;
380 int16_t * d = (int16_t*)mes->data;
381 int sock;
382 int i;
383 int r;
384
385 ROAR_DBG("req_on_exec_stream(client=%i, mes={stream=%i,...},...): execing stream", client, mes->stream);
386
387
388 if ( mes->stream != -1 ) {
389  if ( streams_is_ready(mes->stream) ) {
390   flags[1] |= COMMAND_FLAG_OUT_CLOSECON;
391  } else {
392   if ( (r = client_stream_exec(client, mes->stream)) == -1 )
393    return -1;
394  }
395
396  ROAR_DBG("req_on_exec_stream(client=%i, mes={stream=%i,...},...): returning (OK)...", client, mes->stream);
397  mes->cmd     = ROAR_CMD_OK;
398  mes->datalen = 0;
399  return 0;
400 }
401
402 ROAR_DBG("req_on_exec_stream(client=%i,...): non stream exec", client);
403
404 if ( mes->datalen < 4*2 )
405  return -1;
406
407 ROAR_DBG("req_on_exec_stream(client=%i,...) = ?", client);
408
409 for (i = 0; i < 4; i++) {
410  d[i] = ROAR_NET2HOST16(d[i]);
411 }
412
413 if ( d[0] != 0 ) // version
414  return -1;
415
416 if ( d[1] != 0 ) // flags
417  return -1;
418
419 if ( clients_get_protohandle(d[2]) == NULL )
420  return -1;
421
422 ROAR_DBG("req_on_exec_stream(client=%i,...) = ?", client);
423
424 memset(&m, 0, sizeof(m));
425
426 m.cmd = ROAR_CMD_OK;
427
428 flags[1] |= COMMAND_FLAG_OUT_NOSEND;
429
430 c = ROAR_CLIENT(g_clients[client]);
431
432 sock = c->fh;
433
434 if ( sock == -1 )
435  return -1;
436
437 ROAR_DBG("req_on_exec_stream(client=%i,...) = ?", client);
438
439 roar_connect_fh(&con, sock);
440
441 roar_send_message(&con, &m, NULL);
442
443 clients_set_fh(client, -1);
444 clients_delete(client);
445
446 ROAR_DBG("req_on_exec_stream(client=%i,...): calling clients_new_from_fh(): sock=%i, d={?, ?, %i, %i}", client, sock, (int)d[2], (int)d[3]);
447 if ( clients_new_from_fh(sock, d[2], d[3], 1) == -1 ) {
448  close(sock);
449 }
450
451 ROAR_DBG("req_on_exec_stream(client=%i,...) = 0", client);
452
453 return 0;
454}
455
456int req_on_con_stream  (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
457 char   host[80] = {0};
458 int    port = 0;
459 int    type = ROAR_SOCKET_TYPE_NONE;
460 int    transport_protocol = ROAR_PROTO_NONE;
461 int    fh;
462 int    len;
463
464 if ( mes->datalen < 4 ) {
465  roar_err_set(ROAR_ERROR_BADMSG);
466  return -1;
467 }
468
469 if ( mes->datalen > 80 ) { // we do not support long messages here
470  roar_err_set(ROAR_ERROR_MSGSIZE);
471  return -1;
472 }
473
474 switch (*(mes->data)) {
475  case 0: // version 0 packet:
476    type = (unsigned)mes->data[1];
477    port = ROAR_NET2HOST16(((uint16_t*)mes->data)[1]);
478
479    len = mes->datalen - 4;
480
481    strncpy(host, &(mes->data[4]), len);
482    host[len] = 0;
483   break;
484  default:
485    roar_err_set(ROAR_ERROR_NSVERSION);
486    return -1;
487   break;
488 }
489
490 if ( type > ROAR_SOCKET_TYPE_MAX ) {
491  roar_err_set(ROAR_ERROR_NOENT);
492  return -1;
493 }
494
495 switch (type) {
496  case ROAR_SOCKET_TYPE_NONE:
497  case ROAR_SOCKET_TYPE_FORK:
498  case ROAR_SOCKET_TYPE_GENSTR:
499    roar_err_set(ROAR_ERROR_INVAL);
500    return -1;
501   break;
502  case ROAR_SOCKET_TYPE_FILE:
503    roar_err_set(ROAR_ERROR_PERM);
504    return -1;
505   break;
506  default:
507    // pass.
508   break;
509 }
510
511 switch (transport_protocol) {
512  case ROAR_PROTO_NONE:
513  case ROAR_PROTO_SIMPLE: // same a NONE, plain data over socket. diffrence is only in setup.
514    transport_protocol = ROAR_PROTO_NONE;
515   break;
516  default:
517    roar_err_set(ROAR_ERROR_NOSYS);
518    return -1;
519   break;
520 }
521
522 ROAR_DBG("req_on_con_stream(*): CONNECT(type=%i, host='%s', port=%i)", type, host, port);
523
524 roar_libroar_nowarn();
525 fh = roar_socket_open(ROAR_SOCKET_MODE_CONNECT, type, host, port);
526 roar_libroar_warn();
527
528 if ( fh == -1 )
529  return -1;
530
531 if ( client_stream_set_fh(client, mes->stream, fh) == -1 ) {
532  close(fh);
533  return 1;
534 }
535
536 mes->datalen = 0;
537 mes->cmd     = ROAR_CMD_OK;
538
539 return 0;
540}
541
542int req_on_passfh      (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
543 int sock = clients_get_fh(client);
544 int16_t * d = (int16_t*)mes->data;
545 struct roard_listen * lsock;
546 int listening;
547 int fh;
548 int i;
549
550 ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...) = ?", client, mes->stream);
551
552 if ( (fh = roar_socket_recv_fh(sock, NULL, NULL)) == -1 ) {
553  ROAR_WARN("req_on_passfh(client=%i, mes={stream=%i,...},...): was unabled to get filehandle from remote end. bad.", client, mes->stream);
554  ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): returning (ERROR)...", client, mes->stream);
555  return -1;
556 }
557
558 ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): fh=%i", client, mes->stream, fh);
559
560 if ( mes->stream != -1 ) { // stream pass:
561  ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): This is a stream passfh", client, mes->stream);
562
563  if ( client_stream_set_fh(client, mes->stream, fh) == -1 ) {
564   close(fh);
565   ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): returning (ERROR)...", client, mes->stream);
566   return -1;
567  }
568
569  ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): returning (OK)...", client, mes->stream);
570
571  mes->datalen = 0;
572  mes->cmd     = ROAR_CMD_OK;
573
574  return 0;
575 }
576
577// non-stream pass:
578
579 ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): This is a client passfh", client, mes->stream);
580
581/*
582 0: Version,   16
583 1: Flags,     16
584 2: Protocol,  16
585 3: Byteorder, 16
586 Options...
587*/
588
589 if ( mes->datalen < 4*2 )
590  return -1;
591
592 for (i = 0; i < 4; i++) {
593  d[i] = ROAR_NET2HOST16(d[i]);
594 }
595
596 if ( d[0] != 0 ) // version
597  return -1;
598
599 listening = d[1] & ROAR_CLIENTPASS_FLAG_LISTEN;
600
601 if ( listening )
602  d[1] -= ROAR_CLIENTPASS_FLAG_LISTEN;
603
604 if ( d[1] != 0 ) // flags
605  return -1;
606
607 if ( listening ) {
608  if ( get_listen(&lsock, NULL) == -1 ) {
609   close(fh);
610   return -1;
611  }
612
613  roar_vio_open_fh_socket(&(lsock->sock), fh);
614  lsock->used   = 1;
615  lsock->proto  = d[2];
616 } else {
617  if ( clients_new_from_fh(fh, d[2], d[3], 1) == -1 )
618   return -1;
619 }
620
621 ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): returning (OK)...", client, mes->stream);
622
623 mes->datalen = 0;
624 mes->cmd     = ROAR_CMD_OK;
625
626 return 0;
627}
628
629#ifdef ROAR_SUPPORT_META
630int req_on_set_meta    (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
631 int type;
632 int mode;
633 int namelen, vallen;
634 char   val[255+1];
635 char   name[ROAR_META_MAX_NAMELEN+1];
636
637 if ( mes->datalen < 3 )
638  return -1;
639
640 if ( mes->data[0] != 0 ) // version
641  return -1;
642
643 mode = (unsigned) mes->data[1];
644 type = (unsigned) mes->data[2];
645
646 ROAR_DBG("req_on_set_meta(*): mode=%i, type=%i", mode, type);
647
648 if ( mode == ROAR_META_MODE_CLEAR ) {
649  stream_meta_clear(mes->stream);
650  mes->datalen = 0;
651  mes->cmd     = ROAR_CMD_OK;
652  return 0;
653 } else if ( mode == ROAR_META_MODE_DELETE ) { // unsuppoerted at the moment
654  return -1;
655 } else if ( mode == ROAR_META_MODE_FINALIZE ) {
656  stream_meta_finalize(mes->stream);
657  mes->datalen = 0;
658  mes->cmd     = ROAR_CMD_OK;
659  return 0;
660 } else if ( mode == ROAR_META_MODE_SET || mode == ROAR_META_MODE_ADD ) {
661  if ( mes->datalen < 5 )
662   return -1;
663
664  namelen = (unsigned) mes->data[3];
665  vallen  = (unsigned) mes->data[4];
666
667  ROAR_DBG("req_on_set_meta(*): namelen=%i, vallen=%i", namelen, vallen);
668
669  if ( mes->datalen < (5 + namelen + vallen) )
670   return -1;
671
672  if ( namelen > ROAR_META_MAX_NAMELEN )
673   return -1;
674
675  strncpy(name, &(mes->data[5]), namelen);
676  name[namelen] = 0;
677
678  if ( vallen > 255 )
679   return -1;
680
681  strncpy(val, &(mes->data[5+namelen]), vallen);
682  val[vallen] = 0;
683
684  if ( mode == ROAR_META_MODE_SET ) {
685   if ( stream_meta_set(mes->stream, type, name, val) == -1 )
686    return -1;
687  } else {
688   if ( stream_meta_add(mes->stream, type, name, val) == -1 )
689    return -1;
690  }
691
692  mes->datalen = 0;
693  mes->cmd     = ROAR_CMD_OK;
694  return 0;
695 } else { // unknown mode!
696  return -1;
697 }
698
699 return -1;
700}
701
702int req_on_get_meta    (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
703 int vallen;
704 int type;
705 char val[LIBROAR_BUFFER_MSGDATA-1];
706
707 if ( mes->datalen != 2 )
708  return -1;
709
710 if ( mes->data[0] != 0 ) // version
711  return -1;
712
713 type = (unsigned) mes->data[1];
714
715 if ( stream_meta_get(mes->stream, type, NULL, val, LIBROAR_BUFFER_MSGDATA-2) == -1 )
716  return -1;
717
718 vallen = strlen(val);
719
720 mes->cmd     = ROAR_CMD_OK;
721 mes->datalen = 2 + vallen;
722
723 mes->data[0] = 0;
724 mes->data[1] = (unsigned char) vallen;
725
726 val[vallen] = 0;
727
728 strncpy(&(mes->data[2]), val, vallen+1);
729
730 return 0;
731}
732
733int req_on_list_meta   (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
734 int i;
735 int len = 0;
736 int types[ROAR_META_MAX_PER_STREAM];
737
738 if ( mes->datalen != 1 )
739  return -1;
740
741 if ( mes->data[0] != 0 ) // version
742  return -1;
743
744 if ( (len = stream_meta_list(mes->stream, types, ROAR_META_MAX_PER_STREAM)) == -1 )
745  return -1;
746
747 mes->cmd     = ROAR_CMD_OK;
748 mes->datalen = 1 + len;
749 mes->data[0] = 0;
750
751 for (i = 0; i < len; i++)
752  mes->data[i+1] = types[i];
753
754 return 0;
755}
756#endif
757
758int req_on_gettimeofday (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
759 struct roar_time curtime;
760 uint64_t * d64 = (uint64_t *)mes->data;
761
762 ROAR_DBG("req_on_gettimeofday(client=%i, mes=%p, data=%p, flags=%p) = ?", client, mes, data, flags);
763
764 if ( *data != NULL ) {
765  return -1;
766 }
767
768 ROAR_DBG("req_on_gettimeofday(client=%i, mes=%p, data=%p, flags=%p) = ?", client, mes, data, flags);
769
770 if ( mes->datalen && mes->datalen < 8 ) {
771  return -1;
772 }
773
774 ROAR_DBG("req_on_gettimeofday(client=%i, mes=%p, data=%p, flags=%p) = ?", client, mes, data, flags);
775
776 if ( mes->datalen >= 8 ) {
777  if ( *d64 != 0 ) {
778   return -1;
779  }
780 }
781
782 ROAR_DBG("req_on_gettimeofday(client=%i, mes=%p, data=%p, flags=%p) = ?", client, mes, data, flags);
783
784 if ( roar_clock_gettime(&curtime, ROAR_CLOCK_REALTIME) == -1 )
785  return -1;
786
787 if ( roar_time_to_msg(mes, &curtime) == -1 )
788  return -1;
789
790 mes->cmd = ROAR_CMD_OK;
791
792 ROAR_DBG("req_on_gettimeofday(client=%i, mes=%p, data=%p, flags=%p) = ?", client, mes, data, flags);
793
794 return 0;
795}
796
797int req_on_server_info (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
798#ifdef ROAR_HAVE_UNAME
799 struct utsname utsname;
800#endif
801#ifdef ROAR_HAVE_GETVERSIONEX
802 OSVERSIONINFO osinfo;
803 char buf_release[80];
804#endif
805 struct roar_server_info info;
806 uint16_t * d16;
807#ifdef ROAR_HAVE_GETHOSTID
808 long hostid;
809 char hostidbuf[64];
810#endif
811
812 if ( mes->datalen != 4 )
813  return -1;
814
815 d16 = (uint16_t*)mes->data;
816
817 // check version.
818 if ( ROAR_NET2HOST16(d16[0]) != 0 )
819  return -1;
820
821 switch (ROAR_NET2HOST16(d16[1])) {
822  case ROAR_IT_SERVER:
823   memset(&info, 0, sizeof(info));
824
825   // the following if is optimized out by compiler.
826   if ( ROAR_VERSION_DISTRIBUTION_STRING[0] == 0 ) {
827    info.version = "roard/" ROAR_VERSION_STRING " <" ROAR_DEV_VENDOR_STRING ">";
828   } else {
829    info.version = "roard/" ROAR_VERSION_STRING " <" ROAR_DEV_VENDOR_STRING "> (" ROAR_VERSION_DISTRIBUTION_STRING ")";
830   }
831
832   info.build   = ROAR_BUILD_STAMP;
833   info.license = ROAR_LICENSE_GPLv3_0;
834
835#ifdef ROAR_HAVE_GETHOSTID
836   hostid = gethostid();
837   snprintf(hostidbuf, sizeof(hostidbuf), sizeof(long) == 8 ? "0x%.16lx" : "0x%.8lx", hostid);
838   info.hostid = hostidbuf;
839#endif
840
841   if ( !!strcmp(g_config->location, CONF_DEF_STRING) )
842    info.location = g_config->location;
843
844   if ( !!strcmp(g_config->description, CONF_DEF_STRING) )
845    info.description = g_config->description;
846
847   info.contact = g_config->contact;
848   info.serial  = g_config->serial;
849   info.uiurl   = g_config->uiurl;
850
851#ifdef ROAR_HAVE_UNAME
852   if ( uname(&utsname) == 0 ) {
853    roar_random_salt_nonce(&utsname, sizeof(utsname));
854    info.un.sysname  = utsname.sysname;
855    info.un.release  = utsname.release;
856    info.un.nodename = utsname.nodename;
857    info.un.machine  = utsname.machine;
858   }
859#endif
860#ifdef ROAR_HAVE_GETVERSIONEX
861   osinfo.dwOSVersionInfoSize = sizeof(osinfo);
862   if ( GetVersionEx(&osinfo) ) {
863    info.un.sysname = "Windows";
864    snprintf(buf_release, sizeof(buf_release), "%i.%i.%i",
865               (int)osinfo.dwMajorVersion, (int)osinfo.dwMinorVersion, (int)osinfo.dwBuildNumber);
866    buf_release[sizeof(buf_release)-1] = 0;
867    info.un.release = buf_release;
868   }
869#endif
870
871   *data = NULL;
872
873   if ( roar_server_info_to_mes(mes, &info, (void**)data) == -1 )
874    return -1;
875
876   if ( *data != NULL )
877    flags[1] |= COMMAND_FLAG_OUT_LONGDATA;
878  break;
879  default: /* unknown request */
880    return -1;
881   break;
882 }
883
884 mes->cmd = ROAR_CMD_OK;
885
886 return 0;
887}
888
889int req_on_server_oinfo    (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
890 struct roar_stream s;
891 int dir = ROAR_DIR_PLAY;
892 int subsys;
893//ROAR_DIR_OUTPUT
894
895 if ( mes->datalen != 0 ) {
896  if ( mes->datalen != 2 )
897   return -1;
898
899  if ( mes->data[0] != 0 )
900   return -1;
901
902  dir = mes->data[1];
903 }
904
905 subsys = streams_dir2subsys(dir);
906
907 memset(&s, 0, sizeof(struct roar_stream));
908
909 s.dir           = ROAR_DIR_MIXING;
910 s.pos_rel_id    = -1;
911
912 switch (subsys) {
913  case ROAR_SUBSYS_WAVEFORM:
914    s.info.rate     = g_sa->rate;
915    s.info.bits     = g_sa->bits;
916    s.info.channels = g_sa->channels;
917    s.info.codec    = g_sa->codec;
918    s.pos           = g_pos;
919   break;
920#ifndef ROAR_WITHOUT_DCOMP_MIDI
921  case ROAR_SUBSYS_MIDI:
922   break;
923#endif
924#ifndef ROAR_WITHOUT_DCOMP_LIGHT
925  case ROAR_SUBSYS_LIGHT:
926    s.info.rate     = ROAR_OUTPUT_CFREQ;
927    s.info.bits     = ROAR_LIGHT_BITS;
928    s.info.channels = g_light_state.channels;
929   break;
930#endif
931#ifndef ROAR_WITHOUT_DCOMP_RAW
932  case ROAR_SUBSYS_RAW:
933    // no need to set anything here.
934   break;
935#endif
936#ifndef ROAR_WITHOUT_DCOMP_RDTCS
937  case ROAR_SUBSYS_RDTCS:
938    s.info.rate     = ROAR_OUTPUT_CFREQ;
939    s.info.bits     = ROAR_RDTCS_BITS;
940    s.info.channels = ROAR_RDTCS_CHANNELS;
941    s.info.codec    = ROAR_RDTCS_CODEC;
942   break;
943#endif
944  default:
945    return -1;
946   break;
947 }
948
949 if ( roar_stream_s2m(&s, mes) == -1 )
950  return -1;
951
952 mes->cmd = ROAR_CMD_OK;
953
954 return 0;
955}
956
957int req_on_caps        (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
958 struct roar_caps caps;
959 struct roar_stds * stds;
960 size_t i;
961
962 if ( roar_caps_from_msg(&caps, mes, *data) == -1 )
963  return -1;
964
965 // handle the data from the caps command here...
966
967 if ( !(caps.flags & ROAR_CF_REQUEST) ) {
968  mes->cmd = ROAR_CMD_OK;
969  mes->datalen = 0;
970  return 0;
971 }
972
973 mes->datalen = 0;
974
975 switch (caps.type) {
976  case ROAR_CT_STANDARDS:
977    if ( (stds = roar_stds_new(g_caps_stds.stds_len)) == NULL )
978     return -1;
979
980    for ( i = 0; i < stds->stds_len; i++) {
981     stds->stds[i] = ROAR_HOST2NET32(g_caps_stds.stds[i]);
982    }
983
984    caps.data = stds->stds;
985    caps.len  = stds->stds_len * 4;
986    // TODO: add support for **data.
987    if ( roar_caps_to_msg(mes, &caps, NULL) == -1 ) {
988     roar_stds_free(stds);
989     return -1;
990    }
991    roar_stds_free(stds);
992   break;
993  default:
994    return -1;
995   break;
996 }
997
998 mes->cmd = ROAR_CMD_OK;
999
1000 return 0;
1001}
1002
1003int req_on_get_standby (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1004 uint16_t * d16 = (uint16_t*)mes->data;
1005
1006 mes->cmd     = ROAR_CMD_OK;
1007 mes->pos     = g_pos;
1008 mes->datalen = 2;
1009
1010 *d16 = ROAR_HOST2NET16((unsigned) g_standby);
1011
1012 return 0;
1013}
1014
1015int req_on_set_standby (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1016 uint16_t * d16 = (uint16_t*)mes->data;
1017
1018 if ( mes->datalen != 2 )
1019  return -1;
1020
1021 g_standby = ROAR_NET2HOST16(*d16);
1022
1023 mes->cmd     = ROAR_CMD_OK;
1024 mes->pos     = g_pos;
1025 mes->datalen = 0;
1026
1027 return 0;
1028}
1029
1030int req_on_exit      (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1031 int term = 0;
1032
1033 if ( mes->datalen == 1 )
1034  term = mes->data[0];
1035
1036 mes->cmd     = ROAR_CMD_OK;
1037 mes->pos     = g_pos;
1038 mes->datalen = 0;
1039
1040 ROAR_DBG("req_on_exit(*): term=%i", term);
1041
1042 if ( term ) {
1043  cleanup_listen_socket(1);
1044 } else {
1045  alive = 0;
1046 }
1047
1048 return 0;
1049}
1050
1051int req_on_list_clients(int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1052 unsigned char filter, cmp;
1053 uint32_t id;
1054 int clients[ROAR_CLIENTS_MAX];
1055 int i, c = 0;
1056
1057 if ( roar_ctl_m2f(mes, &filter, &cmp, &id) == -1 )
1058  return -1;
1059
1060 // TODO: add code to support filter
1061 if ( filter != ROAR_CTL_FILTER_ANY )
1062  return -1;
1063
1064 for (i = 0; i < ROAR_CLIENTS_MAX; i++) {
1065  if ( g_clients[i] != NULL ) {
1066   clients[c++] = i;
1067  }
1068 }
1069
1070 roar_ctl_ia2m(mes, clients, c);
1071
1072 mes->cmd = ROAR_CMD_OK;
1073
1074 return 0;
1075}
1076int req_on_list_streams(int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1077 unsigned char filter, cmp;
1078 uint32_t id;
1079 int streams[ROAR_STREAMS_MAX];
1080 int i, c = 0;
1081 int match;
1082
1083 if ( roar_ctl_m2f(mes, &filter, &cmp, &id) == -1 )
1084  return -1;
1085
1086 for (i = 0; i < ROAR_STREAMS_MAX; i++) {
1087  if ( g_streams[i] == NULL )
1088   continue;
1089
1090  match = 0;
1091
1092  switch (filter) {
1093   case ROAR_CTL_FILTER_ANY:
1094     match = 1;
1095    break;
1096   case ROAR_CTL_FILTER_DIR:
1097     match = roar_filter_match(cmp, id, ROAR_STREAM(g_streams[i])->dir);
1098    break;
1099   default: // unsupported filter...
1100     return -1;
1101    break;
1102  }
1103
1104  if ( match )
1105   streams[c++] = i;
1106 }
1107
1108 roar_ctl_ia2m(mes, streams, c);
1109
1110 mes->cmd = ROAR_CMD_OK;
1111
1112 return 0;
1113}
1114
1115int req_on_get_client  (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1116 struct roar_client * c;
1117 int ret;
1118
1119 if ( mes->datalen != 1 )
1120  return -1;
1121
1122 if ( *data != NULL )
1123  roar_mm_free(*data);
1124 *data = NULL;
1125
1126 if ( clients_get(mes->data[0], &c) == -1 )
1127  return -1;
1128
1129 mes->cmd = ROAR_CMD_OK;
1130
1131 ret = roar_ctl_c2m2(mes, c, (void**)data);
1132
1133 if ( *data != NULL )
1134  flags[1] |= COMMAND_FLAG_OUT_LONGDATA;
1135
1136 return ret;
1137}
1138
1139int req_on_get_stream  (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1140 struct roar_stream_server * s;
1141
1142 if ( mes->datalen != 1 )
1143  return -1;
1144
1145 if ( streams_get(mes->data[0], &s) == -1 )
1146  return -1;
1147
1148 mes->cmd = ROAR_CMD_OK;
1149 mes->stream = mes->data[0];
1150
1151 return roar_stream_s2m(ROAR_STREAM(s), mes);
1152}
1153
1154int req_on_get_stream_para (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1155 struct roar_stream * s;
1156 struct roar_stream_server * ss;
1157 struct roar_audio_info * audio_info;
1158 struct roar_stream_ltm * ltm;
1159 struct roar_stream_rpg   rpg;
1160 uint16_t * d  = (uint16_t *) mes->data;
1161 int64_t * d64 = ( int64_t *) mes->data;
1162 int64_t * d64ptr;
1163 int i, h, k;
1164 char * str;
1165 size_t needed;
1166 int test, bits;
1167
1168 ROAR_DBG("req_on_get_stream_para(client=%i, mes=%p{.stream=%i, .datalen=%i,...}, data=%p, flags=%p) = ?", client, mes, (int)mes->stream, (int)mes->datalen, data, flags);
1169
1170 if ( mes->datalen < 4 )
1171  return -1;
1172
1173 for (i = 0; i < 2; i++) {
1174  d[i] = ROAR_NET2HOST16(d[i]);
1175 }
1176
1177 if ( d[0] != 0 ) {
1178  ROAR_WARN("req_on_get_stream_para(*): unsupported command version: %i, %i", (int)d[0], (int)d[1]);
1179  return -1;
1180 }
1181
1182 switch (d[1]) {
1183  case ROAR_STREAM_PARA_INFO:
1184    if ( streams_get(mes->stream, &ss) == -1 ) {
1185     ROAR_WARN("req_on_get_stream_para(*): request on non existing (or other error?) stream %i", mes->stream);
1186     return -1;
1187    }
1188
1189    if ( streams_calc_delay(mes->stream) == -1 ) {
1190     ROAR_WARN("req_on_get_stream_para(*): can not calc delay for stream %i", mes->stream);
1191    }
1192
1193    s = ROAR_STREAM(ss);
1194
1195    audio_info = &(s->info);
1196
1197    mes->datalen = 2*12;
1198
1199    d[ 2] = ROAR_OUTPUT_CALC_OUTBUFSIZE(audio_info);
1200    d[ 3] = ss->pre_underruns;
1201    d[ 4] = ss->post_underruns;
1202    d[ 5] = ss->codec_orgi;
1203    d[ 6] = (ss->flags & 0xFFFF) | (ss->primary ? ROAR_FLAG_PRIMARY : 0) | (ss->driver_id != -1 ? ROAR_FLAG_OUTPUT : 0);
1204    d[ 7] = ss->delay/1000;
1205    d[ 8] = ss->state;
1206    d[ 9] = (ss->flags & 0xFFFF0000) >> 16;
1207    d[10] = ss->mixer_stream;
1208    d[11] = ss->role;
1209
1210    ROAR_DBG("req_on_get_stream_para(*): ss->driver_id=%i", ss->driver_id);
1211
1212    ROAR_DBG("req_on_get_stream_para(*): delay=%i, send delay=%i", ss->delay, d[7]);
1213
1214    for (i = 0; i < mes->datalen/2; i++) {
1215     d[i] = ROAR_HOST2NET16(d[i]);
1216    }
1217
1218    mes->pos = s->pos;
1219   break;
1220
1221  case ROAR_STREAM_PARA_NAME:
1222   str = streams_get_name(mes->stream);
1223
1224   if ( str == NULL )
1225    return -1;
1226
1227    mes->datalen = 4 + strlen(str);
1228
1229    if ( mes->datalen > LIBROAR_BUFFER_MSGDATA )
1230     return -1;
1231
1232    strncpy(((char*)&(mes->data))+4, str, mes->datalen);
1233
1234    d[0] = ROAR_HOST2NET16(d[0]);
1235    d[1] = ROAR_HOST2NET16(d[1]);
1236   break;
1237
1238  case ROAR_STREAM_PARA_CHANMAP:
1239    if ( streams_get(mes->stream, &ss) == -1 ) {
1240     ROAR_WARN("req_on_get_stream_para(*): request on non existing (or other error?) stream %i", mes->stream);
1241     return -1;
1242    }
1243
1244    s = ROAR_STREAM(ss);
1245
1246    memcpy(&(mes->data[4]), ss->chanmap.in, s->info.channels);
1247    mes->datalen = 2*2 + s->info.channels;
1248
1249    d[0] = ROAR_HOST2NET16(d[0]);
1250    d[1] = ROAR_HOST2NET16(d[1]);
1251   break;
1252
1253  case ROAR_STREAM_PARA_LTM:
1254    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM request...", client);
1255
1256    if ( mes->datalen < (6 * 2) ) {
1257     ROAR_ERR("req_on_get_stream_para(client=%i, ...): LTM request of client is corruped: message too short", client);
1258     return -1;
1259    }
1260
1261    for (i = 2; i < mes->datalen/2; i++) {
1262     d[i] = ROAR_NET2HOST16(d[i]);
1263    }
1264
1265    if ( d[2] != ROAR_LTM_SST_GET_RAW ) {
1266     ROAR_ERR("req_on_get_stream_para(client=%i, ...): LTM request of client is corruped: unknown LTM subtype: %i", client, (int)d[2]);
1267     return -1;
1268    }
1269
1270    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM request of type GET_RAW", client);
1271
1272    test = d[5];
1273    bits = 0;
1274    while (test) {
1275     if ( test & 0x1 )
1276      bits++;
1277
1278     test >>= 1;
1279    }
1280
1281    needed = 0;
1282
1283    if ( mes->stream == -1 ) {
1284     ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM multi-stream request...", client);
1285
1286     for (i = 6; i < mes->datalen/2; i++) {
1287      if ( (ltm = streams_ltm_get(d[i], d[5], d[3])) == NULL )
1288       return -1;
1289
1290      needed += ltm->channels;
1291     }
1292    } else {
1293     ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM single-stream request for stream %i...", client, mes->stream);
1294     if ( (ltm = streams_ltm_get(mes->stream, d[5], d[3])) == NULL )
1295      return -1;
1296
1297     needed = ltm->channels;
1298    }
1299
1300    needed *= bits;
1301
1302    needed += mes->stream == -1 ? (mes->datalen/2) - 6 : 1;
1303
1304    ROAR_DBG("req_on_get_stream_para(client=%i, ...): data size for answer is %i 64 bit sub-packets", client, (int)needed);
1305
1306    ROAR_DBG("req_on_get_stream_para(client=%i, ...): mes->datalen=%i, data=%p{%p}", client, (int)mes->datalen, data, *data);
1307    d64 = _dataspace(mes, data, flags, needed * 8);
1308    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1309
1310    if ( (d = roar_mm_malloc(mes->datalen)) == NULL )
1311     return -1;
1312
1313    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d=%p, data=%p{%p}", client, d, data, *data);
1314
1315
1316    ROAR_DBG("req_on_get_stream_para(client=%i, ...): mes->datalen=%i, data=%p{%p}", client, (int)mes->datalen, data, *data);
1317    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1318    memcpy(d, mes->data, mes->datalen);
1319    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1320
1321    d64ptr = d64;
1322
1323    ROAR_DBG("req_on_get_stream_para(client=%i, ...): mes->datalen=%i, data=%p{%p}", client, (int)mes->datalen, data, *data);
1324    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1325
1326    if ( mes->stream == -1 ) {
1327     for (i = 6; i < mes->datalen/2; i++) {
1328      ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1329
1330      if ( (ltm = streams_ltm_get(d[i], d[5], d[3])) == NULL )
1331       return -1;
1332
1333      *d64ptr = ltm->channels & 0xFFFF;
1334       d64ptr++;
1335
1336      for (h = 0; h < ltm->channels; h++) {
1337       for (k = 0; k < ROAR_LTM_MTBITS; k++) {
1338        if ( d[5] & (1<<k) ) {
1339         switch (1<<k) {
1340          case ROAR_LTM_MT_RMS:
1341            *d64ptr = ltm->cur[h].rms;
1342           break;
1343          default:
1344            ROAR_ERR("req_on_get_stream_para(client=%i, ...): client requets unknown MT for LTM: bit %i", client, k);
1345         }
1346         d64ptr++;
1347        }
1348       }
1349      }
1350     }
1351    } else {
1352     if ( (ltm = streams_ltm_get(mes->stream, d[5], d[3])) == NULL )
1353      return -1;
1354
1355     *d64ptr = ltm->channels & 0xFFFF;
1356      d64ptr++;
1357
1358     for (h = 0; h < ltm->channels; h++) {
1359      for (k = 0; k < ROAR_LTM_MTBITS; k++) {
1360       if ( d[5] & (1<<k) ) {
1361        switch (1<<k) {
1362         case ROAR_LTM_MT_RMS:
1363           *d64ptr = ltm->cur[h].rms;
1364           ROAR_DBG("req_on_get_stream_para(client=%i, ...): rms=%lli to %p", client, (long long int)*d64ptr, d64ptr);
1365          break;
1366         default:
1367           ROAR_ERR("req_on_get_stream_para(client=%i, ...): client requets unknown MT for LTM: bit %i", client, k);
1368        }
1369        d64ptr++;
1370       }
1371      }
1372     }
1373    }
1374
1375    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1376
1377    roar_mm_free(d);
1378
1379    for (i = 0; i < needed; i++) {
1380     d64[i] = ROAR_HOST2NET64(d64[i]);
1381    }
1382
1383    mes->datalen = needed * 8;
1384    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM d64=%p, d64ptr=%p", client, d64, d64ptr);
1385    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM final message has %i byte of data", client, (int)mes->datalen);
1386    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1387    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM GET_RAW request: OK. returning...", client);
1388   break;
1389
1390  case ROAR_STREAM_PARA_RPG:
1391    if ( streams_get_rpg(mes->stream, &rpg) == -1 ) {
1392     return -1;
1393    }
1394
1395    mes->datalen = 2*5;
1396
1397    d[2] = rpg.mode;
1398    d[3] = rpg.mul;
1399    d[4] = rpg.div;
1400
1401    for (i = 0; i < mes->datalen/2; i++) {
1402     d[i] = ROAR_HOST2NET16(d[i]);
1403    }
1404   break;
1405
1406  default:
1407    ROAR_WARN("req_on_get_stream_para(*): unsupported command: %i", d[1]);
1408    return -1;
1409 }
1410
1411 ROAR_DBG("req_on_get_stream_para(client=%i, mes=%p{.stream=%i, .datalen=%i,...}, data=%p, flags=%p) = 0 // returning OK", client, mes, (int)mes->stream, (int)mes->datalen, data, flags);
1412 mes->cmd = ROAR_CMD_OK;
1413 return 0;
1414}
1415
1416int req_on_set_stream_para (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1417 struct roar_stream_server * ss;
1418 struct roar_stream_rpg rpg;
1419 uint16_t * d = (uint16_t *) mes->data;
1420 uint32_t tmp, tmp2, flagstore;
1421 int protect = 0;
1422 int i;
1423
1424 if ( mes->datalen < 2*2 )
1425  return -1;
1426
1427 for (i = 0; i < 2; i++) {
1428  d[i] = ROAR_NET2HOST16(d[i]);
1429 }
1430
1431 if ( d[0] != 0 )
1432  return -1;
1433
1434 switch (d[1]) {
1435  case ROAR_STREAM_PARA_FLAGS:
1436    if ( mes->datalen != 2*4 && mes->datalen != 2*5 )
1437     return -1;
1438
1439    d[2] = ROAR_NET2HOST16(d[2]);
1440    d[3] = ROAR_NET2HOST16(d[3]);
1441
1442    ROAR_DBG("req_on_set_stream_para(*): request seems to be valid");
1443
1444    tmp = 0;
1445
1446    if ( mes->datalen == 2*5 ) {
1447     d[4] = ROAR_NET2HOST16(d[4]);
1448     tmp   = d[4];
1449     tmp <<= 16;
1450    }
1451
1452    tmp |= d[3];
1453
1454    if ( d[2] & ROAR_PROTECT_FLAG ) {
1455     protect = 1;
1456     d[2] -= ROAR_PROTECT_FLAG;
1457    }
1458
1459    switch (d[2]) {
1460     case ROAR_SET_FLAG:
1461       if ( streams_set_flag(mes->stream, tmp) == -1 )
1462        return -1;
1463      break;
1464     case ROAR_RESET_FLAG:
1465       if ( streams_reset_flag(mes->stream, tmp) == -1 )
1466        return -1;
1467      break;
1468     case ROAR_NOOP_FLAG:
1469      break;
1470     case ROAR_TOGGLE_FLAG:
1471       if ( streams_get(mes->stream, &ss) == -1 )
1472        return -1;
1473
1474       flagstore = ss->flags;
1475
1476       tmp2 = flagstore & tmp; // those are the flags we need to reset.
1477       ROAR_DBG("req_on_set_stream_para(*): tmp2=0x%.8lx", (long int)tmp2);
1478       if ( tmp2 )
1479        if ( streams_reset_flag(mes->stream, tmp2) == -1 )
1480         return -1;
1481
1482       tmp2 = (flagstore ^ tmp) & tmp; // those are the flags we need to set.
1483       ROAR_DBG("req_on_set_stream_para(*): tmp2=0x%.8lx", (long int)tmp2);
1484       if ( tmp2 )
1485        if ( streams_set_flag(mes->stream, tmp2) == -1 )
1486         return -1;
1487      break;
1488     default:
1489       return -1;
1490      break;
1491    }
1492
1493   ROAR_DBG("req_on_set_stream_para(*): protect=%i", protect);
1494   if ( protect )
1495    if ( streams_protect_flag(mes->stream, tmp) == -1 )
1496     return -1;
1497
1498   break;
1499  case ROAR_STREAM_PARA_CHANMAP:
1500    if ( streams_set_map(mes->stream, &(mes->data[4]), mes->datalen - 4) == -1 )
1501     return -1;
1502   break;
1503  case ROAR_STREAM_PARA_ROLE:
1504    if ( mes->datalen != 2*3 )
1505     return -1;
1506
1507    d[2] = ROAR_NET2HOST16(d[2]);
1508
1509    if ( streams_set_role(mes->stream, d[2]) == -1 )
1510     return -1;
1511   break;
1512  case ROAR_STREAM_PARA_LTM:
1513    if ( mes->datalen < (6 * 2) )
1514     return -1;
1515
1516    for (i = 2; i < mes->datalen/2; i++) {
1517     d[i] = ROAR_NET2HOST16(d[i]);
1518    }
1519
1520    if ( mes->stream == -1 ) {
1521     for (i = 6; i < mes->datalen/2; i++)
1522      if ( streams_ltm_ctl(d[i], d[5], d[3], d[2]) == -1 )
1523       return -1;
1524    } else {
1525     if ( streams_ltm_ctl(mes->stream, d[5], d[3], d[2]) == -1 )
1526      return -1;
1527    }
1528   break;
1529  case ROAR_STREAM_PARA_RPG:
1530    if ( mes->datalen != (5 * 2) )
1531     return -1;
1532
1533    for (i = 2; i < mes->datalen/2; i++) {
1534     d[i] = ROAR_NET2HOST16(d[i]);
1535    }
1536
1537    rpg.mode = d[2];
1538    rpg.mul  = d[3];
1539    rpg.div  = d[4];
1540
1541    if ( streams_set_rpg(mes->stream, &rpg) == -1 )
1542     return -1;
1543   break;
1544  default:
1545    ROAR_WARN("req_on_set_stream_para(*): unsupported command version: %i, %i", d[0], d[1]);
1546    return -1;
1547   break;
1548 }
1549
1550 mes->cmd     = ROAR_CMD_OK;
1551 mes->datalen = 0;
1552
1553 return 0;
1554}
1555
1556int req_on_kick (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1557 struct roar_stream_server * ss;
1558 uint16_t * info = (uint16_t *) mes->data;
1559 int is_stream = 0;
1560
1561 if ( mes->datalen != 4 )
1562  return -1;
1563
1564 info[0] = ROAR_NET2HOST16(info[0]);
1565 info[1] = ROAR_NET2HOST16(info[1]);
1566
1567 switch (info[0]) {
1568  case ROAR_OT_CLIENT:
1569    clients_delete(info[1]);
1570   break;
1571  case ROAR_OT_STREAM:
1572    is_stream = 1;
1573   break;
1574  case ROAR_OT_SOURCE:
1575    if ( streams_get_flag(info[1], ROAR_FLAG_SOURCE) != 1 )
1576     return -1;
1577    is_stream = 1;
1578   break;
1579  case ROAR_OT_OUTPUT:
1580    if ( streams_get(info[1], &ss) == -1 )
1581     return -1;
1582
1583    if ( ss->driver_id == -1 )
1584     return -1;
1585
1586    is_stream = 1;
1587   break;
1588  case ROAR_OT_MIXER:
1589    if ( streams_get(info[1], &ss) == -1 )
1590     return -1;
1591
1592    if ( ROAR_STREAM(ss)->dir != ROAR_DIR_MIXING )
1593     return -1;
1594
1595    is_stream = 1;
1596   break;
1597  case ROAR_OT_BRIDGE:
1598    if ( streams_get(info[1], &ss) == -1 )
1599     return -1;
1600
1601    if ( ROAR_STREAM(ss)->dir != ROAR_DIR_BRIDGE )
1602     return -1;
1603
1604    is_stream = 1;
1605   break;
1606  default:
1607/* TODO: those types should be handled, too:
1608#define ROAR_OT_SAMPLE    4
1609#define ROAR_OT_LISTEN    8
1610#define ROAR_OT_ACTION    9
1611#define ROAR_OT_MSGQUEUE 10
1612#define ROAR_OT_MSGBUS   11
1613*/
1614    return -1;
1615   break;
1616 }
1617
1618 if ( is_stream ) {
1619  if ( streams_get_flag(info[1], ROAR_FLAG_IMMUTABLE) == 1 )
1620   return -1;
1621
1622  streams_delete(info[1]);
1623 }
1624
1625 mes->cmd     = ROAR_CMD_OK;
1626 mes->datalen = 0;
1627
1628 return 0;
1629}
1630
1631int req_on_attach      (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1632 uint16_t * info = (uint16_t *) mes->data;
1633
1634 if ( mes->datalen < 6 )
1635  return -1;
1636
1637 info[0] = ROAR_NET2HOST16(info[0]);
1638 info[1] = ROAR_NET2HOST16(info[1]);
1639 info[2] = ROAR_NET2HOST16(info[2]);
1640
1641 if ( info[0] != 0 )
1642  return -1;
1643
1644 if ( info[1] == ROAR_ATTACH_SIMPLE ) {
1645  if ( client_stream_move(info[2], mes->stream) == -1 )
1646   return -1;
1647 } else {
1648  return -1;
1649 }
1650
1651 mes->cmd     = ROAR_CMD_OK;
1652 mes->datalen = 0;
1653
1654 return 0;
1655}
1656
1657int req_on_set_vol (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1658 struct roar_mixer_settings tmpmixer;
1659 struct roar_stream_server * s;
1660 uint16_t * info = (uint16_t *) mes->data;
1661 uint16_t   version;
1662 uint16_t   scale = 65535;
1663 int stream;
1664 int i;
1665 int chans;
1666
1667 ROAR_DBG("req_on_set_vol(*) = ?");
1668 ROAR_DBG("req_on_set_vol(*): mes->datalen=%i", mes->datalen);
1669
1670 if ( mes->datalen < (4*2) )
1671  return -1;
1672
1673 version = ROAR_NET2HOST16(info[0]);
1674 ROAR_DBG("req_on_set_vol(*): version=%i", (int)version);
1675
1676 switch (version) {
1677  case 0:
1678    stream = ROAR_NET2HOST16(info[1]);
1679   break;
1680  case 1:
1681    stream = mes->stream;
1682    scale  = ROAR_NET2HOST16(info[1]);
1683   break;
1684  default:
1685    return -1;
1686   break;
1687 }
1688 ROAR_DBG("req_on_set_vol(*): stream=%i", stream);
1689
1690 if ( scale == 0 )
1691  return -1;
1692
1693 // TODO: change this code.
1694 //       we should not directly change the stream object but use some stream_*()-func
1695 //       for that job.
1696
1697 if ( stream < 0 || stream >= ROAR_STREAMS_MAX )
1698  return -1;
1699
1700 s = g_streams[stream];
1701
1702 if ( s == NULL )
1703  return -1;
1704
1705 ROAR_DBG("req_on_set_vol(*): s=%p", s);
1706
1707 info[2] = ROAR_NET2HOST16(info[2]);
1708
1709 switch (info[2]) {
1710  case ROAR_SET_VOL_ALL:
1711    chans = (mes->datalen/2) - 3;
1712    ROAR_DBG("req_on_set_vol(*): mode is ROAR_SET_VOL_ALL, channes=%i", chans);
1713
1714    if ( chans >= ROAR_MAX_CHANNELS )
1715     return -1;
1716
1717    ROAR_DBG("req_on_set_vol(*): mixer at %p", s->mixer.mixer);
1718
1719    for (i = 0; i < chans; i++) {
1720     s->mixer.mixer[i] = ROAR_NET2HOST16(info[i+3]);
1721     ROAR_DBG("req_on_set_vol(*): channel %i: %i", i, ROAR_NET2HOST16(info[i+3]));
1722    }
1723
1724    s->mixer.scale = scale;
1725
1726    ROAR_DBG("req_on_set_vol(*): mixer changed!");
1727
1728   break;
1729  case ROAR_SET_VOL_ONE:
1730    ROAR_DBG("req_on_set_vol(*): mode is ROAR_SET_VOL_ONE");
1731    if ( ROAR_NET2HOST16(info[3]) >= ROAR_MAX_CHANNELS )
1732     return -1;
1733
1734    s->mixer.mixer[ROAR_NET2HOST16(info[3])] = ROAR_NET2HOST16(info[4]);
1735
1736    s->mixer.scale = scale;
1737   break;
1738  case ROAR_SET_VOL_UNMAPPED:
1739    chans = (mes->datalen/2) - 3;
1740
1741    if ( chans >= ROAR_MAX_CHANNELS )
1742     return -1;
1743
1744    memcpy(&tmpmixer, &(s->mixer), sizeof(tmpmixer));
1745
1746    for (i = 0; i < chans; i++) {
1747     tmpmixer.mixer[i] = ROAR_NET2HOST16(info[i+3]);
1748    }
1749
1750    tmpmixer.scale = scale;
1751
1752    if ( roar_conv_volume(&(s->mixer), &tmpmixer, ROAR_STREAM(s)->info.channels, chans) == -1 )
1753     return -1;
1754
1755   break;
1756  case ROAR_SET_VOL_MS:
1757  default:
1758    return -1;
1759 }
1760
1761 if ( streams_set_mixer(stream) == -1 )
1762  return -1;
1763
1764 mes->cmd     = ROAR_CMD_OK;
1765 mes->datalen = 0;
1766
1767 return 0;
1768}
1769
1770int req_on_get_vol (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1771 uint16_t * info = (uint16_t *) mes->data;
1772 uint16_t   version = -1;
1773 int stream;
1774 struct roar_stream_server * s;
1775 int i;
1776 int chans;
1777
1778 ROAR_DBG("req_on_get_vol(*) = ?");
1779 ROAR_DBG("req_on_get_vol(*): mes->datalen=%i", mes->datalen);
1780
1781 if ( mes->datalen < 2 ) {
1782  return -1;
1783 }
1784
1785 version = ROAR_NET2HOST16(info[0]);
1786
1787 switch (version) {
1788  case 0:
1789    if ( mes->datalen < (2*2) )
1790     return -1;
1791
1792    stream = ROAR_NET2HOST16(info[1]);
1793   break;
1794  case 1:
1795    stream = mes->stream;
1796   break;
1797  default:
1798    return -1;
1799   break;
1800 }
1801
1802 ROAR_DBG("req_on_get_vol(*): stream=%i", stream);
1803
1804 // TODO: change this code.
1805 //       we should not directly change the stream object but use some stream_*()-func
1806 //       for that job.
1807
1808 if ( stream < 0 || stream >= ROAR_STREAMS_MAX )
1809  return -1;
1810
1811 s = g_streams[stream];
1812
1813 if ( s == NULL )
1814  return -1;
1815
1816 ROAR_DBG("req_on_get_vol(*): s=%p", s);
1817
1818 // ok, we have everything
1819
1820 info[0] = ROAR_HOST2NET16(version);
1821
1822 switch (version) {
1823  case 0:
1824    info[1] = ROAR_HOST2NET16(chans = ROAR_STREAM(s)->info.channels);
1825
1826    for (i = 0; i < chans; i++)
1827     info[2+i] = ROAR_HOST2NET16(s->mixer.mixer[i]);
1828
1829     mes->datalen = (2 + chans)*2;
1830   break;
1831  case 1:
1832    info[1] = ROAR_HOST2NET16(chans = ROAR_STREAM(s)->info.channels);
1833    info[2] = ROAR_HOST2NET16(s->mixer.scale);
1834    info[3] = ROAR_HOST2NET16(s->mixer.rpg_mul);
1835    info[4] = ROAR_HOST2NET16(s->mixer.rpg_div);
1836
1837    for (i = 0; i < chans; i++)
1838     info[5+i] = ROAR_HOST2NET16(s->mixer.mixer[i]);
1839
1840     mes->datalen = (5 + chans)*2;
1841   break;
1842  default:
1843    return -1;
1844   break;
1845 }
1846
1847 mes->cmd = ROAR_CMD_OK;
1848
1849 return 0;
1850}
1851
1852int req_on_add_data (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1853 struct roar_buffer * b;
1854 void               * buf;
1855
1856 if ( roar_buffer_new_data(&b, mes->datalen, &buf) == -1 ) {
1857  ROAR_ERR("req_on_add_data(*): Can not alloc buffer space!");
1858  ROAR_DBG("req_on_add_data(*) = -1");
1859  return -1;
1860 }
1861
1862 if ( data == NULL ) {
1863  memcpy(buf, mes->data, mes->datalen);
1864 } else {
1865  memcpy(buf, *data, mes->datalen);
1866 }
1867
1868 if ( stream_add_buffer(mes->stream, &b) == -1 ) {
1869  roar_buffer_free(b);
1870  return -1;
1871 }
1872
1873 mes->cmd     = ROAR_CMD_OK_STOP;
1874 mes->datalen = 0;
1875
1876 return 0;
1877}
1878
1879int req_on_beep        (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1880 struct roar_beep bs;
1881 int16_t * info = (int16_t*)mes->data;
1882 int stream;
1883
1884 memset(&bs, 0, sizeof(bs));
1885
1886 if ( mes->datalen > 0 ) {
1887  if ( mes->datalen < 2 )
1888   return -1;
1889
1890  if ( ROAR_NET2HOST16(info[0]) != 0 ) /* version */
1891   return -1;
1892
1893  if ( mes->datalen != 8*2 )
1894   return -1;
1895
1896  bs.vol  = ROAR_NET2HOST16(info[1]);
1897  bs.time = ROAR_NET2HOST16(info[2]);
1898  bs.freq = ROAR_NET2HOST16(info[3]);
1899  bs.type = ROAR_NET2HOST16(info[4]);
1900  bs.x    = ROAR_NET2HOST16(info[5]);
1901  bs.y    = ROAR_NET2HOST16(info[6]);
1902  bs.z    = ROAR_NET2HOST16(info[7]);
1903 }
1904
1905 if ( (stream = beep_start(client, &bs)) == -1 )
1906  return -1;
1907
1908 mes->stream  = stream;
1909 mes->cmd     = ROAR_CMD_OK_STOP;
1910 mes->datalen = 0;
1911
1912 return 0;
1913}
1914
1915int req_on_wait        (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1916 uint16_t * u16 = (uint16_t*)mes->data;
1917 struct roar_event events[4];
1918 size_t left, tmp;
1919 size_t num = 0;
1920 void * vp = mes->data;
1921
1922 vp += 4;
1923
1924 // check for complet header...
1925 if ( mes->datalen < 4 )
1926  return -1;
1927
1928 u16[0] = ROAR_NET2HOST16(u16[0]);
1929 u16[1] = ROAR_NET2HOST16(u16[1]);
1930
1931 // do we support version and flags?
1932 if ( u16[0] != 0 || u16[1] != 0 )
1933  return -1;
1934
1935 memset(events, 0, sizeof(events));
1936
1937 left = mes->datalen - 4;
1938
1939 while (left) {
1940  tmp = left;
1941  if ( roar_event_from_blob(&(events[num]), vp, &tmp) == -1 )
1942   return -1;
1943
1944  vp   += tmp;
1945  left -= tmp;
1946  num++;
1947 }
1948
1949 if ( clients_wait(client, events, num) == -1 )
1950  return -1;
1951
1952 flags[1] |= COMMAND_FLAG_OUT_NOSEND;
1953
1954 return 0;
1955}
1956
1957//ll
Note: See TracBrowser for help on using the repository browser.