source: roaraudio/roard/req.c @ 4468:f8d2cccafc74

Last change on this file since 4468:f8d2cccafc74 was 4468:f8d2cccafc74, checked in by phi, 14 years ago

do very basic auth stuff

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