source: roaraudio/roard/req.c @ 5586:5b82b3417705

Last change on this file since 5586:5b82b3417705 was 5586:5b82b3417705, checked in by phi, 12 years ago

general cleanup for -Wextra

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