source: roaraudio/roard/req.c @ 5439:7950543cabbc

Last change on this file since 5439:7950543cabbc was 5381:430b1d26e12d, checked in by phi, 12 years ago

updated copyright years

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