source: roaraudio/roard/clients.c @ 4923:eb6f9e17661a

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

use new target syntax of ckport

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