source: roaraudio/roard/req.c @ 437:38e4b190c0e8

Last change on this file since 437:38e4b190c0e8 was 437:38e4b190c0e8, checked in by phi, 16 years ago

added support UID/GID of client

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