source: roaraudio/roard/req.c @ 5301:f3e9cd30574d

Last change on this file since 5301:f3e9cd30574d was 5301:f3e9cd30574d, checked in by phi, 12 years ago

move away from roar_buffer_add() (See: #126)

File size: 45.4 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/* 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.license = "GPL-3.0";
778
779#ifdef ROAR_HAVE_GETHOSTID
780   hostid = gethostid();
781   snprintf(hostidbuf, sizeof(hostidbuf), sizeof(long) == 8 ? "0x%.16lx" : "0x%.8lx", hostid);
782   info.hostid = hostidbuf;
783#endif
784
785   if ( !!strcmp(g_config->location, CONF_DEF_STRING) )
786    info.location = g_config->location;
787
788   if ( !!strcmp(g_config->description, CONF_DEF_STRING) )
789    info.description = g_config->description;
790
791   info.contact = g_config->contact;
792   info.serial  = g_config->serial;
793   info.uiurl   = g_config->uiurl;
794
795#ifdef ROAR_HAVE_UNAME
796   if ( uname(&utsname) == 0 ) {
797    info.un.sysname  = utsname.sysname;
798    info.un.release  = utsname.release;
799    info.un.nodename = utsname.nodename;
800    info.un.machine  = utsname.machine;
801   }
802#endif
803#ifdef ROAR_HAVE_GETVERSIONEX
804   osinfo.dwOSVersionInfoSize = sizeof(osinfo);
805   if ( GetVersionEx(&osinfo) ) {
806    info.un.sysname = "Windows";
807    snprintf(buf_release, sizeof(buf_release), "%i.%i.%i",
808               (int)osinfo.dwMajorVersion, (int)osinfo.dwMinorVersion, (int)osinfo.dwBuildNumber);
809    buf_release[sizeof(buf_release)-1] = 0;
810    info.un.release = buf_release;
811   }
812#endif
813
814   *data = NULL;
815
816   if ( roar_server_info_to_mes(mes, &info, (void**)data) == -1 )
817    return -1;
818
819   if ( *data != NULL )
820    flags[1] |= COMMAND_FLAG_OUT_LONGDATA;
821  break;
822  default: /* unknown request */
823    return -1;
824   break;
825 }
826
827 mes->cmd = ROAR_CMD_OK;
828
829 return 0;
830}
831
832int req_on_server_oinfo    (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
833 struct roar_stream s;
834 int dir = ROAR_DIR_PLAY;
835 int subsys;
836//ROAR_DIR_OUTPUT
837
838 if ( mes->datalen != 0 ) {
839  if ( mes->datalen != 2 )
840   return -1;
841
842  if ( mes->data[0] != 0 )
843   return -1;
844
845  dir = mes->data[1];
846 }
847
848 subsys = streams_dir2subsys(dir);
849
850 memset(&s, 0, sizeof(struct roar_stream));
851
852 s.dir           = ROAR_DIR_MIXING;
853 s.pos_rel_id    = -1;
854
855 switch (subsys) {
856  case ROAR_SUBSYS_WAVEFORM:
857    s.info.rate     = g_sa->rate;
858    s.info.bits     = g_sa->bits;
859    s.info.channels = g_sa->channels;
860    s.info.codec    = g_sa->codec;
861    s.pos           = g_pos;
862   break;
863#ifndef ROAR_WITHOUT_DCOMP_MIDI
864  case ROAR_SUBSYS_MIDI:
865   break;
866#endif
867#ifndef ROAR_WITHOUT_DCOMP_LIGHT
868  case ROAR_SUBSYS_LIGHT:
869    s.info.rate     = ROAR_OUTPUT_CFREQ;
870    s.info.bits     = ROAR_LIGHT_BITS;
871    s.info.channels = g_light_state.channels;
872   break;
873#endif
874#ifndef ROAR_WITHOUT_DCOMP_RAW
875  case ROAR_SUBSYS_RAW:
876    // no need to set anything here.
877   break;
878#endif
879#ifndef ROAR_WITHOUT_DCOMP_RDTCS
880  case ROAR_SUBSYS_RDTCS:
881    s.info.rate     = ROAR_OUTPUT_CFREQ;
882    s.info.bits     = ROAR_RDTCS_BITS;
883    s.info.channels = ROAR_RDTCS_CHANNELS;
884    s.info.codec    = ROAR_RDTCS_CODEC;
885   break;
886#endif
887  default:
888    return -1;
889   break;
890 }
891
892 if ( roar_stream_s2m(&s, mes) == -1 )
893  return -1;
894
895 mes->cmd = ROAR_CMD_OK;
896
897 return 0;
898}
899
900int req_on_caps        (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
901 struct roar_caps caps;
902 struct roar_stds * stds;
903 size_t i;
904
905 if ( roar_caps_from_msg(&caps, mes, *data) == -1 )
906  return -1;
907
908 // handle the data from the caps command here...
909
910 if ( !(caps.flags & ROAR_CF_REQUEST) ) {
911  mes->cmd = ROAR_CMD_OK;
912  mes->datalen = 0;
913  return 0;
914 }
915
916 mes->datalen = 0;
917
918 switch (caps.type) {
919  case ROAR_CT_STANDARDS:
920    if ( (stds = roar_stds_new(g_caps_stds.stds_len)) == NULL )
921     return -1;
922
923    for ( i = 0; i < stds->stds_len; i++) {
924     stds->stds[i] = ROAR_HOST2NET32(g_caps_stds.stds[i]);
925    }
926
927    caps.data = stds->stds;
928    caps.len  = stds->stds_len * 4;
929    // TODO: add support for **data.
930    if ( roar_caps_to_msg(mes, &caps, NULL) == -1 ) {
931     roar_stds_free(stds);
932     return -1;
933    }
934    roar_stds_free(stds);
935   break;
936  default:
937    return -1;
938   break;
939 }
940
941 mes->cmd = ROAR_CMD_OK;
942
943 return 0;
944}
945
946int req_on_get_standby (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
947 mes->cmd     = ROAR_CMD_OK;
948 mes->pos     = g_pos;
949 mes->datalen = 2;
950
951 *((uint16_t*)mes->data) = ROAR_HOST2NET16((unsigned) g_standby);
952
953 return 0;
954}
955
956int req_on_set_standby (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
957 if ( mes->datalen != 2 )
958  return -1;
959
960 g_standby = ROAR_NET2HOST16(*((uint16_t*)mes->data));
961
962 mes->cmd     = ROAR_CMD_OK;
963 mes->pos     = g_pos;
964 mes->datalen = 0;
965
966 return 0;
967}
968
969int req_on_exit      (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
970 int term = 0;
971
972 if ( mes->datalen == 1 )
973  term = mes->data[0];
974
975 mes->cmd     = ROAR_CMD_OK;
976 mes->pos     = g_pos;
977 mes->datalen = 0;
978
979 ROAR_DBG("req_on_exit(*): term=%i", term);
980
981 if ( term ) {
982  cleanup_listen_socket(1);
983 } else {
984  alive = 0;
985 }
986
987 return 0;
988}
989
990int req_on_list_clients(int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
991 unsigned char filter, cmp;
992 uint32_t id;
993 int clients[ROAR_CLIENTS_MAX];
994 int i, c = 0;
995
996 if ( roar_ctl_m2f(mes, &filter, &cmp, &id) == -1 )
997  return -1;
998
999 // TODO: add code to support filter
1000 if ( filter != ROAR_CTL_FILTER_ANY )
1001  return -1;
1002
1003 for (i = 0; i < ROAR_CLIENTS_MAX; i++) {
1004  if ( g_clients[i] != NULL ) {
1005   clients[c++] = i;
1006  }
1007 }
1008
1009 roar_ctl_ia2m(mes, clients, c);
1010
1011 mes->cmd = ROAR_CMD_OK;
1012
1013 return 0;
1014}
1015int req_on_list_streams(int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1016 unsigned char filter, cmp;
1017 uint32_t id;
1018 int streams[ROAR_STREAMS_MAX];
1019 int i, c = 0;
1020 int match;
1021
1022 if ( roar_ctl_m2f(mes, &filter, &cmp, &id) == -1 )
1023  return -1;
1024
1025 for (i = 0; i < ROAR_STREAMS_MAX; i++) {
1026  if ( g_streams[i] == NULL )
1027   continue;
1028
1029  match = 0;
1030
1031  switch (filter) {
1032   case ROAR_CTL_FILTER_ANY:
1033     match = 1;
1034    break;
1035   case ROAR_CTL_FILTER_DIR:
1036     match = roar_filter_match(cmp, id, ROAR_STREAM(g_streams[i])->dir);
1037    break;
1038   default: // unsupported filter...
1039     return -1;
1040    break;
1041  }
1042
1043  if ( match )
1044   streams[c++] = i;
1045 }
1046
1047 roar_ctl_ia2m(mes, streams, c);
1048
1049 mes->cmd = ROAR_CMD_OK;
1050
1051 return 0;
1052}
1053
1054int req_on_get_client  (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1055 struct roar_client * c;
1056
1057 if ( mes->datalen != 1 )
1058  return -1;
1059
1060 if ( clients_get(mes->data[0], &c) == -1 )
1061  return -1;
1062
1063 mes->cmd = ROAR_CMD_OK;
1064
1065 return roar_ctl_c2m(mes, c);
1066}
1067
1068int req_on_get_stream  (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1069 struct roar_stream_server * s;
1070
1071 if ( mes->datalen != 1 )
1072  return -1;
1073
1074 if ( streams_get(mes->data[0], &s) == -1 )
1075  return -1;
1076
1077 mes->cmd = ROAR_CMD_OK;
1078 mes->stream = mes->data[0];
1079
1080 return roar_stream_s2m(ROAR_STREAM(s), mes);
1081}
1082
1083int req_on_get_stream_para (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1084 struct roar_stream * s;
1085 struct roar_stream_server * ss;
1086 struct roar_audio_info * audio_info;
1087 struct roar_stream_ltm * ltm;
1088 uint16_t * d  = (uint16_t *) mes->data;
1089 int64_t * d64 = ( int64_t *) mes->data;
1090 int64_t * d64ptr;
1091 int i, h, k;
1092 char * str;
1093 size_t needed;
1094 int test, bits;
1095
1096 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);
1097
1098 if ( mes->datalen < 4 )
1099  return -1;
1100
1101 for (i = 0; i < 2; i++) {
1102  d[i] = ROAR_NET2HOST16(d[i]);
1103 }
1104
1105 if ( d[0] != 0 ) {
1106  ROAR_WARN("req_on_get_stream_para(*): unsupported command version: %i, %i", (int)d[0], (int)d[1]);
1107  return -1;
1108 }
1109
1110 switch (d[1]) {
1111  case ROAR_STREAM_PARA_INFO:
1112    if ( streams_get(mes->stream, &ss) == -1 ) {
1113     ROAR_WARN("req_on_get_stream_para(*): request on non existing (or other error?) stream %i", mes->stream);
1114     return -1;
1115    }
1116
1117    if ( streams_calc_delay(mes->stream) == -1 ) {
1118     ROAR_WARN("req_on_get_stream_para(*): can not calc delay for stream %i", mes->stream);
1119    }
1120
1121    s = ROAR_STREAM(ss);
1122
1123    audio_info = &(s->info);
1124
1125    mes->datalen = 2*12;
1126
1127    d[ 2] = ROAR_OUTPUT_CALC_OUTBUFSIZE(audio_info);
1128    d[ 3] = ss->pre_underruns;
1129    d[ 4] = ss->post_underruns;
1130    d[ 5] = ss->codec_orgi;
1131    d[ 6] = (ss->flags & 0xFFFF) | (ss->primary ? ROAR_FLAG_PRIMARY : 0) | (ss->driver_id != -1 ? ROAR_FLAG_OUTPUT : 0);
1132    d[ 7] = ss->delay/1000;
1133    d[ 8] = ss->state;
1134    d[ 9] = (ss->flags & 0xFFFF0000) >> 16;
1135    d[10] = ss->mixer_stream;
1136    d[11] = ss->role;
1137
1138    ROAR_DBG("req_on_get_stream_para(*): ss->driver_id=%i", ss->driver_id);
1139
1140    ROAR_DBG("req_on_get_stream_para(*): delay=%i, send delay=%i", ss->delay, d[7]);
1141
1142    for (i = 0; i < mes->datalen/2; i++) {
1143     d[i] = ROAR_HOST2NET16(d[i]);
1144    }
1145
1146    mes->pos = s->pos;
1147   break;
1148
1149  case ROAR_STREAM_PARA_NAME:
1150   str = streams_get_name(mes->stream);
1151
1152   if ( str == NULL )
1153    return -1;
1154
1155    mes->datalen = 4 + strlen(str);
1156
1157    if ( mes->datalen > LIBROAR_BUFFER_MSGDATA )
1158     return -1;
1159
1160    strncpy(((char*)&(mes->data))+4, str, mes->datalen);
1161
1162    d[0] = ROAR_HOST2NET16(d[0]);
1163    d[1] = ROAR_HOST2NET16(d[1]);
1164   break;
1165
1166  case ROAR_STREAM_PARA_CHANMAP:
1167    if ( streams_get(mes->stream, &ss) == -1 ) {
1168     ROAR_WARN("req_on_get_stream_para(*): request on non existing (or other error?) stream %i", mes->stream);
1169     return -1;
1170    }
1171
1172    s = ROAR_STREAM(ss);
1173
1174    memcpy(&(mes->data[4]), ss->chanmap.in, s->info.channels);
1175    mes->datalen = 2*2 + s->info.channels;
1176
1177    d[0] = ROAR_HOST2NET16(d[0]);
1178    d[1] = ROAR_HOST2NET16(d[1]);
1179   break;
1180
1181  case ROAR_STREAM_PARA_LTM:
1182    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM request...", client);
1183
1184    if ( mes->datalen < (6 * 2) ) {
1185     ROAR_ERR("req_on_get_stream_para(client=%i, ...): LTM request of client is corruped: message too short", client);
1186     return -1;
1187    }
1188
1189    for (i = 2; i < mes->datalen/2; i++) {
1190     d[i] = ROAR_NET2HOST16(d[i]);
1191    }
1192
1193    if ( d[2] != ROAR_LTM_SST_GET_RAW ) {
1194     ROAR_ERR("req_on_get_stream_para(client=%i, ...): LTM request of client is corruped: unknown LTM subtype: %i", client, (int)d[2]);
1195     return -1;
1196    }
1197
1198    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM request of type GET_RAW", client);
1199
1200    test = d[5];
1201    bits = 0;
1202    while (test) {
1203     if ( test & 0x1 )
1204      bits++;
1205
1206     test >>= 1;
1207    }
1208
1209    needed = 0;
1210
1211    if ( mes->stream == -1 ) {
1212     ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM multi-stream request...", client);
1213
1214     for (i = 6; i < mes->datalen/2; i++) {
1215      if ( (ltm = streams_ltm_get(d[i], d[5], d[3])) == NULL )
1216       return -1;
1217
1218      needed += ltm->channels;
1219     }
1220    } else {
1221     ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM single-stream request for stream %i...", client, mes->stream);
1222     if ( (ltm = streams_ltm_get(mes->stream, d[5], d[3])) == NULL )
1223      return -1;
1224
1225     needed = ltm->channels;
1226    }
1227
1228    needed *= bits;
1229
1230    needed += mes->stream == -1 ? (mes->datalen/2) - 6 : 1;
1231
1232    ROAR_DBG("req_on_get_stream_para(client=%i, ...): data size for answer is %i 64 bit sub-packets", client, (int)needed);
1233
1234    ROAR_DBG("req_on_get_stream_para(client=%i, ...): mes->datalen=%i, data=%p{%p}", client, (int)mes->datalen, data, *data);
1235    d64 = _dataspace(mes, data, flags, needed * 8);
1236    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1237
1238    if ( (d = roar_mm_malloc(mes->datalen)) == NULL )
1239     return -1;
1240
1241    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d=%p, data=%p{%p}", client, d, data, *data);
1242
1243
1244    ROAR_DBG("req_on_get_stream_para(client=%i, ...): mes->datalen=%i, data=%p{%p}", client, (int)mes->datalen, data, *data);
1245    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1246    memcpy(d, mes->data, mes->datalen);
1247    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1248
1249    d64ptr = d64;
1250
1251    ROAR_DBG("req_on_get_stream_para(client=%i, ...): mes->datalen=%i, data=%p{%p}", client, (int)mes->datalen, data, *data);
1252    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1253
1254    if ( mes->stream == -1 ) {
1255     for (i = 6; i < mes->datalen/2; i++) {
1256      ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1257
1258      if ( (ltm = streams_ltm_get(d[i], d[5], d[3])) == NULL )
1259       return -1;
1260
1261      *d64ptr = ltm->channels & 0xFFFF;
1262       d64ptr++;
1263
1264      for (h = 0; h < ltm->channels; h++) {
1265       for (k = 0; k < ROAR_LTM_MTBITS; k++) {
1266        if ( d[5] & (1<<k) ) {
1267         switch (1<<k) {
1268          case ROAR_LTM_MT_RMS:
1269            *d64ptr = ltm->cur[h].rms;
1270           break;
1271          default:
1272            ROAR_ERR("req_on_get_stream_para(client=%i, ...): client requets unknown MT for LTM: bit %i", client, k);
1273         }
1274         d64ptr++;
1275        }
1276       }
1277      }
1278     }
1279    } else {
1280     if ( (ltm = streams_ltm_get(mes->stream, d[5], d[3])) == NULL )
1281      return -1;
1282
1283     *d64ptr = ltm->channels & 0xFFFF;
1284      d64ptr++;
1285
1286     for (h = 0; h < ltm->channels; h++) {
1287      for (k = 0; k < ROAR_LTM_MTBITS; k++) {
1288       if ( d[5] & (1<<k) ) {
1289        switch (1<<k) {
1290         case ROAR_LTM_MT_RMS:
1291           *d64ptr = ltm->cur[h].rms;
1292           ROAR_DBG("req_on_get_stream_para(client=%i, ...): rms=%lli to %p", client, (long long int)*d64ptr, d64ptr);
1293          break;
1294         default:
1295           ROAR_ERR("req_on_get_stream_para(client=%i, ...): client requets unknown MT for LTM: bit %i", client, k);
1296        }
1297        d64ptr++;
1298       }
1299      }
1300     }
1301    }
1302
1303    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1304
1305    roar_mm_free(d);
1306
1307    for (i = 0; i < needed; i++) {
1308     d64[i] = ROAR_HOST2NET64(d64[i]);
1309    }
1310
1311    mes->datalen = needed * 8;
1312    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM d64=%p, d64ptr=%p", client, d64, d64ptr);
1313    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM final message has %i byte of data", client, (int)mes->datalen);
1314    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1315    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM GET_RAW request: OK. returning...", client);
1316   break;
1317
1318  default:
1319    ROAR_WARN("req_on_get_stream_para(*): unsupported command: %i", d[1]);
1320    return -1;
1321 }
1322
1323 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);
1324 mes->cmd = ROAR_CMD_OK;
1325 return 0;
1326}
1327
1328int req_on_set_stream_para (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1329 struct roar_stream_server * ss;
1330 uint16_t * d = (uint16_t *) mes->data;
1331 uint32_t tmp, tmp2, flagstore;
1332 int protect = 0;
1333 int i;
1334
1335 if ( mes->datalen < 2*2 )
1336  return -1;
1337
1338 for (i = 0; i < 2; i++) {
1339  d[i] = ROAR_NET2HOST16(d[i]);
1340 }
1341
1342 if ( d[0] != 0 )
1343  return -1;
1344
1345 switch (d[1]) {
1346  case ROAR_STREAM_PARA_FLAGS:
1347    if ( mes->datalen != 2*4 && mes->datalen != 2*5 )
1348     return -1;
1349
1350    d[2] = ROAR_NET2HOST16(d[2]);
1351    d[3] = ROAR_NET2HOST16(d[3]);
1352
1353    ROAR_DBG("req_on_set_stream_para(*): request seems to be valid");
1354
1355    tmp = 0;
1356
1357    if ( mes->datalen == 2*5 ) {
1358     d[4] = ROAR_NET2HOST16(d[4]);
1359     tmp   = d[4];
1360     tmp <<= 16;
1361    }
1362
1363    tmp |= d[3];
1364
1365    if ( d[2] & ROAR_PROTECT_FLAG ) {
1366     protect = 1;
1367     d[2] -= ROAR_PROTECT_FLAG;
1368    }
1369
1370    switch (d[2]) {
1371     case ROAR_SET_FLAG:
1372       if ( streams_set_flag(mes->stream, tmp) == -1 )
1373        return -1;
1374      break;
1375     case ROAR_RESET_FLAG:
1376       if ( streams_reset_flag(mes->stream, tmp) == -1 )
1377        return -1;
1378      break;
1379     case ROAR_NOOP_FLAG:
1380      break;
1381     case ROAR_TOGGLE_FLAG:
1382       if ( streams_get(mes->stream, &ss) == -1 )
1383        return -1;
1384
1385       flagstore = ss->flags;
1386
1387       tmp2 = flagstore & tmp; // those are the flags we need to reset.
1388       ROAR_DBG("req_on_set_stream_para(*): tmp2=0x%.8lx", (long int)tmp2);
1389       if ( tmp2 )
1390        if ( streams_reset_flag(mes->stream, tmp2) == -1 )
1391         return -1;
1392
1393       tmp2 = (flagstore ^ tmp) & tmp; // those are the flags we need to set.
1394       ROAR_DBG("req_on_set_stream_para(*): tmp2=0x%.8lx", (long int)tmp2);
1395       if ( tmp2 )
1396        if ( streams_set_flag(mes->stream, tmp2) == -1 )
1397         return -1;
1398      break;
1399     default:
1400       return -1;
1401      break;
1402    }
1403
1404   ROAR_DBG("req_on_set_stream_para(*): protect=%i", protect);
1405   if ( protect )
1406    if ( streams_protect_flag(mes->stream, tmp) == -1 )
1407     return -1;
1408
1409   break;
1410  case ROAR_STREAM_PARA_CHANMAP:
1411    if ( streams_set_map(mes->stream, &(mes->data[4]), mes->datalen - 4) == -1 )
1412     return -1;
1413   break;
1414  case ROAR_STREAM_PARA_ROLE:
1415    if ( mes->datalen != 2*3 )
1416     return -1;
1417
1418    d[2] = ROAR_NET2HOST16(d[2]);
1419
1420    if ( streams_set_role(mes->stream, d[2]) == -1 )
1421     return -1;
1422   break;
1423  case ROAR_STREAM_PARA_LTM:
1424    if ( mes->datalen < (6 * 2) )
1425     return -1;
1426
1427    for (i = 2; i < mes->datalen/2; i++) {
1428     d[i] = ROAR_NET2HOST16(d[i]);
1429    }
1430
1431    if ( mes->stream == -1 ) {
1432     for (i = 6; i < mes->datalen/2; i++)
1433      if ( streams_ltm_ctl(d[i], d[5], d[3], d[2]) == -1 )
1434       return -1;
1435    } else {
1436     if ( streams_ltm_ctl(mes->stream, d[5], d[3], d[2]) == -1 )
1437      return -1;
1438    }
1439   break;
1440  default:
1441    ROAR_WARN("req_on_set_stream_para(*): unsupported command version: %i, %i", d[0], d[1]);
1442    return -1;
1443   break;
1444 }
1445
1446 mes->cmd     = ROAR_CMD_OK;
1447 mes->datalen = 0;
1448
1449 return 0;
1450}
1451
1452int req_on_kick (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1453 struct roar_stream_server * ss;
1454 uint16_t * info = (uint16_t *) mes->data;
1455 int is_stream = 0;
1456
1457 if ( mes->datalen != 4 )
1458  return -1;
1459
1460 info[0] = ROAR_NET2HOST16(info[0]);
1461 info[1] = ROAR_NET2HOST16(info[1]);
1462
1463 switch (info[0]) {
1464  case ROAR_OT_CLIENT:
1465    clients_delete(info[1]);
1466   break;
1467  case ROAR_OT_STREAM:
1468    is_stream = 1;
1469   break;
1470  case ROAR_OT_SOURCE:
1471    if ( streams_get_flag(info[1], ROAR_FLAG_SOURCE) != 1 )
1472     return -1;
1473    is_stream = 1;
1474   break;
1475  case ROAR_OT_OUTPUT:
1476    if ( streams_get(info[1], &ss) == -1 )
1477     return -1;
1478
1479    if ( ss->driver_id == -1 )
1480     return -1;
1481
1482    is_stream = 1;
1483   break;
1484  case ROAR_OT_MIXER:
1485    if ( streams_get(info[1], &ss) == -1 )
1486     return -1;
1487
1488    if ( ROAR_STREAM(ss)->dir != ROAR_DIR_MIXING )
1489     return -1;
1490
1491    is_stream = 1;
1492   break;
1493  case ROAR_OT_BRIDGE:
1494    if ( streams_get(info[1], &ss) == -1 )
1495     return -1;
1496
1497    if ( ROAR_STREAM(ss)->dir != ROAR_DIR_BRIDGE )
1498     return -1;
1499
1500    is_stream = 1;
1501   break;
1502  default:
1503/* TODO: those types should be handled, too:
1504#define ROAR_OT_SAMPLE    4
1505#define ROAR_OT_LISTEN    8
1506#define ROAR_OT_ACTION    9
1507#define ROAR_OT_MSGQUEUE 10
1508#define ROAR_OT_MSGBUS   11
1509*/
1510    return -1;
1511   break;
1512 }
1513
1514 if ( is_stream ) {
1515  if ( streams_get_flag(info[1], ROAR_FLAG_IMMUTABLE) == 1 )
1516   return -1;
1517
1518  streams_delete(info[1]);
1519 }
1520
1521 mes->cmd     = ROAR_CMD_OK;
1522 mes->datalen = 0;
1523
1524 return 0;
1525}
1526
1527int req_on_attach      (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1528 uint16_t * info = (uint16_t *) mes->data;
1529
1530 if ( mes->datalen < 6 )
1531  return -1;
1532
1533 info[0] = ROAR_NET2HOST16(info[0]);
1534 info[1] = ROAR_NET2HOST16(info[1]);
1535 info[2] = ROAR_NET2HOST16(info[2]);
1536
1537 if ( info[0] != 0 )
1538  return -1;
1539
1540 if ( info[1] == ROAR_ATTACH_SIMPLE ) {
1541  if ( client_stream_move(info[2], mes->stream) == -1 )
1542   return -1;
1543 } else {
1544  return -1;
1545 }
1546
1547 mes->cmd     = ROAR_CMD_OK;
1548 mes->datalen = 0;
1549
1550 return 0;
1551}
1552
1553int req_on_set_vol (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1554 struct roar_mixer_settings tmpmixer;
1555 struct roar_stream_server * s;
1556 uint16_t * info = (uint16_t *) mes->data;
1557 uint16_t   version;
1558 uint16_t   scale = 65535;
1559 int stream;
1560 int i;
1561 int chans;
1562
1563 ROAR_DBG("req_on_set_vol(*) = ?");
1564 ROAR_DBG("req_on_set_vol(*): mes->datalen=%i", mes->datalen);
1565
1566 if ( mes->datalen < (4*2) )
1567  return -1;
1568
1569 version = ROAR_NET2HOST16(info[0]);
1570 ROAR_DBG("req_on_set_vol(*): version=%i", (int)version);
1571
1572 switch (version) {
1573  case 0:
1574    stream = ROAR_NET2HOST16(info[1]);
1575   break;
1576  case 1:
1577    stream = mes->stream;
1578    scale  = ROAR_NET2HOST16(info[1]);
1579   break;
1580  default:
1581    return -1;
1582   break;
1583 }
1584 ROAR_DBG("req_on_set_vol(*): stream=%i", stream);
1585
1586 if ( scale == 0 )
1587  return -1;
1588
1589 // TODO: change this code.
1590 //       we should not directly change the stream object but use some stream_*()-func
1591 //       for that job.
1592
1593 if ( stream < 0 || stream >= ROAR_STREAMS_MAX )
1594  return -1;
1595
1596 s = g_streams[stream];
1597
1598 if ( s == NULL )
1599  return -1;
1600
1601 ROAR_DBG("req_on_set_vol(*): s=%p", s);
1602
1603 info[2] = ROAR_NET2HOST16(info[2]);
1604
1605 switch (info[2]) {
1606  case ROAR_SET_VOL_ALL:
1607    chans = (mes->datalen/2) - 3;
1608    ROAR_DBG("req_on_set_vol(*): mode is ROAR_SET_VOL_ALL, channes=%i", chans);
1609
1610    if ( chans >= ROAR_MAX_CHANNELS )
1611     return -1;
1612
1613    ROAR_DBG("req_on_set_vol(*): mixer at %p", s->mixer.mixer);
1614
1615    for (i = 0; i < chans; i++) {
1616     s->mixer.mixer[i] = ROAR_NET2HOST16(info[i+3]);
1617     ROAR_DBG("req_on_set_vol(*): channel %i: %i", i, ROAR_NET2HOST16(info[i+3]));
1618    }
1619
1620    s->mixer.scale = scale;
1621
1622    ROAR_DBG("req_on_set_vol(*): mixer changed!");
1623
1624   break;
1625  case ROAR_SET_VOL_ONE:
1626    ROAR_DBG("req_on_set_vol(*): mode is ROAR_SET_VOL_ONE");
1627    if ( ROAR_NET2HOST16(info[3]) >= ROAR_MAX_CHANNELS )
1628     return -1;
1629
1630    s->mixer.mixer[ROAR_NET2HOST16(info[3])] = ROAR_NET2HOST16(info[4]);
1631
1632    s->mixer.scale = scale;
1633   break;
1634  case ROAR_SET_VOL_UNMAPPED:
1635    chans = (mes->datalen/2) - 3;
1636
1637    if ( chans >= ROAR_MAX_CHANNELS )
1638     return -1;
1639
1640    memcpy(&tmpmixer, &(s->mixer), sizeof(tmpmixer));
1641
1642    for (i = 0; i < chans; i++) {
1643     tmpmixer.mixer[i] = ROAR_NET2HOST16(info[i+3]);
1644    }
1645
1646    tmpmixer.scale = scale;
1647
1648    if ( roar_conv_volume(&(s->mixer), &tmpmixer, ROAR_STREAM(s)->info.channels, chans) == -1 )
1649     return -1;
1650
1651   break;
1652  case ROAR_SET_VOL_MS:
1653  default:
1654    return -1;
1655 }
1656
1657 if ( streams_set_mixer(stream) == -1 )
1658  return -1;
1659
1660 mes->cmd     = ROAR_CMD_OK;
1661 mes->datalen = 0;
1662
1663 return 0;
1664}
1665
1666int req_on_get_vol (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1667 uint16_t * info = (uint16_t *) mes->data;
1668 uint16_t   version = -1;
1669 int stream;
1670 struct roar_stream_server * s;
1671 int i;
1672 int chans;
1673
1674 ROAR_DBG("req_on_get_vol(*) = ?");
1675 ROAR_DBG("req_on_get_vol(*): mes->datalen=%i", mes->datalen);
1676
1677 if ( mes->datalen < 2 ) {
1678  return -1;
1679 }
1680
1681 version = ROAR_NET2HOST16(info[0]);
1682
1683 switch (version) {
1684  case 0:
1685    if ( mes->datalen < (2*2) )
1686     return -1;
1687
1688    stream = ROAR_NET2HOST16(info[1]);
1689   break;
1690  case 1:
1691    stream = mes->stream;
1692   break;
1693  default:
1694    return -1;
1695   break;
1696 }
1697
1698 ROAR_DBG("req_on_get_vol(*): stream=%i", stream);
1699
1700 // TODO: change this code.
1701 //       we should not directly change the stream object but use some stream_*()-func
1702 //       for that job.
1703
1704 if ( stream < 0 || stream >= ROAR_STREAMS_MAX )
1705  return -1;
1706
1707 s = g_streams[stream];
1708
1709 if ( s == NULL )
1710  return -1;
1711
1712 ROAR_DBG("req_on_get_vol(*): s=%p", s);
1713
1714 // ok, we have everything
1715
1716 info[0] = ROAR_HOST2NET16(version);
1717
1718 switch (version) {
1719  case 0:
1720    info[1] = ROAR_HOST2NET16(chans = ROAR_STREAM(s)->info.channels);
1721
1722    for (i = 0; i < chans; i++)
1723     info[2+i] = ROAR_HOST2NET16(s->mixer.mixer[i]);
1724
1725     mes->datalen = (2 + chans)*2;
1726   break;
1727  case 1:
1728    info[1] = ROAR_HOST2NET16(chans = ROAR_STREAM(s)->info.channels);
1729    info[2] = ROAR_HOST2NET16(s->mixer.scale);
1730    info[3] = ROAR_HOST2NET16(s->mixer.rpg_mul);
1731    info[4] = ROAR_HOST2NET16(s->mixer.rpg_div);
1732
1733    for (i = 0; i < chans; i++)
1734     info[5+i] = ROAR_HOST2NET16(s->mixer.mixer[i]);
1735
1736     mes->datalen = (5 + chans)*2;
1737   break;
1738  default:
1739    return -1;
1740   break;
1741 }
1742
1743 mes->cmd = ROAR_CMD_OK;
1744
1745 return 0;
1746}
1747
1748int req_on_add_data (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1749 struct roar_buffer * b;
1750 void               * buf;
1751
1752 if ( roar_buffer_new_data(&b, mes->datalen, &buf) == -1 ) {
1753  ROAR_ERR("req_on_add_data(*): Can not alloc buffer space!");
1754  ROAR_DBG("req_on_add_data(*) = -1");
1755  return -1;
1756 }
1757
1758 if ( data == NULL ) {
1759  memcpy(buf, mes->data, mes->datalen);
1760 } else {
1761  memcpy(buf, *data, mes->datalen);
1762 }
1763
1764 if ( stream_add_buffer(mes->stream, &b) == -1 ) {
1765  roar_buffer_free(b);
1766  return -1;
1767 }
1768
1769 mes->cmd     = ROAR_CMD_OK_STOP;
1770 mes->datalen = 0;
1771
1772 return 0;
1773}
1774
1775int req_on_beep        (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1776 struct roar_beep bs;
1777 int16_t * info = (int16_t*)mes->data;
1778 int stream;
1779
1780 memset(&bs, 0, sizeof(bs));
1781
1782 if ( mes->datalen > 0 ) {
1783  if ( mes->datalen < 2 )
1784   return -1;
1785
1786  if ( ROAR_NET2HOST16(info[0]) != 0 ) /* version */
1787   return -1;
1788
1789  if ( mes->datalen != 8*2 )
1790   return -1;
1791
1792  bs.vol  = ROAR_NET2HOST16(info[1]);
1793  bs.time = ROAR_NET2HOST16(info[2]);
1794  bs.freq = ROAR_NET2HOST16(info[3]);
1795  bs.type = ROAR_NET2HOST16(info[4]);
1796  bs.x    = ROAR_NET2HOST16(info[5]);
1797  bs.y    = ROAR_NET2HOST16(info[6]);
1798  bs.z    = ROAR_NET2HOST16(info[7]);
1799 }
1800
1801 if ( (stream = beep_start(client, &bs)) == -1 )
1802  return -1;
1803
1804 mes->stream  = stream;
1805 mes->cmd     = ROAR_CMD_OK_STOP;
1806 mes->datalen = 0;
1807
1808 return 0;
1809}
1810
1811int req_on_wait        (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1812 uint16_t * u16 = (uint16_t*)mes->data;
1813 struct roar_event events[4];
1814 size_t left, tmp;
1815 size_t num = 0;
1816 void * vp = mes->data;
1817
1818 vp += 4;
1819
1820 // check for complet header...
1821 if ( mes->datalen < 4 )
1822  return -1;
1823
1824 u16[0] = ROAR_NET2HOST16(u16[0]);
1825 u16[1] = ROAR_NET2HOST16(u16[1]);
1826
1827 // do we support version and flags?
1828 if ( u16[0] != 0 || u16[1] != 0 )
1829  return -1;
1830
1831 memset(events, 0, sizeof(events));
1832
1833 left = mes->datalen - 4;
1834
1835 while (left) {
1836  tmp = left;
1837  if ( roar_event_from_blob(&(events[num]), vp, &tmp) == -1 )
1838   return -1;
1839
1840  vp   += tmp;
1841  left -= tmp;
1842  num++;
1843 }
1844
1845 if ( clients_wait(client, events, num) == -1 )
1846  return -1;
1847
1848 flags[1] |= COMMAND_FLAG_OUT_NOSEND;
1849
1850 return 0;
1851}
1852
1853//ll
Note: See TracBrowser for help on using the repository browser.