source: roaraudio/roard/clients.c @ 5192:4237437ca526

Last change on this file since 5192:4237437ca526 was 5192:4237437ca526, checked in by phi, 13 years ago

declare some stuff 'extern', this saves like 5.3KB of diskspace in plugin files and make them more resistant against changes in roard

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