source: roaraudio/roard/req.c @ 5961:06e7fd9e4c25

Last change on this file since 5961:06e7fd9e4c25 was 5961:06e7fd9e4c25, checked in by phi, 10 years ago

Updates of copyright and license headers

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