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

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

updated copyright years

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