source: roaraudio/roard/req.c @ 5146:716400712348

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

Moved error frame handling into proto functions (pr0)

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