source: roaraudio/roard/req.c @ 4472:6c6c758d2b1b

Last change on this file since 4472:6c6c758d2b1b was 4472:6c6c758d2b1b, checked in by phi, 14 years ago

added parsing of auth message

File size: 35.8 KB
Line 
1//req.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2010
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#include "roard.h"
27
28// include for uname() used by req_on_server_info()
29#ifdef ROAR_HAVE_UNAME
30#include <sys/utsname.h>
31#endif
32
33static void * _dataspace(struct roar_message * mes, char ** data, uint32_t flags[2], size_t len) {
34 if ( len <= LIBROAR_BUFFER_MSGDATA )
35  return mes->data;
36
37 if ( *data != NULL )
38  free(*data);
39
40 *data = malloc(len);
41
42 ROAR_DBG("_dataspace(mes=%p, data=%p, flags=%p, len=%llu): *data=%p", mes, data, flags, (long long unsigned int)len, *data);
43
44 if ( *data == NULL )
45  return NULL;
46
47 flags[1] |= COMMAND_FLAG_OUT_LONGDATA;
48
49 return *data;
50}
51
52int req_on_noop        (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
53 mes->cmd     = ROAR_CMD_OK;
54 mes->pos     = g_pos;
55 mes->datalen = 0;
56 return 0;
57}
58
59int req_on_identify    (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
60 struct roar_client_server * cs;
61 struct roar_client        * c;
62 int max_len;
63
64 if ( mes->datalen < 1 )
65  return -1;
66
67 clients_get_server(client, &cs);
68
69 c = ROAR_CLIENT(cs);
70
71 if ( mes->data[0] == 1 ) {
72  if ( c->pid == -1 ) {
73   c->pid       = ROAR_NET2HOST32(*(uint32_t*)((mes->data)+1));
74   ROAR_DBG("req_on_identify(): new PID: c->pid = %i", c->pid);
75  }
76
77  ROAR_DBG("req_on_identify(): final PID: c->pid = %i", c->pid);
78
79  max_len = (mes->datalen - 5) < (ROAR_BUFFER_NAME-1) ? (mes->datalen - 5) : (ROAR_BUFFER_NAME-1);
80
81  strncpy(c->name, mes->data + 5, max_len);
82  c->name[max_len] = 0;
83
84  // we set the acclevel to IDENTED here.
85  // if it is alreay > IDENTED we reset it anyway
86  // as potential auth relevent data changed.
87  cs->acclev = ACCLEV_IDENTED;
88
89  mes->cmd     = ROAR_CMD_OK;
90  mes->pos     = g_pos;
91  mes->datalen = 0;
92
93  ROAR_DBG("req_on_identify(*): client=%i, pid=%i", client, c->pid);
94  ROAR_DBG("req_on_identify(*) = 0");
95  return 0;
96 }
97
98 return -1;
99}
100
101int req_on_auth        (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
102 struct roar_client_server * cs;
103 struct roar_auth_message    authmes;
104
105 clients_get_server(client, &cs);
106
107 // TODO: add code to support some auth.
108
109 if ( roar_auth_from_mes(&authmes, mes, *data) == -1 )
110  return -1;
111
112 ROAR_DBG("req_on_auth(client=%i,...): authtype=%s(%i)", client, roar_autht2str(authmes.type), authmes.type);
113
114 cs->acclev = ACCLEV_ALL;
115
116 mes->cmd     = ROAR_CMD_OK;
117 mes->pos     = g_pos;
118 mes->datalen = 0;
119 return 0;
120}
121
122
123int req_on_whoami      (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
124 mes->cmd     = ROAR_CMD_OK;
125 mes->pos     = g_pos;
126 mes->datalen = 1;
127 mes->data[0] = client;
128 return 0;
129}
130
131
132int req_on_new_stream  (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
133 int stream;
134 struct roar_stream * s;
135 struct roar_stream * source_stream;
136 struct roar_audio_info * info;
137 struct roar_audio_info * source_info;
138
139 ROAR_DBG("req_on_new_stream(client=%i, ...): creating stream...", client);
140 if ((stream = streams_new()) == -1 )
141  return -1;
142
143 ROAR_DBG("req_on_new_stream(client=%i, ...): stream=%i", client, stream);
144
145 ROAR_DBG("req_on_new_stream(client=%i, ...): getting stream...", client);
146 if ( streams_get(stream, (struct roar_stream_server **)&s) == -1 ) {
147  streams_delete(stream);
148  return -1;
149 }
150
151 ROAR_DBG("req_on_new_stream(client=%i, ...): set client of stream...", client);
152 if ( client_stream_add(client, stream) == -1 ) {
153  streams_delete(stream);
154  return -1;
155 }
156
157 ROAR_DBG("req_on_new_stream(client=%i, ...): loading stream from message...", client);
158 if ( roar_stream_m2s(s, mes) == -1 ) {
159  streams_delete(stream);
160  return -1;
161 }
162
163 ROAR_DBG("req_on_new_stream(client=%i, ...): setting id and codec of stream...", client);
164 ROAR_STREAM(s)->id = stream; // roar_stream_m2s() resets this
165 ROAR_STREAM_SERVER(s)->codec_orgi = ROAR_STREAM(s)->info.codec;
166
167 ROAR_DBG("req_on_new_stream(client=%i, ...): setting direction stream...", client);
168 // int streams_set_dir    (int id, int dir, int defaults)
169 if ( streams_set_dir(stream, ROAR_STREAM(s)->dir, 1) == -1 ) {
170  streams_delete(stream);
171  return -1;
172 }
173
174 ROAR_DBG("req_on_new_stream(client=%i, ...): setting up direction specific stream settings...", client);
175 switch (ROAR_STREAM(s)->dir) {
176  case ROAR_DIR_LIGHT_IN:
177  case ROAR_DIR_LIGHT_OUT:
178#ifndef ROAR_WITHOUT_DCOMP_LIGHT
179    info = &(ROAR_STREAM(s)->info);
180
181    info->channels = 0;
182    info->bits     = 0;
183    info->rate     = 0;
184#else
185    streams_delete(stream);
186    return -1;
187#endif
188
189   break;
190  case ROAR_DIR_MIDI_IN:
191  case ROAR_DIR_MIDI_OUT:
192#ifndef ROAR_WITHOUT_DCOMP_MIDI
193    info = &(ROAR_STREAM(s)->info);
194
195    info->channels = ROAR_MIDI_CHANNELS_DEFAULT;
196    info->bits     = ROAR_MIDI_BITS;
197    info->rate     = 0;
198#else
199    streams_delete(stream);
200    return -1;
201#endif
202
203   break;
204
205  case ROAR_DIR_RAW_IN:
206#ifndef ROAR_WITHOUT_DCOMP_RAW
207    if ( ROAR_STREAM(s)->pos_rel_id == -1     ||
208         ROAR_STREAM(s)->pos_rel_id == stream ||
209         streams_get_dir(ROAR_STREAM(s)->pos_rel_id) != ROAR_DIR_RAW_OUT
210       ) {
211     ROAR_STREAM(s)->pos_rel_id = -1; // force this here as it will try to delete itself while deleting
212                                      // in case rel_id == stream
213     streams_delete(stream);
214     return -1;
215    }
216#else
217  case ROAR_DIR_RAW_OUT:
218    streams_delete(stream);
219    return -1;
220#endif
221
222   break;
223  case ROAR_DIR_THRU:
224
225    if ( ROAR_STREAM(s)->pos_rel_id == -1 || ROAR_STREAM(s)->pos_rel_id == stream ) {
226     ROAR_STREAM(s)->pos_rel_id = -1; // force this here as it will try to delete itself while deleting
227                                      // in case rel_id == stream
228     streams_delete(stream);
229     return -1;
230    }
231
232    if ( streams_get(ROAR_STREAM(s)->pos_rel_id, (struct roar_stream_server **)&source_stream) == -1 ) {
233     streams_delete(stream);
234     return -1;
235    }
236
237    info        = &(ROAR_STREAM(s)->info);
238    source_info = &(ROAR_STREAM(source_stream)->info);
239
240    info->channels = source_info->channels;
241    info->bits     = source_info->bits;
242    info->rate     = source_info->rate;
243    info->codec    = source_info->codec;
244    ROAR_STREAM_SERVER(s)->codec_orgi = ROAR_STREAM_SERVER(source_stream)->codec_orgi;
245
246   break;
247  case ROAR_DIR_FILTER:
248    info        = &(ROAR_STREAM(s)->info);
249
250    if ( ROAR_STREAM(s)->pos_rel_id == -1 ) {
251     source_info = g_sa;
252    } else {
253     if ( streams_get(ROAR_STREAM(s)->pos_rel_id, (struct roar_stream_server **)&source_stream) == -1 ) {
254      streams_delete(stream);
255      return -1;
256     }
257     source_info = &(ROAR_STREAM(source_stream)->info);
258    }
259
260    if ( info->channels != source_info->channels || info->bits != source_info->bits ||
261         info->codec    != source_info->codec    || info->rate != source_info->rate ) {
262     // the stream parameters don't match the one of the stream being filtered.
263     // -> delete and reject the stream.
264     streams_delete(stream);
265     return -1;
266    }
267   break;
268 }
269
270 ROAR_DBG("req_on_new_stream(client=%i, ...): returning (OK, stream=%i)...", client, stream);
271
272 mes->cmd     = ROAR_CMD_OK;
273 mes->stream  = stream;
274 mes->datalen = 0;
275
276 return 0;
277}
278
279int req_on_exec_stream (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
280 int r;
281
282 ROAR_DBG("req_on_exec_stream(client=%i, mes={stream=%i,...},...): execing stream", client, mes->stream);
283
284
285 if ( streams_is_ready(mes->stream) ) {
286  flags[1] |= COMMAND_FLAG_OUT_CLOSECON;
287 } else {
288  if ( (r = client_stream_exec(client, mes->stream)) == -1 )
289   return -1;
290 }
291
292 ROAR_DBG("req_on_exec_stream(client=%i, mes={stream=%i,...},...): returning (OK)...", client, mes->stream);
293 mes->cmd     = ROAR_CMD_OK;
294 mes->datalen = 0;
295
296 return 0;
297}
298
299int req_on_con_stream  (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
300 char   host[80] = {0};
301 int    port = 0;
302 int    type;
303 int    fh;
304 int    len;
305
306 if ( mes->datalen < 4 )
307  return -1;
308
309 if ( *(mes->data) != 0 )
310  return -1;
311
312 if ( mes->datalen > 80 ) // we do not support long messages here
313  return -1;
314
315 type = (unsigned)mes->data[1];
316 port = ROAR_NET2HOST16(((uint16_t*)mes->data)[1]);
317
318 len = mes->datalen - 4;
319
320 strncpy(host, &(mes->data[4]), len);
321 host[len] = 0;
322
323 if ( type > ROAR_SOCKET_TYPE_MAX )
324  return -1;
325
326 if ( type == ROAR_SOCKET_TYPE_FILE ) // disabled because of security resons
327  return -1;
328
329 if ( type == ROAR_SOCKET_TYPE_FORK ) // why should we connect to ourself?
330  return -1;
331
332 ROAR_DBG("req_on_con_stream(*): CONNECT(type=%i, host='%s', port=%i)", type, host, port);
333
334 if ( (fh = roar_socket_open(ROAR_SOCKET_MODE_CONNECT, type, host, port)) == -1 )
335  return -1;
336
337 if ( client_stream_set_fh(client, mes->stream, fh) == -1 ) {
338  close(fh);
339  return 1;
340 }
341
342 mes->datalen = 0;
343 mes->cmd     = ROAR_CMD_OK;
344
345 return 0;
346}
347
348int req_on_passfh      (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
349 int sock = clients_get_fh(client);
350 int16_t * d = (int16_t*)mes->data;
351 struct roard_listen * lsock;
352 int listening;
353 int fh;
354 int i;
355
356 ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...) = ?", client, mes->stream);
357
358 if ( (fh = roar_socket_recv_fh(sock, NULL, NULL)) == -1 ) {
359  ROAR_WARN("req_on_passfh(client=%i, mes={stream=%i,...},...): was unabled to get filehandle from remote end. bad.", client, mes->stream);
360  ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): returning (ERROR)...", client, mes->stream);
361  return -1;
362 }
363
364 ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): fh=%i", client, mes->stream, fh);
365
366 if ( mes->stream != -1 ) { // stream pass:
367  ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): This is a stream passfh", client, mes->stream);
368
369  if ( client_stream_set_fh(client, mes->stream, fh) == -1 ) {
370   close(fh);
371   ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): returning (ERROR)...", client, mes->stream);
372   return -1;
373  }
374
375  ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): returning (OK)...", client, mes->stream);
376
377  mes->datalen = 0;
378  mes->cmd     = ROAR_CMD_OK;
379
380  return 0;
381 }
382
383// non-stream pass:
384
385 ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): This is a client passfh", client, mes->stream);
386
387/*
388 0: Version,   16
389 1: Flags,     16
390 2: Protocol,  16
391 3: Byteorder, 16
392 Options...
393*/
394
395 if ( mes->datalen < 4*2 )
396  return -1;
397
398 for (i = 0; i < 4; i++) {
399  d[i] = ROAR_NET2HOST16(d[i]);
400 }
401
402 if ( d[0] != 0 ) // version
403  return -1;
404
405 listening = d[1] & ROAR_CLIENTPASS_FLAG_LISTEN;
406
407 if ( listening )
408  d[1] -= ROAR_CLIENTPASS_FLAG_LISTEN;
409
410 if ( d[1] != 0 ) // flags
411  return -1;
412
413 if ( listening ) {
414  if ( get_listen(&lsock, NULL) == -1 ) {
415   close(fh);
416   return -1;
417  }
418
419  roar_vio_open_fh_socket(&(lsock->sock), fh);
420  lsock->used   = 1;
421  lsock->proto  = d[2];
422 } else {
423  if ( clients_new_from_fh(fh, d[2], d[3], 1) == -1 )
424   return -1;
425 }
426
427 ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): returning (OK)...", client, mes->stream);
428
429 mes->datalen = 0;
430 mes->cmd     = ROAR_CMD_OK;
431
432 return 0;
433}
434
435#ifdef ROAR_SUPPORT_META
436int req_on_set_meta    (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
437 int type;
438 int mode;
439 int namelen, vallen;
440 char   val[255+1];
441 char   name[ROAR_META_MAX_NAMELEN+1];
442
443 if ( mes->datalen < 3 )
444  return -1;
445
446 if ( mes->data[0] != 0 ) // version
447  return -1;
448
449 mode = (unsigned) mes->data[1];
450 type = (unsigned) mes->data[2];
451
452 ROAR_DBG("req_on_set_meta(*): mode=%i, type=%i", mode, type);
453
454 if ( mode == ROAR_META_MODE_CLEAR ) {
455  stream_meta_clear(mes->stream);
456  mes->datalen = 0;
457  mes->cmd     = ROAR_CMD_OK;
458  return 0;
459 } else if ( mode == ROAR_META_MODE_DELETE ) { // unsuppoerted at the moment
460  return -1;
461 } else if ( mode == ROAR_META_MODE_FINALIZE ) {
462  stream_meta_finalize(mes->stream);
463  mes->datalen = 0;
464  mes->cmd     = ROAR_CMD_OK;
465  return 0;
466 } else if ( mode == ROAR_META_MODE_SET || mode == ROAR_META_MODE_ADD ) {
467  if ( mes->datalen < 5 )
468   return -1;
469
470  namelen = (unsigned) mes->data[3];
471  vallen  = (unsigned) mes->data[4];
472
473  ROAR_DBG("req_on_set_meta(*): namelen=%i, vallen=%i", namelen, vallen);
474
475  if ( mes->datalen < (5 + namelen + vallen) )
476   return -1;
477
478  if ( namelen > ROAR_META_MAX_NAMELEN )
479   return -1;
480
481  strncpy(name, &(mes->data[5]), namelen);
482  name[namelen] = 0;
483
484  if ( vallen > 255 )
485   return -1;
486
487  strncpy(val, &(mes->data[5+namelen]), vallen);
488  val[vallen] = 0;
489
490  if ( mode == ROAR_META_MODE_SET ) {
491   if ( stream_meta_set(mes->stream, type, name, val) == -1 )
492    return -1;
493  } else {
494   if ( stream_meta_add(mes->stream, type, name, val) == -1 )
495    return -1;
496  }
497
498  mes->datalen = 0;
499  mes->cmd     = ROAR_CMD_OK;
500  return 0;
501 } else { // unknown mode!
502  return -1;
503 }
504
505 return -1;
506}
507
508int req_on_get_meta    (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
509 int vallen;
510 int type;
511 char val[LIBROAR_BUFFER_MSGDATA-1];
512
513 if ( mes->datalen != 2 )
514  return -1;
515
516 if ( mes->data[0] != 0 ) // version
517  return -1;
518
519 type = (unsigned) mes->data[1];
520
521 if ( stream_meta_get(mes->stream, type, NULL, val, LIBROAR_BUFFER_MSGDATA-2) == -1 )
522  return -1;
523
524 vallen = strlen(val);
525
526 mes->cmd     = ROAR_CMD_OK;
527 mes->datalen = 2 + vallen;
528
529 mes->data[0] = 0;
530 mes->data[1] = (unsigned char) vallen;
531
532 val[vallen] = 0;
533
534 strncpy(&(mes->data[2]), val, vallen+1);
535
536 return 0;
537}
538
539int req_on_list_meta   (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
540 int i;
541 int len = 0;
542 int types[ROAR_META_MAX_PER_STREAM];
543
544 if ( mes->datalen != 1 )
545  return -1;
546
547 if ( mes->data[0] != 0 ) // version
548  return -1;
549
550 if ( (len = stream_meta_list(mes->stream, types, ROAR_META_MAX_PER_STREAM)) == -1 )
551  return -1;
552
553 mes->cmd     = ROAR_CMD_OK;
554 mes->datalen = 1 + len;
555 mes->data[0] = 0;
556
557 for (i = 0; i < len; i++)
558  mes->data[i+1] = types[i];
559
560 return 0;
561}
562#endif
563
564int req_on_server_info (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
565#ifdef ROAR_HAVE_UNAME
566 struct utsname utsname;
567#endif
568 struct roar_server_info info;
569 uint16_t * d16;
570
571 if ( mes->datalen != 4 )
572  return -1;
573
574 d16 = (uint16_t*)mes->data;
575
576 // check version.
577 if ( ROAR_NET2HOST16(d16[0]) != 0 )
578  return -1;
579
580 switch (ROAR_NET2HOST16(d16[1])) {
581  case ROAR_IT_SERVER:
582   memset(&info, 0, sizeof(info));
583
584   info.version = "roard/" PACKAGE_VERSION " <" DEVICE_VENDOR_STRING ">";
585
586   if ( !!strcmp(g_config->location, CONF_DEF_STRING) )
587    info.location = g_config->location;
588
589   if ( !!strcmp(g_config->description, CONF_DEF_STRING) )
590   info.description = g_config->description;
591
592#ifdef ROAR_HAVE_UNAME
593   if ( uname(&utsname) == 0 ) {
594    info.un.sysname  = utsname.sysname;
595    info.un.release  = utsname.release;
596    info.un.nodename = utsname.nodename;
597    info.un.machine  = utsname.machine;
598   }
599#endif
600
601   *data = NULL;
602
603   if ( roar_server_info_to_mes(mes, &info, data) == -1 )
604    return -1;
605
606   if ( *data != NULL )
607    flags[1] |= COMMAND_FLAG_OUT_LONGDATA;
608  break;
609  default: /* unknown request */
610    return -1;
611   break;
612 }
613
614 mes->cmd = ROAR_CMD_OK;
615
616 return 0;
617}
618
619int req_on_server_oinfo    (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
620 struct roar_stream s;
621//ROAR_DIR_OUTPUT
622
623 memset(&s, 0, sizeof(struct roar_stream));
624
625 s.dir           = ROAR_DIR_MIXING;
626 s.pos_rel_id    = -1;
627 s.info.rate     = g_sa->rate;
628 s.info.bits     = g_sa->bits;
629 s.info.channels = g_sa->channels;
630 s.info.codec    = g_sa->codec;
631 s.pos           = g_pos;
632
633 if ( roar_stream_s2m(&s, mes) == -1 )
634  return -1;
635
636 mes->cmd = ROAR_CMD_OK;
637
638 return 0;
639}
640
641
642int req_on_get_standby (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
643 mes->cmd     = ROAR_CMD_OK;
644 mes->pos     = g_pos;
645 mes->datalen = 2;
646
647 *((uint16_t*)mes->data) = ROAR_HOST2NET16((unsigned) g_standby);
648
649 return 0;
650}
651
652int req_on_set_standby (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
653 if ( mes->datalen != 2 )
654  return -1;
655
656 g_standby = ROAR_NET2HOST16(*((uint16_t*)mes->data));
657
658 mes->cmd     = ROAR_CMD_OK;
659 mes->pos     = g_pos;
660 mes->datalen = 0;
661
662 return 0;
663}
664
665int req_on_exit      (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
666 int term = 0;
667
668 if ( mes->datalen == 1 )
669  term = mes->data[0];
670
671 mes->cmd     = ROAR_CMD_OK;
672 mes->pos     = g_pos;
673 mes->datalen = 0;
674
675 ROAR_DBG("req_on_exit(*): term=%i", term);
676
677 if ( term ) {
678  cleanup_listen_socket(1);
679 } else {
680  alive = 0;
681 }
682
683 return 0;
684}
685
686int req_on_list_clients(int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
687 unsigned char filter, cmp;
688 uint32_t id;
689 int clients[ROAR_CLIENTS_MAX];
690 int i, c = 0;
691
692 if ( roar_ctl_m2f(mes, &filter, &cmp, &id) == -1 )
693  return -1;
694
695 // TODO: add code to support filter
696 if ( filter != ROAR_CTL_FILTER_ANY )
697  return -1;
698
699 for (i = 0; i < ROAR_CLIENTS_MAX; i++) {
700  if ( g_clients[i] != NULL ) {
701   clients[c++] = i;
702  }
703 }
704
705 roar_ctl_ia2m(mes, clients, c);
706
707 mes->cmd = ROAR_CMD_OK;
708
709 return 0;
710}
711int req_on_list_streams(int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
712 unsigned char filter, cmp;
713 uint32_t id;
714 int streams[ROAR_STREAMS_MAX];
715 int i, c = 0;
716 int match;
717
718 if ( roar_ctl_m2f(mes, &filter, &cmp, &id) == -1 )
719  return -1;
720
721 for (i = 0; i < ROAR_STREAMS_MAX; i++) {
722  if ( g_streams[i] == NULL )
723   continue;
724
725  match = 0;
726
727  switch (filter) {
728   case ROAR_CTL_FILTER_ANY:
729     match = 1;
730    break;
731   case ROAR_CTL_FILTER_DIR:
732     match = roar_filter_match(cmp, id, ROAR_STREAM(g_streams[i])->dir);
733    break;
734   default: // unsupported filter...
735     return -1;
736    break;
737  }
738
739  if ( match )
740   streams[c++] = i;
741 }
742
743 roar_ctl_ia2m(mes, streams, c);
744
745 mes->cmd = ROAR_CMD_OK;
746
747 return 0;
748}
749
750int req_on_get_client  (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
751 struct roar_client * c;
752
753 if ( mes->datalen != 1 )
754  return -1;
755
756 if ( clients_get(mes->data[0], &c) == -1 )
757  return -1;
758
759 mes->cmd = ROAR_CMD_OK;
760
761 return roar_ctl_c2m(mes, c);
762}
763
764int req_on_get_stream  (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
765 struct roar_stream_server * s;
766
767 if ( mes->datalen != 1 )
768  return -1;
769
770 if ( streams_get(mes->data[0], &s) == -1 )
771  return -1;
772
773 mes->cmd = ROAR_CMD_OK;
774 mes->stream = mes->data[0];
775
776 return roar_stream_s2m(ROAR_STREAM(s), mes);
777}
778
779int req_on_get_stream_para (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
780 struct roar_stream * s;
781 struct roar_stream_server * ss;
782 struct roar_audio_info * audio_info;
783 struct roar_stream_ltm * ltm;
784 uint16_t * d  = (uint16_t *) mes->data;
785 int64_t * d64 = ( int64_t *) mes->data;
786 int64_t * d64ptr;
787 int i, h, k;
788 char * str;
789 size_t needed;
790 int test, bits;
791
792 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);
793
794 if ( mes->datalen < 4 )
795  return -1;
796
797 for (i = 0; i < 2; i++) {
798  d[i] = ROAR_NET2HOST16(d[i]);
799 }
800
801 if ( d[0] != 0 ) {
802  ROAR_WARN("req_on_get_stream_para(*): unsupported command version: %i, %i", (int)d[0], (int)d[1]);
803  return -1;
804 }
805
806 switch (d[1]) {
807  case ROAR_STREAM_PARA_INFO:
808    if ( streams_get(mes->stream, &ss) == -1 ) {
809     ROAR_WARN("req_on_get_stream_para(*): request on non existing (or other error?) stream %i", mes->stream);
810     return -1;
811    }
812
813    if ( streams_calc_delay(mes->stream) == -1 ) {
814     ROAR_WARN("req_on_get_stream_para(*): can not calc delay for stream %i", mes->stream);
815    }
816
817    s = ROAR_STREAM(ss);
818
819    audio_info = &(s->info);
820
821    mes->datalen = 2*12;
822
823    d[ 2] = ROAR_OUTPUT_CALC_OUTBUFSIZE(audio_info);
824    d[ 3] = ss->pre_underruns;
825    d[ 4] = ss->post_underruns;
826    d[ 5] = ss->codec_orgi;
827    d[ 6] = (ss->flags & 0xFFFF) | (ss->primary ? ROAR_FLAG_PRIMARY : 0) | (ss->driver_id != -1 ? ROAR_FLAG_OUTPUT : 0);
828    d[ 7] = ss->delay/1000;
829    d[ 8] = ss->state;
830    d[ 9] = (ss->flags & 0xFFFF0000) >> 16;
831    d[10] = ss->mixer_stream;
832    d[11] = ss->role;
833
834    ROAR_DBG("req_on_get_stream_para(*): ss->driver_id=%i", ss->driver_id);
835
836    ROAR_DBG("req_on_get_stream_para(*): delay=%i, send delay=%i", ss->delay, d[7]);
837
838    for (i = 0; i < mes->datalen/2; i++) {
839     d[i] = ROAR_HOST2NET16(d[i]);
840    }
841
842    mes->pos = s->pos;
843   break;
844
845  case ROAR_STREAM_PARA_NAME:
846   str = streams_get_name(mes->stream);
847
848   if ( str == NULL )
849    return -1;
850
851    mes->datalen = 4 + strlen(str);
852
853    if ( mes->datalen > LIBROAR_BUFFER_MSGDATA )
854     return -1;
855
856    strncpy(((char*)&(mes->data))+4, str, mes->datalen);
857
858    d[0] = ROAR_HOST2NET16(d[0]);
859    d[1] = ROAR_HOST2NET16(d[1]);
860   break;
861
862  case ROAR_STREAM_PARA_CHANMAP:
863    if ( streams_get(mes->stream, &ss) == -1 ) {
864     ROAR_WARN("req_on_get_stream_para(*): request on non existing (or other error?) stream %i", mes->stream);
865     return -1;
866    }
867
868    s = ROAR_STREAM(ss);
869
870    memcpy(&(mes->data[4]), ss->chanmap.in, s->info.channels);
871    mes->datalen = 2*2 + s->info.channels;
872
873    d[0] = ROAR_HOST2NET16(d[0]);
874    d[1] = ROAR_HOST2NET16(d[1]);
875   break;
876
877  case ROAR_STREAM_PARA_LTM:
878    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM request...", client);
879
880    if ( mes->datalen < (6 * 2) ) {
881     ROAR_ERR("req_on_get_stream_para(client=%i, ...): LTM request of client is corruped: message too short", client);
882     return -1;
883    }
884
885    for (i = 2; i < mes->datalen/2; i++) {
886     d[i] = ROAR_NET2HOST16(d[i]);
887    }
888
889    if ( d[2] != ROAR_LTM_SST_GET_RAW ) {
890     ROAR_ERR("req_on_get_stream_para(client=%i, ...): LTM request of client is corruped: unknown LTM subtype: %i", client, (int)d[2]);
891     return -1;
892    }
893
894    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM request of type GET_RAW", client);
895
896    test = d[5];
897    bits = 0;
898    while (test) {
899     if ( test & 0x1 )
900      bits++;
901
902     test >>= 1;
903    }
904
905    needed = 0;
906
907    if ( mes->stream == -1 ) {
908     ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM multi-stream request...", client);
909
910     for (i = 6; i < mes->datalen/2; i++) {
911      if ( (ltm = streams_ltm_get(d[i], d[5], d[3])) == NULL )
912       return -1;
913
914      needed += ltm->channels;
915     }
916    } else {
917     ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM single-stream request for stream %i...", client, mes->stream);
918     if ( (ltm = streams_ltm_get(mes->stream, d[5], d[3])) == NULL )
919      return -1;
920
921     needed = ltm->channels;
922    }
923
924    needed *= bits;
925
926    needed += mes->stream == -1 ? (mes->datalen/2) - 6 : 1;
927
928    ROAR_DBG("req_on_get_stream_para(client=%i, ...): data size for answer is %i 64 bit sub-packets", client, (int)needed);
929
930    ROAR_DBG("req_on_get_stream_para(client=%i, ...): mes->datalen=%i, data=%p{%p}", client, (int)mes->datalen, data, *data);
931    d64 = _dataspace(mes, data, flags, needed * 8);
932    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
933
934    if ( (d = roar_mm_malloc(mes->datalen)) == NULL )
935     return -1;
936
937    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d=%p, data=%p{%p}", client, d, data, *data);
938
939
940    ROAR_DBG("req_on_get_stream_para(client=%i, ...): mes->datalen=%i, data=%p{%p}", client, (int)mes->datalen, data, *data);
941    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
942    memcpy(d, mes->data, mes->datalen);
943    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
944
945    d64ptr = d64;
946
947    ROAR_DBG("req_on_get_stream_para(client=%i, ...): mes->datalen=%i, data=%p{%p}", client, (int)mes->datalen, data, *data);
948    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
949
950    if ( mes->stream == -1 ) {
951     for (i = 6; i < mes->datalen/2; i++) {
952      ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
953
954      if ( (ltm = streams_ltm_get(d[i], d[5], d[3])) == NULL )
955       return -1;
956
957      *d64ptr = ltm->channels & 0xFFFF;
958       d64ptr++;
959
960      for (h = 0; h < ltm->channels; h++) {
961       for (k = 0; k < ROAR_LTM_MTBITS; k++) {
962        if ( d[5] & (1<<k) ) {
963         switch (1<<k) {
964          case ROAR_LTM_MT_RMS:
965            *d64ptr = ltm->cur[h].rms;
966           break;
967          default:
968            ROAR_ERR("req_on_get_stream_para(client=%i, ...): client requets unknown MT for LTM: bit %i", client, k);
969         }
970         d64ptr++;
971        }
972       }
973      }
974     }
975    } else {
976     if ( (ltm = streams_ltm_get(mes->stream, d[5], d[3])) == NULL )
977      return -1;
978
979     *d64ptr = ltm->channels & 0xFFFF;
980      d64ptr++;
981
982     for (h = 0; h < ltm->channels; h++) {
983      for (k = 0; k < ROAR_LTM_MTBITS; k++) {
984       if ( d[5] & (1<<k) ) {
985        switch (1<<k) {
986         case ROAR_LTM_MT_RMS:
987           *d64ptr = ltm->cur[h].rms;
988           ROAR_DBG("req_on_get_stream_para(client=%i, ...): rms=%lli to %p", client, (long long int)*d64ptr, d64ptr);
989          break;
990         default:
991           ROAR_ERR("req_on_get_stream_para(client=%i, ...): client requets unknown MT for LTM: bit %i", client, k);
992        }
993        d64ptr++;
994       }
995      }
996     }
997    }
998
999    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1000
1001    roar_mm_free(d);
1002
1003    for (i = 0; i < needed; i++) {
1004     d64[i] = ROAR_HOST2NET64(d64[i]);
1005    }
1006
1007    mes->datalen = needed * 8;
1008    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM d64=%p, d64ptr=%p", client, d64, d64ptr);
1009    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM final message has %i byte of data", client, (int)mes->datalen);
1010    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1011    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM GET_RAW request: OK. returning...", client);
1012   break;
1013
1014  default:
1015    ROAR_WARN("req_on_get_stream_para(*): unsupported command: %i", d[1]);
1016    return -1;
1017 }
1018
1019 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);
1020 mes->cmd = ROAR_CMD_OK;
1021 return 0;
1022}
1023
1024int req_on_set_stream_para (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1025 uint16_t * d = (uint16_t *) mes->data;
1026 int i;
1027
1028 if ( mes->datalen < 2*2 )
1029  return -1;
1030
1031 for (i = 0; i < 2; i++) {
1032  d[i] = ROAR_NET2HOST16(d[i]);
1033 }
1034
1035 if ( d[0] != 0 )
1036  return -1;
1037
1038 switch (d[1]) {
1039  case ROAR_STREAM_PARA_FLAGS:
1040    if ( mes->datalen != 2*4 )
1041     return -1;
1042
1043    d[2] = ROAR_NET2HOST16(d[2]);
1044    d[3] = ROAR_NET2HOST16(d[3]);
1045
1046    ROAR_DBG("req_on_set_stream_para(*): request seems to be valid");
1047
1048    if ( d[2] == ROAR_RESET_FLAG ) {
1049     if ( streams_reset_flag(mes->stream, d[3]) == -1 )
1050      return -1;
1051    } else {
1052     if ( streams_set_flag(mes->stream, d[3]) == -1 )
1053      return -1;
1054    }
1055   break;
1056  case ROAR_STREAM_PARA_CHANMAP:
1057    if ( streams_set_map(mes->stream, &(mes->data[4]), mes->datalen - 4) == -1 )
1058     return -1;
1059   break;
1060  case ROAR_STREAM_PARA_ROLE:
1061    if ( mes->datalen != 2*3 )
1062     return -1;
1063
1064    d[2] = ROAR_NET2HOST16(d[2]);
1065
1066    if ( streams_set_role(mes->stream, d[2]) == -1 )
1067     return -1;
1068   break;
1069  case ROAR_STREAM_PARA_LTM:
1070    if ( mes->datalen < (6 * 2) )
1071     return -1;
1072
1073    for (i = 2; i < mes->datalen/2; i++) {
1074     d[i] = ROAR_NET2HOST16(d[i]);
1075    }
1076
1077    if ( mes->stream == -1 ) {
1078     for (i = 6; i < mes->datalen/2; i++)
1079      if ( streams_ltm_ctl(d[i], d[5], d[3], d[2]) == -1 )
1080       return -1;
1081    } else {
1082     if ( streams_ltm_ctl(mes->stream, d[5], d[3], d[2]) == -1 )
1083      return -1;
1084    }
1085   break;
1086  default:
1087    ROAR_WARN("req_on_set_stream_para(*): unsupported command version: %i, %i", d[0], d[1]);
1088    return -1;
1089   break;
1090 }
1091
1092 mes->cmd     = ROAR_CMD_OK;
1093 mes->datalen = 0;
1094
1095 return 0;
1096}
1097
1098int req_on_kick (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1099 struct roar_stream_server * ss;
1100 uint16_t * info = (uint16_t *) mes->data;
1101 int is_stream = 0;
1102
1103 if ( mes->datalen != 4 )
1104  return -1;
1105
1106 info[0] = ROAR_NET2HOST16(info[0]);
1107 info[1] = ROAR_NET2HOST16(info[1]);
1108
1109 switch (info[0]) {
1110  case ROAR_OT_CLIENT:
1111    clients_delete(info[1]);
1112   break;
1113  case ROAR_OT_STREAM:
1114    is_stream = 1;
1115   break;
1116  case ROAR_OT_SOURCE:
1117    if ( streams_get_flag(info[1], ROAR_FLAG_SOURCE) != 1 )
1118     return -1;
1119    is_stream = 1;
1120   break;
1121  case ROAR_OT_OUTPUT:
1122    if ( streams_get(info[1], &ss) == -1 )
1123     return -1;
1124
1125    if ( ss->driver_id == -1 )
1126     return -1;
1127
1128    is_stream = 1;
1129   break;
1130  case ROAR_OT_MIXER:
1131    if ( streams_get(info[1], &ss) == -1 )
1132     return -1;
1133
1134    if ( ROAR_STREAM(ss)->dir != ROAR_DIR_MIXING )
1135     return -1;
1136
1137    is_stream = 1;
1138   break;
1139  case ROAR_OT_BRIDGE:
1140    if ( streams_get(info[1], &ss) == -1 )
1141     return -1;
1142
1143    if ( ROAR_STREAM(ss)->dir != ROAR_DIR_BRIDGE )
1144     return -1;
1145
1146    is_stream = 1;
1147   break;
1148  default:
1149/* TODO: those types should be handled, too:
1150#define ROAR_OT_SAMPLE    4
1151#define ROAR_OT_LISTEN    8
1152#define ROAR_OT_ACTION    9
1153#define ROAR_OT_MSGQUEUE 10
1154#define ROAR_OT_MSGBUS   11
1155*/
1156    return -1;
1157   break;
1158 }
1159
1160 if ( is_stream ) {
1161  if ( streams_get_flag(info[1], ROAR_FLAG_IMMUTABLE) == 1 )
1162   return -1;
1163
1164  streams_delete(info[1]);
1165 }
1166
1167 mes->cmd     = ROAR_CMD_OK;
1168 mes->datalen = 0;
1169
1170 return 0;
1171}
1172
1173int req_on_attach      (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1174 uint16_t * info = (uint16_t *) mes->data;
1175
1176 if ( mes->datalen < 6 )
1177  return -1;
1178
1179 info[0] = ROAR_NET2HOST16(info[0]);
1180 info[1] = ROAR_NET2HOST16(info[1]);
1181 info[2] = ROAR_NET2HOST16(info[2]);
1182
1183 if ( info[0] != 0 )
1184  return -1;
1185
1186 if ( info[1] == ROAR_ATTACH_SIMPLE ) {
1187  if ( client_stream_move(info[2], mes->stream) == -1 )
1188   return -1;
1189 } else {
1190  return -1;
1191 }
1192
1193 mes->cmd     = ROAR_CMD_OK;
1194 mes->datalen = 0;
1195
1196 return 0;
1197}
1198
1199int req_on_set_vol (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1200 struct roar_stream_server * s;
1201 uint16_t * info = (uint16_t *) mes->data;
1202 uint16_t   version;
1203 uint16_t   scale = 65535;
1204 int stream;
1205 int i;
1206 int chans;
1207
1208 ROAR_DBG("req_on_set_vol(*) = ?");
1209 ROAR_DBG("req_on_set_vol(*): mes->datalen=%i", mes->datalen);
1210
1211 if ( mes->datalen < (4*2) )
1212  return -1;
1213
1214 version = ROAR_NET2HOST16(info[0]);
1215 ROAR_DBG("req_on_set_vol(*): version=%i", (int)version);
1216
1217 switch (version) {
1218  case 0:
1219    stream = ROAR_NET2HOST16(info[1]);
1220   break;
1221  case 1:
1222    stream = mes->stream;
1223    scale  = ROAR_NET2HOST16(info[1]);
1224   break;
1225  default:
1226    return -1;
1227   break;
1228 }
1229 ROAR_DBG("req_on_set_vol(*): stream=%i", stream);
1230
1231 if ( scale == 0 )
1232  return -1;
1233
1234 // TODO: change this code.
1235 //       we should not directly change the stream object but use some stream_*()-func
1236 //       for that job.
1237
1238 if ( stream < 0 || stream >= ROAR_STREAMS_MAX )
1239  return -1;
1240
1241 s = g_streams[stream];
1242
1243 if ( s == NULL )
1244  return -1;
1245
1246 ROAR_DBG("req_on_set_vol(*): s=%p", s);
1247
1248 info[2] = ROAR_NET2HOST16(info[2]);
1249
1250 if ( info[2] == ROAR_SET_VOL_ALL ) {
1251  chans = (mes->datalen/2) - 3;
1252  ROAR_DBG("req_on_set_vol(*): mode is ROAR_SET_VOL_ALL, channes=%i", chans);
1253
1254  if ( chans >= ROAR_MAX_CHANNELS )
1255   return -1;
1256
1257  ROAR_DBG("req_on_set_vol(*): mixer at %p", s->mixer.mixer);
1258
1259  for (i = 0; i < chans; i++) {
1260   s->mixer.mixer[i] = ROAR_NET2HOST16(info[i+3]);
1261   ROAR_DBG("req_on_set_vol(*): channel %i: %i", i, ROAR_NET2HOST16(info[i+3]));
1262  }
1263
1264  s->mixer.scale = scale;
1265
1266  ROAR_DBG("req_on_set_vol(*): mixer changed!");
1267
1268 } else if ( info[2] == ROAR_SET_VOL_ONE ) {
1269  ROAR_DBG("req_on_set_vol(*): mode is ROAR_SET_VOL_ONE");
1270  if ( ROAR_NET2HOST16(info[3]) >= ROAR_MAX_CHANNELS )
1271   return -1;
1272
1273  s->mixer.mixer[ROAR_NET2HOST16(info[3])] = ROAR_NET2HOST16(info[4]);
1274
1275  s->mixer.scale = scale;
1276 } else {
1277  return -1;
1278 }
1279
1280 if ( streams_set_mixer(stream) == -1 )
1281  return -1;
1282
1283 mes->cmd     = ROAR_CMD_OK;
1284 mes->datalen = 0;
1285
1286 return 0;
1287}
1288
1289int req_on_get_vol (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1290 uint16_t * info = (uint16_t *) mes->data;
1291 uint16_t   version = -1;
1292 int stream;
1293 struct roar_stream_server * s;
1294 int i;
1295 int chans;
1296
1297 ROAR_DBG("req_on_get_vol(*) = ?");
1298 ROAR_DBG("req_on_get_vol(*): mes->datalen=%i", mes->datalen);
1299
1300 if ( mes->datalen < 2 ) {
1301  return -1;
1302 }
1303
1304 version = ROAR_NET2HOST16(info[0]);
1305
1306 switch (version) {
1307  case 0:
1308    if ( mes->datalen < (2*2) )
1309     return -1;
1310
1311    stream = ROAR_NET2HOST16(info[1]);
1312   break;
1313  case 1:
1314    stream = mes->stream;
1315   break;
1316  default:
1317    return -1;
1318   break;
1319 }
1320
1321 ROAR_DBG("req_on_get_vol(*): stream=%i", stream);
1322
1323 // TODO: change this code.
1324 //       we should not directly change the stream object but use some stream_*()-func
1325 //       for that job.
1326
1327 if ( stream < 0 || stream >= ROAR_STREAMS_MAX )
1328  return -1;
1329
1330 s = g_streams[stream];
1331
1332 if ( s == NULL )
1333  return -1;
1334
1335 ROAR_DBG("req_on_get_vol(*): s=%p", s);
1336
1337 // ok, we have everything
1338
1339 info[0] = ROAR_HOST2NET16(version);
1340
1341 switch (version) {
1342  case 0:
1343    info[1] = ROAR_HOST2NET16(chans = ROAR_STREAM(s)->info.channels);
1344
1345    for (i = 0; i < chans; i++)
1346     info[2+i] = ROAR_HOST2NET16(s->mixer.mixer[i]);
1347
1348     mes->datalen = (2 + chans)*2;
1349   break;
1350  case 1:
1351    info[1] = ROAR_HOST2NET16(chans = ROAR_STREAM(s)->info.channels);
1352    info[2] = ROAR_HOST2NET16(s->mixer.scale);
1353    info[3] = ROAR_HOST2NET16(s->mixer.rpg_mul);
1354    info[4] = ROAR_HOST2NET16(s->mixer.rpg_div);
1355
1356    for (i = 0; i < chans; i++)
1357     info[5+i] = ROAR_HOST2NET16(s->mixer.mixer[i]);
1358
1359     mes->datalen = (5 + chans)*2;
1360   break;
1361  default:
1362    return -1;
1363   break;
1364 }
1365
1366 mes->cmd = ROAR_CMD_OK;
1367
1368 return 0;
1369}
1370
1371int req_on_add_data (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1372 struct roar_buffer * b;
1373 char               * buf;
1374
1375 if ( roar_buffer_new_data(&b, mes->datalen, (void **)&buf) == -1 ) {
1376  ROAR_ERR("req_on_add_data(*): Can not alloc buffer space!");
1377  ROAR_DBG("req_on_add_data(*) = -1");
1378  return -1;
1379 }
1380
1381 if ( data == NULL ) {
1382  memcpy(buf, mes->data, mes->datalen);
1383 } else {
1384  memcpy(buf, *data, mes->datalen);
1385 }
1386
1387 if ( stream_add_buffer(mes->stream, b) == -1 ) {
1388  roar_buffer_free(b);
1389  return -1;
1390 }
1391
1392 mes->cmd     = ROAR_CMD_OK_STOP;
1393 mes->datalen = 0;
1394
1395 return 0;
1396}
1397
1398int req_on_beep        (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1399 struct roar_beep bs;
1400 int16_t * info = (int16_t*)mes->data;
1401 int stream;
1402
1403 memset(&bs, 0, sizeof(bs));
1404
1405 if ( mes->datalen > 0 ) {
1406  if ( mes->datalen < 2 )
1407   return -1;
1408
1409  if ( ROAR_NET2HOST16(info[0]) != 0 ) /* version */
1410   return -1;
1411
1412  if ( mes->datalen != 8*2 )
1413   return -1;
1414
1415  bs.vol  = ROAR_NET2HOST16(info[1]);
1416  bs.time = ROAR_NET2HOST16(info[2]);
1417  bs.freq = ROAR_NET2HOST16(info[3]);
1418  bs.type = ROAR_NET2HOST16(info[4]);
1419  bs.x    = ROAR_NET2HOST16(info[5]);
1420  bs.y    = ROAR_NET2HOST16(info[6]);
1421  bs.z    = ROAR_NET2HOST16(info[7]);
1422 }
1423
1424 if ( (stream = beep_start(client, &bs)) == -1 )
1425  return -1;
1426
1427 mes->stream  = stream;
1428 mes->cmd     = ROAR_CMD_OK_STOP;
1429 mes->datalen = 0;
1430
1431 return 0;
1432}
1433
1434int req_on_wait        (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1435 uint16_t * u16 = (uint16_t*)mes->data;
1436 struct roar_event events[4];
1437 size_t left, tmp;
1438 size_t num = 0;
1439 void * vp = mes->data;
1440
1441 vp += 4;
1442
1443 // check for complet header...
1444 if ( mes->datalen < 4 )
1445  return -1;
1446
1447 u16[0] = ROAR_NET2HOST16(u16[0]);
1448 u16[1] = ROAR_NET2HOST16(u16[1]);
1449
1450 // do we support version and flags?
1451 if ( u16[0] != 0 || u16[1] != 0 )
1452  return -1;
1453
1454 memset(events, 0, sizeof(events));
1455
1456 left = mes->datalen - 4;
1457
1458 while (left) {
1459  tmp = left;
1460  if ( roar_event_from_blob(&(events[num]), vp, &tmp) == -1 )
1461   return -1;
1462
1463  vp   += tmp;
1464  left -= tmp;
1465  num++;
1466 }
1467
1468 if ( clients_wait(client, events, num) == -1 )
1469  return -1;
1470
1471 flags[1] |= COMMAND_FLAG_OUT_NOSEND;
1472
1473 return 0;
1474}
1475
1476//ll
Note: See TracBrowser for help on using the repository browser.