source: roaraudio/roard/req.c @ 576:89baebafdc4f

Last change on this file since 576:89baebafdc4f was 576:89baebafdc4f, checked in by phi, 16 years ago

set g_listen_socket to -1 to let g_terminate work :)

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