source: roaraudio/roard/req.c @ 4431:cbea30f1890d

Last change on this file since 4431:cbea30f1890d was 4431:cbea30f1890d, checked in by phi, 14 years ago

implemented basic SERVER_INFO with IT_SERVER

File size: 34.6 KB
Line 
1//req.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2010
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#include "roard.h"
27
28static void * _dataspace(struct roar_message * mes, char ** data, uint32_t flags[2], size_t len) {
29 if ( len <= LIBROAR_BUFFER_MSGDATA )
30  return mes->data;
31
32 if ( *data != NULL )
33  free(*data);
34
35 *data = malloc(len);
36
37 ROAR_DBG("_dataspace(mes=%p, data=%p, flags=%p, len=%llu): *data=%p", mes, data, flags, (long long unsigned int)len, *data);
38
39 if ( *data == NULL )
40  return NULL;
41
42 flags[1] |= COMMAND_FLAG_OUT_LONGDATA;
43
44 return *data;
45}
46
47int req_on_noop        (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
48 mes->cmd     = ROAR_CMD_OK;
49 mes->pos     = g_pos;
50 mes->datalen = 0;
51 return 0;
52}
53
54int req_on_identify    (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
55 struct roar_client * c;
56 int max_len;
57
58 if ( mes->datalen < 1 )
59  return -1;
60
61 clients_get(client, &c);
62
63 if ( mes->data[0] == 1 ) {
64  if ( c->pid == -1 ) {
65   c->pid       = ROAR_NET2HOST32(*(uint32_t*)((mes->data)+1));
66   ROAR_DBG("req_on_identify(): new PID: c->pid = %i", c->pid);
67  }
68
69  ROAR_DBG("req_on_identify(): final PID: c->pid = %i", c->pid);
70
71  max_len = (mes->datalen - 5) < (ROAR_BUFFER_NAME-1) ? (mes->datalen - 5) : (ROAR_BUFFER_NAME-1);
72
73  strncpy(c->name, mes->data + 5, max_len);
74  c->name[max_len] = 0;
75
76  mes->cmd     = ROAR_CMD_OK;
77  mes->pos     = g_pos;
78  mes->datalen = 0;
79
80  ROAR_DBG("req_on_identify(*): client=%i, pid=%i", client, c->pid);
81  ROAR_DBG("req_on_identify(*) = 0");
82  return 0;
83 }
84
85 return -1;
86}
87
88int req_on_auth        (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
89 // TODO: add code to support some auth.
90 mes->cmd     = ROAR_CMD_OK;
91 mes->pos     = g_pos;
92 mes->datalen = 0;
93 return 0;
94}
95
96
97int req_on_whoami      (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
98 mes->cmd     = ROAR_CMD_OK;
99 mes->pos     = g_pos;
100 mes->datalen = 1;
101 mes->data[0] = client;
102 return 0;
103}
104
105
106int req_on_new_stream  (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
107 int stream;
108 struct roar_stream * s;
109 struct roar_stream * source_stream;
110 struct roar_audio_info * info;
111 struct roar_audio_info * source_info;
112
113 ROAR_DBG("req_on_new_stream(client=%i, ...): creating stream...", client);
114 if ((stream = streams_new()) == -1 )
115  return -1;
116
117 ROAR_DBG("req_on_new_stream(client=%i, ...): stream=%i", client, stream);
118
119 ROAR_DBG("req_on_new_stream(client=%i, ...): getting stream...", client);
120 if ( streams_get(stream, (struct roar_stream_server **)&s) == -1 ) {
121  streams_delete(stream);
122  return -1;
123 }
124
125 ROAR_DBG("req_on_new_stream(client=%i, ...): set client of stream...", client);
126 if ( client_stream_add(client, stream) == -1 ) {
127  streams_delete(stream);
128  return -1;
129 }
130
131 ROAR_DBG("req_on_new_stream(client=%i, ...): loading stream from message...", client);
132 if ( roar_stream_m2s(s, mes) == -1 ) {
133  streams_delete(stream);
134  return -1;
135 }
136
137 ROAR_DBG("req_on_new_stream(client=%i, ...): setting id and codec of stream...", client);
138 ROAR_STREAM(s)->id = stream; // roar_stream_m2s() resets this
139 ROAR_STREAM_SERVER(s)->codec_orgi = ROAR_STREAM(s)->info.codec;
140
141 ROAR_DBG("req_on_new_stream(client=%i, ...): setting direction stream...", client);
142 // int streams_set_dir    (int id, int dir, int defaults)
143 if ( streams_set_dir(stream, ROAR_STREAM(s)->dir, 1) == -1 ) {
144  streams_delete(stream);
145  return -1;
146 }
147
148 ROAR_DBG("req_on_new_stream(client=%i, ...): setting up direction specific stream settings...", client);
149 switch (ROAR_STREAM(s)->dir) {
150  case ROAR_DIR_LIGHT_IN:
151  case ROAR_DIR_LIGHT_OUT:
152#ifndef ROAR_WITHOUT_DCOMP_LIGHT
153    info = &(ROAR_STREAM(s)->info);
154
155    info->channels = 0;
156    info->bits     = 0;
157    info->rate     = 0;
158#else
159    streams_delete(stream);
160    return -1;
161#endif
162
163   break;
164  case ROAR_DIR_MIDI_IN:
165  case ROAR_DIR_MIDI_OUT:
166#ifndef ROAR_WITHOUT_DCOMP_MIDI
167    info = &(ROAR_STREAM(s)->info);
168
169    info->channels = ROAR_MIDI_CHANNELS_DEFAULT;
170    info->bits     = ROAR_MIDI_BITS;
171    info->rate     = 0;
172#else
173    streams_delete(stream);
174    return -1;
175#endif
176
177   break;
178
179  case ROAR_DIR_RAW_IN:
180#ifndef ROAR_WITHOUT_DCOMP_RAW
181    if ( ROAR_STREAM(s)->pos_rel_id == -1     ||
182         ROAR_STREAM(s)->pos_rel_id == stream ||
183         streams_get_dir(ROAR_STREAM(s)->pos_rel_id) != ROAR_DIR_RAW_OUT
184       ) {
185     ROAR_STREAM(s)->pos_rel_id = -1; // force this here as it will try to delete itself while deleting
186                                      // in case rel_id == stream
187     streams_delete(stream);
188     return -1;
189    }
190#else
191  case ROAR_DIR_RAW_OUT:
192    streams_delete(stream);
193    return -1;
194#endif
195
196   break;
197  case ROAR_DIR_THRU:
198
199    if ( ROAR_STREAM(s)->pos_rel_id == -1 || ROAR_STREAM(s)->pos_rel_id == stream ) {
200     ROAR_STREAM(s)->pos_rel_id = -1; // force this here as it will try to delete itself while deleting
201                                      // in case rel_id == stream
202     streams_delete(stream);
203     return -1;
204    }
205
206    if ( streams_get(ROAR_STREAM(s)->pos_rel_id, (struct roar_stream_server **)&source_stream) == -1 ) {
207     streams_delete(stream);
208     return -1;
209    }
210
211    info        = &(ROAR_STREAM(s)->info);
212    source_info = &(ROAR_STREAM(source_stream)->info);
213
214    info->channels = source_info->channels;
215    info->bits     = source_info->bits;
216    info->rate     = source_info->rate;
217    info->codec    = source_info->codec;
218    ROAR_STREAM_SERVER(s)->codec_orgi = ROAR_STREAM_SERVER(source_stream)->codec_orgi;
219
220   break;
221  case ROAR_DIR_FILTER:
222    info        = &(ROAR_STREAM(s)->info);
223
224    if ( ROAR_STREAM(s)->pos_rel_id == -1 ) {
225     source_info = g_sa;
226    } else {
227     if ( streams_get(ROAR_STREAM(s)->pos_rel_id, (struct roar_stream_server **)&source_stream) == -1 ) {
228      streams_delete(stream);
229      return -1;
230     }
231     source_info = &(ROAR_STREAM(source_stream)->info);
232    }
233
234    if ( info->channels != source_info->channels || info->bits != source_info->bits ||
235         info->codec    != source_info->codec    || info->rate != source_info->rate ) {
236     // the stream parameters don't match the one of the stream being filtered.
237     // -> delete and reject the stream.
238     streams_delete(stream);
239     return -1;
240    }
241   break;
242 }
243
244 ROAR_DBG("req_on_new_stream(client=%i, ...): returning (OK, stream=%i)...", client, stream);
245
246 mes->cmd     = ROAR_CMD_OK;
247 mes->stream  = stream;
248 mes->datalen = 0;
249
250 return 0;
251}
252
253int req_on_exec_stream (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
254 int r;
255
256 ROAR_DBG("req_on_exec_stream(client=%i, mes={stream=%i,...},...): execing stream", client, mes->stream);
257
258
259 if ( streams_is_ready(mes->stream) ) {
260  flags[1] |= COMMAND_FLAG_OUT_CLOSECON;
261 } else {
262  if ( (r = client_stream_exec(client, mes->stream)) == -1 )
263   return -1;
264 }
265
266 ROAR_DBG("req_on_exec_stream(client=%i, mes={stream=%i,...},...): returning (OK)...", client, mes->stream);
267 mes->cmd     = ROAR_CMD_OK;
268 mes->datalen = 0;
269
270 return 0;
271}
272
273int req_on_con_stream  (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
274 char   host[80] = {0};
275 int    port = 0;
276 int    type;
277 int    fh;
278 int    len;
279
280 if ( mes->datalen < 4 )
281  return -1;
282
283 if ( *(mes->data) != 0 )
284  return -1;
285
286 if ( mes->datalen > 80 ) // we do not support long messages here
287  return -1;
288
289 type = (unsigned)mes->data[1];
290 port = ROAR_NET2HOST16(((uint16_t*)mes->data)[1]);
291
292 len = mes->datalen - 4;
293
294 strncpy(host, &(mes->data[4]), len);
295 host[len] = 0;
296
297 if ( type > ROAR_SOCKET_TYPE_MAX )
298  return -1;
299
300 if ( type == ROAR_SOCKET_TYPE_FILE ) // disabled because of security resons
301  return -1;
302
303 if ( type == ROAR_SOCKET_TYPE_FORK ) // why should we connect to ourself?
304  return -1;
305
306 ROAR_DBG("req_on_con_stream(*): CONNECT(type=%i, host='%s', port=%i)", type, host, port);
307
308 if ( (fh = roar_socket_open(ROAR_SOCKET_MODE_CONNECT, type, host, port)) == -1 )
309  return -1;
310
311 if ( client_stream_set_fh(client, mes->stream, fh) == -1 ) {
312  close(fh);
313  return 1;
314 }
315
316 mes->datalen = 0;
317 mes->cmd     = ROAR_CMD_OK;
318
319 return 0;
320}
321
322int req_on_passfh      (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
323 int sock = clients_get_fh(client);
324 int16_t * d = (int16_t*)mes->data;
325 struct roard_listen * lsock;
326 int listening;
327 int fh;
328 int i;
329
330 ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...) = ?", client, mes->stream);
331
332 if ( (fh = roar_socket_recv_fh(sock, NULL, NULL)) == -1 ) {
333  ROAR_WARN("req_on_passfh(client=%i, mes={stream=%i,...},...): was unabled to get filehandle from remote end. bad.", client, mes->stream);
334  ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): returning (ERROR)...", client, mes->stream);
335  return -1;
336 }
337
338 ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): fh=%i", client, mes->stream, fh);
339
340 if ( mes->stream != -1 ) { // stream pass:
341  ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): This is a stream passfh", client, mes->stream);
342
343  if ( client_stream_set_fh(client, mes->stream, fh) == -1 ) {
344   close(fh);
345   ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): returning (ERROR)...", client, mes->stream);
346   return -1;
347  }
348
349  ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): returning (OK)...", client, mes->stream);
350
351  mes->datalen = 0;
352  mes->cmd     = ROAR_CMD_OK;
353
354  return 0;
355 }
356
357// non-stream pass:
358
359 ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): This is a client passfh", client, mes->stream);
360
361/*
362 0: Version,   16
363 1: Flags,     16
364 2: Protocol,  16
365 3: Byteorder, 16
366 Options...
367*/
368
369 if ( mes->datalen < 4*2 )
370  return -1;
371
372 for (i = 0; i < 4; i++) {
373  d[i] = ROAR_NET2HOST16(d[i]);
374 }
375
376 if ( d[0] != 0 ) // version
377  return -1;
378
379 listening = d[1] & ROAR_CLIENTPASS_FLAG_LISTEN;
380
381 if ( listening )
382  d[1] -= ROAR_CLIENTPASS_FLAG_LISTEN;
383
384 if ( d[1] != 0 ) // flags
385  return -1;
386
387 if ( listening ) {
388  if ( get_listen(&lsock, NULL) == -1 ) {
389   close(fh);
390   return -1;
391  }
392
393  roar_vio_open_fh_socket(&(lsock->sock), fh);
394  lsock->used   = 1;
395  lsock->proto  = d[2];
396 } else {
397  if ( clients_new_from_fh(fh, d[2], d[3], 1) == -1 )
398   return -1;
399 }
400
401 ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): returning (OK)...", client, mes->stream);
402
403 mes->datalen = 0;
404 mes->cmd     = ROAR_CMD_OK;
405
406 return 0;
407}
408
409#ifdef ROAR_SUPPORT_META
410int req_on_set_meta    (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
411 int type;
412 int mode;
413 int namelen, vallen;
414 char   val[255+1];
415 char   name[ROAR_META_MAX_NAMELEN+1];
416
417 if ( mes->datalen < 3 )
418  return -1;
419
420 if ( mes->data[0] != 0 ) // version
421  return -1;
422
423 mode = (unsigned) mes->data[1];
424 type = (unsigned) mes->data[2];
425
426 ROAR_DBG("req_on_set_meta(*): mode=%i, type=%i", mode, type);
427
428 if ( mode == ROAR_META_MODE_CLEAR ) {
429  stream_meta_clear(mes->stream);
430  mes->datalen = 0;
431  mes->cmd     = ROAR_CMD_OK;
432  return 0;
433 } else if ( mode == ROAR_META_MODE_DELETE ) { // unsuppoerted at the moment
434  return -1;
435 } else if ( mode == ROAR_META_MODE_FINALIZE ) {
436  stream_meta_finalize(mes->stream);
437  mes->datalen = 0;
438  mes->cmd     = ROAR_CMD_OK;
439  return 0;
440 } else if ( mode == ROAR_META_MODE_SET || mode == ROAR_META_MODE_ADD ) {
441  if ( mes->datalen < 5 )
442   return -1;
443
444  namelen = (unsigned) mes->data[3];
445  vallen  = (unsigned) mes->data[4];
446
447  ROAR_DBG("req_on_set_meta(*): namelen=%i, vallen=%i", namelen, vallen);
448
449  if ( mes->datalen < (5 + namelen + vallen) )
450   return -1;
451
452  if ( namelen > ROAR_META_MAX_NAMELEN )
453   return -1;
454
455  strncpy(name, &(mes->data[5]), namelen);
456  name[namelen] = 0;
457
458  if ( vallen > 255 )
459   return -1;
460
461  strncpy(val, &(mes->data[5+namelen]), vallen);
462  val[vallen] = 0;
463
464  if ( mode == ROAR_META_MODE_SET ) {
465   if ( stream_meta_set(mes->stream, type, name, val) == -1 )
466    return -1;
467  } else {
468   if ( stream_meta_add(mes->stream, type, name, val) == -1 )
469    return -1;
470  }
471
472  mes->datalen = 0;
473  mes->cmd     = ROAR_CMD_OK;
474  return 0;
475 } else { // unknown mode!
476  return -1;
477 }
478
479 return -1;
480}
481
482int req_on_get_meta    (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
483 int vallen;
484 int type;
485 char val[LIBROAR_BUFFER_MSGDATA-1];
486
487 if ( mes->datalen != 2 )
488  return -1;
489
490 if ( mes->data[0] != 0 ) // version
491  return -1;
492
493 type = (unsigned) mes->data[1];
494
495 if ( stream_meta_get(mes->stream, type, NULL, val, LIBROAR_BUFFER_MSGDATA-2) == -1 )
496  return -1;
497
498 vallen = strlen(val);
499
500 mes->cmd     = ROAR_CMD_OK;
501 mes->datalen = 2 + vallen;
502
503 mes->data[0] = 0;
504 mes->data[1] = (unsigned char) vallen;
505
506 val[vallen] = 0;
507
508 strncpy(&(mes->data[2]), val, vallen+1);
509
510 return 0;
511}
512
513int req_on_list_meta   (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
514 int i;
515 int len = 0;
516 int types[ROAR_META_MAX_PER_STREAM];
517
518 if ( mes->datalen != 1 )
519  return -1;
520
521 if ( mes->data[0] != 0 ) // version
522  return -1;
523
524 if ( (len = stream_meta_list(mes->stream, types, ROAR_META_MAX_PER_STREAM)) == -1 )
525  return -1;
526
527 mes->cmd     = ROAR_CMD_OK;
528 mes->datalen = 1 + len;
529 mes->data[0] = 0;
530
531 for (i = 0; i < len; i++)
532  mes->data[i+1] = types[i];
533
534 return 0;
535}
536#endif
537
538int req_on_server_info (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
539 struct roar_server_info info;
540 uint16_t * d16;
541
542 if ( mes->datalen != 4 )
543  return -1;
544
545 d16 = (uint16_t*)mes->data;
546
547 // check version.
548 if ( ROAR_NET2HOST16(d16[0]) != 0 )
549  return -1;
550
551 switch (ROAR_NET2HOST16(d16[1])) {
552  case ROAR_IT_SERVER:
553   memset(&info, 0, sizeof(info));
554
555   info.version = "roard/? <0/RoarAudio>";
556   info.location = g_config->location;
557   info.description = g_config->description;
558
559   if ( roar_server_info_to_mes(mes, &info) == -1 )
560    return -1;
561  break;
562  default: /* unknown request */
563    return -1;
564   break;
565 }
566
567 mes->cmd = ROAR_CMD_OK;
568
569 return 0;
570}
571
572int req_on_server_oinfo    (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
573 struct roar_stream s;
574//ROAR_DIR_OUTPUT
575
576 memset(&s, 0, sizeof(struct roar_stream));
577
578 s.dir           = ROAR_DIR_MIXING;
579 s.pos_rel_id    = -1;
580 s.info.rate     = g_sa->rate;
581 s.info.bits     = g_sa->bits;
582 s.info.channels = g_sa->channels;
583 s.info.codec    = g_sa->codec;
584 s.pos           = g_pos;
585
586 if ( roar_stream_s2m(&s, mes) == -1 )
587  return -1;
588
589 mes->cmd = ROAR_CMD_OK;
590
591 return 0;
592}
593
594
595int req_on_get_standby (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
596 mes->cmd     = ROAR_CMD_OK;
597 mes->pos     = g_pos;
598 mes->datalen = 2;
599
600 *((uint16_t*)mes->data) = ROAR_HOST2NET16((unsigned) g_standby);
601
602 return 0;
603}
604
605int req_on_set_standby (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
606 if ( mes->datalen != 2 )
607  return -1;
608
609 g_standby = ROAR_NET2HOST16(*((uint16_t*)mes->data));
610
611 mes->cmd     = ROAR_CMD_OK;
612 mes->pos     = g_pos;
613 mes->datalen = 0;
614
615 return 0;
616}
617
618int req_on_exit      (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
619 int term = 0;
620
621 if ( mes->datalen == 1 )
622  term = mes->data[0];
623
624 mes->cmd     = ROAR_CMD_OK;
625 mes->pos     = g_pos;
626 mes->datalen = 0;
627
628 ROAR_DBG("req_on_exit(*): term=%i", term);
629
630 if ( term ) {
631  cleanup_listen_socket(1);
632 } else {
633  alive = 0;
634 }
635
636 return 0;
637}
638
639int req_on_list_clients(int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
640 unsigned char filter, cmp;
641 uint32_t id;
642 int clients[ROAR_CLIENTS_MAX];
643 int i, c = 0;
644
645 if ( roar_ctl_m2f(mes, &filter, &cmp, &id) == -1 )
646  return -1;
647
648 // TODO: add code to support filter
649 if ( filter != ROAR_CTL_FILTER_ANY )
650  return -1;
651
652 for (i = 0; i < ROAR_CLIENTS_MAX; i++) {
653  if ( g_clients[i] != NULL ) {
654   clients[c++] = i;
655  }
656 }
657
658 roar_ctl_ia2m(mes, clients, c);
659
660 mes->cmd = ROAR_CMD_OK;
661
662 return 0;
663}
664int req_on_list_streams(int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
665 unsigned char filter, cmp;
666 uint32_t id;
667 int streams[ROAR_STREAMS_MAX];
668 int i, c = 0;
669 int match;
670
671 if ( roar_ctl_m2f(mes, &filter, &cmp, &id) == -1 )
672  return -1;
673
674 for (i = 0; i < ROAR_STREAMS_MAX; i++) {
675  if ( g_streams[i] == NULL )
676   continue;
677
678  match = 0;
679
680  switch (filter) {
681   case ROAR_CTL_FILTER_ANY:
682     match = 1;
683    break;
684   case ROAR_CTL_FILTER_DIR:
685     match = roar_filter_match(cmp, id, ROAR_STREAM(g_streams[i])->dir);
686    break;
687   default: // unsupported filter...
688     return -1;
689    break;
690  }
691
692  if ( match )
693   streams[c++] = i;
694 }
695
696 roar_ctl_ia2m(mes, streams, c);
697
698 mes->cmd = ROAR_CMD_OK;
699
700 return 0;
701}
702
703int req_on_get_client  (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
704 struct roar_client * c;
705
706 if ( mes->datalen != 1 )
707  return -1;
708
709 if ( clients_get(mes->data[0], &c) == -1 )
710  return -1;
711
712 mes->cmd = ROAR_CMD_OK;
713
714 return roar_ctl_c2m(mes, c);
715}
716
717int req_on_get_stream  (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
718 struct roar_stream_server * s;
719
720 if ( mes->datalen != 1 )
721  return -1;
722
723 if ( streams_get(mes->data[0], &s) == -1 )
724  return -1;
725
726 mes->cmd = ROAR_CMD_OK;
727 mes->stream = mes->data[0];
728
729 return roar_stream_s2m(ROAR_STREAM(s), mes);
730}
731
732int req_on_get_stream_para (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
733 struct roar_stream * s;
734 struct roar_stream_server * ss;
735 struct roar_audio_info * audio_info;
736 struct roar_stream_ltm * ltm;
737 uint16_t * d  = (uint16_t *) mes->data;
738 int64_t * d64 = ( int64_t *) mes->data;
739 int64_t * d64ptr;
740 int i, h, k;
741 char * str;
742 size_t needed;
743 int test, bits;
744
745 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);
746
747 if ( mes->datalen < 4 )
748  return -1;
749
750 for (i = 0; i < 2; i++) {
751  d[i] = ROAR_NET2HOST16(d[i]);
752 }
753
754 if ( d[0] != 0 ) {
755  ROAR_WARN("req_on_get_stream_para(*): unsupported command version: %i, %i", (int)d[0], (int)d[1]);
756  return -1;
757 }
758
759 switch (d[1]) {
760  case ROAR_STREAM_PARA_INFO:
761    if ( streams_get(mes->stream, &ss) == -1 ) {
762     ROAR_WARN("req_on_get_stream_para(*): request on non existing (or other error?) stream %i", mes->stream);
763     return -1;
764    }
765
766    if ( streams_calc_delay(mes->stream) == -1 ) {
767     ROAR_WARN("req_on_get_stream_para(*): can not calc delay for stream %i", mes->stream);
768    }
769
770    s = ROAR_STREAM(ss);
771
772    audio_info = &(s->info);
773
774    mes->datalen = 2*12;
775
776    d[ 2] = ROAR_OUTPUT_CALC_OUTBUFSIZE(audio_info);
777    d[ 3] = ss->pre_underruns;
778    d[ 4] = ss->post_underruns;
779    d[ 5] = ss->codec_orgi;
780    d[ 6] = (ss->flags & 0xFFFF) | (ss->primary ? ROAR_FLAG_PRIMARY : 0) | (ss->driver_id != -1 ? ROAR_FLAG_OUTPUT : 0);
781    d[ 7] = ss->delay/1000;
782    d[ 8] = ss->state;
783    d[ 9] = (ss->flags & 0xFFFF0000) >> 16;
784    d[10] = ss->mixer_stream;
785    d[11] = ss->role;
786
787    ROAR_DBG("req_on_get_stream_para(*): ss->driver_id=%i", ss->driver_id);
788
789    ROAR_DBG("req_on_get_stream_para(*): delay=%i, send delay=%i", ss->delay, d[7]);
790
791    for (i = 0; i < mes->datalen/2; i++) {
792     d[i] = ROAR_HOST2NET16(d[i]);
793    }
794
795    mes->pos = s->pos;
796   break;
797
798  case ROAR_STREAM_PARA_NAME:
799   str = streams_get_name(mes->stream);
800
801   if ( str == NULL )
802    return -1;
803
804    mes->datalen = 4 + strlen(str);
805
806    if ( mes->datalen > LIBROAR_BUFFER_MSGDATA )
807     return -1;
808
809    strncpy(((char*)&(mes->data))+4, str, mes->datalen);
810
811    d[0] = ROAR_HOST2NET16(d[0]);
812    d[1] = ROAR_HOST2NET16(d[1]);
813   break;
814
815  case ROAR_STREAM_PARA_CHANMAP:
816    if ( streams_get(mes->stream, &ss) == -1 ) {
817     ROAR_WARN("req_on_get_stream_para(*): request on non existing (or other error?) stream %i", mes->stream);
818     return -1;
819    }
820
821    s = ROAR_STREAM(ss);
822
823    memcpy(&(mes->data[4]), ss->chanmap.in, s->info.channels);
824    mes->datalen = 2*2 + s->info.channels;
825
826    d[0] = ROAR_HOST2NET16(d[0]);
827    d[1] = ROAR_HOST2NET16(d[1]);
828   break;
829
830  case ROAR_STREAM_PARA_LTM:
831    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM request...", client);
832
833    if ( mes->datalen < (6 * 2) ) {
834     ROAR_ERR("req_on_get_stream_para(client=%i, ...): LTM request of client is corruped: message too short", client);
835     return -1;
836    }
837
838    for (i = 2; i < mes->datalen/2; i++) {
839     d[i] = ROAR_NET2HOST16(d[i]);
840    }
841
842    if ( d[2] != ROAR_LTM_SST_GET_RAW ) {
843     ROAR_ERR("req_on_get_stream_para(client=%i, ...): LTM request of client is corruped: unknown LTM subtype: %i", client, (int)d[2]);
844     return -1;
845    }
846
847    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM request of type GET_RAW", client);
848
849    test = d[5];
850    bits = 0;
851    while (test) {
852     if ( test & 0x1 )
853      bits++;
854
855     test >>= 1;
856    }
857
858    needed = 0;
859
860    if ( mes->stream == -1 ) {
861     ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM multi-stream request...", client);
862
863     for (i = 6; i < mes->datalen/2; i++) {
864      if ( (ltm = streams_ltm_get(d[i], d[5], d[3])) == NULL )
865       return -1;
866
867      needed += ltm->channels;
868     }
869    } else {
870     ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM single-stream request for stream %i...", client, mes->stream);
871     if ( (ltm = streams_ltm_get(mes->stream, d[5], d[3])) == NULL )
872      return -1;
873
874     needed = ltm->channels;
875    }
876
877    needed *= bits;
878
879    needed += mes->stream == -1 ? (mes->datalen/2) - 6 : 1;
880
881    ROAR_DBG("req_on_get_stream_para(client=%i, ...): data size for answer is %i 64 bit sub-packets", client, (int)needed);
882
883    ROAR_DBG("req_on_get_stream_para(client=%i, ...): mes->datalen=%i, data=%p{%p}", client, (int)mes->datalen, data, *data);
884    d64 = _dataspace(mes, data, flags, needed * 8);
885    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
886
887    if ( (d = roar_mm_malloc(mes->datalen)) == NULL )
888     return -1;
889
890    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d=%p, data=%p{%p}", client, d, data, *data);
891
892
893    ROAR_DBG("req_on_get_stream_para(client=%i, ...): mes->datalen=%i, data=%p{%p}", client, (int)mes->datalen, data, *data);
894    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
895    memcpy(d, mes->data, mes->datalen);
896    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
897
898    d64ptr = d64;
899
900    ROAR_DBG("req_on_get_stream_para(client=%i, ...): mes->datalen=%i, data=%p{%p}", client, (int)mes->datalen, data, *data);
901    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
902
903    if ( mes->stream == -1 ) {
904     for (i = 6; i < mes->datalen/2; i++) {
905      ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
906
907      if ( (ltm = streams_ltm_get(d[i], d[5], d[3])) == NULL )
908       return -1;
909
910      *d64ptr = ltm->channels & 0xFFFF;
911       d64ptr++;
912
913      for (h = 0; h < ltm->channels; h++) {
914       for (k = 0; k < ROAR_LTM_MTBITS; k++) {
915        if ( d[5] & (1<<k) ) {
916         switch (1<<k) {
917          case ROAR_LTM_MT_RMS:
918            *d64ptr = ltm->cur[h].rms;
919           break;
920          default:
921            ROAR_ERR("req_on_get_stream_para(client=%i, ...): client requets unknown MT for LTM: bit %i", client, k);
922         }
923         d64ptr++;
924        }
925       }
926      }
927     }
928    } else {
929     if ( (ltm = streams_ltm_get(mes->stream, d[5], d[3])) == NULL )
930      return -1;
931
932     *d64ptr = ltm->channels & 0xFFFF;
933      d64ptr++;
934
935     for (h = 0; h < ltm->channels; h++) {
936      for (k = 0; k < ROAR_LTM_MTBITS; k++) {
937       if ( d[5] & (1<<k) ) {
938        switch (1<<k) {
939         case ROAR_LTM_MT_RMS:
940           *d64ptr = ltm->cur[h].rms;
941           ROAR_DBG("req_on_get_stream_para(client=%i, ...): rms=%lli to %p", client, (long long int)*d64ptr, d64ptr);
942          break;
943         default:
944           ROAR_ERR("req_on_get_stream_para(client=%i, ...): client requets unknown MT for LTM: bit %i", client, k);
945        }
946        d64ptr++;
947       }
948      }
949     }
950    }
951
952    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
953
954    roar_mm_free(d);
955
956    for (i = 0; i < needed; i++) {
957     d64[i] = ROAR_HOST2NET64(d64[i]);
958    }
959
960    mes->datalen = needed * 8;
961    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM d64=%p, d64ptr=%p", client, d64, d64ptr);
962    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM final message has %i byte of data", client, (int)mes->datalen);
963    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
964    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM GET_RAW request: OK. returning...", client);
965   break;
966
967  default:
968    ROAR_WARN("req_on_get_stream_para(*): unsupported command: %i", d[1]);
969    return -1;
970 }
971
972 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);
973 mes->cmd = ROAR_CMD_OK;
974 return 0;
975}
976
977int req_on_set_stream_para (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
978 uint16_t * d = (uint16_t *) mes->data;
979 int i;
980
981 if ( mes->datalen < 2*2 )
982  return -1;
983
984 for (i = 0; i < 2; i++) {
985  d[i] = ROAR_NET2HOST16(d[i]);
986 }
987
988 if ( d[0] != 0 )
989  return -1;
990
991 switch (d[1]) {
992  case ROAR_STREAM_PARA_FLAGS:
993    if ( mes->datalen != 2*4 )
994     return -1;
995
996    d[2] = ROAR_NET2HOST16(d[2]);
997    d[3] = ROAR_NET2HOST16(d[3]);
998
999    ROAR_DBG("req_on_set_stream_para(*): request seems to be valid");
1000
1001    if ( d[2] == ROAR_RESET_FLAG ) {
1002     if ( streams_reset_flag(mes->stream, d[3]) == -1 )
1003      return -1;
1004    } else {
1005     if ( streams_set_flag(mes->stream, d[3]) == -1 )
1006      return -1;
1007    }
1008   break;
1009  case ROAR_STREAM_PARA_CHANMAP:
1010    if ( streams_set_map(mes->stream, &(mes->data[4]), mes->datalen - 4) == -1 )
1011     return -1;
1012   break;
1013  case ROAR_STREAM_PARA_ROLE:
1014    if ( mes->datalen != 2*3 )
1015     return -1;
1016
1017    d[2] = ROAR_NET2HOST16(d[2]);
1018
1019    if ( streams_set_role(mes->stream, d[2]) == -1 )
1020     return -1;
1021   break;
1022  case ROAR_STREAM_PARA_LTM:
1023    if ( mes->datalen < (6 * 2) )
1024     return -1;
1025
1026    for (i = 2; i < mes->datalen/2; i++) {
1027     d[i] = ROAR_NET2HOST16(d[i]);
1028    }
1029
1030    if ( mes->stream == -1 ) {
1031     for (i = 6; i < mes->datalen/2; i++)
1032      if ( streams_ltm_ctl(d[i], d[5], d[3], d[2]) == -1 )
1033       return -1;
1034    } else {
1035     if ( streams_ltm_ctl(mes->stream, d[5], d[3], d[2]) == -1 )
1036      return -1;
1037    }
1038   break;
1039  default:
1040    ROAR_WARN("req_on_set_stream_para(*): unsupported command version: %i, %i", d[0], d[1]);
1041    return -1;
1042   break;
1043 }
1044
1045 mes->cmd     = ROAR_CMD_OK;
1046 mes->datalen = 0;
1047
1048 return 0;
1049}
1050
1051int req_on_kick (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1052 struct roar_stream_server * ss;
1053 uint16_t * info = (uint16_t *) mes->data;
1054 int is_stream = 0;
1055
1056 if ( mes->datalen != 4 )
1057  return -1;
1058
1059 info[0] = ROAR_NET2HOST16(info[0]);
1060 info[1] = ROAR_NET2HOST16(info[1]);
1061
1062 switch (info[0]) {
1063  case ROAR_OT_CLIENT:
1064    clients_delete(info[1]);
1065   break;
1066  case ROAR_OT_STREAM:
1067    is_stream = 1;
1068   break;
1069  case ROAR_OT_SOURCE:
1070    if ( streams_get_flag(info[1], ROAR_FLAG_SOURCE) != 1 )
1071     return -1;
1072    is_stream = 1;
1073   break;
1074  case ROAR_OT_OUTPUT:
1075    if ( streams_get(info[1], &ss) == -1 )
1076     return -1;
1077
1078    if ( ss->driver_id == -1 )
1079     return -1;
1080
1081    is_stream = 1;
1082   break;
1083  case ROAR_OT_MIXER:
1084    if ( streams_get(info[1], &ss) == -1 )
1085     return -1;
1086
1087    if ( ROAR_STREAM(ss)->dir != ROAR_DIR_MIXING )
1088     return -1;
1089
1090    is_stream = 1;
1091   break;
1092  case ROAR_OT_BRIDGE:
1093    if ( streams_get(info[1], &ss) == -1 )
1094     return -1;
1095
1096    if ( ROAR_STREAM(ss)->dir != ROAR_DIR_BRIDGE )
1097     return -1;
1098
1099    is_stream = 1;
1100   break;
1101  default:
1102/* TODO: those types should be handled, too:
1103#define ROAR_OT_SAMPLE    4
1104#define ROAR_OT_LISTEN    8
1105#define ROAR_OT_ACTION    9
1106#define ROAR_OT_MSGQUEUE 10
1107#define ROAR_OT_MSGBUS   11
1108*/
1109    return -1;
1110   break;
1111 }
1112
1113 if ( is_stream ) {
1114  if ( streams_get_flag(info[1], ROAR_FLAG_IMMUTABLE) == 1 )
1115   return -1;
1116
1117  streams_delete(info[1]);
1118 }
1119
1120 mes->cmd     = ROAR_CMD_OK;
1121 mes->datalen = 0;
1122
1123 return 0;
1124}
1125
1126int req_on_attach      (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1127 uint16_t * info = (uint16_t *) mes->data;
1128
1129 if ( mes->datalen < 6 )
1130  return -1;
1131
1132 info[0] = ROAR_NET2HOST16(info[0]);
1133 info[1] = ROAR_NET2HOST16(info[1]);
1134 info[2] = ROAR_NET2HOST16(info[2]);
1135
1136 if ( info[0] != 0 )
1137  return -1;
1138
1139 if ( info[1] == ROAR_ATTACH_SIMPLE ) {
1140  if ( client_stream_move(info[2], mes->stream) == -1 )
1141   return -1;
1142 } else {
1143  return -1;
1144 }
1145
1146 mes->cmd     = ROAR_CMD_OK;
1147 mes->datalen = 0;
1148
1149 return 0;
1150}
1151
1152int req_on_set_vol (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1153 struct roar_stream_server * s;
1154 uint16_t * info = (uint16_t *) mes->data;
1155 uint16_t   version;
1156 uint16_t   scale = 65535;
1157 int stream;
1158 int i;
1159 int chans;
1160
1161 ROAR_DBG("req_on_set_vol(*) = ?");
1162 ROAR_DBG("req_on_set_vol(*): mes->datalen=%i", mes->datalen);
1163
1164 if ( mes->datalen < (4*2) )
1165  return -1;
1166
1167 version = ROAR_NET2HOST16(info[0]);
1168 ROAR_DBG("req_on_set_vol(*): version=%i", (int)version);
1169
1170 switch (version) {
1171  case 0:
1172    stream = ROAR_NET2HOST16(info[1]);
1173   break;
1174  case 1:
1175    stream = mes->stream;
1176    scale  = ROAR_NET2HOST16(info[1]);
1177   break;
1178  default:
1179    return -1;
1180   break;
1181 }
1182 ROAR_DBG("req_on_set_vol(*): stream=%i", stream);
1183
1184 if ( scale == 0 )
1185  return -1;
1186
1187 // TODO: change this code.
1188 //       we should not directly change the stream object but use some stream_*()-func
1189 //       for that job.
1190
1191 if ( stream < 0 || stream >= ROAR_STREAMS_MAX )
1192  return -1;
1193
1194 s = g_streams[stream];
1195
1196 if ( s == NULL )
1197  return -1;
1198
1199 ROAR_DBG("req_on_set_vol(*): s=%p", s);
1200
1201 info[2] = ROAR_NET2HOST16(info[2]);
1202
1203 if ( info[2] == ROAR_SET_VOL_ALL ) {
1204  chans = (mes->datalen/2) - 3;
1205  ROAR_DBG("req_on_set_vol(*): mode is ROAR_SET_VOL_ALL, channes=%i", chans);
1206
1207  if ( chans >= ROAR_MAX_CHANNELS )
1208   return -1;
1209
1210  ROAR_DBG("req_on_set_vol(*): mixer at %p", s->mixer.mixer);
1211
1212  for (i = 0; i < chans; i++) {
1213   s->mixer.mixer[i] = ROAR_NET2HOST16(info[i+3]);
1214   ROAR_DBG("req_on_set_vol(*): channel %i: %i", i, ROAR_NET2HOST16(info[i+3]));
1215  }
1216
1217  s->mixer.scale = scale;
1218
1219  ROAR_DBG("req_on_set_vol(*): mixer changed!");
1220
1221 } else if ( info[2] == ROAR_SET_VOL_ONE ) {
1222  ROAR_DBG("req_on_set_vol(*): mode is ROAR_SET_VOL_ONE");
1223  if ( ROAR_NET2HOST16(info[3]) >= ROAR_MAX_CHANNELS )
1224   return -1;
1225
1226  s->mixer.mixer[ROAR_NET2HOST16(info[3])] = ROAR_NET2HOST16(info[4]);
1227
1228  s->mixer.scale = scale;
1229 } else {
1230  return -1;
1231 }
1232
1233 if ( streams_set_mixer(stream) == -1 )
1234  return -1;
1235
1236 mes->cmd     = ROAR_CMD_OK;
1237 mes->datalen = 0;
1238
1239 return 0;
1240}
1241
1242int req_on_get_vol (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1243 uint16_t * info = (uint16_t *) mes->data;
1244 uint16_t   version = -1;
1245 int stream;
1246 struct roar_stream_server * s;
1247 int i;
1248 int chans;
1249
1250 ROAR_DBG("req_on_get_vol(*) = ?");
1251 ROAR_DBG("req_on_get_vol(*): mes->datalen=%i", mes->datalen);
1252
1253 if ( mes->datalen < 2 ) {
1254  return -1;
1255 }
1256
1257 version = ROAR_NET2HOST16(info[0]);
1258
1259 switch (version) {
1260  case 0:
1261    if ( mes->datalen < (2*2) )
1262     return -1;
1263
1264    stream = ROAR_NET2HOST16(info[1]);
1265   break;
1266  case 1:
1267    stream = mes->stream;
1268   break;
1269  default:
1270    return -1;
1271   break;
1272 }
1273
1274 ROAR_DBG("req_on_get_vol(*): stream=%i", stream);
1275
1276 // TODO: change this code.
1277 //       we should not directly change the stream object but use some stream_*()-func
1278 //       for that job.
1279
1280 if ( stream < 0 || stream >= ROAR_STREAMS_MAX )
1281  return -1;
1282
1283 s = g_streams[stream];
1284
1285 if ( s == NULL )
1286  return -1;
1287
1288 ROAR_DBG("req_on_get_vol(*): s=%p", s);
1289
1290 // ok, we have everything
1291
1292 info[0] = ROAR_HOST2NET16(version);
1293
1294 switch (version) {
1295  case 0:
1296    info[1] = ROAR_HOST2NET16(chans = ROAR_STREAM(s)->info.channels);
1297
1298    for (i = 0; i < chans; i++)
1299     info[2+i] = ROAR_HOST2NET16(s->mixer.mixer[i]);
1300
1301     mes->datalen = (2 + chans)*2;
1302   break;
1303  case 1:
1304    info[1] = ROAR_HOST2NET16(chans = ROAR_STREAM(s)->info.channels);
1305    info[2] = ROAR_HOST2NET16(s->mixer.scale);
1306    info[3] = ROAR_HOST2NET16(s->mixer.rpg_mul);
1307    info[4] = ROAR_HOST2NET16(s->mixer.rpg_div);
1308
1309    for (i = 0; i < chans; i++)
1310     info[5+i] = ROAR_HOST2NET16(s->mixer.mixer[i]);
1311
1312     mes->datalen = (5 + chans)*2;
1313   break;
1314  default:
1315    return -1;
1316   break;
1317 }
1318
1319 mes->cmd = ROAR_CMD_OK;
1320
1321 return 0;
1322}
1323
1324int req_on_add_data (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1325 struct roar_buffer * b;
1326 char               * buf;
1327
1328 if ( roar_buffer_new_data(&b, mes->datalen, (void **)&buf) == -1 ) {
1329  ROAR_ERR("req_on_add_data(*): Can not alloc buffer space!");
1330  ROAR_DBG("req_on_add_data(*) = -1");
1331  return -1;
1332 }
1333
1334 if ( data == NULL ) {
1335  memcpy(buf, mes->data, mes->datalen);
1336 } else {
1337  memcpy(buf, *data, mes->datalen);
1338 }
1339
1340 if ( stream_add_buffer(mes->stream, b) == -1 ) {
1341  roar_buffer_free(b);
1342  return -1;
1343 }
1344
1345 mes->cmd     = ROAR_CMD_OK_STOP;
1346 mes->datalen = 0;
1347
1348 return 0;
1349}
1350
1351int req_on_beep        (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1352 struct roar_beep bs;
1353 int16_t * info = (int16_t*)mes->data;
1354 int stream;
1355
1356 memset(&bs, 0, sizeof(bs));
1357
1358 if ( mes->datalen > 0 ) {
1359  if ( mes->datalen < 2 )
1360   return -1;
1361
1362  if ( ROAR_NET2HOST16(info[0]) != 0 ) /* version */
1363   return -1;
1364
1365  if ( mes->datalen != 8*2 )
1366   return -1;
1367
1368  bs.vol  = ROAR_NET2HOST16(info[1]);
1369  bs.time = ROAR_NET2HOST16(info[2]);
1370  bs.freq = ROAR_NET2HOST16(info[3]);
1371  bs.type = ROAR_NET2HOST16(info[4]);
1372  bs.x    = ROAR_NET2HOST16(info[5]);
1373  bs.y    = ROAR_NET2HOST16(info[6]);
1374  bs.z    = ROAR_NET2HOST16(info[7]);
1375 }
1376
1377 if ( (stream = beep_start(client, &bs)) == -1 )
1378  return -1;
1379
1380 mes->stream  = stream;
1381 mes->cmd     = ROAR_CMD_OK_STOP;
1382 mes->datalen = 0;
1383
1384 return 0;
1385}
1386
1387int req_on_wait        (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1388 uint16_t * u16 = (uint16_t*)mes->data;
1389 struct roar_event events[4];
1390 size_t left, tmp;
1391 size_t num = 0;
1392 void * vp = mes->data;
1393
1394 vp += 4;
1395
1396 // check for complet header...
1397 if ( mes->datalen < 4 )
1398  return -1;
1399
1400 u16[0] = ROAR_NET2HOST16(u16[0]);
1401 u16[1] = ROAR_NET2HOST16(u16[1]);
1402
1403 // do we support version and flags?
1404 if ( u16[0] != 0 || u16[1] != 0 )
1405  return -1;
1406
1407 memset(events, 0, sizeof(events));
1408
1409 left = mes->datalen - 4;
1410
1411 while (left) {
1412  tmp = left;
1413  if ( roar_event_from_blob(&(events[num]), vp, &tmp) == -1 )
1414   return -1;
1415
1416  vp   += tmp;
1417  left -= tmp;
1418  num++;
1419 }
1420
1421 if ( clients_wait(client, events, num) == -1 )
1422  return -1;
1423
1424 flags[1] |= COMMAND_FLAG_OUT_NOSEND;
1425
1426 return 0;
1427}
1428
1429//ll
Note: See TracBrowser for help on using the repository browser.