source: roaraudio/roard/req.c @ 668:71ac426690da

Last change on this file since 668:71ac426690da was 668:71ac426690da, checked in by phi, 16 years ago

added license statements

File size: 13.7 KB
Line 
1//req.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008
5 *
6 *  This file is part of roard a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  RoarAudio is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 */
24
25#include "roard.h"
26
27int req_on_noop        (int client, struct roar_message * mes, char * data) {
28 mes->cmd     = ROAR_CMD_OK;
29 mes->datalen = 0;
30 return 0;
31}
32
33int req_on_identify    (int client, struct roar_message * mes, char * data) {
34 struct roar_client * c;
35 int max_len;
36
37 if ( mes->datalen < 1 )
38  return -1;
39
40 clients_get(client, &c);
41
42 if ( mes->data[0] == 1 ) {
43  if ( c->pid == -1 ) {
44   c->pid       = ROAR_NET2HOST32(*(uint32_t*)((mes->data)+1));
45   ROAR_DBG("req_on_identify(): new PID: c->pid = %i", c->pid);
46  }
47
48  ROAR_DBG("req_on_identify(): final PID: c->pid = %i", c->pid);
49
50  max_len = (mes->datalen - 5) < (ROAR_BUFFER_NAME-1) ? (mes->datalen - 5) : (ROAR_BUFFER_NAME-1);
51
52  strncpy(c->name, mes->data + 5, max_len);
53  c->name[max_len] = 0;
54
55  mes->cmd     = ROAR_CMD_OK;
56  mes->datalen = 0;
57
58  ROAR_DBG("req_on_identify(*): client=%i, pid=%i", client, c->pid);
59  ROAR_DBG("req_on_identify(*) = 0");
60  return 0;
61 }
62
63 return -1;
64}
65
66int req_on_auth        (int client, struct roar_message * mes, char * data) {
67 // TODO: add code to support some auth.
68 mes->cmd     = ROAR_CMD_OK;
69 mes->datalen = 0;
70 return 0;
71}
72
73
74int req_on_new_stream  (int client, struct roar_message * mes, char * data) {
75 int stream;
76 struct roar_stream * s;
77
78 if ((stream = streams_new()) == -1 )
79  return -1;
80
81 if ( streams_get(stream, (struct roar_stream_server **)&s) == -1 ) {
82  streams_delete(stream);
83  return -1;
84 }
85
86 if ( client_stream_add(client, stream) == -1 ) {
87  streams_delete(stream);
88  return -1;
89 }
90
91 if ( roar_stream_m2s(s, mes) == -1 ) {
92  streams_delete(stream);
93  return -1;
94 }
95
96 ROAR_STREAM(s)->id = stream; // roar_stream_m2s() resets this
97 ROAR_STREAM_SERVER(s)->codec_orgi = ROAR_STREAM(s)->info.codec;
98
99 mes->cmd     = ROAR_CMD_OK;
100 mes->stream  = stream;
101 mes->datalen = 0;
102
103 return 0;
104}
105
106int req_on_exec_stream (int client, struct roar_message * mes, char * data) {
107 int r;
108
109 if ( (r = client_stream_exec(client, mes->stream)) == -1 )
110  return -1;
111
112 mes->cmd     = ROAR_CMD_OK;
113 mes->datalen = 0;
114
115 return 0;
116}
117
118int req_on_con_stream  (int client, struct roar_message * mes, char * data) {
119 char   host[80] = {0};
120 int    port = 0;
121 int    type;
122 int    fh;
123 int    len;
124
125 if ( mes->datalen < 4 )
126  return -1;
127
128 if ( *(mes->data) != 0 )
129  return -1;
130
131 if ( mes->datalen > 80 ) // we do not support long messages here
132  return -1;
133
134 type = (unsigned)mes->data[1];
135 port = ROAR_NET2HOST16(((uint16_t*)mes->data)[1]);
136
137 len = mes->datalen - 4;
138
139 strncpy(host, &(mes->data[4]), len);
140 host[len] = 0;
141
142 if ( type > ROAR_SOCKET_TYPE_MAX )
143  return -1;
144
145 if ( type == ROAR_SOCKET_TYPE_FILE ) // disabled because of security resons
146  return -1;
147
148 if ( type == ROAR_SOCKET_TYPE_FORK ) // why should we connect to ourself?
149  return -1;
150
151 ROAR_DBG("req_on_con_stream(*): CONNECT(type=%i, host='%s', port=%i)", type, host, port);
152
153 if ( (fh = roar_socket_open(ROAR_SOCKET_MODE_CONNECT, type, host, port)) == -1 )
154  return -1;
155
156 if ( client_stream_set_fh(client, mes->stream, fh) == -1 ) {
157  close(fh);
158  return 1;
159 }
160
161 return 0;
162
163 mes->datalen = 0;
164 mes->cmd     = ROAR_CMD_OK;
165}
166
167
168int req_on_set_meta    (int client, struct roar_message * mes, char * data) {
169 int type;
170 int mode;
171 int namelen, vallen;
172 char   val[255+1];
173 char   name[ROAR_META_MAX_NAMELEN+1];
174
175 if ( mes->datalen < 3 )
176  return -1;
177
178 if ( mes->data[0] != 0 ) // version
179  return -1;
180
181 mode = (unsigned) mes->data[1];
182 type = (unsigned) mes->data[2];
183
184 ROAR_DBG("req_on_set_meta(*): mode=%i, type=%i", mode, type);
185
186 if ( mode == ROAR_META_MODE_CLEAR ) {
187  stream_meta_clear(mes->stream);
188  mes->datalen = 0;
189  mes->cmd     = ROAR_CMD_OK;
190  return 0;
191 } else if ( mode == ROAR_META_MODE_DELETE ) { // unsuppoerted at the moment
192 } else if ( mode == ROAR_META_MODE_SET || mode == ROAR_META_MODE_ADD ) {
193  if ( mes->datalen < 5 )
194   return -1;
195
196  namelen = (unsigned) mes->data[3];
197  vallen  = (unsigned) mes->data[4];
198
199  ROAR_DBG("req_on_set_meta(*): namelen=%i, vallen=%i", namelen, vallen);
200
201  if ( mes->datalen < (5 + namelen + vallen) )
202   return -1;
203
204  if ( namelen > ROAR_META_MAX_NAMELEN )
205   return -1;
206
207  strncpy(name, &(mes->data[5]), namelen);
208  name[namelen] = 0;
209
210  if ( vallen > 255 )
211   return -1;
212
213  strncpy(val, &(mes->data[5+namelen]), vallen);
214  val[vallen] = 0;
215
216  if ( mode == ROAR_META_MODE_SET ) {
217   if ( stream_meta_set(mes->stream, type, name, val) == -1 )
218    return -1;
219  } else {
220   if ( stream_meta_add(mes->stream, type, name, val) == -1 )
221    return -1;
222  }
223
224  mes->datalen = 0;
225  mes->cmd     = ROAR_CMD_OK;
226  return 0;
227 } else { // unknown mode!
228  return -1;
229 }
230
231 return -1;
232}
233
234int req_on_get_meta    (int client, struct roar_message * mes, char * data) {
235 int vallen;
236 int type;
237 char val[LIBROAR_BUFFER_MSGDATA-1];
238
239 if ( mes->datalen != 2 )
240  return -1;
241
242 if ( mes->data[0] != 0 ) // version
243  return -1;
244
245 type = (unsigned) mes->data[1];
246
247 if ( stream_meta_get(mes->stream, type, NULL, val, LIBROAR_BUFFER_MSGDATA-2) == -1 )
248  return -1;
249
250 vallen = strlen(val);
251
252 mes->cmd     = ROAR_CMD_OK;
253 mes->datalen = 2 + vallen;
254
255 mes->data[0] = 0;
256 mes->data[1] = (unsigned char) vallen;
257
258 val[vallen] = 0;
259
260 strncpy(&(mes->data[2]), val, vallen+1);
261
262 return 0;
263}
264
265int req_on_list_meta   (int client, struct roar_message * mes, char * data) {
266 int i;
267 int len = 0;
268 int types[ROAR_META_MAX_PER_STREAM];
269
270 if ( mes->datalen != 1 )
271  return -1;
272
273 if ( mes->data[0] != 0 ) // version
274  return -1;
275
276 if ( (len = stream_meta_list(mes->stream, types, ROAR_META_MAX_PER_STREAM)) == -1 )
277  return -1;
278
279 mes->cmd     = ROAR_CMD_OK;
280 mes->datalen = 1 + len;
281 mes->data[0] = 0;
282
283 for (i = 0; i < len; i++)
284  mes->data[i+1] = types[i];
285
286 return 0;
287}
288
289int req_on_server_oinfo    (int client, struct roar_message * mes, char * data) {
290 struct roar_stream s;
291//ROAR_DIR_OUTPUT
292
293 s.dir           = ROAR_DIR_OUTPUT;
294 s.pos_rel_id    = -1;
295 s.info.rate     = g_sa->rate;
296 s.info.bits     = g_sa->bits;
297 s.info.channels = g_sa->channels;
298 s.info.codec    = g_sa->codec;
299
300 if ( roar_stream_s2m(&s, mes) == -1 )
301  return -1;
302
303 mes->cmd = ROAR_CMD_OK;
304
305 return 0;
306}
307
308
309int req_on_get_standby (int client, struct roar_message * mes, char * data) {
310 mes->cmd = ROAR_CMD_OK;
311 mes->datalen = 2;
312
313 *((uint16_t*)mes->data) = ROAR_HOST2NET16((unsigned) g_standby);
314
315 return 0;
316}
317
318int req_on_set_standby (int client, struct roar_message * mes, char * data) {
319 if ( mes->datalen != 2 )
320  return -1;
321
322 g_standby = ROAR_NET2HOST16(*((uint16_t*)mes->data));
323
324 mes->cmd     = ROAR_CMD_OK;
325 mes->datalen = 0;
326
327 return 0;
328}
329
330int req_on_exit      (int client, struct roar_message * mes, char * data) {
331 int term = 0;
332
333 if ( mes->datalen == 1 )
334  term = mes->data[0];
335
336 mes->cmd     = ROAR_CMD_OK;
337 mes->datalen = 0;
338
339 ROAR_DBG("req_on_exit(*): term=%i", term);
340
341 if ( term ) {
342  cleanup_listen_socket(1);
343 } else {
344  alive = 0;
345 }
346
347 return 0;
348}
349
350int req_on_list_clients(int client, struct roar_message * mes, char * data) {
351 unsigned char filter, cmp;
352 uint32_t id;
353 int clients[ROAR_CLIENTS_MAX];
354 int i, c = 0;
355
356 if ( roar_ctl_m2f(mes, &filter, &cmp, &id) == -1 )
357  return -1;
358
359 // TODO: add code to support filter
360 if ( filter != ROAR_CTL_FILTER_ANY )
361  return -1;
362
363 for (i = 0; i < ROAR_CLIENTS_MAX; i++) {
364  if ( g_clients[i] != NULL ) {
365   clients[c++] = i;
366  }
367 }
368
369 roar_ctl_ia2m(mes, clients, c);
370
371 mes->cmd = ROAR_CMD_OK;
372
373 return 0;
374}
375int req_on_list_streams(int client, struct roar_message * mes, char * data) {
376 unsigned char filter, cmp;
377 uint32_t id;
378 int streams[ROAR_STREAMS_MAX];
379 int i, c = 0;
380
381 if ( roar_ctl_m2f(mes, &filter, &cmp, &id) == -1 )
382  return -1;
383
384 // TODO: add code to support filter
385 if ( filter != ROAR_CTL_FILTER_ANY )
386  return -1;
387
388 for (i = 0; i < ROAR_STREAMS_MAX; i++) {
389  if ( g_streams[i] != NULL ) {
390   streams[c++] = i;
391  }
392 }
393
394 roar_ctl_ia2m(mes, streams, c);
395
396 mes->cmd = ROAR_CMD_OK;
397
398 return 0;
399}
400
401int req_on_get_client  (int client, struct roar_message * mes, char * data) {
402 struct roar_client * c;
403
404 if ( mes->datalen != 1 )
405  return -1;
406
407 if ( clients_get(mes->data[0], &c) == -1 )
408  return -1;
409
410 mes->cmd = ROAR_CMD_OK;
411
412 return roar_ctl_c2m(mes, c);
413}
414
415int req_on_get_stream  (int client, struct roar_message * mes, char * data) {
416 struct roar_stream_server * s;
417
418 if ( mes->datalen != 1 )
419  return -1;
420
421 if ( streams_get(mes->data[0], &s) == -1 )
422  return -1;
423
424 mes->cmd = ROAR_CMD_OK;
425 mes->stream = mes->data[0];
426
427 return roar_stream_s2m(ROAR_STREAM(s), mes);
428}
429
430int req_on_get_stream_para (int client, struct roar_message * mes, char * data) {
431 struct roar_stream * s;
432 struct roar_audio_info * audio_info;
433 uint16_t * d = (uint16_t *) mes->data;
434 int i;
435
436 if ( mes->datalen != 4 )
437  return -1;
438
439 for (i = 0; i < mes->datalen/2; i++) {
440  d[i] = ROAR_NET2HOST16(d[i]);
441 }
442
443 if ( streams_get(mes->stream, (struct roar_stream_server **)&s) == -1 ) {
444  ROAR_WARN("req_on_get_stream_para(*): request on non existing (or other error?) stream %i", mes->stream);
445  return -1;
446 }
447
448 audio_info = &(s->info);
449
450 if ( d[0] != 0 || d[1] != 1 ) {
451  ROAR_WARN("req_on_get_stream_para(*): unsupported command version: %i, %i", d[0], d[1]);
452  return -1;
453 }
454
455 mes->datalen = 2*6;
456
457 d[2] = ROAR_OUTPUT_CALC_OUTBUFSIZE(audio_info);
458 d[3] = ROAR_STREAM_SERVER(s)->pre_underruns;
459 d[4] = ROAR_STREAM_SERVER(s)->post_underruns;
460 d[5] = ROAR_STREAM_SERVER(s)->codec_orgi;
461
462 for (i = 0; i < mes->datalen/2; i++) {
463  d[i] = ROAR_HOST2NET16(d[i]);
464 }
465
466 mes->cmd = ROAR_CMD_OK;
467 return 0;
468}
469
470int req_on_kick (int client, struct roar_message * mes, char * data) {
471 uint16_t * info = (uint16_t *) mes->data;
472
473 if ( mes->datalen != 4 )
474  return -1;
475
476 info[0] = ROAR_NET2HOST16(info[0]);
477 info[1] = ROAR_NET2HOST16(info[1]);
478
479 if ( info[0] == ROAR_OT_CLIENT ) {
480  clients_delete(info[1]);
481 } else if ( info[0] == ROAR_OT_STREAM ) {
482  streams_delete(info[1]);
483 } else {
484  return -1;
485 }
486
487 mes->cmd     = ROAR_CMD_OK;
488 mes->datalen = 0;
489
490 return 0;
491}
492
493int req_on_set_vol (int client, struct roar_message * mes, char * data) {
494 uint16_t * info = (uint16_t *) mes->data;
495 int stream;
496 struct roar_stream_server * s;
497 int i;
498 int chans;
499
500 ROAR_DBG("req_on_set_vol(*) = ?");
501 ROAR_DBG("req_on_set_vol(*): mes->datalen=%i", mes->datalen);
502
503 if ( mes->datalen < (4*2) )
504  return -1;
505
506 if ( info[0] != 0 ) // version
507  return -1;
508
509 stream = ROAR_NET2HOST16(info[1]);
510 ROAR_DBG("req_on_set_vol(*): stream=%i", stream);
511
512 // TODO: change this code.
513 //       we should not directly change the stream object but use some stream_*()-func
514 //       for that job.
515
516 if ( stream < 0 || stream >= ROAR_STREAMS_MAX )
517  return -1;
518
519 s = g_streams[stream];
520
521 if ( s == NULL )
522  return -1;
523
524 ROAR_DBG("req_on_set_vol(*): s=%p", s);
525
526 info[2] = ROAR_NET2HOST16(info[2]);
527
528 if ( info[2] == ROAR_SET_VOL_ALL ) {
529  chans = (mes->datalen/2) - 3;
530  ROAR_DBG("req_on_set_vol(*): mode is ROAR_SET_VOL_ALL, channes=%i", chans);
531
532  if ( chans >= ROAR_MAX_CHANNELS )
533   return -1;
534
535  ROAR_DBG("req_on_set_vol(*): mixer at %p", s->mixer.mixer);
536
537  for (i = 0; i < chans; i++) {
538   s->mixer.mixer[i] = ROAR_NET2HOST16(info[i+3]);
539   ROAR_DBG("req_on_set_vol(*): channel %i: %i", i, ROAR_NET2HOST16(info[i+3]));
540  }
541
542  ROAR_DBG("req_on_set_vol(*): mixer changed!");
543
544 } else if ( info[2] == ROAR_SET_VOL_ONE ) {
545  ROAR_DBG("req_on_set_vol(*): mode is ROAR_SET_VOL_ONE");
546  if ( ROAR_NET2HOST16(info[3]) >= ROAR_MAX_CHANNELS )
547   return -1;
548
549  s->mixer.mixer[ROAR_NET2HOST16(info[3])] = ROAR_NET2HOST16(info[4]);
550 } else {
551  return -1;
552 }
553
554 mes->cmd     = ROAR_CMD_OK;
555 mes->datalen = 0;
556
557 return 0;
558}
559
560int req_on_get_vol (int client, struct roar_message * mes, char * data) {
561 uint16_t * info = (uint16_t *) mes->data;
562 int stream;
563 struct roar_stream_server * s;
564 int i;
565 int chans;
566
567 ROAR_DBG("req_on_get_vol(*) = ?");
568 ROAR_DBG("req_on_get_vol(*): mes->datalen=%i", mes->datalen);
569
570 if ( mes->datalen < (2*2) )
571  return -1;
572
573 if ( info[0] != 0 ) // version
574  return -1;
575
576 stream = ROAR_NET2HOST16(info[1]);
577 ROAR_DBG("req_on_get_vol(*): stream=%i", stream);
578
579 // TODO: change this code.
580 //       we should not directly change the stream object but use some stream_*()-func
581 //       for that job.
582
583 if ( stream < 0 || stream >= ROAR_STREAMS_MAX )
584  return -1;
585
586 s = g_streams[stream];
587
588 if ( s == NULL )
589  return -1;
590
591 ROAR_DBG("req_on_get_vol(*): s=%p", s);
592
593 // ok, we have everything
594
595 info[0] = 0;
596 info[1] = ROAR_HOST2NET16(chans = ROAR_STREAM(s)->info.channels);
597
598 for (i = 0; i < chans; i++)
599  info[2+i] = ROAR_HOST2NET16(s->mixer.mixer[i]);
600
601 mes->datalen = (2 + chans)*2;
602 mes->cmd = ROAR_CMD_OK;
603
604 return 0;
605}
606
607int req_on_add_data (int client, struct roar_message * mes, char * data) {
608 struct roar_buffer * b;
609 char               * buf;
610
611 if ( roar_buffer_new(&b, mes->datalen) == -1 ) {
612  ROAR_ERR("req_on_add_data(*): Can not alloc buffer space!");
613  ROAR_DBG("req_on_add_data(*) = -1");
614  return -1;
615 }
616
617 roar_buffer_get_data(b, (void **)&buf);
618
619 if ( data == NULL ) {
620  memcpy(buf, mes->data, mes->datalen);
621 } else {
622  memcpy(buf, data, mes->datalen);
623 }
624
625 if ( stream_add_buffer(mes->stream, b) == -1 ) {
626  roar_buffer_free(b);
627  return -1;
628 }
629
630 mes->cmd     = ROAR_CMD_OK_STOP;
631 mes->datalen = 0;
632
633 return 0;
634}
635
636//ll
Note: See TracBrowser for help on using the repository browser.