source: roaraudio/roard/clients.c @ 4686:ebb913191f38

Last change on this file since 4686:ebb913191f38 was 4686:ebb913191f38, checked in by phi, 13 years ago

added some common code for client outbuf flushing

File size: 22.1 KB
RevLine 
[0]1//clients.c:
2
[668]3/*
[3358]4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2010
[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 */
25
[0]26#include "roard.h"
27
[4683]28struct roard_proto g_proto[MAX_PROTOS] = {
[4678]29#ifndef ROAR_WITHOUT_DCOMP_EMUL_ESD
30#ifdef ROAR_HAVE_H_ESD
[4686]31 {ROAR_PROTO_ESOUND, NULL, emul_esd_check_client, NULL, NULL},
[4678]32#endif
33#endif
34#ifndef ROAR_WITHOUT_DCOMP_EMUL_RPLAY
[4686]35 {ROAR_PROTO_RPLAY, NULL, emul_rplay_check_client, NULL, NULL},
[4678]36#endif
37 {-1, NULL}
38};
39
[3910]40#define _CHECK_CID_RET(id,ret) if ( (id) < 0 || (id) > ROAR_CLIENTS_MAX || g_clients[(id)] == NULL ) return (ret)
41#define _CHECK_CID(id)         _CHECK_CID_RET((id), -1)
42
[0]43int clients_init (void) {
44 int i;
45
46 for (i = 0; i < ROAR_CLIENTS_MAX; i++)
47  g_clients[i] = NULL;
48
49 return 0;
50}
51
52int clients_free (void) {
53 int i;
54
55 for (i = 0; i < ROAR_CLIENTS_MAX; i++)
[3910]56  if ( g_clients[i] != NULL )
[0]57   clients_delete(i);
58
59 return 0;
60}
61
62int clients_new (void) {
63 int i;
64 int s;
[4326]65 struct roar_client_server * ns;
[0]66 struct roar_client * n;
67
68 for (i = 0; i < ROAR_CLIENTS_MAX; i++) {
69  if ( g_clients[i] == NULL ) {
[4326]70   ns = roar_mm_malloc(sizeof(struct roar_client_server));
71   n = ROAR_CLIENT(ns);
72
73   memset(ns, 0, sizeof(struct roar_client_server));
74
[0]75   if ( n != NULL ) {
76    n->pid    = -1;
[437]77    n->uid    = -1;
78    n->gid    = -1;
[0]79    n->fh     = -1;
80
81    *n->name = 0;
82    *n->host = 0;
83
[2614]84    n->proto     = ROAR_PROTO_ROARAUDIO;
85    n->byteorder = ROAR_BYTEORDER_NETWORK;
[2517]86
[346]87    n->acl   = NULL;
88
[0]89    n->execed = -1;
90    for (s = 0; s < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; s++)
91     n->streams[s] = -1;
92
[2815]93    if ( roar_nnode_new(&(n->nnode), ROAR_SOCKET_TYPE_UNKNOWN) == -1 ) {
[3063]94     roar_mm_free(n);
[2815]95     return -1;
96    }
97
[4343]98    ns->blockc   = 0;
99    ns->waits    = NULL;
[4468]100    ns->acclev   = ACCLEV_NONE;
[4343]101
[4326]102    g_clients[i] = ns;
[0]103
[4101]104    counters_inc(clients, 1);
[4346]105    roar_notify_core_emit_snoargs(ROAR_OE_BASICS_NEW, -1, i, ROAR_OT_CLIENT);
[0]106    ROAR_DBG("clients_new(void) = %i", i);
107    return i;
108   } else {
109    ROAR_ERR("clients_new(void): Can not alloc memory for new client: %s", strerror(errno));
110    ROAR_ERR("clients_new(void) = -1");
111    return -1;
112   }
113  }
114 }
115
116 return -1;
117}
118
[3737]119int clients_new_from_fh(int fh, int proto, int byteorder, int update_nnode) {
120 struct roar_client * c;
121 int client;
122
123 if ( fh == -1 )
124  return -1;
125
126 if ( proto != ROAR_PROTO_ROARAUDIO || byteorder != ROAR_BYTEORDER_NETWORK )
127  return -1;
128
129 if ( (client = clients_new()) == -1 )
130  return -1;
131
132 if ( clients_set_fh(client, fh) == -1 ) {
133  clients_delete(client);
134  return -1;
135 }
136
137 if ( update_nnode ) {
138  if ( clients_get(client, &c) != -1 ) {
139   if ( roar_nnode_free(&(c->nnode)) != -1 ) {
140    roar_nnode_new_from_fh(&(c->nnode), fh, 1);
141   }
142  }
143 }
144
145 return 0;
146}
147
[0]148int clients_delete (int id) {
[4394]149 struct roar_client_server * cs;
[0]150 int i;
[1164]151 int close_client_fh = 1;
[0]152
[2608]153 ROAR_DBG("clients_delete(id=%i) = ?", id);
154
[4394]155 _CHECK_CID(id);
156
157 cs = g_clients[id];
158
159 if ( cs->waits != NULL ) {
160  for (i = 0; cs->waits[i] != NULL; i++)
161   roar_notify_core_unsubscribe(NULL, cs->waits[i]);
162
163  roar_mm_free(cs->waits);
164  cs->waits = NULL;
165 }
166
[4346]167 roar_notify_core_emit_snoargs(ROAR_OE_BASICS_DELETE, -1, id, ROAR_OT_CLIENT);
168
[4101]169 counters_inc(clients, -1);
170
[4395]171 if (ROAR_CLIENT(cs)->execed != -1) {
[0]172//  return streams_delete(g_clients[id]->execed);
[4395]173  ROAR_CLIENT(cs)->execed = -1;
[1164]174  close_client_fh = 0;
[0]175 }
176
177 for (i = 0; i < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; i++) {
[4395]178  streams_delete(ROAR_CLIENT(cs)->streams[i]);
[0]179 }
180
[4395]181 if ( ROAR_CLIENT(cs)->fh != -1 && close_client_fh )
182  close(ROAR_CLIENT(cs)->fh);
[0]183
[4395]184 roar_nnode_free(&(ROAR_CLIENT(cs)->nnode));
[2815]185
[4684]186 if ( cs->inbuf != NULL )
187  roar_buffer_free(cs->inbuf);
188
189 if ( cs->outbuf != NULL )
190  roar_buffer_free(cs->outbuf);
191
[4395]192 roar_mm_free(cs);
[0]193 g_clients[id] = NULL;
194
195 ROAR_DBG("clients_delete(id=%i) = 0", id);
196 return 0;
197}
198
[3927]199int clients_close      (int id, int nocheck_exec) {
200 struct roar_client * c;
201
202 ROAR_DBG("clients_close(id=%i) = ?", id);
203
204 _CHECK_CID(id);
205
[4326]206 c = ROAR_CLIENT(g_clients[id]);
[3927]207
208 if ( c->fh == -1 ) {
209  ROAR_DBG("clients_delete(id=%i) = 0", id);
210  return 0;
211 }
212
[4326]213 if (nocheck_exec || c->execed != -1) {
[3927]214  close(c->fh);
215  c->fh = -1;
216 }
217
218 ROAR_DBG("clients_delete(id=%i) = 0", id);
219 return 0;
220}
221
[0]222int clients_get       (int id, struct roar_client ** client) {
[3910]223 _CHECK_CID(id);
224
[4326]225 *client = ROAR_CLIENT(g_clients[id]);
[0]226
227 if ( *client == NULL )
228  return -1;
229
230 return 0;
231}
232
[4468]233int clients_get_server (int id, struct roar_client_server ** client) {
234 _CHECK_CID(id);
235
236 *client = g_clients[id];
237
238 if ( *client == NULL )
239  return -1;
240
241 return 0;
242}
243
[0]244int clients_set_fh    (int id, int    fh) {
[3713]245 struct roar_client * c;
246#ifdef SO_PEERCRED
247 struct ucred cred;
248 socklen_t cred_len = sizeof(cred);
249#endif
[501]250
[3910]251 _CHECK_CID(id);
252
[4326]253 if ( (c = ROAR_CLIENT(g_clients[id])) == NULL )
[0]254  return -1;
255
[3713]256 c->fh = fh;
257
258#ifdef SO_PEERCRED
259 if (getsockopt(fh, SOL_SOCKET, SO_PEERCRED, &cred, &cred_len) != -1) {
260  if ( cred.pid != 0 ) {
261   c->pid = cred.pid;
262   c->uid = cred.uid;
263   c->gid = cred.gid;
264  }
265 } else {
266  ROAR_DBG("req_on_identify(): Can't get creds via SO_PEERCRED: %s", strerror(errno));
267 }
268#elif defined(ROAR_HAVE_GETPEEREID)
269 if (getpeereid(fh, &(c->uid), &(c->gid)) == -1) {
270  ROAR_DBG("req_on_identify(): Can't get creds via getpeereid(): %s", strerror(errno));
271 }
272#endif
[0]273
274 return 0;
275}
276
[755]277int clients_get_fh    (int id) {
[3910]278 _CHECK_CID(id);
[755]279
[4326]280 return ROAR_CLIENT(g_clients[id])->fh;
[755]281}
282
[0]283int clients_set_pid   (int id, int    pid) {
[3910]284 _CHECK_CID(id);
[0]285
[4326]286 ROAR_CLIENT(g_clients[id])->pid = pid;
[0]287
288 return 0;
289}
290
[439]291int clients_set_uid   (int id, int    uid) {
[3910]292 _CHECK_CID(id);
[439]293
[4326]294 ROAR_CLIENT(g_clients[id])->uid = uid;
[439]295
296 return 0;
297}
298
299int clients_set_gid   (int id, int    gid) {
[3910]300 _CHECK_CID(id);
[439]301
[4326]302 ROAR_CLIENT(g_clients[id])->gid = gid;
[439]303
304 return 0;
305}
306
[2517]307int clients_set_proto (int id, int    proto) {
[2614]308 int byteorder = ROAR_BYTEORDER_UNKNOWN;
309
[3910]310 _CHECK_CID(id);
[2517]311
[2614]312 switch (proto) {
313  case ROAR_PROTO_ROARAUDIO:
[2828]314  case ROAR_PROTO_ESOUND:
[3981]315  case ROAR_PROTO_RPLAY:
[3255]316  case ROAR_PROTO_SIMPLE:
[2614]317    byteorder = ROAR_BYTEORDER_NETWORK;
318   break;
319 }
320
[4326]321 ROAR_CLIENT(g_clients[id])->proto     = proto;
322 ROAR_CLIENT(g_clients[id])->byteorder = byteorder;
[2517]323
324 return 0;
325}
326
[4343]327int clients_block      (int id, int unblock) {
328 _CHECK_CID(id);
329
330 if ( unblock ) {
331  g_clients[id]->blockc--;
332 } else {
333  g_clients[id]->blockc++;
334 }
335
336 return 0;
337}
338
339
[498]340#define MAX_STREAMLESS 8
341
[0]342int clients_check_all (void) {
[1480]343#ifdef ROAR_HAVE_SELECT
[4326]344 struct roar_client * c;
[0]345 struct timeval tv;
[4686]346 fd_set r, w, e;
[66]347 int i, j;
[0]348 int ret;
349 int fh;
350 int max_fh = -1;
[71]351 int have = 0;
[498]352 struct {
353  int id;
354  int fh;
355 } streamless[MAX_STREAMLESS];
356 int have_streamless = 0;
357 int have_stream;
[0]358
359 FD_ZERO(&r);
[4686]360 FD_ZERO(&w);
[0]361 FD_ZERO(&e);
362
363 tv.tv_sec  = 0;
364 tv.tv_usec = 1;
365
366 for (i = 0; i < ROAR_CLIENTS_MAX; i++) {
[4326]367  if ( (c = ROAR_CLIENT(g_clients[i])) == NULL )
[0]368   continue;
369
[4326]370  if ( (fh = c->fh) != -1 ) {
[71]371   have++;
372
[610]373   ROAR_DBG("clients_check_all(*): fh=%i", fh);
374
[66]375   FD_SET(fh, &r);
376   FD_SET(fh, &e);
377
[4686]378   if ( g_clients[i]->outbuf != NULL ) {
379    FD_SET(fh, &w);
380   }
381
[66]382   if ( fh > max_fh )
383    max_fh = fh;
[84]384  }
[0]385
[498]386  have_stream = 0;
387
[84]388  for (j = 0; j < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; j++) {
[4326]389   if ( (fh = streams_get_fh(c->streams[j])) != -1 ) {
390    ROAR_DBG("clients_check_all(*): g_clients[i=%i]->streams[j=%i] = %i, fh = %i", i, j, c->streams[j], fh);
[1504]391    if ( fh > -1 ) {
392     FD_SET(fh, &r);
[0]393
[1504]394     if ( fh > max_fh )
395      max_fh = fh;
[3579]396    } else if ( fh == -2 ) {
[4326]397     streams_check(c->streams[j]);
[1504]398    }
[498]399
400    have_stream = 1;
[66]401   }
[84]402   //printf("D: client=%i, stream=%i, fh=%i\n", i, j, fh);
[66]403  }
404
[498]405  if ( !have_stream && have_streamless < MAX_STREAMLESS ) {
406   streamless[have_streamless  ].id = i;
[4326]407   if ( (streamless[have_streamless++].fh = c->fh) == -1 )
[498]408    have_streamless--;
409  }
[0]410 }
411
[256]412 if ( max_fh == -1 )
413  return 0;
414
[4686]415 if ( (ret = select(max_fh + 1, &r, &w, &e, &tv)) < 1 ) {
[71]416  return ret < 0 ? ret : have;
[0]417 }
418
419 for (i = 0; i < ROAR_CLIENTS_MAX; i++) {
[4326]420  if ( (c = ROAR_CLIENT(g_clients[i])) == NULL )
[0]421   continue;
422
[4326]423  if ( (fh = c->fh) != -1 ) {
[66]424   if ( FD_ISSET(fh, &r) ) {
[4326]425    if ( c->execed == -1 ) {
[66]426     clients_check(i);
[4326]427     if ( g_clients[i] != NULL && ROAR_CLIENT(g_clients[i])->execed != -1 ) {
[1834]428      FD_CLR(fh, &r);
429     }
[255]430/*
[66]431    } else {
432     streams_check(g_clients[i]->execed);
[255]433*/
[66]434    }
435   }
[4686]436   if ( FD_ISSET(fh, &w) ) {
437    clients_flush(i);
438   }
[0]439
[84]440   if ( FD_ISSET(fh, &e) ) {
[66]441    clients_delete(i);
[84]442    continue;
443   }
444  }
445
[4326]446  if ( (c = ROAR_CLIENT(g_clients[i])) == NULL )
[84]447   continue;
448
449  for (j = 0; j < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; j++) {
[1611]450   ROAR_DBG("clients_check_all(*): D: client=%i, stream=%i, g_clients[i=%i] = %p", i, j, i, g_clients[i]);
[136]451   if ( g_clients[i] == NULL ) // streams_check() bellow can delete our client (why?)
452    break;
[1611]453
454   //ROAR_WARN("clients_check_all(*): client=%i: client exists", i);
[4326]455   ROAR_DBG("clients_check_all(*): client=%i, stream=%i: id=%i", i, j, c->streams[j]);
[1611]456
[4326]457   if ( (fh = streams_get_fh(c->streams[j])) != -1 ) {
[1611]458    ROAR_DBG("clients_check_all(*): client=%i, stream=%i: fh=%i", i, j, fh);
[3579]459    if ( fh > -1 && FD_ISSET(fh, &r) ) {
[4326]460     streams_check(c->streams[j]);
[66]461    }
[0]462   }
463  }
464 }
465
[498]466 if ( have_streamless ) {
467   FD_ZERO(&r);
[4686]468   FD_ZERO(&w);
[498]469
470   tv.tv_sec  = 0;
471   tv.tv_usec = 1;
472
473   max_fh = -1;
474
475   for (i = 0; i < have_streamless; i++) {
[4326]476    if ( g_clients[j = streamless[i].id] == NULL )
[607]477     continue;
478
[4326]479    if ( ROAR_CLIENT(g_clients[j])->execed != -1 )
[601]480     continue;
481
[498]482    fh = streamless[i].fh;
483
484    ROAR_DBG("clients_check_all(void): fh=%i", fh);
485    FD_SET(fh, &r);
486
[4686]487    if ( g_clients[i]->outbuf != NULL ) {
488     FD_SET(fh, &w);
489    }
490
[498]491    if ( fh > max_fh )
492     max_fh = fh;
493   }
494
[4686]495   if ( (ret = select(max_fh + 1, &r, &w, NULL, &tv)) < 0 ) {
[498]496    return ret;
497   }
498
499   for (i = 0; i < have_streamless; i++) {
500    if ( FD_ISSET(streamless[i].fh, &r) ) {
501     clients_check(streamless[i].id);
502    }
[4686]503    if ( FD_ISSET(streamless[i].fh, &w) ) {
504     clients_flush(streamless[i].id);
505    }
[498]506   }
507 }
508
[71]509 ROAR_DBG("clients_check_all(void) = %i // have value", have);
510 return have;
[1480]511#else
512 return -1;
513#endif
[0]514}
515
516int clients_check     (int id) {
[4326]517 struct roar_client   * c;
[0]518 struct roar_message    m;
519 struct roar_connection con;
520 char * data = NULL;
521 int oldcmd;
522 int r;
[498]523 int rv = 0;
[3926]524 uint32_t flags[2] = {COMMAND_FLAG_NONE, COMMAND_FLAG_NONE};
[4325]525 uint32_t event;
[4678]526 size_t i;
[0]527
[3910]528 _CHECK_CID(id);
529
[4326]530 c = ROAR_CLIENT(g_clients[id]);
531
532 if ( c->fh == -1 )
[0]533  return -1;
534
[4326]535 roar_connect_fh(&con, c->fh);
[0]536
[4326]537 switch (c->proto) {
[2517]538  case ROAR_PROTO_ROARAUDIO:
539    r = roar_recv_message(&con, &m, &data);
[0]540
[2517]541    if ( r == -1 ) { // should we drop the client?
542     clients_delete(id);
543     return -1;
544    }
[0]545
[4325]546    event = ROAR_NOTIFY_CMD2EVENT(m.cmd);
547
[2517]548    roar_debug_message_print(&m);
[0]549
[2517]550    oldcmd = m.cmd;
[0]551
[3926]552    if ( (r = command_exec(id, &m, &data, flags)) == -1 ) {
[2517]553     m.cmd     = ROAR_CMD_ERROR;
554     m.datalen = 0;
555     ROAR_DBG("clients_check(*): Exec of command faild!");
556    } else {
557     if ( m.cmd == oldcmd ) {
558      m.cmd     = ROAR_CMD_OK;
559      m.datalen = 0;
560     } else if ( m.cmd == ROAR_CMD_OK_STOP ) {
561      m.cmd     = ROAR_CMD_OK;
562      rv        = 1;
563     }
564    }
[4298]565    ROAR_DBG("clients_check(*): data=%p", data);
566
[4347]567    if ( flags[1] & COMMAND_FLAG_OUT_NOSEND ) {
568     roar_notify_core_emit_simple(event, id, -1, -1, -1, -1, NULL, 0);
569    } else {
570     roar_notify_core_emit_simple(event, id, -1, -1, m.cmd, -1, NULL, 0);
[4343]571     roar_send_message(&con, &m, flags[1] & COMMAND_FLAG_OUT_LONGDATA ? data : NULL);
[4347]572    }
[3928]573
574    if ( flags[1] & COMMAND_FLAG_OUT_CLOSECON )
575     clients_close(id, 1);
576
[2517]577   break;
[4020]578#ifndef ROAR_WITHOUT_DCOMP_EMUL_RSOUND
[3684]579  case ROAR_PROTO_RSOUND:
[3820]580    rv = emul_rsound_check_client(id, NULL);
[3825]581    if ( rv == 0 ) { // loop as long as we don't get an error.
582     while (rv == 0)
583      rv = emul_rsound_check_client(id, NULL);
584     rv = 0; // restore
585    } else { // in case of error delete the client
[4131]586     if (
587#ifdef EAGAIN
[4153]588          errno != EAGAIN      &&
[4131]589#endif
590#ifdef EWOULDBLOCK
[4153]591          errno != EWOULDBLOCK &&
[4131]592#endif
593#ifdef EINTR
[4153]594          errno != EINTR       &&
[4131]595#endif
[4153]596          1 ) {
[4131]597      rv = clients_delete(id);
598     } else {
599      rv = 0;
600     }
[3825]601    }
[3684]602   break;
603#endif
[2517]604  default:
605    rv = -1;
[4679]606    for (i = 0; g_proto[i].proto != -1; i++) {
[4678]607     if ( g_proto[i].proto == c->proto ) {
608      rv = g_proto[i].check_client(id, NULL);
609     }
610    }
[0]611 }
612
[4297]613 if ( data != NULL )
[0]614  free(data);
615
[2517]616 ROAR_DBG("clients_check(id=%i) = %i", id, rv);
[498]617 return rv;
[0]618}
619
[4686]620int clients_flush      (int id) {
621 struct roar_vio_calls         vio;
622 struct roar_client_server   * cs;
623 struct roar_client          * c;
624 struct roard_proto          * p = NULL;
625 size_t i;
626 size_t len;
627 ssize_t ret;
628 void * buf;
629
630 _CHECK_CID(id);
631
632 c = ROAR_CLIENT(cs = g_clients[id]);
633
634 for (i = 0; g_proto[i].proto != -1; i++) {
635  if ( g_proto[i].proto == c->proto ) {
636   p = &(g_proto[i]);
637   break;
638  }
639 }
640
641 if ( p == NULL )
642  return -1;
643
644 roar_vio_open_fh_socket(&vio, clients_get_fh(id));
645
646 if ( p->flush_client != NULL ) {
647  return p->flush_client(id, &vio);
648 }
649
650 if ( roar_buffer_get_len(cs->outbuf, &len) == -1 )
651  return -1;
652
653 if ( roar_buffer_get_data(cs->outbuf, &buf) == -1 )
654  return -1;
655
656 ret = roar_vio_write(&vio, buf, len);
657
658 if ( ret < 1 ) {
659  clients_delete(id);
660  return -1;
661 }
662
663 if ( ret == len ) {
664  roar_buffer_next(&(cs->outbuf));
665 } else {
666  if ( roar_buffer_set_offset(cs->outbuf, ret) == -1 ) {
667   clients_delete(id);
668   return -1;
669  }
670 }
671
672 if ( cs->outbuf == NULL ) {
673  if ( p->flushed_client != NULL ) {
674   return p->flushed_client(id, &vio);
675  }
676 }
677
678 return 0;
679}
680
[0]681int clients_send_mon  (struct roar_audio_info * sa, uint32_t pos) {
682 int i;
[934]683// int fh;
684 int j;
[2715]685 int keep_going;
[0]686
687 for (i = 0; i < ROAR_CLIENTS_MAX; i++) {
688  if ( g_clients[i] == NULL )
689   continue;
690
[2715]691  keep_going = 1;
692
[934]693/*
[0]694  if ( (fh = g_clients[i]->fh) == -1 )
695   continue;
[934]696*/
[0]697
[4326]698  ROAR_DBG("clients_send_mon(*): client=%i, execed=%i", i, ROAR_CLIENT(g_clients[i])->execed);
[1905]699
[2706]700/*
[0]701  if ( g_clients[i]->execed == -1 ) {
702   // TODO: add some code to send a message to the client insetd of the raw data.
[2706]703*/
[2715]704   for (j = 0; keep_going && j < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; j++) {
[934]705    //if ( (fh = streams_get_fh(g_clients[i]->streams[j])) != -1 ) {
[2715]706    ROAR_DBG("clients_send_mon(*): client=%i, stream=%i -> ?", i, j);
[4326]707    if ( ROAR_CLIENT(g_clients[i])->streams[j] != -1 ) {
708     ROAR_DBG("clients_send_mon(*): client=%i, stream=%i -> %i", i, j, ROAR_CLIENT(g_clients[i])->streams[j]);
709     streams_send_mon(ROAR_CLIENT(g_clients[i])->streams[j]);
[2715]710
711     // the client may be deleted here, check if it still exists:
712     if ( g_clients[i] == NULL )
713      keep_going = 0;
[1905]714    }
[934]715   }
[2706]716/*
[0]717  } else {
718//   streams_check(g_clients[i]->execed);
719   streams_send_mon(g_clients[i]->execed);
720//   if ( streams_send_mon(g_clients[i]->execed) == -1 )
721//    clients_delete(i); // delete client in case we could not write
722  }
[2706]723*/
[0]724 }
725
[1902]726 // TODO: FIXME: should this really be -1?
[0]727 return -1;
728}
729
730int clients_send_filter(struct roar_audio_info * sa, uint32_t pos) {
[4326]731 struct roar_client * c;
[0]732 int i;
733 int fh;
734
735 for (i = 0; i < ROAR_CLIENTS_MAX; i++) {
[4326]736  if ( (c = ROAR_CLIENT(g_clients[i])) == NULL )
[0]737   continue;
738
[4326]739  if ( (fh = c->fh) == -1 )
[0]740   continue;
741
[4326]742  if ( c->execed == -1 ) {
[0]743   // TODO: add some code to send a message to the client insetd of the raw data.
744  } else {
745//   streams_check(g_clients[i]->execed);
[4326]746   streams_send_filter(c->execed);
[0]747//   if ( streams_send_mon(g_clients[i]->execed) == -1 )
748//    clients_delete(i); // delete client in case we could not write
749  }
750 }
751
752 return -1;
753}
754
[4686]755int clients_add_output (int id, struct roar_buffer * buf) {
756 struct roar_client_server   * cs;
757
758 _CHECK_CID(id);
759 cs = g_clients[id];
760
761 if ( cs->outbuf == NULL ) {
762  cs->outbuf = buf;
763 } else {
764  return roar_buffer_add(cs->outbuf, buf);
765 }
766
767 return 0;
768}
769
[4679]770// proto support
771int clients_register_proto(struct roard_proto * proto) {
772 const size_t len = sizeof(g_proto)/sizeof(*g_proto);
773 size_t i;
774
775 if ( proto == NULL )
776  return -1;
777
778 for (i = 0; g_proto[i].proto != -1; i++);
779
780 // i is now at pos of current EOS entry.
781
782 // test if we have space for one more entry:
783 if ( (i+1) >= len )
784  return -1;
785
786 memcpy(&(g_proto[i]), proto, sizeof(*g_proto));
787
788 i++;
789
790 memset(&(g_proto[i]), 0, sizeof(*g_proto));
791 g_proto[i].proto = -1;
792
793 return 0;
794}
795
796
[0]797int client_stream_exec   (int client, int stream) {
[4326]798 struct roar_client * c;
[0]799 int i;
[3920]800 int fh;
[0]801
[3910]802 _CHECK_CID(client);
803
804#if 0
[1901]805 if ( g_clients[client] == NULL ) {
806  ROAR_WARN("client_stream_exec(client=%i, stream=%i) = -1 // client does not exist", client, stream);
[0]807  return -1;
[1901]808 }
[3910]809#endif
[0]810
[4326]811 c = ROAR_CLIENT(g_clients[client]);
812
[0]813 for (i = 0; i < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; i++) {
[4326]814  if ( c->streams[i] == stream ) {
815   c->execed = stream;
[3921]816   if ( streams_is_ready(stream) == 0 ) {
[4326]817    streams_set_fh(stream, c->fh);
[3920]818    streams_set_socktype(stream, ROAR_SOCKET_TYPE_GENSTR);
819   } else {
[4254]820    ROAR_DBG("client_stream_exec(client=%i, stream=%i): fh=?", client, stream);
[4326]821    if ( (fh = c->fh) != -1 ) {
[3925]822     close(fh);
[4326]823     c->fh = -1;
[3925]824    }
[3920]825   }
[2815]826   ROAR_DBG("client_stream_exec(client=%i, stream=%i) = 0", client, stream);
[0]827   return 0;
828  }
829 }
830
[1901]831 ROAR_WARN("client_stream_exec(client=%i, stream=%i) = -1 // client does not own stream", client, stream);
[0]832 return -1;
833}
834
[78]835int client_stream_set_fh (int client, int stream, int fh) {
836 int i;
837
[4240]838 ROAR_DBG("client_stream_set_fh(client=%i, stream=%i, fh=%i) = ?", client, stream, fh);
839
[3910]840 _CHECK_CID(client);
[78]841
842 for (i = 0; i < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; i++) {
[4326]843  if ( ROAR_CLIENT(g_clients[client])->streams[i] == stream ) {
[4240]844   ROAR_DBG("client_stream_set_fh(client=%i, stream=%i, fh=%i): stream found, index %i", client, stream, fh, i);
[4229]845   return streams_set_fh(stream, fh);
[78]846  }
847 }
848
[4240]849 ROAR_WARN("client_stream_set_fh(client=%i, stream=%i, fh=%i) = -1 // client does not own stream", client, stream, fh);
[78]850 return -1;
851}
852
[0]853int client_stream_add    (int client, int stream) {
854 int i;
855
[3910]856 _CHECK_CID(client);
[0]857
858 for (i = 0; i < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; i++) {
[4326]859  if ( ROAR_CLIENT(g_clients[client])->streams[i] == -1 ) {
860   ROAR_CLIENT(g_clients[client])->streams[i] = stream;
[0]861   streams_set_client(stream, client);
862   return 0;
863  }
864 }
865
866 return -1;
867}
868
869int client_stream_delete (int client, int stream) {
870 int i;
871
[3910]872 _CHECK_CID(client);
[0]873
874 for (i = 0; i < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; i++) {
[4326]875  if ( ROAR_CLIENT(g_clients[client])->streams[i] == stream ) {
876   ROAR_CLIENT(g_clients[client])->streams[i] = -1;
[0]877
[4326]878   if ( stream == ROAR_CLIENT(g_clients[client])->execed ) {
[0]879    ROAR_DBG("client_stream_delete(client=%i, stream=%i): stream is execed one, deleting client!", client, stream);
880    clients_delete(client);
881   }
882
883   ROAR_DBG("client_stream_delete(client=%i, stream=%i) = 0", client, stream);
884   return 0;
885  }
886 }
887
888 ROAR_DBG("client_stream_delete(client=%i, stream=%i) = -1", client, stream);
889 return -1;
890}
891
[767]892int client_stream_move   (int client, int stream) {
893 int old_client = streams_get_client(stream);
894
[771]895 ROAR_DBG("client_stream_move(client=%i, stream=%i): old_client = %i", client, stream, old_client);
896
[767]897 if ( old_client != -1 )
898  if ( client_stream_delete(old_client, stream) == -1 )
899   return -1;
900
901 return client_stream_add(client, stream);
902}
903
[4343]904
905// notify thingys
906int clients_wait    (int client, struct roar_event * events, size_t num) {
907 struct roar_client_server * cs;
908 size_t i, c;
909
910 ROAR_DBG("clients_wait(client=%i, events=%p, num=%llu) = ?", client, events, (long long unsigned int)num);
911
912 _CHECK_CID(client);
913
914 cs = g_clients[client];
915
916 if ( cs->waits != NULL )
917  return -1;
918
919 cs->waits = roar_mm_malloc((num+1) * sizeof(struct roar_subscriber *));
920
921 if ( cs->waits == NULL )
922  return -1;
923
924 if ( clients_block(client, 0) != 0 )
925  return -1;
926
927 for (i = 0; i < num; i++) {
928#if defined(DEBUG) && 0
929  dbg_notify_cb(NULL, &(events[i]), cs);
930#endif
931  cs->waits[i] = roar_notify_core_subscribe(NULL, &(events[i]), clients_ncb_wait, cs);
932  if ( cs->waits[i] == NULL ) {
933   for (c = 0; c < i; c++)
934    roar_notify_core_unsubscribe(NULL, cs->waits[c]);
935   roar_mm_free(cs->waits);
936   cs->waits = NULL;
937   clients_block(client, 1);
938   return -1;
939  }
940 }
941
942 cs->waits[num] = NULL;
943
944 ROAR_DBG("clients_wait(client=%i, events=%p, num=%llu) = 0", client, events, (long long unsigned int)num);
945 return 0;
946}
947
948void clients_ncb_wait(struct roar_notify_core * core, struct roar_event * event, void * userdata) {
949 struct roar_client_server * cs = userdata;
950 struct roar_message m;
951 struct roar_connection con;
952 uint16_t * u16 = (uint16_t *) m.data;
953 size_t tmp;
954 size_t i;
955
956 ROAR_DBG("clients_ncb_wait(core=%p, event=%p, userdata=%p) = ?", core, event, userdata);
957
958 for (i = 0; cs->waits[i] != NULL; i++)
959  roar_notify_core_unsubscribe(NULL, cs->waits[i]);
960
961 roar_mm_free(cs->waits);
962 cs->waits = NULL;
963
964 // protocol depended handling...
965 memset(&m, 0, sizeof(m));
966 m.cmd = ROAR_CMD_OK;
967 u16[0] = ROAR_HOST2NET16(0); // Version
968 u16[1] = ROAR_HOST2NET16(0); // flags
969
970 tmp = sizeof(m.data) - 4;
971
972 roar_event_to_blob(event, m.data + 4, &tmp);
973
974 m.datalen = tmp + 4;
975
976 roar_connect_fh(&con, ROAR_CLIENT(cs)->fh);
977 roar_send_message(&con, &m, NULL);
978 // ...end of protocol depended handling.
979
980// clients_block(, 1);
981 // TODO: FIXME: bad hack...
982 cs->blockc--;
983}
984
[4480]985
986// acclev:
987static struct {
988 const enum roard_client_acclev acclev;
989 const char *                   name;
990} _g_acclevs[] = {
991 {ACCLEV_NONE,    "none"   },
992 {ACCLEV_IDENTED, "idented"},
993 {ACCLEV_CONCTL,  "conctl" },
994 {ACCLEV_GUEST,   "guest"  },
995 {ACCLEV_USER,    "user"   },
996 {ACCLEV_PWRUSER, "pwruser"},
997 {ACCLEV_ALL,     "all"    },
998 {-1, NULL}
999};
1000
1001enum roard_client_acclev clients_str2acclev(const char * acclev) {
1002 int i;
1003
1004 for (i = 0; _g_acclevs[i].name != NULL; i++)
1005  if ( !strcasecmp(_g_acclevs[i].name, acclev) )
1006   return _g_acclevs[i].acclev;
1007
1008 return -1;
1009}
1010
1011const char * clients_acclev2str(const enum roard_client_acclev acclev) {
1012 int i;
1013
1014 for (i = 0; _g_acclevs[i].name != NULL; i++)
1015  if ( _g_acclevs[i].acclev == acclev )
1016   return _g_acclevs[i].name;
1017
1018 return NULL;
1019}
1020
[0]1021//ll
Note: See TracBrowser for help on using the repository browser.