source: roaraudio/roard/req.c @ 1812:d46222e215af

Last change on this file since 1812:d46222e215af was 1812:d46222e215af, checked in by phi, 15 years ago

copy stream info from source stream in case of thru stream

File size: 17.0 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_whoami      (int client, struct roar_message * mes, char * data) {
75 mes->cmd     = ROAR_CMD_OK;
76 mes->datalen = 1;
77 mes->data[0] = client;
78 return 0;
79}
80
81
82int req_on_new_stream  (int client, struct roar_message * mes, char * data) {
83 int stream;
84 struct roar_stream * s;
85 struct roar_stream * source_stream;
86 struct roar_audio_info * info;
87 struct roar_audio_info * source_info;
88
89 if ((stream = streams_new()) == -1 )
90  return -1;
91
92 if ( streams_get(stream, (struct roar_stream_server **)&s) == -1 ) {
93  streams_delete(stream);
94  return -1;
95 }
96
97 if ( client_stream_add(client, stream) == -1 ) {
98  streams_delete(stream);
99  return -1;
100 }
101
102 if ( roar_stream_m2s(s, mes) == -1 ) {
103  streams_delete(stream);
104  return -1;
105 }
106
107 ROAR_STREAM(s)->id = stream; // roar_stream_m2s() resets this
108 ROAR_STREAM_SERVER(s)->codec_orgi = ROAR_STREAM(s)->info.codec;
109
110 switch (ROAR_STREAM(s)->dir) {
111  case ROAR_DIR_LIGHT_IN:
112  case ROAR_DIR_LIGHT_OUT:
113    info = &(ROAR_STREAM(s)->info);
114
115    info->channels = 0;
116    info->bits     = 0;
117    info->rate     = 0;
118
119   break;
120  case ROAR_DIR_THRU:
121    if ( streams_get(ROAR_STREAM(s)->pos_rel_id, (struct roar_stream_server **)&source_stream) == -1 ) {
122     streams_delete(stream);
123     return -1;
124    }
125
126    info        = &(ROAR_STREAM(s)->info);
127    source_info = &(ROAR_STREAM(source_stream)->info);
128
129    info->channels = source_info->channels;
130    info->bits     = source_info->bits;
131    info->rate     = source_info->rate;
132    info->codec    = source_info->codec;
133    ROAR_STREAM_SERVER(s)->codec_orgi = ROAR_STREAM_SERVER(source_info)->codec_orgi;
134
135   break;
136 }
137
138 mes->cmd     = ROAR_CMD_OK;
139 mes->stream  = stream;
140 mes->datalen = 0;
141
142 return 0;
143}
144
145int req_on_exec_stream (int client, struct roar_message * mes, char * data) {
146 int r;
147
148 if ( (r = client_stream_exec(client, mes->stream)) == -1 )
149  return -1;
150
151 mes->cmd     = ROAR_CMD_OK;
152 mes->datalen = 0;
153
154 return 0;
155}
156
157int req_on_con_stream  (int client, struct roar_message * mes, char * data) {
158 char   host[80] = {0};
159 int    port = 0;
160 int    type;
161 int    fh;
162 int    len;
163
164 if ( mes->datalen < 4 )
165  return -1;
166
167 if ( *(mes->data) != 0 )
168  return -1;
169
170 if ( mes->datalen > 80 ) // we do not support long messages here
171  return -1;
172
173 type = (unsigned)mes->data[1];
174 port = ROAR_NET2HOST16(((uint16_t*)mes->data)[1]);
175
176 len = mes->datalen - 4;
177
178 strncpy(host, &(mes->data[4]), len);
179 host[len] = 0;
180
181 if ( type > ROAR_SOCKET_TYPE_MAX )
182  return -1;
183
184 if ( type == ROAR_SOCKET_TYPE_FILE ) // disabled because of security resons
185  return -1;
186
187 if ( type == ROAR_SOCKET_TYPE_FORK ) // why should we connect to ourself?
188  return -1;
189
190 ROAR_DBG("req_on_con_stream(*): CONNECT(type=%i, host='%s', port=%i)", type, host, port);
191
192 if ( (fh = roar_socket_open(ROAR_SOCKET_MODE_CONNECT, type, host, port)) == -1 )
193  return -1;
194
195 if ( client_stream_set_fh(client, mes->stream, fh) == -1 ) {
196  close(fh);
197  return 1;
198 }
199
200 mes->datalen = 0;
201 mes->cmd     = ROAR_CMD_OK;
202
203 return 0;
204}
205
206int req_on_passfh      (int client, struct roar_message * mes, char * data) {
207 int fh;
208 int sock = clients_get_fh(client);
209
210 if ( (fh = roar_socket_recv_fh(sock, NULL, NULL)) == -1 )
211  return -1;
212
213 if ( client_stream_set_fh(client, mes->stream, fh) == -1 ) {
214  close(fh);
215  return 1;
216 }
217
218
219 mes->datalen = 0;
220 mes->cmd     = ROAR_CMD_OK;
221
222 return 0;
223}
224
225#ifdef ROAR_SUPPORT_META
226int req_on_set_meta    (int client, struct roar_message * mes, char * data) {
227 int type;
228 int mode;
229 int namelen, vallen;
230 char   val[255+1];
231 char   name[ROAR_META_MAX_NAMELEN+1];
232
233 if ( mes->datalen < 3 )
234  return -1;
235
236 if ( mes->data[0] != 0 ) // version
237  return -1;
238
239 mode = (unsigned) mes->data[1];
240 type = (unsigned) mes->data[2];
241
242 ROAR_DBG("req_on_set_meta(*): mode=%i, type=%i", mode, type);
243
244 if ( mode == ROAR_META_MODE_CLEAR ) {
245  stream_meta_clear(mes->stream);
246  mes->datalen = 0;
247  mes->cmd     = ROAR_CMD_OK;
248  return 0;
249 } else if ( mode == ROAR_META_MODE_DELETE ) { // unsuppoerted at the moment
250  return -1;
251 } else if ( mode == ROAR_META_MODE_FINALIZE ) {
252  stream_meta_finalize(mes->stream);
253  mes->datalen = 0;
254  mes->cmd     = ROAR_CMD_OK;
255  return 0;
256 } else if ( mode == ROAR_META_MODE_SET || mode == ROAR_META_MODE_ADD ) {
257  if ( mes->datalen < 5 )
258   return -1;
259
260  namelen = (unsigned) mes->data[3];
261  vallen  = (unsigned) mes->data[4];
262
263  ROAR_DBG("req_on_set_meta(*): namelen=%i, vallen=%i", namelen, vallen);
264
265  if ( mes->datalen < (5 + namelen + vallen) )
266   return -1;
267
268  if ( namelen > ROAR_META_MAX_NAMELEN )
269   return -1;
270
271  strncpy(name, &(mes->data[5]), namelen);
272  name[namelen] = 0;
273
274  if ( vallen > 255 )
275   return -1;
276
277  strncpy(val, &(mes->data[5+namelen]), vallen);
278  val[vallen] = 0;
279
280  if ( mode == ROAR_META_MODE_SET ) {
281   if ( stream_meta_set(mes->stream, type, name, val) == -1 )
282    return -1;
283  } else {
284   if ( stream_meta_add(mes->stream, type, name, val) == -1 )
285    return -1;
286  }
287
288  mes->datalen = 0;
289  mes->cmd     = ROAR_CMD_OK;
290  return 0;
291 } else { // unknown mode!
292  return -1;
293 }
294
295 return -1;
296}
297
298int req_on_get_meta    (int client, struct roar_message * mes, char * data) {
299 int vallen;
300 int type;
301 char val[LIBROAR_BUFFER_MSGDATA-1];
302
303 if ( mes->datalen != 2 )
304  return -1;
305
306 if ( mes->data[0] != 0 ) // version
307  return -1;
308
309 type = (unsigned) mes->data[1];
310
311 if ( stream_meta_get(mes->stream, type, NULL, val, LIBROAR_BUFFER_MSGDATA-2) == -1 )
312  return -1;
313
314 vallen = strlen(val);
315
316 mes->cmd     = ROAR_CMD_OK;
317 mes->datalen = 2 + vallen;
318
319 mes->data[0] = 0;
320 mes->data[1] = (unsigned char) vallen;
321
322 val[vallen] = 0;
323
324 strncpy(&(mes->data[2]), val, vallen+1);
325
326 return 0;
327}
328
329int req_on_list_meta   (int client, struct roar_message * mes, char * data) {
330 int i;
331 int len = 0;
332 int types[ROAR_META_MAX_PER_STREAM];
333
334 if ( mes->datalen != 1 )
335  return -1;
336
337 if ( mes->data[0] != 0 ) // version
338  return -1;
339
340 if ( (len = stream_meta_list(mes->stream, types, ROAR_META_MAX_PER_STREAM)) == -1 )
341  return -1;
342
343 mes->cmd     = ROAR_CMD_OK;
344 mes->datalen = 1 + len;
345 mes->data[0] = 0;
346
347 for (i = 0; i < len; i++)
348  mes->data[i+1] = types[i];
349
350 return 0;
351}
352#endif
353
354int req_on_server_oinfo    (int client, struct roar_message * mes, char * data) {
355 struct roar_stream s;
356//ROAR_DIR_OUTPUT
357
358 memset(&s, 0, sizeof(struct roar_stream));
359
360 s.dir           = ROAR_DIR_MIXING;
361 s.pos_rel_id    = -1;
362 s.info.rate     = g_sa->rate;
363 s.info.bits     = g_sa->bits;
364 s.info.channels = g_sa->channels;
365 s.info.codec    = g_sa->codec;
366 s.pos           = g_pos;
367
368 if ( roar_stream_s2m(&s, mes) == -1 )
369  return -1;
370
371 mes->cmd = ROAR_CMD_OK;
372
373 return 0;
374}
375
376
377int req_on_get_standby (int client, struct roar_message * mes, char * data) {
378 mes->cmd = ROAR_CMD_OK;
379 mes->datalen = 2;
380
381 *((uint16_t*)mes->data) = ROAR_HOST2NET16((unsigned) g_standby);
382
383 return 0;
384}
385
386int req_on_set_standby (int client, struct roar_message * mes, char * data) {
387 if ( mes->datalen != 2 )
388  return -1;
389
390 g_standby = ROAR_NET2HOST16(*((uint16_t*)mes->data));
391
392 mes->cmd     = ROAR_CMD_OK;
393 mes->datalen = 0;
394
395 return 0;
396}
397
398int req_on_exit      (int client, struct roar_message * mes, char * data) {
399 int term = 0;
400
401 if ( mes->datalen == 1 )
402  term = mes->data[0];
403
404 mes->cmd     = ROAR_CMD_OK;
405 mes->datalen = 0;
406
407 ROAR_DBG("req_on_exit(*): term=%i", term);
408
409 if ( term ) {
410  cleanup_listen_socket(1);
411 } else {
412  alive = 0;
413 }
414
415 return 0;
416}
417
418int req_on_list_clients(int client, struct roar_message * mes, char * data) {
419 unsigned char filter, cmp;
420 uint32_t id;
421 int clients[ROAR_CLIENTS_MAX];
422 int i, c = 0;
423
424 if ( roar_ctl_m2f(mes, &filter, &cmp, &id) == -1 )
425  return -1;
426
427 // TODO: add code to support filter
428 if ( filter != ROAR_CTL_FILTER_ANY )
429  return -1;
430
431 for (i = 0; i < ROAR_CLIENTS_MAX; i++) {
432  if ( g_clients[i] != NULL ) {
433   clients[c++] = i;
434  }
435 }
436
437 roar_ctl_ia2m(mes, clients, c);
438
439 mes->cmd = ROAR_CMD_OK;
440
441 return 0;
442}
443int req_on_list_streams(int client, struct roar_message * mes, char * data) {
444 unsigned char filter, cmp;
445 uint32_t id;
446 int streams[ROAR_STREAMS_MAX];
447 int i, c = 0;
448
449 if ( roar_ctl_m2f(mes, &filter, &cmp, &id) == -1 )
450  return -1;
451
452 // TODO: add code to support filter
453 if ( filter != ROAR_CTL_FILTER_ANY )
454  return -1;
455
456 for (i = 0; i < ROAR_STREAMS_MAX; i++) {
457  if ( g_streams[i] != NULL ) {
458   streams[c++] = i;
459  }
460 }
461
462 roar_ctl_ia2m(mes, streams, c);
463
464 mes->cmd = ROAR_CMD_OK;
465
466 return 0;
467}
468
469int req_on_get_client  (int client, struct roar_message * mes, char * data) {
470 struct roar_client * c;
471
472 if ( mes->datalen != 1 )
473  return -1;
474
475 if ( clients_get(mes->data[0], &c) == -1 )
476  return -1;
477
478 mes->cmd = ROAR_CMD_OK;
479
480 return roar_ctl_c2m(mes, c);
481}
482
483int req_on_get_stream  (int client, struct roar_message * mes, char * data) {
484 struct roar_stream_server * s;
485
486 if ( mes->datalen != 1 )
487  return -1;
488
489 if ( streams_get(mes->data[0], &s) == -1 )
490  return -1;
491
492 mes->cmd = ROAR_CMD_OK;
493 mes->stream = mes->data[0];
494
495 return roar_stream_s2m(ROAR_STREAM(s), mes);
496}
497
498int req_on_get_stream_para (int client, struct roar_message * mes, char * data) {
499 struct roar_stream * s;
500 struct roar_stream_server * ss;
501 struct roar_audio_info * audio_info;
502 uint16_t * d = (uint16_t *) mes->data;
503 int i;
504
505 if ( mes->datalen != 4 )
506  return -1;
507
508 for (i = 0; i < mes->datalen/2; i++) {
509  d[i] = ROAR_NET2HOST16(d[i]);
510 }
511
512 if ( streams_get(mes->stream, &ss) == -1 ) {
513  ROAR_WARN("req_on_get_stream_para(*): request on non existing (or other error?) stream %i", mes->stream);
514  return -1;
515 }
516
517 if ( streams_calc_delay(mes->stream) == -1 ) {
518  ROAR_WARN("req_on_get_stream_para(*): can not calc delay for stream %i", mes->stream);
519 }
520
521 s = ROAR_STREAM(ss);
522
523 audio_info = &(s->info);
524
525 if ( d[0] != 0 || d[1] != 1 ) {
526  ROAR_WARN("req_on_get_stream_para(*): unsupported command version: %i, %i", d[0], d[1]);
527  return -1;
528 }
529
530 mes->datalen = 2*8;
531
532 d[2] = ROAR_OUTPUT_CALC_OUTBUFSIZE(audio_info);
533 d[3] = ss->pre_underruns;
534 d[4] = ss->post_underruns;
535 d[5] = ss->codec_orgi;
536 d[6] = ss->flags | (ss->primary ? ROAR_FLAG_PRIMARY : 0) | (ss->driver_id != -1 ? ROAR_FLAG_OUTPUT : 0);
537 d[7] = ss->delay/1000;
538
539 ROAR_DBG("req_on_get_stream_para(*): ss->driver_id=%i", ss->driver_id);
540
541 ROAR_DBG("req_on_get_stream_para(*): delay=%i, send delay=%i", ss->delay, d[7]);
542
543 for (i = 0; i < mes->datalen/2; i++) {
544  d[i] = ROAR_HOST2NET16(d[i]);
545 }
546
547 mes->pos = s->pos;
548
549 mes->cmd = ROAR_CMD_OK;
550 return 0;
551}
552
553int req_on_set_stream_para (int client, struct roar_message * mes, char * data) {
554 uint16_t * d = (uint16_t *) mes->data;
555 int i;
556
557 if ( mes->datalen != 8 )
558  return -1;
559
560 for (i = 0; i < mes->datalen/2; i++) {
561  d[i] = ROAR_NET2HOST16(d[i]);
562 }
563
564 if ( d[0] != 0 || d[1] != 2 ) {
565  ROAR_WARN("req_on_set_stream_para(*): unsupported command version: %i, %i", d[0], d[1]);
566  return -1;
567 }
568
569 mes->cmd     = ROAR_CMD_OK;
570 mes->datalen = 0;
571
572 ROAR_DBG("req_on_set_stream_para(*): request seems to be valid");
573
574 if ( d[2] == ROAR_RESET_FLAG ) {
575  return streams_reset_flag(mes->stream, d[3]);
576 } else {
577  return streams_set_flag(mes->stream, d[3]);
578 }
579
580 return -1;
581}
582
583int req_on_kick (int client, struct roar_message * mes, char * data) {
584 uint16_t * info = (uint16_t *) mes->data;
585
586 if ( mes->datalen != 4 )
587  return -1;
588
589 info[0] = ROAR_NET2HOST16(info[0]);
590 info[1] = ROAR_NET2HOST16(info[1]);
591
592 if ( info[0] == ROAR_OT_CLIENT ) {
593  clients_delete(info[1]);
594 } else if ( info[0] == ROAR_OT_STREAM ) {
595  streams_delete(info[1]);
596 } else if ( info[0] == ROAR_OT_SOURCE ) {
597  if ( streams_get_flag(info[1], ROAR_FLAG_SOURCE) == 1 ) {
598   streams_delete(info[1]);
599  } else {
600   return -1;
601  }
602 } else {
603  return -1;
604 }
605
606 mes->cmd     = ROAR_CMD_OK;
607 mes->datalen = 0;
608
609 return 0;
610}
611
612int req_on_attach      (int client, struct roar_message * mes, char * data) {
613 uint16_t * info = (uint16_t *) mes->data;
614
615 if ( mes->datalen < 6 )
616  return -1;
617
618 info[0] = ROAR_NET2HOST16(info[0]);
619 info[1] = ROAR_NET2HOST16(info[1]);
620 info[2] = ROAR_NET2HOST16(info[2]);
621
622 if ( info[0] != 0 )
623  return -1;
624
625 if ( info[1] == ROAR_ATTACH_SIMPLE ) {
626  if ( client_stream_move(info[2], mes->stream) == -1 )
627   return -1;
628 } else {
629  return -1;
630 }
631
632 mes->cmd     = ROAR_CMD_OK;
633 mes->datalen = 0;
634
635 return 0;
636}
637
638int req_on_set_vol (int client, struct roar_message * mes, char * data) {
639 uint16_t * info = (uint16_t *) mes->data;
640 int stream;
641 struct roar_stream_server * s;
642 int i;
643 int chans;
644
645 ROAR_DBG("req_on_set_vol(*) = ?");
646 ROAR_DBG("req_on_set_vol(*): mes->datalen=%i", mes->datalen);
647
648 if ( mes->datalen < (4*2) )
649  return -1;
650
651 if ( info[0] != 0 ) // version
652  return -1;
653
654 stream = ROAR_NET2HOST16(info[1]);
655 ROAR_DBG("req_on_set_vol(*): stream=%i", stream);
656
657 // TODO: change this code.
658 //       we should not directly change the stream object but use some stream_*()-func
659 //       for that job.
660
661 if ( stream < 0 || stream >= ROAR_STREAMS_MAX )
662  return -1;
663
664 s = g_streams[stream];
665
666 if ( s == NULL )
667  return -1;
668
669 ROAR_DBG("req_on_set_vol(*): s=%p", s);
670
671 info[2] = ROAR_NET2HOST16(info[2]);
672
673 if ( info[2] == ROAR_SET_VOL_ALL ) {
674  chans = (mes->datalen/2) - 3;
675  ROAR_DBG("req_on_set_vol(*): mode is ROAR_SET_VOL_ALL, channes=%i", chans);
676
677  if ( chans >= ROAR_MAX_CHANNELS )
678   return -1;
679
680  ROAR_DBG("req_on_set_vol(*): mixer at %p", s->mixer.mixer);
681
682  for (i = 0; i < chans; i++) {
683   s->mixer.mixer[i] = ROAR_NET2HOST16(info[i+3]);
684   ROAR_DBG("req_on_set_vol(*): channel %i: %i", i, ROAR_NET2HOST16(info[i+3]));
685  }
686
687  ROAR_DBG("req_on_set_vol(*): mixer changed!");
688
689 } else if ( info[2] == ROAR_SET_VOL_ONE ) {
690  ROAR_DBG("req_on_set_vol(*): mode is ROAR_SET_VOL_ONE");
691  if ( ROAR_NET2HOST16(info[3]) >= ROAR_MAX_CHANNELS )
692   return -1;
693
694  s->mixer.mixer[ROAR_NET2HOST16(info[3])] = ROAR_NET2HOST16(info[4]);
695 } else {
696  return -1;
697 }
698
699 if ( streams_set_mixer(stream) == -1 )
700  return -1;
701
702 mes->cmd     = ROAR_CMD_OK;
703 mes->datalen = 0;
704
705 return 0;
706}
707
708int req_on_get_vol (int client, struct roar_message * mes, char * data) {
709 uint16_t * info = (uint16_t *) mes->data;
710 int stream;
711 struct roar_stream_server * s;
712 int i;
713 int chans;
714
715 ROAR_DBG("req_on_get_vol(*) = ?");
716 ROAR_DBG("req_on_get_vol(*): mes->datalen=%i", mes->datalen);
717
718 if ( mes->datalen < (2*2) )
719  return -1;
720
721 if ( info[0] != 0 ) // version
722  return -1;
723
724 stream = ROAR_NET2HOST16(info[1]);
725 ROAR_DBG("req_on_get_vol(*): stream=%i", stream);
726
727 // TODO: change this code.
728 //       we should not directly change the stream object but use some stream_*()-func
729 //       for that job.
730
731 if ( stream < 0 || stream >= ROAR_STREAMS_MAX )
732  return -1;
733
734 s = g_streams[stream];
735
736 if ( s == NULL )
737  return -1;
738
739 ROAR_DBG("req_on_get_vol(*): s=%p", s);
740
741 // ok, we have everything
742
743 info[0] = 0;
744 info[1] = ROAR_HOST2NET16(chans = ROAR_STREAM(s)->info.channels);
745
746 for (i = 0; i < chans; i++)
747  info[2+i] = ROAR_HOST2NET16(s->mixer.mixer[i]);
748
749 mes->datalen = (2 + chans)*2;
750 mes->cmd = ROAR_CMD_OK;
751
752 return 0;
753}
754
755int req_on_add_data (int client, struct roar_message * mes, char * data) {
756 struct roar_buffer * b;
757 char               * buf;
758
759 if ( roar_buffer_new(&b, mes->datalen) == -1 ) {
760  ROAR_ERR("req_on_add_data(*): Can not alloc buffer space!");
761  ROAR_DBG("req_on_add_data(*) = -1");
762  return -1;
763 }
764
765 roar_buffer_get_data(b, (void **)&buf);
766
767 if ( data == NULL ) {
768  memcpy(buf, mes->data, mes->datalen);
769 } else {
770  memcpy(buf, data, mes->datalen);
771 }
772
773 if ( stream_add_buffer(mes->stream, b) == -1 ) {
774  roar_buffer_free(b);
775  return -1;
776 }
777
778 mes->cmd     = ROAR_CMD_OK_STOP;
779 mes->datalen = 0;
780
781 return 0;
782}
783
784//ll
Note: See TracBrowser for help on using the repository browser.