source: roaraudio/roard/req.c @ 6020:11e65673ee8c

Last change on this file since 6020:11e65673ee8c was 6020:11e65673ee8c, checked in by phi, 10 years ago

a little cleanup and some preparing for v1 CON_STREAM messages

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