source: roaraudio/roard/req.c @ 5581:c00aa79358ad

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

avoid false positive reply on client exec with non supported protocol or parameters

File size: 45.5 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 if ( clients_get_protohandle(d[2]) == NULL )
404  return -1;
405
406 ROAR_DBG("req_on_exec_stream(client=%i,...) = ?", client);
407
408 memset(&m, 0, sizeof(m));
409
410 m.cmd = ROAR_CMD_OK;
411
412 flags[1] |= COMMAND_FLAG_OUT_NOSEND;
413
414 c = ROAR_CLIENT(g_clients[client]);
415
416 sock = c->fh;
417
418 if ( sock == -1 )
419  return -1;
420
421 ROAR_DBG("req_on_exec_stream(client=%i,...) = ?", client);
422
423 roar_connect_fh(&con, sock);
424
425 roar_send_message(&con, &m, NULL);
426
427 clients_set_fh(client, -1);
428 clients_delete(client);
429
430 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]);
431 if ( clients_new_from_fh(sock, d[2], d[3], 1) == -1 ) {
432  close(sock);
433 }
434
435 ROAR_DBG("req_on_exec_stream(client=%i,...) = 0", client);
436
437 return 0;
438}
439
440int req_on_con_stream  (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
441 char   host[80] = {0};
442 int    port = 0;
443 int    type;
444 int    fh;
445 int    len;
446
447 if ( mes->datalen < 4 )
448  return -1;
449
450 if ( *(mes->data) != 0 )
451  return -1;
452
453 if ( mes->datalen > 80 ) // we do not support long messages here
454  return -1;
455
456 type = (unsigned)mes->data[1];
457 port = ROAR_NET2HOST16(((uint16_t*)mes->data)[1]);
458
459 len = mes->datalen - 4;
460
461 strncpy(host, &(mes->data[4]), len);
462 host[len] = 0;
463
464 if ( type > ROAR_SOCKET_TYPE_MAX )
465  return -1;
466
467 if ( type == ROAR_SOCKET_TYPE_FILE ) // disabled because of security resons
468  return -1;
469
470 if ( type == ROAR_SOCKET_TYPE_FORK ) // why should we connect to ourself?
471  return -1;
472
473 ROAR_DBG("req_on_con_stream(*): CONNECT(type=%i, host='%s', port=%i)", type, host, port);
474
475 roar_libroar_nowarn();
476 fh = roar_socket_open(ROAR_SOCKET_MODE_CONNECT, type, host, port);
477 roar_libroar_warn();
478
479 if ( fh == -1 )
480  return -1;
481
482 if ( client_stream_set_fh(client, mes->stream, fh) == -1 ) {
483  close(fh);
484  return 1;
485 }
486
487 mes->datalen = 0;
488 mes->cmd     = ROAR_CMD_OK;
489
490 return 0;
491}
492
493int req_on_passfh      (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
494 int sock = clients_get_fh(client);
495 int16_t * d = (int16_t*)mes->data;
496 struct roard_listen * lsock;
497 int listening;
498 int fh;
499 int i;
500
501 ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...) = ?", client, mes->stream);
502
503 if ( (fh = roar_socket_recv_fh(sock, NULL, NULL)) == -1 ) {
504  ROAR_WARN("req_on_passfh(client=%i, mes={stream=%i,...},...): was unabled to get filehandle from remote end. bad.", client, mes->stream);
505  ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): returning (ERROR)...", client, mes->stream);
506  return -1;
507 }
508
509 ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): fh=%i", client, mes->stream, fh);
510
511 if ( mes->stream != -1 ) { // stream pass:
512  ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): This is a stream passfh", client, mes->stream);
513
514  if ( client_stream_set_fh(client, mes->stream, fh) == -1 ) {
515   close(fh);
516   ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): returning (ERROR)...", client, mes->stream);
517   return -1;
518  }
519
520  ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): returning (OK)...", client, mes->stream);
521
522  mes->datalen = 0;
523  mes->cmd     = ROAR_CMD_OK;
524
525  return 0;
526 }
527
528// non-stream pass:
529
530 ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): This is a client passfh", client, mes->stream);
531
532/*
533 0: Version,   16
534 1: Flags,     16
535 2: Protocol,  16
536 3: Byteorder, 16
537 Options...
538*/
539
540 if ( mes->datalen < 4*2 )
541  return -1;
542
543 for (i = 0; i < 4; i++) {
544  d[i] = ROAR_NET2HOST16(d[i]);
545 }
546
547 if ( d[0] != 0 ) // version
548  return -1;
549
550 listening = d[1] & ROAR_CLIENTPASS_FLAG_LISTEN;
551
552 if ( listening )
553  d[1] -= ROAR_CLIENTPASS_FLAG_LISTEN;
554
555 if ( d[1] != 0 ) // flags
556  return -1;
557
558 if ( listening ) {
559  if ( get_listen(&lsock, NULL) == -1 ) {
560   close(fh);
561   return -1;
562  }
563
564  roar_vio_open_fh_socket(&(lsock->sock), fh);
565  lsock->used   = 1;
566  lsock->proto  = d[2];
567 } else {
568  if ( clients_new_from_fh(fh, d[2], d[3], 1) == -1 )
569   return -1;
570 }
571
572 ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): returning (OK)...", client, mes->stream);
573
574 mes->datalen = 0;
575 mes->cmd     = ROAR_CMD_OK;
576
577 return 0;
578}
579
580#ifdef ROAR_SUPPORT_META
581int req_on_set_meta    (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
582 int type;
583 int mode;
584 int namelen, vallen;
585 char   val[255+1];
586 char   name[ROAR_META_MAX_NAMELEN+1];
587
588 if ( mes->datalen < 3 )
589  return -1;
590
591 if ( mes->data[0] != 0 ) // version
592  return -1;
593
594 mode = (unsigned) mes->data[1];
595 type = (unsigned) mes->data[2];
596
597 ROAR_DBG("req_on_set_meta(*): mode=%i, type=%i", mode, type);
598
599 if ( mode == ROAR_META_MODE_CLEAR ) {
600  stream_meta_clear(mes->stream);
601  mes->datalen = 0;
602  mes->cmd     = ROAR_CMD_OK;
603  return 0;
604 } else if ( mode == ROAR_META_MODE_DELETE ) { // unsuppoerted at the moment
605  return -1;
606 } else if ( mode == ROAR_META_MODE_FINALIZE ) {
607  stream_meta_finalize(mes->stream);
608  mes->datalen = 0;
609  mes->cmd     = ROAR_CMD_OK;
610  return 0;
611 } else if ( mode == ROAR_META_MODE_SET || mode == ROAR_META_MODE_ADD ) {
612  if ( mes->datalen < 5 )
613   return -1;
614
615  namelen = (unsigned) mes->data[3];
616  vallen  = (unsigned) mes->data[4];
617
618  ROAR_DBG("req_on_set_meta(*): namelen=%i, vallen=%i", namelen, vallen);
619
620  if ( mes->datalen < (5 + namelen + vallen) )
621   return -1;
622
623  if ( namelen > ROAR_META_MAX_NAMELEN )
624   return -1;
625
626  strncpy(name, &(mes->data[5]), namelen);
627  name[namelen] = 0;
628
629  if ( vallen > 255 )
630   return -1;
631
632  strncpy(val, &(mes->data[5+namelen]), vallen);
633  val[vallen] = 0;
634
635  if ( mode == ROAR_META_MODE_SET ) {
636   if ( stream_meta_set(mes->stream, type, name, val) == -1 )
637    return -1;
638  } else {
639   if ( stream_meta_add(mes->stream, type, name, val) == -1 )
640    return -1;
641  }
642
643  mes->datalen = 0;
644  mes->cmd     = ROAR_CMD_OK;
645  return 0;
646 } else { // unknown mode!
647  return -1;
648 }
649
650 return -1;
651}
652
653int req_on_get_meta    (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
654 int vallen;
655 int type;
656 char val[LIBROAR_BUFFER_MSGDATA-1];
657
658 if ( mes->datalen != 2 )
659  return -1;
660
661 if ( mes->data[0] != 0 ) // version
662  return -1;
663
664 type = (unsigned) mes->data[1];
665
666 if ( stream_meta_get(mes->stream, type, NULL, val, LIBROAR_BUFFER_MSGDATA-2) == -1 )
667  return -1;
668
669 vallen = strlen(val);
670
671 mes->cmd     = ROAR_CMD_OK;
672 mes->datalen = 2 + vallen;
673
674 mes->data[0] = 0;
675 mes->data[1] = (unsigned char) vallen;
676
677 val[vallen] = 0;
678
679 strncpy(&(mes->data[2]), val, vallen+1);
680
681 return 0;
682}
683
684int req_on_list_meta   (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
685 int i;
686 int len = 0;
687 int types[ROAR_META_MAX_PER_STREAM];
688
689 if ( mes->datalen != 1 )
690  return -1;
691
692 if ( mes->data[0] != 0 ) // version
693  return -1;
694
695 if ( (len = stream_meta_list(mes->stream, types, ROAR_META_MAX_PER_STREAM)) == -1 )
696  return -1;
697
698 mes->cmd     = ROAR_CMD_OK;
699 mes->datalen = 1 + len;
700 mes->data[0] = 0;
701
702 for (i = 0; i < len; i++)
703  mes->data[i+1] = types[i];
704
705 return 0;
706}
707#endif
708
709int req_on_gettimeofday (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
710 struct roar_time curtime;
711
712 ROAR_DBG("req_on_gettimeofday(client=%i, mes=%p, data=%p, flags=%p) = ?", client, mes, data, flags);
713
714 if ( *data != NULL ) {
715  return -1;
716 }
717
718 ROAR_DBG("req_on_gettimeofday(client=%i, mes=%p, data=%p, flags=%p) = ?", client, mes, data, flags);
719
720 if ( mes->datalen && mes->datalen < 8 ) {
721  return -1;
722 }
723
724 ROAR_DBG("req_on_gettimeofday(client=%i, mes=%p, data=%p, flags=%p) = ?", client, mes, data, flags);
725
726 if ( mes->datalen >= 8 ) {
727  if ( *(uint64_t *)mes->data != 0 ) {
728   return -1;
729  }
730 }
731
732 ROAR_DBG("req_on_gettimeofday(client=%i, mes=%p, data=%p, flags=%p) = ?", client, mes, data, flags);
733
734 if ( roar_clock_gettime(&curtime, ROAR_CLOCK_REALTIME) == -1 )
735  return -1;
736
737 if ( roar_time_to_msg(mes, &curtime) == -1 )
738  return -1;
739
740 mes->cmd = ROAR_CMD_OK;
741
742 ROAR_DBG("req_on_gettimeofday(client=%i, mes=%p, data=%p, flags=%p) = ?", client, mes, data, flags);
743
744 return 0;
745}
746
747int req_on_server_info (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
748#ifdef ROAR_HAVE_UNAME
749 struct utsname utsname;
750#endif
751#ifdef ROAR_HAVE_GETVERSIONEX
752 OSVERSIONINFO osinfo;
753 char buf_release[80];
754#endif
755 struct roar_server_info info;
756 uint16_t * d16;
757#ifdef ROAR_HAVE_GETHOSTID
758 long hostid;
759 char hostidbuf[64];
760#endif
761
762 if ( mes->datalen != 4 )
763  return -1;
764
765 d16 = (uint16_t*)mes->data;
766
767 // check version.
768 if ( ROAR_NET2HOST16(d16[0]) != 0 )
769  return -1;
770
771 switch (ROAR_NET2HOST16(d16[1])) {
772  case ROAR_IT_SERVER:
773   memset(&info, 0, sizeof(info));
774
775   // the following if is optimized out by compiler.
776   if ( DISTRIBUTION_VERSION_STRING[0] == 0 ) {
777    info.version = "roard/" PACKAGE_VERSION " <" DEVICE_VENDOR_STRING ">";
778   } else {
779    info.version = "roard/" PACKAGE_VERSION " <" DEVICE_VENDOR_STRING "> (" DISTRIBUTION_VERSION_STRING ")";
780   }
781
782   info.build   = ROAR_BUILD_STAMP;
783   info.license = ROAR_LICENSE_GPLv3_0;
784
785#ifdef ROAR_HAVE_GETHOSTID
786   hostid = gethostid();
787   snprintf(hostidbuf, sizeof(hostidbuf), sizeof(long) == 8 ? "0x%.16lx" : "0x%.8lx", hostid);
788   info.hostid = hostidbuf;
789#endif
790
791   if ( !!strcmp(g_config->location, CONF_DEF_STRING) )
792    info.location = g_config->location;
793
794   if ( !!strcmp(g_config->description, CONF_DEF_STRING) )
795    info.description = g_config->description;
796
797   info.contact = g_config->contact;
798   info.serial  = g_config->serial;
799   info.uiurl   = g_config->uiurl;
800
801#ifdef ROAR_HAVE_UNAME
802   if ( uname(&utsname) == 0 ) {
803    info.un.sysname  = utsname.sysname;
804    info.un.release  = utsname.release;
805    info.un.nodename = utsname.nodename;
806    info.un.machine  = utsname.machine;
807   }
808#endif
809#ifdef ROAR_HAVE_GETVERSIONEX
810   osinfo.dwOSVersionInfoSize = sizeof(osinfo);
811   if ( GetVersionEx(&osinfo) ) {
812    info.un.sysname = "Windows";
813    snprintf(buf_release, sizeof(buf_release), "%i.%i.%i",
814               (int)osinfo.dwMajorVersion, (int)osinfo.dwMinorVersion, (int)osinfo.dwBuildNumber);
815    buf_release[sizeof(buf_release)-1] = 0;
816    info.un.release = buf_release;
817   }
818#endif
819
820   *data = NULL;
821
822   if ( roar_server_info_to_mes(mes, &info, (void**)data) == -1 )
823    return -1;
824
825   if ( *data != NULL )
826    flags[1] |= COMMAND_FLAG_OUT_LONGDATA;
827  break;
828  default: /* unknown request */
829    return -1;
830   break;
831 }
832
833 mes->cmd = ROAR_CMD_OK;
834
835 return 0;
836}
837
838int req_on_server_oinfo    (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
839 struct roar_stream s;
840 int dir = ROAR_DIR_PLAY;
841 int subsys;
842//ROAR_DIR_OUTPUT
843
844 if ( mes->datalen != 0 ) {
845  if ( mes->datalen != 2 )
846   return -1;
847
848  if ( mes->data[0] != 0 )
849   return -1;
850
851  dir = mes->data[1];
852 }
853
854 subsys = streams_dir2subsys(dir);
855
856 memset(&s, 0, sizeof(struct roar_stream));
857
858 s.dir           = ROAR_DIR_MIXING;
859 s.pos_rel_id    = -1;
860
861 switch (subsys) {
862  case ROAR_SUBSYS_WAVEFORM:
863    s.info.rate     = g_sa->rate;
864    s.info.bits     = g_sa->bits;
865    s.info.channels = g_sa->channels;
866    s.info.codec    = g_sa->codec;
867    s.pos           = g_pos;
868   break;
869#ifndef ROAR_WITHOUT_DCOMP_MIDI
870  case ROAR_SUBSYS_MIDI:
871   break;
872#endif
873#ifndef ROAR_WITHOUT_DCOMP_LIGHT
874  case ROAR_SUBSYS_LIGHT:
875    s.info.rate     = ROAR_OUTPUT_CFREQ;
876    s.info.bits     = ROAR_LIGHT_BITS;
877    s.info.channels = g_light_state.channels;
878   break;
879#endif
880#ifndef ROAR_WITHOUT_DCOMP_RAW
881  case ROAR_SUBSYS_RAW:
882    // no need to set anything here.
883   break;
884#endif
885#ifndef ROAR_WITHOUT_DCOMP_RDTCS
886  case ROAR_SUBSYS_RDTCS:
887    s.info.rate     = ROAR_OUTPUT_CFREQ;
888    s.info.bits     = ROAR_RDTCS_BITS;
889    s.info.channels = ROAR_RDTCS_CHANNELS;
890    s.info.codec    = ROAR_RDTCS_CODEC;
891   break;
892#endif
893  default:
894    return -1;
895   break;
896 }
897
898 if ( roar_stream_s2m(&s, mes) == -1 )
899  return -1;
900
901 mes->cmd = ROAR_CMD_OK;
902
903 return 0;
904}
905
906int req_on_caps        (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
907 struct roar_caps caps;
908 struct roar_stds * stds;
909 size_t i;
910
911 if ( roar_caps_from_msg(&caps, mes, *data) == -1 )
912  return -1;
913
914 // handle the data from the caps command here...
915
916 if ( !(caps.flags & ROAR_CF_REQUEST) ) {
917  mes->cmd = ROAR_CMD_OK;
918  mes->datalen = 0;
919  return 0;
920 }
921
922 mes->datalen = 0;
923
924 switch (caps.type) {
925  case ROAR_CT_STANDARDS:
926    if ( (stds = roar_stds_new(g_caps_stds.stds_len)) == NULL )
927     return -1;
928
929    for ( i = 0; i < stds->stds_len; i++) {
930     stds->stds[i] = ROAR_HOST2NET32(g_caps_stds.stds[i]);
931    }
932
933    caps.data = stds->stds;
934    caps.len  = stds->stds_len * 4;
935    // TODO: add support for **data.
936    if ( roar_caps_to_msg(mes, &caps, NULL) == -1 ) {
937     roar_stds_free(stds);
938     return -1;
939    }
940    roar_stds_free(stds);
941   break;
942  default:
943    return -1;
944   break;
945 }
946
947 mes->cmd = ROAR_CMD_OK;
948
949 return 0;
950}
951
952int req_on_get_standby (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
953 mes->cmd     = ROAR_CMD_OK;
954 mes->pos     = g_pos;
955 mes->datalen = 2;
956
957 *((uint16_t*)mes->data) = ROAR_HOST2NET16((unsigned) g_standby);
958
959 return 0;
960}
961
962int req_on_set_standby (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
963 if ( mes->datalen != 2 )
964  return -1;
965
966 g_standby = ROAR_NET2HOST16(*((uint16_t*)mes->data));
967
968 mes->cmd     = ROAR_CMD_OK;
969 mes->pos     = g_pos;
970 mes->datalen = 0;
971
972 return 0;
973}
974
975int req_on_exit      (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
976 int term = 0;
977
978 if ( mes->datalen == 1 )
979  term = mes->data[0];
980
981 mes->cmd     = ROAR_CMD_OK;
982 mes->pos     = g_pos;
983 mes->datalen = 0;
984
985 ROAR_DBG("req_on_exit(*): term=%i", term);
986
987 if ( term ) {
988  cleanup_listen_socket(1);
989 } else {
990  alive = 0;
991 }
992
993 return 0;
994}
995
996int req_on_list_clients(int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
997 unsigned char filter, cmp;
998 uint32_t id;
999 int clients[ROAR_CLIENTS_MAX];
1000 int i, c = 0;
1001
1002 if ( roar_ctl_m2f(mes, &filter, &cmp, &id) == -1 )
1003  return -1;
1004
1005 // TODO: add code to support filter
1006 if ( filter != ROAR_CTL_FILTER_ANY )
1007  return -1;
1008
1009 for (i = 0; i < ROAR_CLIENTS_MAX; i++) {
1010  if ( g_clients[i] != NULL ) {
1011   clients[c++] = i;
1012  }
1013 }
1014
1015 roar_ctl_ia2m(mes, clients, c);
1016
1017 mes->cmd = ROAR_CMD_OK;
1018
1019 return 0;
1020}
1021int req_on_list_streams(int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1022 unsigned char filter, cmp;
1023 uint32_t id;
1024 int streams[ROAR_STREAMS_MAX];
1025 int i, c = 0;
1026 int match;
1027
1028 if ( roar_ctl_m2f(mes, &filter, &cmp, &id) == -1 )
1029  return -1;
1030
1031 for (i = 0; i < ROAR_STREAMS_MAX; i++) {
1032  if ( g_streams[i] == NULL )
1033   continue;
1034
1035  match = 0;
1036
1037  switch (filter) {
1038   case ROAR_CTL_FILTER_ANY:
1039     match = 1;
1040    break;
1041   case ROAR_CTL_FILTER_DIR:
1042     match = roar_filter_match(cmp, id, ROAR_STREAM(g_streams[i])->dir);
1043    break;
1044   default: // unsupported filter...
1045     return -1;
1046    break;
1047  }
1048
1049  if ( match )
1050   streams[c++] = i;
1051 }
1052
1053 roar_ctl_ia2m(mes, streams, c);
1054
1055 mes->cmd = ROAR_CMD_OK;
1056
1057 return 0;
1058}
1059
1060int req_on_get_client  (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1061 struct roar_client * c;
1062
1063 if ( mes->datalen != 1 )
1064  return -1;
1065
1066 if ( clients_get(mes->data[0], &c) == -1 )
1067  return -1;
1068
1069 mes->cmd = ROAR_CMD_OK;
1070
1071 return roar_ctl_c2m(mes, c);
1072}
1073
1074int req_on_get_stream  (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1075 struct roar_stream_server * s;
1076
1077 if ( mes->datalen != 1 )
1078  return -1;
1079
1080 if ( streams_get(mes->data[0], &s) == -1 )
1081  return -1;
1082
1083 mes->cmd = ROAR_CMD_OK;
1084 mes->stream = mes->data[0];
1085
1086 return roar_stream_s2m(ROAR_STREAM(s), mes);
1087}
1088
1089int req_on_get_stream_para (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1090 struct roar_stream * s;
1091 struct roar_stream_server * ss;
1092 struct roar_audio_info * audio_info;
1093 struct roar_stream_ltm * ltm;
1094 uint16_t * d  = (uint16_t *) mes->data;
1095 int64_t * d64 = ( int64_t *) mes->data;
1096 int64_t * d64ptr;
1097 int i, h, k;
1098 char * str;
1099 size_t needed;
1100 int test, bits;
1101
1102 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);
1103
1104 if ( mes->datalen < 4 )
1105  return -1;
1106
1107 for (i = 0; i < 2; i++) {
1108  d[i] = ROAR_NET2HOST16(d[i]);
1109 }
1110
1111 if ( d[0] != 0 ) {
1112  ROAR_WARN("req_on_get_stream_para(*): unsupported command version: %i, %i", (int)d[0], (int)d[1]);
1113  return -1;
1114 }
1115
1116 switch (d[1]) {
1117  case ROAR_STREAM_PARA_INFO:
1118    if ( streams_get(mes->stream, &ss) == -1 ) {
1119     ROAR_WARN("req_on_get_stream_para(*): request on non existing (or other error?) stream %i", mes->stream);
1120     return -1;
1121    }
1122
1123    if ( streams_calc_delay(mes->stream) == -1 ) {
1124     ROAR_WARN("req_on_get_stream_para(*): can not calc delay for stream %i", mes->stream);
1125    }
1126
1127    s = ROAR_STREAM(ss);
1128
1129    audio_info = &(s->info);
1130
1131    mes->datalen = 2*12;
1132
1133    d[ 2] = ROAR_OUTPUT_CALC_OUTBUFSIZE(audio_info);
1134    d[ 3] = ss->pre_underruns;
1135    d[ 4] = ss->post_underruns;
1136    d[ 5] = ss->codec_orgi;
1137    d[ 6] = (ss->flags & 0xFFFF) | (ss->primary ? ROAR_FLAG_PRIMARY : 0) | (ss->driver_id != -1 ? ROAR_FLAG_OUTPUT : 0);
1138    d[ 7] = ss->delay/1000;
1139    d[ 8] = ss->state;
1140    d[ 9] = (ss->flags & 0xFFFF0000) >> 16;
1141    d[10] = ss->mixer_stream;
1142    d[11] = ss->role;
1143
1144    ROAR_DBG("req_on_get_stream_para(*): ss->driver_id=%i", ss->driver_id);
1145
1146    ROAR_DBG("req_on_get_stream_para(*): delay=%i, send delay=%i", ss->delay, d[7]);
1147
1148    for (i = 0; i < mes->datalen/2; i++) {
1149     d[i] = ROAR_HOST2NET16(d[i]);
1150    }
1151
1152    mes->pos = s->pos;
1153   break;
1154
1155  case ROAR_STREAM_PARA_NAME:
1156   str = streams_get_name(mes->stream);
1157
1158   if ( str == NULL )
1159    return -1;
1160
1161    mes->datalen = 4 + strlen(str);
1162
1163    if ( mes->datalen > LIBROAR_BUFFER_MSGDATA )
1164     return -1;
1165
1166    strncpy(((char*)&(mes->data))+4, str, mes->datalen);
1167
1168    d[0] = ROAR_HOST2NET16(d[0]);
1169    d[1] = ROAR_HOST2NET16(d[1]);
1170   break;
1171
1172  case ROAR_STREAM_PARA_CHANMAP:
1173    if ( streams_get(mes->stream, &ss) == -1 ) {
1174     ROAR_WARN("req_on_get_stream_para(*): request on non existing (or other error?) stream %i", mes->stream);
1175     return -1;
1176    }
1177
1178    s = ROAR_STREAM(ss);
1179
1180    memcpy(&(mes->data[4]), ss->chanmap.in, s->info.channels);
1181    mes->datalen = 2*2 + s->info.channels;
1182
1183    d[0] = ROAR_HOST2NET16(d[0]);
1184    d[1] = ROAR_HOST2NET16(d[1]);
1185   break;
1186
1187  case ROAR_STREAM_PARA_LTM:
1188    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM request...", client);
1189
1190    if ( mes->datalen < (6 * 2) ) {
1191     ROAR_ERR("req_on_get_stream_para(client=%i, ...): LTM request of client is corruped: message too short", client);
1192     return -1;
1193    }
1194
1195    for (i = 2; i < mes->datalen/2; i++) {
1196     d[i] = ROAR_NET2HOST16(d[i]);
1197    }
1198
1199    if ( d[2] != ROAR_LTM_SST_GET_RAW ) {
1200     ROAR_ERR("req_on_get_stream_para(client=%i, ...): LTM request of client is corruped: unknown LTM subtype: %i", client, (int)d[2]);
1201     return -1;
1202    }
1203
1204    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM request of type GET_RAW", client);
1205
1206    test = d[5];
1207    bits = 0;
1208    while (test) {
1209     if ( test & 0x1 )
1210      bits++;
1211
1212     test >>= 1;
1213    }
1214
1215    needed = 0;
1216
1217    if ( mes->stream == -1 ) {
1218     ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM multi-stream request...", client);
1219
1220     for (i = 6; i < mes->datalen/2; i++) {
1221      if ( (ltm = streams_ltm_get(d[i], d[5], d[3])) == NULL )
1222       return -1;
1223
1224      needed += ltm->channels;
1225     }
1226    } else {
1227     ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM single-stream request for stream %i...", client, mes->stream);
1228     if ( (ltm = streams_ltm_get(mes->stream, d[5], d[3])) == NULL )
1229      return -1;
1230
1231     needed = ltm->channels;
1232    }
1233
1234    needed *= bits;
1235
1236    needed += mes->stream == -1 ? (mes->datalen/2) - 6 : 1;
1237
1238    ROAR_DBG("req_on_get_stream_para(client=%i, ...): data size for answer is %i 64 bit sub-packets", client, (int)needed);
1239
1240    ROAR_DBG("req_on_get_stream_para(client=%i, ...): mes->datalen=%i, data=%p{%p}", client, (int)mes->datalen, data, *data);
1241    d64 = _dataspace(mes, data, flags, needed * 8);
1242    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1243
1244    if ( (d = roar_mm_malloc(mes->datalen)) == NULL )
1245     return -1;
1246
1247    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d=%p, data=%p{%p}", client, d, data, *data);
1248
1249
1250    ROAR_DBG("req_on_get_stream_para(client=%i, ...): mes->datalen=%i, data=%p{%p}", client, (int)mes->datalen, data, *data);
1251    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1252    memcpy(d, mes->data, mes->datalen);
1253    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1254
1255    d64ptr = d64;
1256
1257    ROAR_DBG("req_on_get_stream_para(client=%i, ...): mes->datalen=%i, data=%p{%p}", client, (int)mes->datalen, data, *data);
1258    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1259
1260    if ( mes->stream == -1 ) {
1261     for (i = 6; i < mes->datalen/2; i++) {
1262      ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1263
1264      if ( (ltm = streams_ltm_get(d[i], d[5], d[3])) == NULL )
1265       return -1;
1266
1267      *d64ptr = ltm->channels & 0xFFFF;
1268       d64ptr++;
1269
1270      for (h = 0; h < ltm->channels; h++) {
1271       for (k = 0; k < ROAR_LTM_MTBITS; k++) {
1272        if ( d[5] & (1<<k) ) {
1273         switch (1<<k) {
1274          case ROAR_LTM_MT_RMS:
1275            *d64ptr = ltm->cur[h].rms;
1276           break;
1277          default:
1278            ROAR_ERR("req_on_get_stream_para(client=%i, ...): client requets unknown MT for LTM: bit %i", client, k);
1279         }
1280         d64ptr++;
1281        }
1282       }
1283      }
1284     }
1285    } else {
1286     if ( (ltm = streams_ltm_get(mes->stream, d[5], d[3])) == NULL )
1287      return -1;
1288
1289     *d64ptr = ltm->channels & 0xFFFF;
1290      d64ptr++;
1291
1292     for (h = 0; h < ltm->channels; h++) {
1293      for (k = 0; k < ROAR_LTM_MTBITS; k++) {
1294       if ( d[5] & (1<<k) ) {
1295        switch (1<<k) {
1296         case ROAR_LTM_MT_RMS:
1297           *d64ptr = ltm->cur[h].rms;
1298           ROAR_DBG("req_on_get_stream_para(client=%i, ...): rms=%lli to %p", client, (long long int)*d64ptr, d64ptr);
1299          break;
1300         default:
1301           ROAR_ERR("req_on_get_stream_para(client=%i, ...): client requets unknown MT for LTM: bit %i", client, k);
1302        }
1303        d64ptr++;
1304       }
1305      }
1306     }
1307    }
1308
1309    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1310
1311    roar_mm_free(d);
1312
1313    for (i = 0; i < needed; i++) {
1314     d64[i] = ROAR_HOST2NET64(d64[i]);
1315    }
1316
1317    mes->datalen = needed * 8;
1318    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM d64=%p, d64ptr=%p", client, d64, d64ptr);
1319    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM final message has %i byte of data", client, (int)mes->datalen);
1320    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1321    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM GET_RAW request: OK. returning...", client);
1322   break;
1323
1324  default:
1325    ROAR_WARN("req_on_get_stream_para(*): unsupported command: %i", d[1]);
1326    return -1;
1327 }
1328
1329 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);
1330 mes->cmd = ROAR_CMD_OK;
1331 return 0;
1332}
1333
1334int req_on_set_stream_para (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1335 struct roar_stream_server * ss;
1336 uint16_t * d = (uint16_t *) mes->data;
1337 uint32_t tmp, tmp2, flagstore;
1338 int protect = 0;
1339 int i;
1340
1341 if ( mes->datalen < 2*2 )
1342  return -1;
1343
1344 for (i = 0; i < 2; i++) {
1345  d[i] = ROAR_NET2HOST16(d[i]);
1346 }
1347
1348 if ( d[0] != 0 )
1349  return -1;
1350
1351 switch (d[1]) {
1352  case ROAR_STREAM_PARA_FLAGS:
1353    if ( mes->datalen != 2*4 && mes->datalen != 2*5 )
1354     return -1;
1355
1356    d[2] = ROAR_NET2HOST16(d[2]);
1357    d[3] = ROAR_NET2HOST16(d[3]);
1358
1359    ROAR_DBG("req_on_set_stream_para(*): request seems to be valid");
1360
1361    tmp = 0;
1362
1363    if ( mes->datalen == 2*5 ) {
1364     d[4] = ROAR_NET2HOST16(d[4]);
1365     tmp   = d[4];
1366     tmp <<= 16;
1367    }
1368
1369    tmp |= d[3];
1370
1371    if ( d[2] & ROAR_PROTECT_FLAG ) {
1372     protect = 1;
1373     d[2] -= ROAR_PROTECT_FLAG;
1374    }
1375
1376    switch (d[2]) {
1377     case ROAR_SET_FLAG:
1378       if ( streams_set_flag(mes->stream, tmp) == -1 )
1379        return -1;
1380      break;
1381     case ROAR_RESET_FLAG:
1382       if ( streams_reset_flag(mes->stream, tmp) == -1 )
1383        return -1;
1384      break;
1385     case ROAR_NOOP_FLAG:
1386      break;
1387     case ROAR_TOGGLE_FLAG:
1388       if ( streams_get(mes->stream, &ss) == -1 )
1389        return -1;
1390
1391       flagstore = ss->flags;
1392
1393       tmp2 = flagstore & tmp; // those are the flags we need to reset.
1394       ROAR_DBG("req_on_set_stream_para(*): tmp2=0x%.8lx", (long int)tmp2);
1395       if ( tmp2 )
1396        if ( streams_reset_flag(mes->stream, tmp2) == -1 )
1397         return -1;
1398
1399       tmp2 = (flagstore ^ tmp) & tmp; // those are the flags we need to set.
1400       ROAR_DBG("req_on_set_stream_para(*): tmp2=0x%.8lx", (long int)tmp2);
1401       if ( tmp2 )
1402        if ( streams_set_flag(mes->stream, tmp2) == -1 )
1403         return -1;
1404      break;
1405     default:
1406       return -1;
1407      break;
1408    }
1409
1410   ROAR_DBG("req_on_set_stream_para(*): protect=%i", protect);
1411   if ( protect )
1412    if ( streams_protect_flag(mes->stream, tmp) == -1 )
1413     return -1;
1414
1415   break;
1416  case ROAR_STREAM_PARA_CHANMAP:
1417    if ( streams_set_map(mes->stream, &(mes->data[4]), mes->datalen - 4) == -1 )
1418     return -1;
1419   break;
1420  case ROAR_STREAM_PARA_ROLE:
1421    if ( mes->datalen != 2*3 )
1422     return -1;
1423
1424    d[2] = ROAR_NET2HOST16(d[2]);
1425
1426    if ( streams_set_role(mes->stream, d[2]) == -1 )
1427     return -1;
1428   break;
1429  case ROAR_STREAM_PARA_LTM:
1430    if ( mes->datalen < (6 * 2) )
1431     return -1;
1432
1433    for (i = 2; i < mes->datalen/2; i++) {
1434     d[i] = ROAR_NET2HOST16(d[i]);
1435    }
1436
1437    if ( mes->stream == -1 ) {
1438     for (i = 6; i < mes->datalen/2; i++)
1439      if ( streams_ltm_ctl(d[i], d[5], d[3], d[2]) == -1 )
1440       return -1;
1441    } else {
1442     if ( streams_ltm_ctl(mes->stream, d[5], d[3], d[2]) == -1 )
1443      return -1;
1444    }
1445   break;
1446  default:
1447    ROAR_WARN("req_on_set_stream_para(*): unsupported command version: %i, %i", d[0], d[1]);
1448    return -1;
1449   break;
1450 }
1451
1452 mes->cmd     = ROAR_CMD_OK;
1453 mes->datalen = 0;
1454
1455 return 0;
1456}
1457
1458int req_on_kick (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1459 struct roar_stream_server * ss;
1460 uint16_t * info = (uint16_t *) mes->data;
1461 int is_stream = 0;
1462
1463 if ( mes->datalen != 4 )
1464  return -1;
1465
1466 info[0] = ROAR_NET2HOST16(info[0]);
1467 info[1] = ROAR_NET2HOST16(info[1]);
1468
1469 switch (info[0]) {
1470  case ROAR_OT_CLIENT:
1471    clients_delete(info[1]);
1472   break;
1473  case ROAR_OT_STREAM:
1474    is_stream = 1;
1475   break;
1476  case ROAR_OT_SOURCE:
1477    if ( streams_get_flag(info[1], ROAR_FLAG_SOURCE) != 1 )
1478     return -1;
1479    is_stream = 1;
1480   break;
1481  case ROAR_OT_OUTPUT:
1482    if ( streams_get(info[1], &ss) == -1 )
1483     return -1;
1484
1485    if ( ss->driver_id == -1 )
1486     return -1;
1487
1488    is_stream = 1;
1489   break;
1490  case ROAR_OT_MIXER:
1491    if ( streams_get(info[1], &ss) == -1 )
1492     return -1;
1493
1494    if ( ROAR_STREAM(ss)->dir != ROAR_DIR_MIXING )
1495     return -1;
1496
1497    is_stream = 1;
1498   break;
1499  case ROAR_OT_BRIDGE:
1500    if ( streams_get(info[1], &ss) == -1 )
1501     return -1;
1502
1503    if ( ROAR_STREAM(ss)->dir != ROAR_DIR_BRIDGE )
1504     return -1;
1505
1506    is_stream = 1;
1507   break;
1508  default:
1509/* TODO: those types should be handled, too:
1510#define ROAR_OT_SAMPLE    4
1511#define ROAR_OT_LISTEN    8
1512#define ROAR_OT_ACTION    9
1513#define ROAR_OT_MSGQUEUE 10
1514#define ROAR_OT_MSGBUS   11
1515*/
1516    return -1;
1517   break;
1518 }
1519
1520 if ( is_stream ) {
1521  if ( streams_get_flag(info[1], ROAR_FLAG_IMMUTABLE) == 1 )
1522   return -1;
1523
1524  streams_delete(info[1]);
1525 }
1526
1527 mes->cmd     = ROAR_CMD_OK;
1528 mes->datalen = 0;
1529
1530 return 0;
1531}
1532
1533int req_on_attach      (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1534 uint16_t * info = (uint16_t *) mes->data;
1535
1536 if ( mes->datalen < 6 )
1537  return -1;
1538
1539 info[0] = ROAR_NET2HOST16(info[0]);
1540 info[1] = ROAR_NET2HOST16(info[1]);
1541 info[2] = ROAR_NET2HOST16(info[2]);
1542
1543 if ( info[0] != 0 )
1544  return -1;
1545
1546 if ( info[1] == ROAR_ATTACH_SIMPLE ) {
1547  if ( client_stream_move(info[2], mes->stream) == -1 )
1548   return -1;
1549 } else {
1550  return -1;
1551 }
1552
1553 mes->cmd     = ROAR_CMD_OK;
1554 mes->datalen = 0;
1555
1556 return 0;
1557}
1558
1559int req_on_set_vol (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1560 struct roar_mixer_settings tmpmixer;
1561 struct roar_stream_server * s;
1562 uint16_t * info = (uint16_t *) mes->data;
1563 uint16_t   version;
1564 uint16_t   scale = 65535;
1565 int stream;
1566 int i;
1567 int chans;
1568
1569 ROAR_DBG("req_on_set_vol(*) = ?");
1570 ROAR_DBG("req_on_set_vol(*): mes->datalen=%i", mes->datalen);
1571
1572 if ( mes->datalen < (4*2) )
1573  return -1;
1574
1575 version = ROAR_NET2HOST16(info[0]);
1576 ROAR_DBG("req_on_set_vol(*): version=%i", (int)version);
1577
1578 switch (version) {
1579  case 0:
1580    stream = ROAR_NET2HOST16(info[1]);
1581   break;
1582  case 1:
1583    stream = mes->stream;
1584    scale  = ROAR_NET2HOST16(info[1]);
1585   break;
1586  default:
1587    return -1;
1588   break;
1589 }
1590 ROAR_DBG("req_on_set_vol(*): stream=%i", stream);
1591
1592 if ( scale == 0 )
1593  return -1;
1594
1595 // TODO: change this code.
1596 //       we should not directly change the stream object but use some stream_*()-func
1597 //       for that job.
1598
1599 if ( stream < 0 || stream >= ROAR_STREAMS_MAX )
1600  return -1;
1601
1602 s = g_streams[stream];
1603
1604 if ( s == NULL )
1605  return -1;
1606
1607 ROAR_DBG("req_on_set_vol(*): s=%p", s);
1608
1609 info[2] = ROAR_NET2HOST16(info[2]);
1610
1611 switch (info[2]) {
1612  case ROAR_SET_VOL_ALL:
1613    chans = (mes->datalen/2) - 3;
1614    ROAR_DBG("req_on_set_vol(*): mode is ROAR_SET_VOL_ALL, channes=%i", chans);
1615
1616    if ( chans >= ROAR_MAX_CHANNELS )
1617     return -1;
1618
1619    ROAR_DBG("req_on_set_vol(*): mixer at %p", s->mixer.mixer);
1620
1621    for (i = 0; i < chans; i++) {
1622     s->mixer.mixer[i] = ROAR_NET2HOST16(info[i+3]);
1623     ROAR_DBG("req_on_set_vol(*): channel %i: %i", i, ROAR_NET2HOST16(info[i+3]));
1624    }
1625
1626    s->mixer.scale = scale;
1627
1628    ROAR_DBG("req_on_set_vol(*): mixer changed!");
1629
1630   break;
1631  case ROAR_SET_VOL_ONE:
1632    ROAR_DBG("req_on_set_vol(*): mode is ROAR_SET_VOL_ONE");
1633    if ( ROAR_NET2HOST16(info[3]) >= ROAR_MAX_CHANNELS )
1634     return -1;
1635
1636    s->mixer.mixer[ROAR_NET2HOST16(info[3])] = ROAR_NET2HOST16(info[4]);
1637
1638    s->mixer.scale = scale;
1639   break;
1640  case ROAR_SET_VOL_UNMAPPED:
1641    chans = (mes->datalen/2) - 3;
1642
1643    if ( chans >= ROAR_MAX_CHANNELS )
1644     return -1;
1645
1646    memcpy(&tmpmixer, &(s->mixer), sizeof(tmpmixer));
1647
1648    for (i = 0; i < chans; i++) {
1649     tmpmixer.mixer[i] = ROAR_NET2HOST16(info[i+3]);
1650    }
1651
1652    tmpmixer.scale = scale;
1653
1654    if ( roar_conv_volume(&(s->mixer), &tmpmixer, ROAR_STREAM(s)->info.channels, chans) == -1 )
1655     return -1;
1656
1657   break;
1658  case ROAR_SET_VOL_MS:
1659  default:
1660    return -1;
1661 }
1662
1663 if ( streams_set_mixer(stream) == -1 )
1664  return -1;
1665
1666 mes->cmd     = ROAR_CMD_OK;
1667 mes->datalen = 0;
1668
1669 return 0;
1670}
1671
1672int req_on_get_vol (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1673 uint16_t * info = (uint16_t *) mes->data;
1674 uint16_t   version = -1;
1675 int stream;
1676 struct roar_stream_server * s;
1677 int i;
1678 int chans;
1679
1680 ROAR_DBG("req_on_get_vol(*) = ?");
1681 ROAR_DBG("req_on_get_vol(*): mes->datalen=%i", mes->datalen);
1682
1683 if ( mes->datalen < 2 ) {
1684  return -1;
1685 }
1686
1687 version = ROAR_NET2HOST16(info[0]);
1688
1689 switch (version) {
1690  case 0:
1691    if ( mes->datalen < (2*2) )
1692     return -1;
1693
1694    stream = ROAR_NET2HOST16(info[1]);
1695   break;
1696  case 1:
1697    stream = mes->stream;
1698   break;
1699  default:
1700    return -1;
1701   break;
1702 }
1703
1704 ROAR_DBG("req_on_get_vol(*): stream=%i", stream);
1705
1706 // TODO: change this code.
1707 //       we should not directly change the stream object but use some stream_*()-func
1708 //       for that job.
1709
1710 if ( stream < 0 || stream >= ROAR_STREAMS_MAX )
1711  return -1;
1712
1713 s = g_streams[stream];
1714
1715 if ( s == NULL )
1716  return -1;
1717
1718 ROAR_DBG("req_on_get_vol(*): s=%p", s);
1719
1720 // ok, we have everything
1721
1722 info[0] = ROAR_HOST2NET16(version);
1723
1724 switch (version) {
1725  case 0:
1726    info[1] = ROAR_HOST2NET16(chans = ROAR_STREAM(s)->info.channels);
1727
1728    for (i = 0; i < chans; i++)
1729     info[2+i] = ROAR_HOST2NET16(s->mixer.mixer[i]);
1730
1731     mes->datalen = (2 + chans)*2;
1732   break;
1733  case 1:
1734    info[1] = ROAR_HOST2NET16(chans = ROAR_STREAM(s)->info.channels);
1735    info[2] = ROAR_HOST2NET16(s->mixer.scale);
1736    info[3] = ROAR_HOST2NET16(s->mixer.rpg_mul);
1737    info[4] = ROAR_HOST2NET16(s->mixer.rpg_div);
1738
1739    for (i = 0; i < chans; i++)
1740     info[5+i] = ROAR_HOST2NET16(s->mixer.mixer[i]);
1741
1742     mes->datalen = (5 + chans)*2;
1743   break;
1744  default:
1745    return -1;
1746   break;
1747 }
1748
1749 mes->cmd = ROAR_CMD_OK;
1750
1751 return 0;
1752}
1753
1754int req_on_add_data (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1755 struct roar_buffer * b;
1756 void               * buf;
1757
1758 if ( roar_buffer_new_data(&b, mes->datalen, &buf) == -1 ) {
1759  ROAR_ERR("req_on_add_data(*): Can not alloc buffer space!");
1760  ROAR_DBG("req_on_add_data(*) = -1");
1761  return -1;
1762 }
1763
1764 if ( data == NULL ) {
1765  memcpy(buf, mes->data, mes->datalen);
1766 } else {
1767  memcpy(buf, *data, mes->datalen);
1768 }
1769
1770 if ( stream_add_buffer(mes->stream, &b) == -1 ) {
1771  roar_buffer_free(b);
1772  return -1;
1773 }
1774
1775 mes->cmd     = ROAR_CMD_OK_STOP;
1776 mes->datalen = 0;
1777
1778 return 0;
1779}
1780
1781int req_on_beep        (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1782 struct roar_beep bs;
1783 int16_t * info = (int16_t*)mes->data;
1784 int stream;
1785
1786 memset(&bs, 0, sizeof(bs));
1787
1788 if ( mes->datalen > 0 ) {
1789  if ( mes->datalen < 2 )
1790   return -1;
1791
1792  if ( ROAR_NET2HOST16(info[0]) != 0 ) /* version */
1793   return -1;
1794
1795  if ( mes->datalen != 8*2 )
1796   return -1;
1797
1798  bs.vol  = ROAR_NET2HOST16(info[1]);
1799  bs.time = ROAR_NET2HOST16(info[2]);
1800  bs.freq = ROAR_NET2HOST16(info[3]);
1801  bs.type = ROAR_NET2HOST16(info[4]);
1802  bs.x    = ROAR_NET2HOST16(info[5]);
1803  bs.y    = ROAR_NET2HOST16(info[6]);
1804  bs.z    = ROAR_NET2HOST16(info[7]);
1805 }
1806
1807 if ( (stream = beep_start(client, &bs)) == -1 )
1808  return -1;
1809
1810 mes->stream  = stream;
1811 mes->cmd     = ROAR_CMD_OK_STOP;
1812 mes->datalen = 0;
1813
1814 return 0;
1815}
1816
1817int req_on_wait        (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1818 uint16_t * u16 = (uint16_t*)mes->data;
1819 struct roar_event events[4];
1820 size_t left, tmp;
1821 size_t num = 0;
1822 void * vp = mes->data;
1823
1824 vp += 4;
1825
1826 // check for complet header...
1827 if ( mes->datalen < 4 )
1828  return -1;
1829
1830 u16[0] = ROAR_NET2HOST16(u16[0]);
1831 u16[1] = ROAR_NET2HOST16(u16[1]);
1832
1833 // do we support version and flags?
1834 if ( u16[0] != 0 || u16[1] != 0 )
1835  return -1;
1836
1837 memset(events, 0, sizeof(events));
1838
1839 left = mes->datalen - 4;
1840
1841 while (left) {
1842  tmp = left;
1843  if ( roar_event_from_blob(&(events[num]), vp, &tmp) == -1 )
1844   return -1;
1845
1846  vp   += tmp;
1847  left -= tmp;
1848  num++;
1849 }
1850
1851 if ( clients_wait(client, events, num) == -1 )
1852  return -1;
1853
1854 flags[1] |= COMMAND_FLAG_OUT_NOSEND;
1855
1856 return 0;
1857}
1858
1859//ll
Note: See TracBrowser for help on using the repository browser.