source: roaraudio/roard/req.c @ 4790:c1073581d7c2

Last change on this file since 4790:c1073581d7c2 was 4790:c1073581d7c2, checked in by phi, 13 years ago

added support for long (> sizeof(mes.data)-4) cookies, fixed memory use-after-free bug in roard

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