source: roaraudio/roard/req.c @ 5826:edb28d83ca21

Last change on this file since 5826:edb28d83ca21 was 5826:edb28d83ca21, checked in by phi, 11 years ago

killed compiler warning

File size: 46.7 KB
Line 
1//req.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2013
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    info.un.sysname  = utsname.sysname;
820    info.un.release  = utsname.release;
821    info.un.nodename = utsname.nodename;
822    info.un.machine  = utsname.machine;
823   }
824#endif
825#ifdef ROAR_HAVE_GETVERSIONEX
826   osinfo.dwOSVersionInfoSize = sizeof(osinfo);
827   if ( GetVersionEx(&osinfo) ) {
828    info.un.sysname = "Windows";
829    snprintf(buf_release, sizeof(buf_release), "%i.%i.%i",
830               (int)osinfo.dwMajorVersion, (int)osinfo.dwMinorVersion, (int)osinfo.dwBuildNumber);
831    buf_release[sizeof(buf_release)-1] = 0;
832    info.un.release = buf_release;
833   }
834#endif
835
836   *data = NULL;
837
838   if ( roar_server_info_to_mes(mes, &info, (void**)data) == -1 )
839    return -1;
840
841   if ( *data != NULL )
842    flags[1] |= COMMAND_FLAG_OUT_LONGDATA;
843  break;
844  default: /* unknown request */
845    return -1;
846   break;
847 }
848
849 mes->cmd = ROAR_CMD_OK;
850
851 return 0;
852}
853
854int req_on_server_oinfo    (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
855 struct roar_stream s;
856 int dir = ROAR_DIR_PLAY;
857 int subsys;
858//ROAR_DIR_OUTPUT
859
860 if ( mes->datalen != 0 ) {
861  if ( mes->datalen != 2 )
862   return -1;
863
864  if ( mes->data[0] != 0 )
865   return -1;
866
867  dir = mes->data[1];
868 }
869
870 subsys = streams_dir2subsys(dir);
871
872 memset(&s, 0, sizeof(struct roar_stream));
873
874 s.dir           = ROAR_DIR_MIXING;
875 s.pos_rel_id    = -1;
876
877 switch (subsys) {
878  case ROAR_SUBSYS_WAVEFORM:
879    s.info.rate     = g_sa->rate;
880    s.info.bits     = g_sa->bits;
881    s.info.channels = g_sa->channels;
882    s.info.codec    = g_sa->codec;
883    s.pos           = g_pos;
884   break;
885#ifndef ROAR_WITHOUT_DCOMP_MIDI
886  case ROAR_SUBSYS_MIDI:
887   break;
888#endif
889#ifndef ROAR_WITHOUT_DCOMP_LIGHT
890  case ROAR_SUBSYS_LIGHT:
891    s.info.rate     = ROAR_OUTPUT_CFREQ;
892    s.info.bits     = ROAR_LIGHT_BITS;
893    s.info.channels = g_light_state.channels;
894   break;
895#endif
896#ifndef ROAR_WITHOUT_DCOMP_RAW
897  case ROAR_SUBSYS_RAW:
898    // no need to set anything here.
899   break;
900#endif
901#ifndef ROAR_WITHOUT_DCOMP_RDTCS
902  case ROAR_SUBSYS_RDTCS:
903    s.info.rate     = ROAR_OUTPUT_CFREQ;
904    s.info.bits     = ROAR_RDTCS_BITS;
905    s.info.channels = ROAR_RDTCS_CHANNELS;
906    s.info.codec    = ROAR_RDTCS_CODEC;
907   break;
908#endif
909  default:
910    return -1;
911   break;
912 }
913
914 if ( roar_stream_s2m(&s, mes) == -1 )
915  return -1;
916
917 mes->cmd = ROAR_CMD_OK;
918
919 return 0;
920}
921
922int req_on_caps        (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
923 struct roar_caps caps;
924 struct roar_stds * stds;
925 size_t i;
926
927 if ( roar_caps_from_msg(&caps, mes, *data) == -1 )
928  return -1;
929
930 // handle the data from the caps command here...
931
932 if ( !(caps.flags & ROAR_CF_REQUEST) ) {
933  mes->cmd = ROAR_CMD_OK;
934  mes->datalen = 0;
935  return 0;
936 }
937
938 mes->datalen = 0;
939
940 switch (caps.type) {
941  case ROAR_CT_STANDARDS:
942    if ( (stds = roar_stds_new(g_caps_stds.stds_len)) == NULL )
943     return -1;
944
945    for ( i = 0; i < stds->stds_len; i++) {
946     stds->stds[i] = ROAR_HOST2NET32(g_caps_stds.stds[i]);
947    }
948
949    caps.data = stds->stds;
950    caps.len  = stds->stds_len * 4;
951    // TODO: add support for **data.
952    if ( roar_caps_to_msg(mes, &caps, NULL) == -1 ) {
953     roar_stds_free(stds);
954     return -1;
955    }
956    roar_stds_free(stds);
957   break;
958  default:
959    return -1;
960   break;
961 }
962
963 mes->cmd = ROAR_CMD_OK;
964
965 return 0;
966}
967
968int req_on_get_standby (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
969 mes->cmd     = ROAR_CMD_OK;
970 mes->pos     = g_pos;
971 mes->datalen = 2;
972
973 *((uint16_t*)mes->data) = ROAR_HOST2NET16((unsigned) g_standby);
974
975 return 0;
976}
977
978int req_on_set_standby (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
979 if ( mes->datalen != 2 )
980  return -1;
981
982 g_standby = ROAR_NET2HOST16(*((uint16_t*)mes->data));
983
984 mes->cmd     = ROAR_CMD_OK;
985 mes->pos     = g_pos;
986 mes->datalen = 0;
987
988 return 0;
989}
990
991int req_on_exit      (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
992 int term = 0;
993
994 if ( mes->datalen == 1 )
995  term = mes->data[0];
996
997 mes->cmd     = ROAR_CMD_OK;
998 mes->pos     = g_pos;
999 mes->datalen = 0;
1000
1001 ROAR_DBG("req_on_exit(*): term=%i", term);
1002
1003 if ( term ) {
1004  cleanup_listen_socket(1);
1005 } else {
1006  alive = 0;
1007 }
1008
1009 return 0;
1010}
1011
1012int req_on_list_clients(int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1013 unsigned char filter, cmp;
1014 uint32_t id;
1015 int clients[ROAR_CLIENTS_MAX];
1016 int i, c = 0;
1017
1018 if ( roar_ctl_m2f(mes, &filter, &cmp, &id) == -1 )
1019  return -1;
1020
1021 // TODO: add code to support filter
1022 if ( filter != ROAR_CTL_FILTER_ANY )
1023  return -1;
1024
1025 for (i = 0; i < ROAR_CLIENTS_MAX; i++) {
1026  if ( g_clients[i] != NULL ) {
1027   clients[c++] = i;
1028  }
1029 }
1030
1031 roar_ctl_ia2m(mes, clients, c);
1032
1033 mes->cmd = ROAR_CMD_OK;
1034
1035 return 0;
1036}
1037int req_on_list_streams(int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1038 unsigned char filter, cmp;
1039 uint32_t id;
1040 int streams[ROAR_STREAMS_MAX];
1041 int i, c = 0;
1042 int match;
1043
1044 if ( roar_ctl_m2f(mes, &filter, &cmp, &id) == -1 )
1045  return -1;
1046
1047 for (i = 0; i < ROAR_STREAMS_MAX; i++) {
1048  if ( g_streams[i] == NULL )
1049   continue;
1050
1051  match = 0;
1052
1053  switch (filter) {
1054   case ROAR_CTL_FILTER_ANY:
1055     match = 1;
1056    break;
1057   case ROAR_CTL_FILTER_DIR:
1058     match = roar_filter_match(cmp, id, ROAR_STREAM(g_streams[i])->dir);
1059    break;
1060   default: // unsupported filter...
1061     return -1;
1062    break;
1063  }
1064
1065  if ( match )
1066   streams[c++] = i;
1067 }
1068
1069 roar_ctl_ia2m(mes, streams, c);
1070
1071 mes->cmd = ROAR_CMD_OK;
1072
1073 return 0;
1074}
1075
1076int req_on_get_client  (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1077 struct roar_client * c;
1078 int ret;
1079
1080 if ( mes->datalen != 1 )
1081  return -1;
1082
1083 if ( *data != NULL )
1084  roar_mm_free(*data);
1085 *data = NULL;
1086
1087 if ( clients_get(mes->data[0], &c) == -1 )
1088  return -1;
1089
1090 mes->cmd = ROAR_CMD_OK;
1091
1092 ret = roar_ctl_c2m2(mes, c, (void**)data);
1093
1094 if ( *data != NULL )
1095  flags[1] |= COMMAND_FLAG_OUT_LONGDATA;
1096
1097 return ret;
1098}
1099
1100int req_on_get_stream  (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1101 struct roar_stream_server * s;
1102
1103 if ( mes->datalen != 1 )
1104  return -1;
1105
1106 if ( streams_get(mes->data[0], &s) == -1 )
1107  return -1;
1108
1109 mes->cmd = ROAR_CMD_OK;
1110 mes->stream = mes->data[0];
1111
1112 return roar_stream_s2m(ROAR_STREAM(s), mes);
1113}
1114
1115int req_on_get_stream_para (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1116 struct roar_stream * s;
1117 struct roar_stream_server * ss;
1118 struct roar_audio_info * audio_info;
1119 struct roar_stream_ltm * ltm;
1120 struct roar_stream_rpg   rpg;
1121 uint16_t * d  = (uint16_t *) mes->data;
1122 int64_t * d64 = ( int64_t *) mes->data;
1123 int64_t * d64ptr;
1124 int i, h, k;
1125 char * str;
1126 size_t needed;
1127 int test, bits;
1128
1129 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);
1130
1131 if ( mes->datalen < 4 )
1132  return -1;
1133
1134 for (i = 0; i < 2; i++) {
1135  d[i] = ROAR_NET2HOST16(d[i]);
1136 }
1137
1138 if ( d[0] != 0 ) {
1139  ROAR_WARN("req_on_get_stream_para(*): unsupported command version: %i, %i", (int)d[0], (int)d[1]);
1140  return -1;
1141 }
1142
1143 switch (d[1]) {
1144  case ROAR_STREAM_PARA_INFO:
1145    if ( streams_get(mes->stream, &ss) == -1 ) {
1146     ROAR_WARN("req_on_get_stream_para(*): request on non existing (or other error?) stream %i", mes->stream);
1147     return -1;
1148    }
1149
1150    if ( streams_calc_delay(mes->stream) == -1 ) {
1151     ROAR_WARN("req_on_get_stream_para(*): can not calc delay for stream %i", mes->stream);
1152    }
1153
1154    s = ROAR_STREAM(ss);
1155
1156    audio_info = &(s->info);
1157
1158    mes->datalen = 2*12;
1159
1160    d[ 2] = ROAR_OUTPUT_CALC_OUTBUFSIZE(audio_info);
1161    d[ 3] = ss->pre_underruns;
1162    d[ 4] = ss->post_underruns;
1163    d[ 5] = ss->codec_orgi;
1164    d[ 6] = (ss->flags & 0xFFFF) | (ss->primary ? ROAR_FLAG_PRIMARY : 0) | (ss->driver_id != -1 ? ROAR_FLAG_OUTPUT : 0);
1165    d[ 7] = ss->delay/1000;
1166    d[ 8] = ss->state;
1167    d[ 9] = (ss->flags & 0xFFFF0000) >> 16;
1168    d[10] = ss->mixer_stream;
1169    d[11] = ss->role;
1170
1171    ROAR_DBG("req_on_get_stream_para(*): ss->driver_id=%i", ss->driver_id);
1172
1173    ROAR_DBG("req_on_get_stream_para(*): delay=%i, send delay=%i", ss->delay, d[7]);
1174
1175    for (i = 0; i < mes->datalen/2; i++) {
1176     d[i] = ROAR_HOST2NET16(d[i]);
1177    }
1178
1179    mes->pos = s->pos;
1180   break;
1181
1182  case ROAR_STREAM_PARA_NAME:
1183   str = streams_get_name(mes->stream);
1184
1185   if ( str == NULL )
1186    return -1;
1187
1188    mes->datalen = 4 + strlen(str);
1189
1190    if ( mes->datalen > LIBROAR_BUFFER_MSGDATA )
1191     return -1;
1192
1193    strncpy(((char*)&(mes->data))+4, str, mes->datalen);
1194
1195    d[0] = ROAR_HOST2NET16(d[0]);
1196    d[1] = ROAR_HOST2NET16(d[1]);
1197   break;
1198
1199  case ROAR_STREAM_PARA_CHANMAP:
1200    if ( streams_get(mes->stream, &ss) == -1 ) {
1201     ROAR_WARN("req_on_get_stream_para(*): request on non existing (or other error?) stream %i", mes->stream);
1202     return -1;
1203    }
1204
1205    s = ROAR_STREAM(ss);
1206
1207    memcpy(&(mes->data[4]), ss->chanmap.in, s->info.channels);
1208    mes->datalen = 2*2 + s->info.channels;
1209
1210    d[0] = ROAR_HOST2NET16(d[0]);
1211    d[1] = ROAR_HOST2NET16(d[1]);
1212   break;
1213
1214  case ROAR_STREAM_PARA_LTM:
1215    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM request...", client);
1216
1217    if ( mes->datalen < (6 * 2) ) {
1218     ROAR_ERR("req_on_get_stream_para(client=%i, ...): LTM request of client is corruped: message too short", client);
1219     return -1;
1220    }
1221
1222    for (i = 2; i < mes->datalen/2; i++) {
1223     d[i] = ROAR_NET2HOST16(d[i]);
1224    }
1225
1226    if ( d[2] != ROAR_LTM_SST_GET_RAW ) {
1227     ROAR_ERR("req_on_get_stream_para(client=%i, ...): LTM request of client is corruped: unknown LTM subtype: %i", client, (int)d[2]);
1228     return -1;
1229    }
1230
1231    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM request of type GET_RAW", client);
1232
1233    test = d[5];
1234    bits = 0;
1235    while (test) {
1236     if ( test & 0x1 )
1237      bits++;
1238
1239     test >>= 1;
1240    }
1241
1242    needed = 0;
1243
1244    if ( mes->stream == -1 ) {
1245     ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM multi-stream request...", client);
1246
1247     for (i = 6; i < mes->datalen/2; i++) {
1248      if ( (ltm = streams_ltm_get(d[i], d[5], d[3])) == NULL )
1249       return -1;
1250
1251      needed += ltm->channels;
1252     }
1253    } else {
1254     ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM single-stream request for stream %i...", client, mes->stream);
1255     if ( (ltm = streams_ltm_get(mes->stream, d[5], d[3])) == NULL )
1256      return -1;
1257
1258     needed = ltm->channels;
1259    }
1260
1261    needed *= bits;
1262
1263    needed += mes->stream == -1 ? (mes->datalen/2) - 6 : 1;
1264
1265    ROAR_DBG("req_on_get_stream_para(client=%i, ...): data size for answer is %i 64 bit sub-packets", client, (int)needed);
1266
1267    ROAR_DBG("req_on_get_stream_para(client=%i, ...): mes->datalen=%i, data=%p{%p}", client, (int)mes->datalen, data, *data);
1268    d64 = _dataspace(mes, data, flags, needed * 8);
1269    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1270
1271    if ( (d = roar_mm_malloc(mes->datalen)) == NULL )
1272     return -1;
1273
1274    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d=%p, data=%p{%p}", client, d, data, *data);
1275
1276
1277    ROAR_DBG("req_on_get_stream_para(client=%i, ...): mes->datalen=%i, data=%p{%p}", client, (int)mes->datalen, data, *data);
1278    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1279    memcpy(d, mes->data, mes->datalen);
1280    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1281
1282    d64ptr = d64;
1283
1284    ROAR_DBG("req_on_get_stream_para(client=%i, ...): mes->datalen=%i, data=%p{%p}", client, (int)mes->datalen, data, *data);
1285    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1286
1287    if ( mes->stream == -1 ) {
1288     for (i = 6; i < mes->datalen/2; i++) {
1289      ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1290
1291      if ( (ltm = streams_ltm_get(d[i], d[5], d[3])) == NULL )
1292       return -1;
1293
1294      *d64ptr = ltm->channels & 0xFFFF;
1295       d64ptr++;
1296
1297      for (h = 0; h < ltm->channels; h++) {
1298       for (k = 0; k < ROAR_LTM_MTBITS; k++) {
1299        if ( d[5] & (1<<k) ) {
1300         switch (1<<k) {
1301          case ROAR_LTM_MT_RMS:
1302            *d64ptr = ltm->cur[h].rms;
1303           break;
1304          default:
1305            ROAR_ERR("req_on_get_stream_para(client=%i, ...): client requets unknown MT for LTM: bit %i", client, k);
1306         }
1307         d64ptr++;
1308        }
1309       }
1310      }
1311     }
1312    } else {
1313     if ( (ltm = streams_ltm_get(mes->stream, d[5], d[3])) == NULL )
1314      return -1;
1315
1316     *d64ptr = ltm->channels & 0xFFFF;
1317      d64ptr++;
1318
1319     for (h = 0; h < ltm->channels; h++) {
1320      for (k = 0; k < ROAR_LTM_MTBITS; k++) {
1321       if ( d[5] & (1<<k) ) {
1322        switch (1<<k) {
1323         case ROAR_LTM_MT_RMS:
1324           *d64ptr = ltm->cur[h].rms;
1325           ROAR_DBG("req_on_get_stream_para(client=%i, ...): rms=%lli to %p", client, (long long int)*d64ptr, d64ptr);
1326          break;
1327         default:
1328           ROAR_ERR("req_on_get_stream_para(client=%i, ...): client requets unknown MT for LTM: bit %i", client, k);
1329        }
1330        d64ptr++;
1331       }
1332      }
1333     }
1334    }
1335
1336    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1337
1338    roar_mm_free(d);
1339
1340    for (i = 0; i < needed; i++) {
1341     d64[i] = ROAR_HOST2NET64(d64[i]);
1342    }
1343
1344    mes->datalen = needed * 8;
1345    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM d64=%p, d64ptr=%p", client, d64, d64ptr);
1346    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM final message has %i byte of data", client, (int)mes->datalen);
1347    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1348    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM GET_RAW request: OK. returning...", client);
1349   break;
1350
1351  case ROAR_STREAM_PARA_RPG:
1352    if ( streams_get_rpg(mes->stream, &rpg) == -1 ) {
1353     return -1;
1354    }
1355
1356    mes->datalen = 2*5;
1357
1358    d[2] = rpg.mode;
1359    d[3] = rpg.mul;
1360    d[4] = rpg.div;
1361
1362    for (i = 0; i < mes->datalen/2; i++) {
1363     d[i] = ROAR_HOST2NET16(d[i]);
1364    }
1365   break;
1366
1367  default:
1368    ROAR_WARN("req_on_get_stream_para(*): unsupported command: %i", d[1]);
1369    return -1;
1370 }
1371
1372 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);
1373 mes->cmd = ROAR_CMD_OK;
1374 return 0;
1375}
1376
1377int req_on_set_stream_para (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1378 struct roar_stream_server * ss;
1379 struct roar_stream_rpg rpg;
1380 uint16_t * d = (uint16_t *) mes->data;
1381 uint32_t tmp, tmp2, flagstore;
1382 int protect = 0;
1383 int i;
1384
1385 if ( mes->datalen < 2*2 )
1386  return -1;
1387
1388 for (i = 0; i < 2; i++) {
1389  d[i] = ROAR_NET2HOST16(d[i]);
1390 }
1391
1392 if ( d[0] != 0 )
1393  return -1;
1394
1395 switch (d[1]) {
1396  case ROAR_STREAM_PARA_FLAGS:
1397    if ( mes->datalen != 2*4 && mes->datalen != 2*5 )
1398     return -1;
1399
1400    d[2] = ROAR_NET2HOST16(d[2]);
1401    d[3] = ROAR_NET2HOST16(d[3]);
1402
1403    ROAR_DBG("req_on_set_stream_para(*): request seems to be valid");
1404
1405    tmp = 0;
1406
1407    if ( mes->datalen == 2*5 ) {
1408     d[4] = ROAR_NET2HOST16(d[4]);
1409     tmp   = d[4];
1410     tmp <<= 16;
1411    }
1412
1413    tmp |= d[3];
1414
1415    if ( d[2] & ROAR_PROTECT_FLAG ) {
1416     protect = 1;
1417     d[2] -= ROAR_PROTECT_FLAG;
1418    }
1419
1420    switch (d[2]) {
1421     case ROAR_SET_FLAG:
1422       if ( streams_set_flag(mes->stream, tmp) == -1 )
1423        return -1;
1424      break;
1425     case ROAR_RESET_FLAG:
1426       if ( streams_reset_flag(mes->stream, tmp) == -1 )
1427        return -1;
1428      break;
1429     case ROAR_NOOP_FLAG:
1430      break;
1431     case ROAR_TOGGLE_FLAG:
1432       if ( streams_get(mes->stream, &ss) == -1 )
1433        return -1;
1434
1435       flagstore = ss->flags;
1436
1437       tmp2 = flagstore & tmp; // those are the flags we need to reset.
1438       ROAR_DBG("req_on_set_stream_para(*): tmp2=0x%.8lx", (long int)tmp2);
1439       if ( tmp2 )
1440        if ( streams_reset_flag(mes->stream, tmp2) == -1 )
1441         return -1;
1442
1443       tmp2 = (flagstore ^ tmp) & tmp; // those are the flags we need to set.
1444       ROAR_DBG("req_on_set_stream_para(*): tmp2=0x%.8lx", (long int)tmp2);
1445       if ( tmp2 )
1446        if ( streams_set_flag(mes->stream, tmp2) == -1 )
1447         return -1;
1448      break;
1449     default:
1450       return -1;
1451      break;
1452    }
1453
1454   ROAR_DBG("req_on_set_stream_para(*): protect=%i", protect);
1455   if ( protect )
1456    if ( streams_protect_flag(mes->stream, tmp) == -1 )
1457     return -1;
1458
1459   break;
1460  case ROAR_STREAM_PARA_CHANMAP:
1461    if ( streams_set_map(mes->stream, &(mes->data[4]), mes->datalen - 4) == -1 )
1462     return -1;
1463   break;
1464  case ROAR_STREAM_PARA_ROLE:
1465    if ( mes->datalen != 2*3 )
1466     return -1;
1467
1468    d[2] = ROAR_NET2HOST16(d[2]);
1469
1470    if ( streams_set_role(mes->stream, d[2]) == -1 )
1471     return -1;
1472   break;
1473  case ROAR_STREAM_PARA_LTM:
1474    if ( mes->datalen < (6 * 2) )
1475     return -1;
1476
1477    for (i = 2; i < mes->datalen/2; i++) {
1478     d[i] = ROAR_NET2HOST16(d[i]);
1479    }
1480
1481    if ( mes->stream == -1 ) {
1482     for (i = 6; i < mes->datalen/2; i++)
1483      if ( streams_ltm_ctl(d[i], d[5], d[3], d[2]) == -1 )
1484       return -1;
1485    } else {
1486     if ( streams_ltm_ctl(mes->stream, d[5], d[3], d[2]) == -1 )
1487      return -1;
1488    }
1489   break;
1490  case ROAR_STREAM_PARA_RPG:
1491    if ( mes->datalen != (5 * 2) )
1492     return -1;
1493
1494    for (i = 2; i < mes->datalen/2; i++) {
1495     d[i] = ROAR_NET2HOST16(d[i]);
1496    }
1497
1498    rpg.mode = d[2];
1499    rpg.mul  = d[3];
1500    rpg.div  = d[4];
1501
1502    if ( streams_set_rpg(mes->stream, &rpg) == -1 )
1503     return -1;
1504   break;
1505  default:
1506    ROAR_WARN("req_on_set_stream_para(*): unsupported command version: %i, %i", d[0], d[1]);
1507    return -1;
1508   break;
1509 }
1510
1511 mes->cmd     = ROAR_CMD_OK;
1512 mes->datalen = 0;
1513
1514 return 0;
1515}
1516
1517int req_on_kick (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1518 struct roar_stream_server * ss;
1519 uint16_t * info = (uint16_t *) mes->data;
1520 int is_stream = 0;
1521
1522 if ( mes->datalen != 4 )
1523  return -1;
1524
1525 info[0] = ROAR_NET2HOST16(info[0]);
1526 info[1] = ROAR_NET2HOST16(info[1]);
1527
1528 switch (info[0]) {
1529  case ROAR_OT_CLIENT:
1530    clients_delete(info[1]);
1531   break;
1532  case ROAR_OT_STREAM:
1533    is_stream = 1;
1534   break;
1535  case ROAR_OT_SOURCE:
1536    if ( streams_get_flag(info[1], ROAR_FLAG_SOURCE) != 1 )
1537     return -1;
1538    is_stream = 1;
1539   break;
1540  case ROAR_OT_OUTPUT:
1541    if ( streams_get(info[1], &ss) == -1 )
1542     return -1;
1543
1544    if ( ss->driver_id == -1 )
1545     return -1;
1546
1547    is_stream = 1;
1548   break;
1549  case ROAR_OT_MIXER:
1550    if ( streams_get(info[1], &ss) == -1 )
1551     return -1;
1552
1553    if ( ROAR_STREAM(ss)->dir != ROAR_DIR_MIXING )
1554     return -1;
1555
1556    is_stream = 1;
1557   break;
1558  case ROAR_OT_BRIDGE:
1559    if ( streams_get(info[1], &ss) == -1 )
1560     return -1;
1561
1562    if ( ROAR_STREAM(ss)->dir != ROAR_DIR_BRIDGE )
1563     return -1;
1564
1565    is_stream = 1;
1566   break;
1567  default:
1568/* TODO: those types should be handled, too:
1569#define ROAR_OT_SAMPLE    4
1570#define ROAR_OT_LISTEN    8
1571#define ROAR_OT_ACTION    9
1572#define ROAR_OT_MSGQUEUE 10
1573#define ROAR_OT_MSGBUS   11
1574*/
1575    return -1;
1576   break;
1577 }
1578
1579 if ( is_stream ) {
1580  if ( streams_get_flag(info[1], ROAR_FLAG_IMMUTABLE) == 1 )
1581   return -1;
1582
1583  streams_delete(info[1]);
1584 }
1585
1586 mes->cmd     = ROAR_CMD_OK;
1587 mes->datalen = 0;
1588
1589 return 0;
1590}
1591
1592int req_on_attach      (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1593 uint16_t * info = (uint16_t *) mes->data;
1594
1595 if ( mes->datalen < 6 )
1596  return -1;
1597
1598 info[0] = ROAR_NET2HOST16(info[0]);
1599 info[1] = ROAR_NET2HOST16(info[1]);
1600 info[2] = ROAR_NET2HOST16(info[2]);
1601
1602 if ( info[0] != 0 )
1603  return -1;
1604
1605 if ( info[1] == ROAR_ATTACH_SIMPLE ) {
1606  if ( client_stream_move(info[2], mes->stream) == -1 )
1607   return -1;
1608 } else {
1609  return -1;
1610 }
1611
1612 mes->cmd     = ROAR_CMD_OK;
1613 mes->datalen = 0;
1614
1615 return 0;
1616}
1617
1618int req_on_set_vol (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1619 struct roar_mixer_settings tmpmixer;
1620 struct roar_stream_server * s;
1621 uint16_t * info = (uint16_t *) mes->data;
1622 uint16_t   version;
1623 uint16_t   scale = 65535;
1624 int stream;
1625 int i;
1626 int chans;
1627
1628 ROAR_DBG("req_on_set_vol(*) = ?");
1629 ROAR_DBG("req_on_set_vol(*): mes->datalen=%i", mes->datalen);
1630
1631 if ( mes->datalen < (4*2) )
1632  return -1;
1633
1634 version = ROAR_NET2HOST16(info[0]);
1635 ROAR_DBG("req_on_set_vol(*): version=%i", (int)version);
1636
1637 switch (version) {
1638  case 0:
1639    stream = ROAR_NET2HOST16(info[1]);
1640   break;
1641  case 1:
1642    stream = mes->stream;
1643    scale  = ROAR_NET2HOST16(info[1]);
1644   break;
1645  default:
1646    return -1;
1647   break;
1648 }
1649 ROAR_DBG("req_on_set_vol(*): stream=%i", stream);
1650
1651 if ( scale == 0 )
1652  return -1;
1653
1654 // TODO: change this code.
1655 //       we should not directly change the stream object but use some stream_*()-func
1656 //       for that job.
1657
1658 if ( stream < 0 || stream >= ROAR_STREAMS_MAX )
1659  return -1;
1660
1661 s = g_streams[stream];
1662
1663 if ( s == NULL )
1664  return -1;
1665
1666 ROAR_DBG("req_on_set_vol(*): s=%p", s);
1667
1668 info[2] = ROAR_NET2HOST16(info[2]);
1669
1670 switch (info[2]) {
1671  case ROAR_SET_VOL_ALL:
1672    chans = (mes->datalen/2) - 3;
1673    ROAR_DBG("req_on_set_vol(*): mode is ROAR_SET_VOL_ALL, channes=%i", chans);
1674
1675    if ( chans >= ROAR_MAX_CHANNELS )
1676     return -1;
1677
1678    ROAR_DBG("req_on_set_vol(*): mixer at %p", s->mixer.mixer);
1679
1680    for (i = 0; i < chans; i++) {
1681     s->mixer.mixer[i] = ROAR_NET2HOST16(info[i+3]);
1682     ROAR_DBG("req_on_set_vol(*): channel %i: %i", i, ROAR_NET2HOST16(info[i+3]));
1683    }
1684
1685    s->mixer.scale = scale;
1686
1687    ROAR_DBG("req_on_set_vol(*): mixer changed!");
1688
1689   break;
1690  case ROAR_SET_VOL_ONE:
1691    ROAR_DBG("req_on_set_vol(*): mode is ROAR_SET_VOL_ONE");
1692    if ( ROAR_NET2HOST16(info[3]) >= ROAR_MAX_CHANNELS )
1693     return -1;
1694
1695    s->mixer.mixer[ROAR_NET2HOST16(info[3])] = ROAR_NET2HOST16(info[4]);
1696
1697    s->mixer.scale = scale;
1698   break;
1699  case ROAR_SET_VOL_UNMAPPED:
1700    chans = (mes->datalen/2) - 3;
1701
1702    if ( chans >= ROAR_MAX_CHANNELS )
1703     return -1;
1704
1705    memcpy(&tmpmixer, &(s->mixer), sizeof(tmpmixer));
1706
1707    for (i = 0; i < chans; i++) {
1708     tmpmixer.mixer[i] = ROAR_NET2HOST16(info[i+3]);
1709    }
1710
1711    tmpmixer.scale = scale;
1712
1713    if ( roar_conv_volume(&(s->mixer), &tmpmixer, ROAR_STREAM(s)->info.channels, chans) == -1 )
1714     return -1;
1715
1716   break;
1717  case ROAR_SET_VOL_MS:
1718  default:
1719    return -1;
1720 }
1721
1722 if ( streams_set_mixer(stream) == -1 )
1723  return -1;
1724
1725 mes->cmd     = ROAR_CMD_OK;
1726 mes->datalen = 0;
1727
1728 return 0;
1729}
1730
1731int req_on_get_vol (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1732 uint16_t * info = (uint16_t *) mes->data;
1733 uint16_t   version = -1;
1734 int stream;
1735 struct roar_stream_server * s;
1736 int i;
1737 int chans;
1738
1739 ROAR_DBG("req_on_get_vol(*) = ?");
1740 ROAR_DBG("req_on_get_vol(*): mes->datalen=%i", mes->datalen);
1741
1742 if ( mes->datalen < 2 ) {
1743  return -1;
1744 }
1745
1746 version = ROAR_NET2HOST16(info[0]);
1747
1748 switch (version) {
1749  case 0:
1750    if ( mes->datalen < (2*2) )
1751     return -1;
1752
1753    stream = ROAR_NET2HOST16(info[1]);
1754   break;
1755  case 1:
1756    stream = mes->stream;
1757   break;
1758  default:
1759    return -1;
1760   break;
1761 }
1762
1763 ROAR_DBG("req_on_get_vol(*): stream=%i", stream);
1764
1765 // TODO: change this code.
1766 //       we should not directly change the stream object but use some stream_*()-func
1767 //       for that job.
1768
1769 if ( stream < 0 || stream >= ROAR_STREAMS_MAX )
1770  return -1;
1771
1772 s = g_streams[stream];
1773
1774 if ( s == NULL )
1775  return -1;
1776
1777 ROAR_DBG("req_on_get_vol(*): s=%p", s);
1778
1779 // ok, we have everything
1780
1781 info[0] = ROAR_HOST2NET16(version);
1782
1783 switch (version) {
1784  case 0:
1785    info[1] = ROAR_HOST2NET16(chans = ROAR_STREAM(s)->info.channels);
1786
1787    for (i = 0; i < chans; i++)
1788     info[2+i] = ROAR_HOST2NET16(s->mixer.mixer[i]);
1789
1790     mes->datalen = (2 + chans)*2;
1791   break;
1792  case 1:
1793    info[1] = ROAR_HOST2NET16(chans = ROAR_STREAM(s)->info.channels);
1794    info[2] = ROAR_HOST2NET16(s->mixer.scale);
1795    info[3] = ROAR_HOST2NET16(s->mixer.rpg_mul);
1796    info[4] = ROAR_HOST2NET16(s->mixer.rpg_div);
1797
1798    for (i = 0; i < chans; i++)
1799     info[5+i] = ROAR_HOST2NET16(s->mixer.mixer[i]);
1800
1801     mes->datalen = (5 + chans)*2;
1802   break;
1803  default:
1804    return -1;
1805   break;
1806 }
1807
1808 mes->cmd = ROAR_CMD_OK;
1809
1810 return 0;
1811}
1812
1813int req_on_add_data (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1814 struct roar_buffer * b;
1815 void               * buf;
1816
1817 if ( roar_buffer_new_data(&b, mes->datalen, &buf) == -1 ) {
1818  ROAR_ERR("req_on_add_data(*): Can not alloc buffer space!");
1819  ROAR_DBG("req_on_add_data(*) = -1");
1820  return -1;
1821 }
1822
1823 if ( data == NULL ) {
1824  memcpy(buf, mes->data, mes->datalen);
1825 } else {
1826  memcpy(buf, *data, mes->datalen);
1827 }
1828
1829 if ( stream_add_buffer(mes->stream, &b) == -1 ) {
1830  roar_buffer_free(b);
1831  return -1;
1832 }
1833
1834 mes->cmd     = ROAR_CMD_OK_STOP;
1835 mes->datalen = 0;
1836
1837 return 0;
1838}
1839
1840int req_on_beep        (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1841 struct roar_beep bs;
1842 int16_t * info = (int16_t*)mes->data;
1843 int stream;
1844
1845 memset(&bs, 0, sizeof(bs));
1846
1847 if ( mes->datalen > 0 ) {
1848  if ( mes->datalen < 2 )
1849   return -1;
1850
1851  if ( ROAR_NET2HOST16(info[0]) != 0 ) /* version */
1852   return -1;
1853
1854  if ( mes->datalen != 8*2 )
1855   return -1;
1856
1857  bs.vol  = ROAR_NET2HOST16(info[1]);
1858  bs.time = ROAR_NET2HOST16(info[2]);
1859  bs.freq = ROAR_NET2HOST16(info[3]);
1860  bs.type = ROAR_NET2HOST16(info[4]);
1861  bs.x    = ROAR_NET2HOST16(info[5]);
1862  bs.y    = ROAR_NET2HOST16(info[6]);
1863  bs.z    = ROAR_NET2HOST16(info[7]);
1864 }
1865
1866 if ( (stream = beep_start(client, &bs)) == -1 )
1867  return -1;
1868
1869 mes->stream  = stream;
1870 mes->cmd     = ROAR_CMD_OK_STOP;
1871 mes->datalen = 0;
1872
1873 return 0;
1874}
1875
1876int req_on_wait        (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1877 uint16_t * u16 = (uint16_t*)mes->data;
1878 struct roar_event events[4];
1879 size_t left, tmp;
1880 size_t num = 0;
1881 void * vp = mes->data;
1882
1883 vp += 4;
1884
1885 // check for complet header...
1886 if ( mes->datalen < 4 )
1887  return -1;
1888
1889 u16[0] = ROAR_NET2HOST16(u16[0]);
1890 u16[1] = ROAR_NET2HOST16(u16[1]);
1891
1892 // do we support version and flags?
1893 if ( u16[0] != 0 || u16[1] != 0 )
1894  return -1;
1895
1896 memset(events, 0, sizeof(events));
1897
1898 left = mes->datalen - 4;
1899
1900 while (left) {
1901  tmp = left;
1902  if ( roar_event_from_blob(&(events[num]), vp, &tmp) == -1 )
1903   return -1;
1904
1905  vp   += tmp;
1906  left -= tmp;
1907  num++;
1908 }
1909
1910 if ( clients_wait(client, events, num) == -1 )
1911  return -1;
1912
1913 flags[1] |= COMMAND_FLAG_OUT_NOSEND;
1914
1915 return 0;
1916}
1917
1918//ll
Note: See TracBrowser for help on using the repository browser.