source: roaraudio/roard/clients.c @ 4882:e6ef52e26c53

Last change on this file since 4882:e6ef52e26c53 was 4815:df2ef6edb97f, checked in by phi, 13 years ago

added support to roard for record streams.

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