source: roaraudio/roard/req.c @ 5959:b568f7b84e08

Last change on this file since 5959:b568f7b84e08 was 5959:b568f7b84e08, checked in by phi, 10 years ago

Also use uname() and hostid for seeding nonce generator.

File size: 46.7 KB
RevLine 
[668]1//req.c:
[486]2
[668]3/*
[5823]4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2013
[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;
459 int    type;
460 int    fh;
461 int    len;
462
463 if ( mes->datalen < 4 )
464  return -1;
465
466 if ( *(mes->data) != 0 )
467  return -1;
468
[80]469 if ( mes->datalen > 80 ) // we do not support long messages here
470  return -1;
471
[77]472 type = (unsigned)mes->data[1];
[79]473 port = ROAR_NET2HOST16(((uint16_t*)mes->data)[1]);
[77]474
[80]475 len = mes->datalen - 4;
[77]476
[84]477 strncpy(host, &(mes->data[4]), len);
[77]478 host[len] = 0;
479
480 if ( type > ROAR_SOCKET_TYPE_MAX )
481  return -1;
482
483 if ( type == ROAR_SOCKET_TYPE_FILE ) // disabled because of security resons
484  return -1;
485
486 if ( type == ROAR_SOCKET_TYPE_FORK ) // why should we connect to ourself?
487  return -1;
488
[525]489 ROAR_DBG("req_on_con_stream(*): CONNECT(type=%i, host='%s', port=%i)", type, host, port);
490
[5164]491 roar_libroar_nowarn();
492 fh = roar_socket_open(ROAR_SOCKET_MODE_CONNECT, type, host, port);
493 roar_libroar_warn();
494
495 if ( fh == -1 )
[77]496  return -1;
497
[78]498 if ( client_stream_set_fh(client, mes->stream, fh) == -1 ) {
499  close(fh);
500  return 1;
501 }
502
[757]503 mes->datalen = 0;
504 mes->cmd     = ROAR_CMD_OK;
505
[78]506 return 0;
[757]507}
508
[3926]509int req_on_passfh      (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
[3714]510 int sock = clients_get_fh(client);
[3720]511 int16_t * d = (int16_t*)mes->data;
[3732]512 struct roard_listen * lsock;
513 int listening;
[757]514 int fh;
[3714]515 int i;
[757]516
[4236]517 ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...) = ?", client, mes->stream);
518
[4255]519 if ( (fh = roar_socket_recv_fh(sock, NULL, NULL)) == -1 ) {
520  ROAR_WARN("req_on_passfh(client=%i, mes={stream=%i,...},...): was unabled to get filehandle from remote end. bad.", client, mes->stream);
521  ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): returning (ERROR)...", client, mes->stream);
[757]522  return -1;
[4255]523 }
[757]524
[4236]525 ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): fh=%i", client, mes->stream, fh);
526
[3723]527 if ( mes->stream != -1 ) { // stream pass:
[4236]528  ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): This is a stream passfh", client, mes->stream);
529
[3714]530  if ( client_stream_set_fh(client, mes->stream, fh) == -1 ) {
531   close(fh);
[4236]532   ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): returning (ERROR)...", client, mes->stream);
[4235]533   return -1;
[3714]534  }
535
[4236]536  ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): returning (OK)...", client, mes->stream);
537
[3714]538  mes->datalen = 0;
539  mes->cmd     = ROAR_CMD_OK;
540
541  return 0;
[757]542 }
543
[3714]544// non-stream pass:
545
[4236]546 ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): This is a client passfh", client, mes->stream);
547
[3714]548/*
[3745]549 0: Version,   16
550 1: Flags,     16
551 2: Protocol,  16
552 3: Byteorder, 16
[3714]553 Options...
554*/
555
556 if ( mes->datalen < 4*2 )
557  return -1;
558
559 for (i = 0; i < 4; i++) {
560  d[i] = ROAR_NET2HOST16(d[i]);
561 }
562
563 if ( d[0] != 0 ) // version
564  return -1;
565
[3732]566 listening = d[1] & ROAR_CLIENTPASS_FLAG_LISTEN;
567
568 if ( listening )
569  d[1] -= ROAR_CLIENTPASS_FLAG_LISTEN;
570
[3714]571 if ( d[1] != 0 ) // flags
572  return -1;
573
[3732]574 if ( listening ) {
[3734]575  if ( get_listen(&lsock, NULL) == -1 ) {
576   close(fh);
[3732]577   return -1;
[3734]578  }
[3714]579
[3802]580  roar_vio_open_fh_socket(&(lsock->sock), fh);
581  lsock->used   = 1;
[3732]582  lsock->proto  = d[2];
583 } else {
[3737]584  if ( clients_new_from_fh(fh, d[2], d[3], 1) == -1 )
[3732]585   return -1;
[3729]586 }
587
[4236]588 ROAR_DBG("req_on_passfh(client=%i, mes={stream=%i,...},...): returning (OK)...", client, mes->stream);
589
[78]590 mes->datalen = 0;
591 mes->cmd     = ROAR_CMD_OK;
[757]592
[3720]593 return 0;
[77]594}
595
[1493]596#ifdef ROAR_SUPPORT_META
[3926]597int req_on_set_meta    (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
[92]598 int type;
599 int mode;
600 int namelen, vallen;
[99]601 char   val[255+1];
[92]602 char   name[ROAR_META_MAX_NAMELEN+1];
603
604 if ( mes->datalen < 3 )
605  return -1;
606
607 if ( mes->data[0] != 0 ) // version
608  return -1;
609
610 mode = (unsigned) mes->data[1];
611 type = (unsigned) mes->data[2];
612
[99]613 ROAR_DBG("req_on_set_meta(*): mode=%i, type=%i", mode, type);
614
[92]615 if ( mode == ROAR_META_MODE_CLEAR ) {
616  stream_meta_clear(mes->stream);
617  mes->datalen = 0;
618  mes->cmd     = ROAR_CMD_OK;
619  return 0;
620 } else if ( mode == ROAR_META_MODE_DELETE ) { // unsuppoerted at the moment
[1038]621  return -1;
622 } else if ( mode == ROAR_META_MODE_FINALIZE ) {
623  stream_meta_finalize(mes->stream);
624  mes->datalen = 0;
625  mes->cmd     = ROAR_CMD_OK;
626  return 0;
[92]627 } else if ( mode == ROAR_META_MODE_SET || mode == ROAR_META_MODE_ADD ) {
628  if ( mes->datalen < 5 )
629   return -1;
630
631  namelen = (unsigned) mes->data[3];
632  vallen  = (unsigned) mes->data[4];
633
[99]634  ROAR_DBG("req_on_set_meta(*): namelen=%i, vallen=%i", namelen, vallen);
635
[92]636  if ( mes->datalen < (5 + namelen + vallen) )
637   return -1;
638
639  if ( namelen > ROAR_META_MAX_NAMELEN )
640   return -1;
641
642  strncpy(name, &(mes->data[5]), namelen);
643  name[namelen] = 0;
644
[99]645  if ( vallen > 255 )
[92]646   return -1;
647
648  strncpy(val, &(mes->data[5+namelen]), vallen);
649  val[vallen] = 0;
650
651  if ( mode == ROAR_META_MODE_SET ) {
652   if ( stream_meta_set(mes->stream, type, name, val) == -1 )
653    return -1;
654  } else {
655   if ( stream_meta_add(mes->stream, type, name, val) == -1 )
656    return -1;
657  }
658
659  mes->datalen = 0;
660  mes->cmd     = ROAR_CMD_OK;
661  return 0;
662 } else { // unknown mode!
663  return -1;
664 }
665
[0]666 return -1;
667}
668
[3926]669int req_on_get_meta    (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
[101]670 int vallen;
671 int type;
[107]672 char val[LIBROAR_BUFFER_MSGDATA-1];
[101]673
674 if ( mes->datalen != 2 )
675  return -1;
676
677 if ( mes->data[0] != 0 ) // version
678  return -1;
679
680 type = (unsigned) mes->data[1];
681
682 if ( stream_meta_get(mes->stream, type, NULL, val, LIBROAR_BUFFER_MSGDATA-2) == -1 )
683  return -1;
684
685 vallen = strlen(val);
686
687 mes->cmd     = ROAR_CMD_OK;
688 mes->datalen = 2 + vallen;
689
690 mes->data[0] = 0;
691 mes->data[1] = (unsigned char) vallen;
692
[107]693 val[vallen] = 0;
694
695 strncpy(&(mes->data[2]), val, vallen+1);
[101]696
697 return 0;
[100]698}
[0]699
[3926]700int req_on_list_meta   (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
[113]701 int i;
702 int len = 0;
703 int types[ROAR_META_MAX_PER_STREAM];
704
705 if ( mes->datalen != 1 )
706  return -1;
707
708 if ( mes->data[0] != 0 ) // version
709  return -1;
710
711 if ( (len = stream_meta_list(mes->stream, types, ROAR_META_MAX_PER_STREAM)) == -1 )
712  return -1;
713
714 mes->cmd     = ROAR_CMD_OK;
715 mes->datalen = 1 + len;
716 mes->data[0] = 0;
717
718 for (i = 0; i < len; i++)
719  mes->data[i+1] = types[i];
720
721 return 0;
722}
[1493]723#endif
[113]724
[5031]725int req_on_gettimeofday (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
726 struct roar_time curtime;
727
728 ROAR_DBG("req_on_gettimeofday(client=%i, mes=%p, data=%p, flags=%p) = ?", client, mes, data, flags);
729
730 if ( *data != NULL ) {
731  return -1;
732 }
733
734 ROAR_DBG("req_on_gettimeofday(client=%i, mes=%p, data=%p, flags=%p) = ?", client, mes, data, flags);
735
736 if ( mes->datalen && mes->datalen < 8 ) {
737  return -1;
738 }
739
740 ROAR_DBG("req_on_gettimeofday(client=%i, mes=%p, data=%p, flags=%p) = ?", client, mes, data, flags);
741
742 if ( mes->datalen >= 8 ) {
743  if ( *(uint64_t *)mes->data != 0 ) {
744   return -1;
745  }
746 }
747
748 ROAR_DBG("req_on_gettimeofday(client=%i, mes=%p, data=%p, flags=%p) = ?", client, mes, data, flags);
749
[5065]750 if ( roar_clock_gettime(&curtime, ROAR_CLOCK_REALTIME) == -1 )
[5031]751  return -1;
752
753 if ( roar_time_to_msg(mes, &curtime) == -1 )
754  return -1;
755
756 mes->cmd = ROAR_CMD_OK;
757
758 ROAR_DBG("req_on_gettimeofday(client=%i, mes=%p, data=%p, flags=%p) = ?", client, mes, data, flags);
759
760 return 0;
761}
762
[4431]763int req_on_server_info (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
[4438]764#ifdef ROAR_HAVE_UNAME
765 struct utsname utsname;
766#endif
[4695]767#ifdef ROAR_HAVE_GETVERSIONEX
768 OSVERSIONINFO osinfo;
769 char buf_release[80];
770#endif
[4431]771 struct roar_server_info info;
772 uint16_t * d16;
[5279]773#ifdef ROAR_HAVE_GETHOSTID
774 long hostid;
775 char hostidbuf[64];
776#endif
[4431]777
778 if ( mes->datalen != 4 )
779  return -1;
780
781 d16 = (uint16_t*)mes->data;
782
783 // check version.
784 if ( ROAR_NET2HOST16(d16[0]) != 0 )
785  return -1;
786
787 switch (ROAR_NET2HOST16(d16[1])) {
788  case ROAR_IT_SERVER:
789   memset(&info, 0, sizeof(info));
790
[4652]791   // the following if is optimized out by compiler.
[5825]792   if ( ROAR_VERSION_DISTRIBUTION_STRING[0] == 0 ) {
793    info.version = "roard/" ROAR_VERSION_STRING " <" ROAR_DEV_VENDOR_STRING ">";
[4652]794   } else {
[5825]795    info.version = "roard/" ROAR_VERSION_STRING " <" ROAR_DEV_VENDOR_STRING "> (" ROAR_VERSION_DISTRIBUTION_STRING ")";
[4652]796   }
[4442]797
[5379]798   info.build   = ROAR_BUILD_STAMP;
[5370]799   info.license = ROAR_LICENSE_GPLv3_0;
[5279]800
801#ifdef ROAR_HAVE_GETHOSTID
802   hostid = gethostid();
803   snprintf(hostidbuf, sizeof(hostidbuf), sizeof(long) == 8 ? "0x%.16lx" : "0x%.8lx", hostid);
804   info.hostid = hostidbuf;
805#endif
806
[4442]807   if ( !!strcmp(g_config->location, CONF_DEF_STRING) )
808    info.location = g_config->location;
809
810   if ( !!strcmp(g_config->description, CONF_DEF_STRING) )
[5279]811    info.description = g_config->description;
812
813   info.contact = g_config->contact;
814   info.serial  = g_config->serial;
815   info.uiurl   = g_config->uiurl;
[4431]816
[4438]817#ifdef ROAR_HAVE_UNAME
818   if ( uname(&utsname) == 0 ) {
[5959]819    roar_random_salt_nonce(&utsname, sizeof(utsname));
[4438]820    info.un.sysname  = utsname.sysname;
821    info.un.release  = utsname.release;
822    info.un.nodename = utsname.nodename;
823    info.un.machine  = utsname.machine;
824   }
825#endif
[4695]826#ifdef ROAR_HAVE_GETVERSIONEX
827   osinfo.dwOSVersionInfoSize = sizeof(osinfo);
828   if ( GetVersionEx(&osinfo) ) {
829    info.un.sysname = "Windows";
830    snprintf(buf_release, sizeof(buf_release), "%i.%i.%i",
[4780]831               (int)osinfo.dwMajorVersion, (int)osinfo.dwMinorVersion, (int)osinfo.dwBuildNumber);
[4695]832    buf_release[sizeof(buf_release)-1] = 0;
833    info.un.release = buf_release;
834   }
835#endif
[4438]836
[4441]837   *data = NULL;
838
[4521]839   if ( roar_server_info_to_mes(mes, &info, (void**)data) == -1 )
[4431]840    return -1;
[4441]841
842   if ( *data != NULL )
843    flags[1] |= COMMAND_FLAG_OUT_LONGDATA;
[4431]844  break;
845  default: /* unknown request */
846    return -1;
847   break;
848 }
849
850 mes->cmd = ROAR_CMD_OK;
851
852 return 0;
853}
854
[3926]855int req_on_server_oinfo    (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
[0]856 struct roar_stream s;
[4614]857 int dir = ROAR_DIR_PLAY;
858 int subsys;
[0]859//ROAR_DIR_OUTPUT
860
[4614]861 if ( mes->datalen != 0 ) {
862  if ( mes->datalen != 2 )
863   return -1;
864
865  if ( mes->data[0] != 0 )
866   return -1;
867
868  dir = mes->data[1];
869 }
870
871 subsys = streams_dir2subsys(dir);
872
[966]873 memset(&s, 0, sizeof(struct roar_stream));
[964]874
[977]875 s.dir           = ROAR_DIR_MIXING;
[0]876 s.pos_rel_id    = -1;
[4614]877
878 switch (subsys) {
879  case ROAR_SUBSYS_WAVEFORM:
880    s.info.rate     = g_sa->rate;
881    s.info.bits     = g_sa->bits;
882    s.info.channels = g_sa->channels;
883    s.info.codec    = g_sa->codec;
884    s.pos           = g_pos;
885   break;
886#ifndef ROAR_WITHOUT_DCOMP_MIDI
887  case ROAR_SUBSYS_MIDI:
888   break;
889#endif
890#ifndef ROAR_WITHOUT_DCOMP_LIGHT
891  case ROAR_SUBSYS_LIGHT:
892    s.info.rate     = ROAR_OUTPUT_CFREQ;
893    s.info.bits     = ROAR_LIGHT_BITS;
894    s.info.channels = g_light_state.channels;
895   break;
896#endif
897#ifndef ROAR_WITHOUT_DCOMP_RAW
898  case ROAR_SUBSYS_RAW:
899    // no need to set anything here.
900   break;
901#endif
902#ifndef ROAR_WITHOUT_DCOMP_RDTCS
903  case ROAR_SUBSYS_RDTCS:
904    s.info.rate     = ROAR_OUTPUT_CFREQ;
905    s.info.bits     = ROAR_RDTCS_BITS;
906    s.info.channels = ROAR_RDTCS_CHANNELS;
907    s.info.codec    = ROAR_RDTCS_CODEC;
908   break;
909#endif
910  default:
911    return -1;
912   break;
913 }
[0]914
915 if ( roar_stream_s2m(&s, mes) == -1 )
916  return -1;
917
918 mes->cmd = ROAR_CMD_OK;
919
920 return 0;
921}
922
[4500]923int req_on_caps        (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
924 struct roar_caps caps;
925 struct roar_stds * stds;
926 size_t i;
927
928 if ( roar_caps_from_msg(&caps, mes, *data) == -1 )
929  return -1;
930
931 // handle the data from the caps command here...
932
933 if ( !(caps.flags & ROAR_CF_REQUEST) ) {
934  mes->cmd = ROAR_CMD_OK;
935  mes->datalen = 0;
936  return 0;
937 }
938
939 mes->datalen = 0;
940
941 switch (caps.type) {
942  case ROAR_CT_STANDARDS:
[4505]943    if ( (stds = roar_stds_new(g_caps_stds.stds_len)) == NULL )
[4500]944     return -1;
945
946    for ( i = 0; i < stds->stds_len; i++) {
[4505]947     stds->stds[i] = ROAR_HOST2NET32(g_caps_stds.stds[i]);
[4500]948    }
949
950    caps.data = stds->stds;
951    caps.len  = stds->stds_len * 4;
952    // TODO: add support for **data.
953    if ( roar_caps_to_msg(mes, &caps, NULL) == -1 ) {
954     roar_stds_free(stds);
955     return -1;
956    }
957    roar_stds_free(stds);
958   break;
959  default:
960    return -1;
961   break;
962 }
963
964 mes->cmd = ROAR_CMD_OK;
965
966 return 0;
967}
[0]968
[3926]969int req_on_get_standby (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
[3741]970 mes->cmd     = ROAR_CMD_OK;
971 mes->pos     = g_pos;
[0]972 mes->datalen = 2;
973
974 *((uint16_t*)mes->data) = ROAR_HOST2NET16((unsigned) g_standby);
975
976 return 0;
977}
978
[3926]979int req_on_set_standby (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
[0]980 if ( mes->datalen != 2 )
981  return -1;
982
983 g_standby = ROAR_NET2HOST16(*((uint16_t*)mes->data));
984
985 mes->cmd     = ROAR_CMD_OK;
[3741]986 mes->pos     = g_pos;
[0]987 mes->datalen = 0;
988
989 return 0;
990}
991
[3926]992int req_on_exit      (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
[575]993 int term = 0;
994
995 if ( mes->datalen == 1 )
996  term = mes->data[0];
997
[0]998 mes->cmd     = ROAR_CMD_OK;
[3741]999 mes->pos     = g_pos;
[0]1000 mes->datalen = 0;
1001
[576]1002 ROAR_DBG("req_on_exit(*): term=%i", term);
1003
[575]1004 if ( term ) {
1005  cleanup_listen_socket(1);
1006 } else {
1007  alive = 0;
1008 }
[0]1009
1010 return 0;
1011}
1012
[3926]1013int req_on_list_clients(int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
[0]1014 unsigned char filter, cmp;
1015 uint32_t id;
1016 int clients[ROAR_CLIENTS_MAX];
1017 int i, c = 0;
1018
1019 if ( roar_ctl_m2f(mes, &filter, &cmp, &id) == -1 )
1020  return -1;
1021
1022 // TODO: add code to support filter
1023 if ( filter != ROAR_CTL_FILTER_ANY )
1024  return -1;
1025
1026 for (i = 0; i < ROAR_CLIENTS_MAX; i++) {
1027  if ( g_clients[i] != NULL ) {
1028   clients[c++] = i;
1029  }
1030 }
1031
1032 roar_ctl_ia2m(mes, clients, c);
1033
1034 mes->cmd = ROAR_CMD_OK;
1035
1036 return 0;
1037}
[3926]1038int req_on_list_streams(int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
[0]1039 unsigned char filter, cmp;
1040 uint32_t id;
1041 int streams[ROAR_STREAMS_MAX];
1042 int i, c = 0;
[4333]1043 int match;
[0]1044
1045 if ( roar_ctl_m2f(mes, &filter, &cmp, &id) == -1 )
1046  return -1;
1047
[4333]1048 for (i = 0; i < ROAR_STREAMS_MAX; i++) {
1049  if ( g_streams[i] == NULL )
1050   continue;
1051
1052  match = 0;
[0]1053
[4333]1054  switch (filter) {
1055   case ROAR_CTL_FILTER_ANY:
1056     match = 1;
1057    break;
1058   case ROAR_CTL_FILTER_DIR:
1059     match = roar_filter_match(cmp, id, ROAR_STREAM(g_streams[i])->dir);
1060    break;
1061   default: // unsupported filter...
1062     return -1;
1063    break;
1064  }
1065
1066  if ( match )
[0]1067   streams[c++] = i;
1068 }
1069
1070 roar_ctl_ia2m(mes, streams, c);
1071
1072 mes->cmd = ROAR_CMD_OK;
1073
1074 return 0;
1075}
1076
[3926]1077int req_on_get_client  (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
[0]1078 struct roar_client * c;
[5608]1079 int ret;
[0]1080
1081 if ( mes->datalen != 1 )
1082  return -1;
1083
[5608]1084 if ( *data != NULL )
1085  roar_mm_free(*data);
1086 *data = NULL;
1087
[0]1088 if ( clients_get(mes->data[0], &c) == -1 )
1089  return -1;
1090
1091 mes->cmd = ROAR_CMD_OK;
1092
[5826]1093 ret = roar_ctl_c2m2(mes, c, (void**)data);
[5608]1094
1095 if ( *data != NULL )
1096  flags[1] |= COMMAND_FLAG_OUT_LONGDATA;
1097
1098 return ret;
[0]1099}
1100
[3926]1101int req_on_get_stream  (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
[0]1102 struct roar_stream_server * s;
1103
1104 if ( mes->datalen != 1 )
1105  return -1;
1106
1107 if ( streams_get(mes->data[0], &s) == -1 )
1108  return -1;
1109
1110 mes->cmd = ROAR_CMD_OK;
[465]1111 mes->stream = mes->data[0];
[0]1112
1113 return roar_stream_s2m(ROAR_STREAM(s), mes);
1114}
1115
[3926]1116int req_on_get_stream_para (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
[465]1117 struct roar_stream * s;
[963]1118 struct roar_stream_server * ss;
[465]1119 struct roar_audio_info * audio_info;
[4277]1120 struct roar_stream_ltm * ltm;
[5624]1121 struct roar_stream_rpg   rpg;
[4277]1122 uint16_t * d  = (uint16_t *) mes->data;
1123 int64_t * d64 = ( int64_t *) mes->data;
1124 int64_t * d64ptr;
1125 int i, h, k;
[1842]1126 char * str;
[4277]1127 size_t needed;
1128 int test, bits;
[465]1129
[4279]1130 ROAR_DBG("req_on_get_stream_para(client=%i, mes=%p{.stream=%i, .datalen=%i,...}, data=%p, flags=%p) = ?", client, mes, (int)mes->stream, (int)mes->datalen, data, flags);
1131
[4280]1132 if ( mes->datalen < 4 )
[465]1133  return -1;
1134
[4281]1135 for (i = 0; i < 2; i++) {
[465]1136  d[i] = ROAR_NET2HOST16(d[i]);
1137 }
1138
[1842]1139 if ( d[0] != 0 ) {
[4066]1140  ROAR_WARN("req_on_get_stream_para(*): unsupported command version: %i, %i", (int)d[0], (int)d[1]);
[465]1141  return -1;
1142 }
1143
[1842]1144 switch (d[1]) {
1145  case ROAR_STREAM_PARA_INFO:
1146    if ( streams_get(mes->stream, &ss) == -1 ) {
1147     ROAR_WARN("req_on_get_stream_para(*): request on non existing (or other error?) stream %i", mes->stream);
1148     return -1;
1149    }
1150
1151    if ( streams_calc_delay(mes->stream) == -1 ) {
1152     ROAR_WARN("req_on_get_stream_para(*): can not calc delay for stream %i", mes->stream);
1153    }
1154
1155    s = ROAR_STREAM(ss);
[465]1156
[1842]1157    audio_info = &(s->info);
1158
[3630]1159    mes->datalen = 2*12;
[1842]1160
[3213]1161    d[ 2] = ROAR_OUTPUT_CALC_OUTBUFSIZE(audio_info);
1162    d[ 3] = ss->pre_underruns;
1163    d[ 4] = ss->post_underruns;
1164    d[ 5] = ss->codec_orgi;
1165    d[ 6] = (ss->flags & 0xFFFF) | (ss->primary ? ROAR_FLAG_PRIMARY : 0) | (ss->driver_id != -1 ? ROAR_FLAG_OUTPUT : 0);
1166    d[ 7] = ss->delay/1000;
1167    d[ 8] = ss->state;
1168    d[ 9] = (ss->flags & 0xFFFF0000) >> 16;
1169    d[10] = ss->mixer_stream;
[3630]1170    d[11] = ss->role;
[1842]1171
1172    ROAR_DBG("req_on_get_stream_para(*): ss->driver_id=%i", ss->driver_id);
1173
1174    ROAR_DBG("req_on_get_stream_para(*): delay=%i, send delay=%i", ss->delay, d[7]);
[465]1175
[1842]1176    for (i = 0; i < mes->datalen/2; i++) {
1177     d[i] = ROAR_HOST2NET16(d[i]);
1178    }
[1156]1179
[1842]1180    mes->pos = s->pos;
1181   break;
1182
1183  case ROAR_STREAM_PARA_NAME:
1184   str = streams_get_name(mes->stream);
1185
1186   if ( str == NULL )
1187    return -1;
[1151]1188
[1842]1189    mes->datalen = 4 + strlen(str);
1190
1191    if ( mes->datalen > LIBROAR_BUFFER_MSGDATA )
1192     return -1;
1193
1194    strncpy(((char*)&(mes->data))+4, str, mes->datalen);
1195
1196    d[0] = ROAR_HOST2NET16(d[0]);
1197    d[1] = ROAR_HOST2NET16(d[1]);
1198   break;
1199
[3539]1200  case ROAR_STREAM_PARA_CHANMAP:
1201    if ( streams_get(mes->stream, &ss) == -1 ) {
1202     ROAR_WARN("req_on_get_stream_para(*): request on non existing (or other error?) stream %i", mes->stream);
1203     return -1;
1204    }
1205
1206    s = ROAR_STREAM(ss);
1207
1208    memcpy(&(mes->data[4]), ss->chanmap.in, s->info.channels);
1209    mes->datalen = 2*2 + s->info.channels;
1210
1211    d[0] = ROAR_HOST2NET16(d[0]);
1212    d[1] = ROAR_HOST2NET16(d[1]);
1213   break;
1214
[4277]1215  case ROAR_STREAM_PARA_LTM:
[4279]1216    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM request...", client);
1217
[4281]1218    if ( mes->datalen < (6 * 2) ) {
1219     ROAR_ERR("req_on_get_stream_para(client=%i, ...): LTM request of client is corruped: message too short", client);
[4277]1220     return -1;
[4281]1221    }
[4277]1222
1223    for (i = 2; i < mes->datalen/2; i++) {
1224     d[i] = ROAR_NET2HOST16(d[i]);
1225    }
1226
[4281]1227    if ( d[2] != ROAR_LTM_SST_GET_RAW ) {
1228     ROAR_ERR("req_on_get_stream_para(client=%i, ...): LTM request of client is corruped: unknown LTM subtype: %i", client, (int)d[2]);
[4277]1229     return -1;
[4281]1230    }
[4277]1231
[4279]1232    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM request of type GET_RAW", client);
1233
[4277]1234    test = d[5];
1235    bits = 0;
1236    while (test) {
1237     if ( test & 0x1 )
1238      bits++;
1239
1240     test >>= 1;
1241    }
1242
1243    needed = 0;
1244
1245    if ( mes->stream == -1 ) {
[4279]1246     ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM multi-stream request...", client);
1247
[4277]1248     for (i = 6; i < mes->datalen/2; i++) {
[4289]1249      if ( (ltm = streams_ltm_get(d[i], d[5], d[3])) == NULL )
[4277]1250       return -1;
1251
1252      needed += ltm->channels;
1253     }
1254    } else {
[4279]1255     ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM single-stream request for stream %i...", client, mes->stream);
[4289]1256     if ( (ltm = streams_ltm_get(mes->stream, d[5], d[3])) == NULL )
[4277]1257      return -1;
1258
1259     needed = ltm->channels;
1260    }
1261
1262    needed *= bits;
1263
1264    needed += mes->stream == -1 ? (mes->datalen/2) - 6 : 1;
1265
[4279]1266    ROAR_DBG("req_on_get_stream_para(client=%i, ...): data size for answer is %i 64 bit sub-packets", client, (int)needed);
1267
[4298]1268    ROAR_DBG("req_on_get_stream_para(client=%i, ...): mes->datalen=%i, data=%p{%p}", client, (int)mes->datalen, data, *data);
1269    d64 = _dataspace(mes, data, flags, needed * 8);
1270    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
[4277]1271
1272    if ( (d = roar_mm_malloc(mes->datalen)) == NULL )
1273     return -1;
1274
[4298]1275    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d=%p, data=%p{%p}", client, d, data, *data);
1276
1277
1278    ROAR_DBG("req_on_get_stream_para(client=%i, ...): mes->datalen=%i, data=%p{%p}", client, (int)mes->datalen, data, *data);
1279    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
[4277]1280    memcpy(d, mes->data, mes->datalen);
[4298]1281    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
[4277]1282
[4291]1283    d64ptr = d64;
[4277]1284
[4298]1285    ROAR_DBG("req_on_get_stream_para(client=%i, ...): mes->datalen=%i, data=%p{%p}", client, (int)mes->datalen, data, *data);
1286    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1287
[4277]1288    if ( mes->stream == -1 ) {
1289     for (i = 6; i < mes->datalen/2; i++) {
[4298]1290      ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1291
[4289]1292      if ( (ltm = streams_ltm_get(d[i], d[5], d[3])) == NULL )
[4277]1293       return -1;
1294
1295      *d64ptr = ltm->channels & 0xFFFF;
1296       d64ptr++;
1297
1298      for (h = 0; h < ltm->channels; h++) {
1299       for (k = 0; k < ROAR_LTM_MTBITS; k++) {
1300        if ( d[5] & (1<<k) ) {
1301         switch (1<<k) {
1302          case ROAR_LTM_MT_RMS:
1303            *d64ptr = ltm->cur[h].rms;
1304           break;
1305          default:
1306            ROAR_ERR("req_on_get_stream_para(client=%i, ...): client requets unknown MT for LTM: bit %i", client, k);
1307         }
1308         d64ptr++;
1309        }
1310       }
1311      }
1312     }
1313    } else {
[4289]1314     if ( (ltm = streams_ltm_get(mes->stream, d[5], d[3])) == NULL )
[4277]1315      return -1;
1316
1317     *d64ptr = ltm->channels & 0xFFFF;
1318      d64ptr++;
1319
1320     for (h = 0; h < ltm->channels; h++) {
1321      for (k = 0; k < ROAR_LTM_MTBITS; k++) {
1322       if ( d[5] & (1<<k) ) {
1323        switch (1<<k) {
1324         case ROAR_LTM_MT_RMS:
1325           *d64ptr = ltm->cur[h].rms;
[4287]1326           ROAR_DBG("req_on_get_stream_para(client=%i, ...): rms=%lli to %p", client, (long long int)*d64ptr, d64ptr);
[4277]1327          break;
1328         default:
1329           ROAR_ERR("req_on_get_stream_para(client=%i, ...): client requets unknown MT for LTM: bit %i", client, k);
1330        }
1331        d64ptr++;
1332       }
1333      }
1334     }
1335    }
1336
[4298]1337    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
1338
[4277]1339    roar_mm_free(d);
1340
1341    for (i = 0; i < needed; i++) {
1342     d64[i] = ROAR_HOST2NET64(d64[i]);
1343    }
1344
1345    mes->datalen = needed * 8;
[4283]1346    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM d64=%p, d64ptr=%p", client, d64, d64ptr);
[4279]1347    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM final message has %i byte of data", client, (int)mes->datalen);
[4298]1348    ROAR_DBG("req_on_get_stream_para(client=%i, ...): d64=%p, data=%p{%p}", client, d64, data, *data);
[4279]1349    ROAR_DBG("req_on_get_stream_para(client=%i, ...): LTM GET_RAW request: OK. returning...", client);
[4277]1350   break;
1351
[5624]1352  case ROAR_STREAM_PARA_RPG:
1353    if ( streams_get_rpg(mes->stream, &rpg) == -1 ) {
1354     return -1;
1355    }
1356
1357    mes->datalen = 2*5;
1358
1359    d[2] = rpg.mode;
1360    d[3] = rpg.mul;
1361    d[4] = rpg.div;
1362
1363    for (i = 0; i < mes->datalen/2; i++) {
1364     d[i] = ROAR_HOST2NET16(d[i]);
1365    }
1366   break;
1367
[1842]1368  default:
1369    ROAR_WARN("req_on_get_stream_para(*): unsupported command: %i", d[1]);
1370    return -1;
[465]1371 }
1372
[4279]1373 ROAR_DBG("req_on_get_stream_para(client=%i, mes=%p{.stream=%i, .datalen=%i,...}, data=%p, flags=%p) = 0 // returning OK", client, mes, (int)mes->stream, (int)mes->datalen, data, flags);
[465]1374 mes->cmd = ROAR_CMD_OK;
1375 return 0;
1376}
1377
[3926]1378int req_on_set_stream_para (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
[4552]1379 struct roar_stream_server * ss;
[5624]1380 struct roar_stream_rpg rpg;
[1043]1381 uint16_t * d = (uint16_t *) mes->data;
[4552]1382 uint32_t tmp, tmp2, flagstore;
1383 int protect = 0;
[1043]1384 int i;
1385
[3542]1386 if ( mes->datalen < 2*2 )
[1043]1387  return -1;
1388
[3542]1389 for (i = 0; i < 2; i++) {
[1043]1390  d[i] = ROAR_NET2HOST16(d[i]);
1391 }
1392
[3542]1393 if ( d[0] != 0 )
[1043]1394  return -1;
[3542]1395
1396 switch (d[1]) {
1397  case ROAR_STREAM_PARA_FLAGS:
[4538]1398    if ( mes->datalen != 2*4 && mes->datalen != 2*5 )
[3542]1399     return -1;
1400
1401    d[2] = ROAR_NET2HOST16(d[2]);
1402    d[3] = ROAR_NET2HOST16(d[3]);
1403
1404    ROAR_DBG("req_on_set_stream_para(*): request seems to be valid");
1405
[4538]1406    tmp = 0;
1407
1408    if ( mes->datalen == 2*5 ) {
1409     d[4] = ROAR_NET2HOST16(d[4]);
1410     tmp   = d[4];
1411     tmp <<= 16;
1412    }
1413
1414    tmp |= d[3];
1415
[4552]1416    if ( d[2] & ROAR_PROTECT_FLAG ) {
1417     protect = 1;
1418     d[2] -= ROAR_PROTECT_FLAG;
[3542]1419    }
[4552]1420
1421    switch (d[2]) {
1422     case ROAR_SET_FLAG:
1423       if ( streams_set_flag(mes->stream, tmp) == -1 )
1424        return -1;
1425      break;
1426     case ROAR_RESET_FLAG:
1427       if ( streams_reset_flag(mes->stream, tmp) == -1 )
1428        return -1;
1429      break;
1430     case ROAR_NOOP_FLAG:
1431      break;
1432     case ROAR_TOGGLE_FLAG:
1433       if ( streams_get(mes->stream, &ss) == -1 )
1434        return -1;
1435
1436       flagstore = ss->flags;
1437
1438       tmp2 = flagstore & tmp; // those are the flags we need to reset.
1439       ROAR_DBG("req_on_set_stream_para(*): tmp2=0x%.8lx", (long int)tmp2);
1440       if ( tmp2 )
1441        if ( streams_reset_flag(mes->stream, tmp2) == -1 )
1442         return -1;
1443
1444       tmp2 = (flagstore ^ tmp) & tmp; // those are the flags we need to set.
1445       ROAR_DBG("req_on_set_stream_para(*): tmp2=0x%.8lx", (long int)tmp2);
1446       if ( tmp2 )
1447        if ( streams_set_flag(mes->stream, tmp2) == -1 )
1448         return -1;
1449      break;
1450     default:
1451       return -1;
1452      break;
1453    }
1454
1455   ROAR_DBG("req_on_set_stream_para(*): protect=%i", protect);
1456   if ( protect )
1457    if ( streams_protect_flag(mes->stream, tmp) == -1 )
1458     return -1;
1459
[3542]1460   break;
1461  case ROAR_STREAM_PARA_CHANMAP:
1462    if ( streams_set_map(mes->stream, &(mes->data[4]), mes->datalen - 4) == -1 )
1463     return -1;
1464   break;
[3696]1465  case ROAR_STREAM_PARA_ROLE:
1466    if ( mes->datalen != 2*3 )
1467     return -1;
1468
1469    d[2] = ROAR_NET2HOST16(d[2]);
1470
1471    if ( streams_set_role(mes->stream, d[2]) == -1 )
1472     return -1;
1473   break;
[4272]1474  case ROAR_STREAM_PARA_LTM:
[4277]1475    if ( mes->datalen < (6 * 2) )
1476     return -1;
1477
[4272]1478    for (i = 2; i < mes->datalen/2; i++) {
1479     d[i] = ROAR_NET2HOST16(d[i]);
1480    }
1481
[4273]1482    if ( mes->stream == -1 ) {
1483     for (i = 6; i < mes->datalen/2; i++)
1484      if ( streams_ltm_ctl(d[i], d[5], d[3], d[2]) == -1 )
1485       return -1;
1486    } else {
1487     if ( streams_ltm_ctl(mes->stream, d[5], d[3], d[2]) == -1 )
1488      return -1;
1489    }
[4272]1490   break;
[5624]1491  case ROAR_STREAM_PARA_RPG:
1492    if ( mes->datalen != (5 * 2) )
1493     return -1;
1494
1495    for (i = 2; i < mes->datalen/2; i++) {
1496     d[i] = ROAR_NET2HOST16(d[i]);
1497    }
1498
1499    rpg.mode = d[2];
1500    rpg.mul  = d[3];
1501    rpg.div  = d[4];
1502
1503    if ( streams_set_rpg(mes->stream, &rpg) == -1 )
1504     return -1;
1505   break;
[3542]1506  default:
1507    ROAR_WARN("req_on_set_stream_para(*): unsupported command version: %i, %i", d[0], d[1]);
1508    return -1;
1509   break;
[1043]1510 }
1511
1512 mes->cmd     = ROAR_CMD_OK;
1513 mes->datalen = 0;
1514
[3542]1515 return 0;
[1043]1516}
1517
[3926]1518int req_on_kick (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
[4330]1519 struct roar_stream_server * ss;
[17]1520 uint16_t * info = (uint16_t *) mes->data;
[4329]1521 int is_stream = 0;
[0]1522
1523 if ( mes->datalen != 4 )
1524  return -1;
1525
[251]1526 info[0] = ROAR_NET2HOST16(info[0]);
1527 info[1] = ROAR_NET2HOST16(info[1]);
1528
[4329]1529 switch (info[0]) {
1530  case ROAR_OT_CLIENT:
1531    clients_delete(info[1]);
1532   break;
1533  case ROAR_OT_STREAM:
1534    is_stream = 1;
1535   break;
1536  case ROAR_OT_SOURCE:
1537    if ( streams_get_flag(info[1], ROAR_FLAG_SOURCE) != 1 )
1538     return -1;
1539    is_stream = 1;
1540   break;
1541  case ROAR_OT_OUTPUT:
[4330]1542    if ( streams_get(info[1], &ss) == -1 )
1543     return -1;
1544
1545    if ( ss->driver_id == -1 )
1546     return -1;
1547
1548    is_stream = 1;
1549   break;
1550  case ROAR_OT_MIXER:
1551    if ( streams_get(info[1], &ss) == -1 )
[4329]1552     return -1;
[4330]1553
1554    if ( ROAR_STREAM(ss)->dir != ROAR_DIR_MIXING )
1555     return -1;
1556
1557    is_stream = 1;
1558   break;
1559  case ROAR_OT_BRIDGE:
1560    if ( streams_get(info[1], &ss) == -1 )
1561     return -1;
1562
1563    if ( ROAR_STREAM(ss)->dir != ROAR_DIR_BRIDGE )
1564     return -1;
1565
[4329]1566    is_stream = 1;
1567   break;
1568  default:
1569/* TODO: those types should be handled, too:
1570#define ROAR_OT_SAMPLE    4
1571#define ROAR_OT_LISTEN    8
1572#define ROAR_OT_ACTION    9
1573#define ROAR_OT_MSGQUEUE 10
1574#define ROAR_OT_MSGBUS   11
1575*/
1576    return -1;
1577   break;
1578 }
1579
1580 if ( is_stream ) {
[2952]1581  if ( streams_get_flag(info[1], ROAR_FLAG_IMMUTABLE) == 1 )
1582   return -1;
1583
[0]1584  streams_delete(info[1]);
1585 }
1586
1587 mes->cmd     = ROAR_CMD_OK;
1588 mes->datalen = 0;
1589
1590 return 0;
1591}
1592
[3926]1593int req_on_attach      (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
[769]1594 uint16_t * info = (uint16_t *) mes->data;
1595
1596 if ( mes->datalen < 6 )
1597  return -1;
1598
1599 info[0] = ROAR_NET2HOST16(info[0]);
1600 info[1] = ROAR_NET2HOST16(info[1]);
1601 info[2] = ROAR_NET2HOST16(info[2]);
1602
1603 if ( info[0] != 0 )
1604  return -1;
1605
1606 if ( info[1] == ROAR_ATTACH_SIMPLE ) {
1607  if ( client_stream_move(info[2], mes->stream) == -1 )
1608   return -1;
1609 } else {
1610  return -1;
1611 }
1612
1613 mes->cmd     = ROAR_CMD_OK;
1614 mes->datalen = 0;
1615
1616 return 0;
[768]1617}
1618
[3926]1619int req_on_set_vol (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
[4740]1620 struct roar_mixer_settings tmpmixer;
[3530]1621 struct roar_stream_server * s;
[17]1622 uint16_t * info = (uint16_t *) mes->data;
[3530]1623 uint16_t   version;
1624 uint16_t   scale = 65535;
[17]1625 int stream;
1626 int i;
1627 int chans;
1628
1629 ROAR_DBG("req_on_set_vol(*) = ?");
1630 ROAR_DBG("req_on_set_vol(*): mes->datalen=%i", mes->datalen);
1631
1632 if ( mes->datalen < (4*2) )
1633  return -1;
1634
[3530]1635 version = ROAR_NET2HOST16(info[0]);
1636 ROAR_DBG("req_on_set_vol(*): version=%i", (int)version);
[17]1637
[3530]1638 switch (version) {
1639  case 0:
1640    stream = ROAR_NET2HOST16(info[1]);
1641   break;
1642  case 1:
1643    stream = mes->stream;
1644    scale  = ROAR_NET2HOST16(info[1]);
1645   break;
1646  default:
1647    return -1;
1648   break;
1649 }
[17]1650 ROAR_DBG("req_on_set_vol(*): stream=%i", stream);
1651
[3561]1652 if ( scale == 0 )
1653  return -1;
1654
[17]1655 // TODO: change this code.
1656 //       we should not directly change the stream object but use some stream_*()-func
1657 //       for that job.
1658
1659 if ( stream < 0 || stream >= ROAR_STREAMS_MAX )
1660  return -1;
1661
1662 s = g_streams[stream];
1663
1664 if ( s == NULL )
1665  return -1;
1666
1667 ROAR_DBG("req_on_set_vol(*): s=%p", s);
1668
[252]1669 info[2] = ROAR_NET2HOST16(info[2]);
1670
[4738]1671 switch (info[2]) {
1672  case ROAR_SET_VOL_ALL:
1673    chans = (mes->datalen/2) - 3;
1674    ROAR_DBG("req_on_set_vol(*): mode is ROAR_SET_VOL_ALL, channes=%i", chans);
[17]1675
[4738]1676    if ( chans >= ROAR_MAX_CHANNELS )
1677     return -1;
1678
1679    ROAR_DBG("req_on_set_vol(*): mixer at %p", s->mixer.mixer);
[18]1680
[4738]1681    for (i = 0; i < chans; i++) {
1682     s->mixer.mixer[i] = ROAR_NET2HOST16(info[i+3]);
1683     ROAR_DBG("req_on_set_vol(*): channel %i: %i", i, ROAR_NET2HOST16(info[i+3]));
1684    }
[17]1685
[4738]1686    s->mixer.scale = scale;
[3530]1687
[4738]1688    ROAR_DBG("req_on_set_vol(*): mixer changed!");
[17]1689
[4738]1690   break;
1691  case ROAR_SET_VOL_ONE:
1692    ROAR_DBG("req_on_set_vol(*): mode is ROAR_SET_VOL_ONE");
1693    if ( ROAR_NET2HOST16(info[3]) >= ROAR_MAX_CHANNELS )
1694     return -1;
[17]1695
[4738]1696    s->mixer.mixer[ROAR_NET2HOST16(info[3])] = ROAR_NET2HOST16(info[4]);
[3530]1697
[4738]1698    s->mixer.scale = scale;
1699   break;
[4740]1700  case ROAR_SET_VOL_UNMAPPED:
1701    chans = (mes->datalen/2) - 3;
1702
1703    if ( chans >= ROAR_MAX_CHANNELS )
1704     return -1;
1705
1706    memcpy(&tmpmixer, &(s->mixer), sizeof(tmpmixer));
1707
1708    for (i = 0; i < chans; i++) {
1709     tmpmixer.mixer[i] = ROAR_NET2HOST16(info[i+3]);
1710    }
1711
1712    tmpmixer.scale = scale;
1713
1714    if ( roar_conv_volume(&(s->mixer), &tmpmixer, ROAR_STREAM(s)->info.channels, chans) == -1 )
1715     return -1;
1716
1717   break;
1718  case ROAR_SET_VOL_MS:
[4738]1719  default:
1720    return -1;
[17]1721 }
1722
[1590]1723 if ( streams_set_mixer(stream) == -1 )
1724  return -1;
1725
[17]1726 mes->cmd     = ROAR_CMD_OK;
1727 mes->datalen = 0;
1728
1729 return 0;
1730}
[0]1731
[3926]1732int req_on_get_vol (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
[23]1733 uint16_t * info = (uint16_t *) mes->data;
[3529]1734 uint16_t   version = -1;
[23]1735 int stream;
1736 struct roar_stream_server * s;
1737 int i;
1738 int chans;
1739
1740 ROAR_DBG("req_on_get_vol(*) = ?");
1741 ROAR_DBG("req_on_get_vol(*): mes->datalen=%i", mes->datalen);
1742
[3529]1743 if ( mes->datalen < 2 ) {
[23]1744  return -1;
[3529]1745 }
1746
1747 version = ROAR_NET2HOST16(info[0]);
1748
1749 switch (version) {
1750  case 0:
1751    if ( mes->datalen < (2*2) )
1752     return -1;
[23]1753
[3529]1754    stream = ROAR_NET2HOST16(info[1]);
1755   break;
1756  case 1:
1757    stream = mes->stream;
1758   break;
1759  default:
1760    return -1;
1761   break;
1762 }
[23]1763
1764 ROAR_DBG("req_on_get_vol(*): stream=%i", stream);
1765
1766 // TODO: change this code.
1767 //       we should not directly change the stream object but use some stream_*()-func
1768 //       for that job.
1769
1770 if ( stream < 0 || stream >= ROAR_STREAMS_MAX )
1771  return -1;
1772
1773 s = g_streams[stream];
1774
1775 if ( s == NULL )
1776  return -1;
1777
1778 ROAR_DBG("req_on_get_vol(*): s=%p", s);
1779
1780 // ok, we have everything
1781
[3529]1782 info[0] = ROAR_HOST2NET16(version);
1783
1784 switch (version) {
1785  case 0:
1786    info[1] = ROAR_HOST2NET16(chans = ROAR_STREAM(s)->info.channels);
1787
1788    for (i = 0; i < chans; i++)
1789     info[2+i] = ROAR_HOST2NET16(s->mixer.mixer[i]);
[23]1790
[3529]1791     mes->datalen = (2 + chans)*2;
1792   break;
1793  case 1:
1794    info[1] = ROAR_HOST2NET16(chans = ROAR_STREAM(s)->info.channels);
1795    info[2] = ROAR_HOST2NET16(s->mixer.scale);
1796    info[3] = ROAR_HOST2NET16(s->mixer.rpg_mul);
1797    info[4] = ROAR_HOST2NET16(s->mixer.rpg_div);
[23]1798
[3529]1799    for (i = 0; i < chans; i++)
1800     info[5+i] = ROAR_HOST2NET16(s->mixer.mixer[i]);
1801
1802     mes->datalen = (5 + chans)*2;
1803   break;
1804  default:
1805    return -1;
1806   break;
1807 }
1808
[23]1809 mes->cmd = ROAR_CMD_OK;
1810
1811 return 0;
1812}
1813
[3926]1814int req_on_add_data (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
[0]1815 struct roar_buffer * b;
[4521]1816 void               * buf;
[0]1817
[4521]1818 if ( roar_buffer_new_data(&b, mes->datalen, &buf) == -1 ) {
[0]1819  ROAR_ERR("req_on_add_data(*): Can not alloc buffer space!");
1820  ROAR_DBG("req_on_add_data(*) = -1");
1821  return -1;
1822 }
1823
1824 if ( data == NULL ) {
1825  memcpy(buf, mes->data, mes->datalen);
1826 } else {
[3926]1827  memcpy(buf, *data, mes->datalen);
[0]1828 }
1829
[5301]1830 if ( stream_add_buffer(mes->stream, &b) == -1 ) {
[0]1831  roar_buffer_free(b);
1832  return -1;
1833 }
1834
[498]1835 mes->cmd     = ROAR_CMD_OK_STOP;
[0]1836 mes->datalen = 0;
1837
1838 return 0;
1839}
1840
[3926]1841int req_on_beep        (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
[3575]1842 struct roar_beep bs;
1843 int16_t * info = (int16_t*)mes->data;
1844 int stream;
1845
1846 memset(&bs, 0, sizeof(bs));
1847
1848 if ( mes->datalen > 0 ) {
1849  if ( mes->datalen < 2 )
1850   return -1;
1851
1852  if ( ROAR_NET2HOST16(info[0]) != 0 ) /* version */
1853   return -1;
1854
1855  if ( mes->datalen != 8*2 )
1856   return -1;
1857
1858  bs.vol  = ROAR_NET2HOST16(info[1]);
1859  bs.time = ROAR_NET2HOST16(info[2]);
1860  bs.freq = ROAR_NET2HOST16(info[3]);
1861  bs.type = ROAR_NET2HOST16(info[4]);
1862  bs.x    = ROAR_NET2HOST16(info[5]);
1863  bs.y    = ROAR_NET2HOST16(info[6]);
1864  bs.z    = ROAR_NET2HOST16(info[7]);
1865 }
1866
1867 if ( (stream = beep_start(client, &bs)) == -1 )
1868  return -1;
1869
1870 mes->stream  = stream;
1871 mes->cmd     = ROAR_CMD_OK_STOP;
1872 mes->datalen = 0;
1873
1874 return 0;
[3574]1875}
1876
[4343]1877int req_on_wait        (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
1878 uint16_t * u16 = (uint16_t*)mes->data;
1879 struct roar_event events[4];
1880 size_t left, tmp;
1881 size_t num = 0;
1882 void * vp = mes->data;
1883
1884 vp += 4;
1885
1886 // check for complet header...
1887 if ( mes->datalen < 4 )
1888  return -1;
1889
1890 u16[0] = ROAR_NET2HOST16(u16[0]);
1891 u16[1] = ROAR_NET2HOST16(u16[1]);
1892
1893 // do we support version and flags?
1894 if ( u16[0] != 0 || u16[1] != 0 )
1895  return -1;
1896
1897 memset(events, 0, sizeof(events));
1898
1899 left = mes->datalen - 4;
1900
1901 while (left) {
1902  tmp = left;
1903  if ( roar_event_from_blob(&(events[num]), vp, &tmp) == -1 )
1904   return -1;
1905
1906  vp   += tmp;
1907  left -= tmp;
1908  num++;
1909 }
1910
1911 if ( clients_wait(client, events, num) == -1 )
1912  return -1;
1913
1914 flags[1] |= COMMAND_FLAG_OUT_NOSEND;
1915
1916 return 0;
1917}
1918
[0]1919//ll
Note: See TracBrowser for help on using the repository browser.