source: roaraudio/roard/clients.c @ 4480:007d11d94d3f

Last change on this file since 4480:007d11d94d3f was 4480:007d11d94d3f, checked in by phi, 14 years ago

added functions for acclev<->string conv

File size: 19.7 KB
Line 
1//clients.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2010
5 *
6 *  This file is part of roard a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  RoarAudio is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
23 *
24 */
25
26#include "roard.h"
27
28#define _CHECK_CID_RET(id,ret) if ( (id) < 0 || (id) > ROAR_CLIENTS_MAX || g_clients[(id)] == NULL ) return (ret)
29#define _CHECK_CID(id)         _CHECK_CID_RET((id), -1)
30
31int clients_init (void) {
32 int i;
33
34 for (i = 0; i < ROAR_CLIENTS_MAX; i++)
35  g_clients[i] = NULL;
36
37 return 0;
38}
39
40int clients_free (void) {
41 int i;
42
43 for (i = 0; i < ROAR_CLIENTS_MAX; i++)
44  if ( g_clients[i] != NULL )
45   clients_delete(i);
46
47 return 0;
48}
49
50int clients_new (void) {
51 int i;
52 int s;
53 struct roar_client_server * ns;
54 struct roar_client * n;
55
56 for (i = 0; i < ROAR_CLIENTS_MAX; i++) {
57  if ( g_clients[i] == NULL ) {
58   ns = roar_mm_malloc(sizeof(struct roar_client_server));
59   n = ROAR_CLIENT(ns);
60
61   memset(ns, 0, sizeof(struct roar_client_server));
62
63   if ( n != NULL ) {
64    n->pid    = -1;
65    n->uid    = -1;
66    n->gid    = -1;
67    n->fh     = -1;
68
69    *n->name = 0;
70    *n->host = 0;
71
72    n->proto     = ROAR_PROTO_ROARAUDIO;
73    n->byteorder = ROAR_BYTEORDER_NETWORK;
74
75    n->acl   = NULL;
76
77    n->execed = -1;
78    for (s = 0; s < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; s++)
79     n->streams[s] = -1;
80
81    if ( roar_nnode_new(&(n->nnode), ROAR_SOCKET_TYPE_UNKNOWN) == -1 ) {
82     roar_mm_free(n);
83     return -1;
84    }
85
86    ns->blockc   = 0;
87    ns->waits    = NULL;
88    ns->acclev   = ACCLEV_NONE;
89
90    g_clients[i] = ns;
91
92    counters_inc(clients, 1);
93    roar_notify_core_emit_snoargs(ROAR_OE_BASICS_NEW, -1, i, ROAR_OT_CLIENT);
94    ROAR_DBG("clients_new(void) = %i", i);
95    return i;
96   } else {
97    ROAR_ERR("clients_new(void): Can not alloc memory for new client: %s", strerror(errno));
98    ROAR_ERR("clients_new(void) = -1");
99    return -1;
100   }
101  }
102 }
103
104 return -1;
105}
106
107int clients_new_from_fh(int fh, int proto, int byteorder, int update_nnode) {
108 struct roar_client * c;
109 int client;
110
111 if ( fh == -1 )
112  return -1;
113
114 if ( proto != ROAR_PROTO_ROARAUDIO || byteorder != ROAR_BYTEORDER_NETWORK )
115  return -1;
116
117 if ( (client = clients_new()) == -1 )
118  return -1;
119
120 if ( clients_set_fh(client, fh) == -1 ) {
121  clients_delete(client);
122  return -1;
123 }
124
125 if ( update_nnode ) {
126  if ( clients_get(client, &c) != -1 ) {
127   if ( roar_nnode_free(&(c->nnode)) != -1 ) {
128    roar_nnode_new_from_fh(&(c->nnode), fh, 1);
129   }
130  }
131 }
132
133 return 0;
134}
135
136int clients_delete (int id) {
137 struct roar_client_server * cs;
138 int i;
139 int close_client_fh = 1;
140
141 ROAR_DBG("clients_delete(id=%i) = ?", id);
142
143 _CHECK_CID(id);
144
145 cs = g_clients[id];
146
147 if ( cs->waits != NULL ) {
148  for (i = 0; cs->waits[i] != NULL; i++)
149   roar_notify_core_unsubscribe(NULL, cs->waits[i]);
150
151  roar_mm_free(cs->waits);
152  cs->waits = NULL;
153 }
154
155 roar_notify_core_emit_snoargs(ROAR_OE_BASICS_DELETE, -1, id, ROAR_OT_CLIENT);
156
157 counters_inc(clients, -1);
158
159 if (ROAR_CLIENT(cs)->execed != -1) {
160//  return streams_delete(g_clients[id]->execed);
161  ROAR_CLIENT(cs)->execed = -1;
162  close_client_fh = 0;
163 }
164
165 for (i = 0; i < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; i++) {
166  streams_delete(ROAR_CLIENT(cs)->streams[i]);
167 }
168
169 if ( ROAR_CLIENT(cs)->fh != -1 && close_client_fh )
170  close(ROAR_CLIENT(cs)->fh);
171
172 roar_nnode_free(&(ROAR_CLIENT(cs)->nnode));
173
174 roar_mm_free(cs);
175 g_clients[id] = NULL;
176
177 ROAR_DBG("clients_delete(id=%i) = 0", id);
178 return 0;
179}
180
181int clients_close      (int id, int nocheck_exec) {
182 struct roar_client * c;
183
184 ROAR_DBG("clients_close(id=%i) = ?", id);
185
186 _CHECK_CID(id);
187
188 c = ROAR_CLIENT(g_clients[id]);
189
190 if ( c->fh == -1 ) {
191  ROAR_DBG("clients_delete(id=%i) = 0", id);
192  return 0;
193 }
194
195 if (nocheck_exec || c->execed != -1) {
196  close(c->fh);
197  c->fh = -1;
198 }
199
200 ROAR_DBG("clients_delete(id=%i) = 0", id);
201 return 0;
202}
203
204int clients_get       (int id, struct roar_client ** client) {
205 _CHECK_CID(id);
206
207 *client = ROAR_CLIENT(g_clients[id]);
208
209 if ( *client == NULL )
210  return -1;
211
212 return 0;
213}
214
215int clients_get_server (int id, struct roar_client_server ** client) {
216 _CHECK_CID(id);
217
218 *client = g_clients[id];
219
220 if ( *client == NULL )
221  return -1;
222
223 return 0;
224}
225
226int clients_set_fh    (int id, int    fh) {
227 struct roar_client * c;
228#ifdef SO_PEERCRED
229 struct ucred cred;
230 socklen_t cred_len = sizeof(cred);
231#endif
232
233 _CHECK_CID(id);
234
235 if ( (c = ROAR_CLIENT(g_clients[id])) == NULL )
236  return -1;
237
238 c->fh = fh;
239
240#ifdef SO_PEERCRED
241 if (getsockopt(fh, SOL_SOCKET, SO_PEERCRED, &cred, &cred_len) != -1) {
242  if ( cred.pid != 0 ) {
243   c->pid = cred.pid;
244   c->uid = cred.uid;
245   c->gid = cred.gid;
246  }
247 } else {
248  ROAR_DBG("req_on_identify(): Can't get creds via SO_PEERCRED: %s", strerror(errno));
249 }
250#elif defined(ROAR_HAVE_GETPEEREID)
251 if (getpeereid(fh, &(c->uid), &(c->gid)) == -1) {
252  ROAR_DBG("req_on_identify(): Can't get creds via getpeereid(): %s", strerror(errno));
253 }
254#endif
255
256 return 0;
257}
258
259int clients_get_fh    (int id) {
260 _CHECK_CID(id);
261
262 return ROAR_CLIENT(g_clients[id])->fh;
263}
264
265int clients_set_pid   (int id, int    pid) {
266 _CHECK_CID(id);
267
268 ROAR_CLIENT(g_clients[id])->pid = pid;
269
270 return 0;
271}
272
273int clients_set_uid   (int id, int    uid) {
274 _CHECK_CID(id);
275
276 ROAR_CLIENT(g_clients[id])->uid = uid;
277
278 return 0;
279}
280
281int clients_set_gid   (int id, int    gid) {
282 _CHECK_CID(id);
283
284 ROAR_CLIENT(g_clients[id])->gid = gid;
285
286 return 0;
287}
288
289int clients_set_proto (int id, int    proto) {
290 int byteorder = ROAR_BYTEORDER_UNKNOWN;
291
292 _CHECK_CID(id);
293
294 switch (proto) {
295  case ROAR_PROTO_ROARAUDIO:
296  case ROAR_PROTO_ESOUND:
297  case ROAR_PROTO_RPLAY:
298  case ROAR_PROTO_SIMPLE:
299    byteorder = ROAR_BYTEORDER_NETWORK;
300   break;
301 }
302
303 ROAR_CLIENT(g_clients[id])->proto     = proto;
304 ROAR_CLIENT(g_clients[id])->byteorder = byteorder;
305
306 return 0;
307}
308
309int clients_block      (int id, int unblock) {
310 _CHECK_CID(id);
311
312 if ( unblock ) {
313  g_clients[id]->blockc--;
314 } else {
315  g_clients[id]->blockc++;
316 }
317
318 return 0;
319}
320
321
322#define MAX_STREAMLESS 8
323
324int clients_check_all (void) {
325#ifdef ROAR_HAVE_SELECT
326 struct roar_client * c;
327 struct timeval tv;
328 fd_set r, e;
329 int i, j;
330 int ret;
331 int fh;
332 int max_fh = -1;
333 int have = 0;
334 struct {
335  int id;
336  int fh;
337 } streamless[MAX_STREAMLESS];
338 int have_streamless = 0;
339 int have_stream;
340
341 FD_ZERO(&r);
342 FD_ZERO(&e);
343
344 tv.tv_sec  = 0;
345 tv.tv_usec = 1;
346
347 for (i = 0; i < ROAR_CLIENTS_MAX; i++) {
348  if ( (c = ROAR_CLIENT(g_clients[i])) == NULL )
349   continue;
350
351  if ( (fh = c->fh) != -1 ) {
352   have++;
353
354   ROAR_DBG("clients_check_all(*): fh=%i", fh);
355
356   FD_SET(fh, &r);
357   FD_SET(fh, &e);
358
359   if ( fh > max_fh )
360    max_fh = fh;
361  }
362
363  have_stream = 0;
364
365  for (j = 0; j < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; j++) {
366   if ( (fh = streams_get_fh(c->streams[j])) != -1 ) {
367    ROAR_DBG("clients_check_all(*): g_clients[i=%i]->streams[j=%i] = %i, fh = %i", i, j, c->streams[j], fh);
368    if ( fh > -1 ) {
369     FD_SET(fh, &r);
370
371     if ( fh > max_fh )
372      max_fh = fh;
373    } else if ( fh == -2 ) {
374     streams_check(c->streams[j]);
375    }
376
377    have_stream = 1;
378   }
379   //printf("D: client=%i, stream=%i, fh=%i\n", i, j, fh);
380  }
381
382  if ( !have_stream && have_streamless < MAX_STREAMLESS ) {
383   streamless[have_streamless  ].id = i;
384   if ( (streamless[have_streamless++].fh = c->fh) == -1 )
385    have_streamless--;
386  }
387 }
388
389 if ( max_fh == -1 )
390  return 0;
391
392 if ( (ret = select(max_fh + 1, &r, NULL, &e, &tv)) < 1 ) {
393  return ret < 0 ? ret : have;
394 }
395
396 for (i = 0; i < ROAR_CLIENTS_MAX; i++) {
397  if ( (c = ROAR_CLIENT(g_clients[i])) == NULL )
398   continue;
399
400  if ( (fh = c->fh) != -1 ) {
401   if ( FD_ISSET(fh, &r) ) {
402    if ( c->execed == -1 ) {
403     clients_check(i);
404     if ( g_clients[i] != NULL && ROAR_CLIENT(g_clients[i])->execed != -1 ) {
405      FD_CLR(fh, &r);
406     }
407/*
408    } else {
409     streams_check(g_clients[i]->execed);
410*/
411    }
412   }
413
414   if ( FD_ISSET(fh, &e) ) {
415    clients_delete(i);
416    continue;
417   }
418  }
419
420  if ( (c = ROAR_CLIENT(g_clients[i])) == NULL )
421   continue;
422
423  for (j = 0; j < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; j++) {
424   ROAR_DBG("clients_check_all(*): D: client=%i, stream=%i, g_clients[i=%i] = %p", i, j, i, g_clients[i]);
425   if ( g_clients[i] == NULL ) // streams_check() bellow can delete our client (why?)
426    break;
427
428   //ROAR_WARN("clients_check_all(*): client=%i: client exists", i);
429   ROAR_DBG("clients_check_all(*): client=%i, stream=%i: id=%i", i, j, c->streams[j]);
430
431   if ( (fh = streams_get_fh(c->streams[j])) != -1 ) {
432    ROAR_DBG("clients_check_all(*): client=%i, stream=%i: fh=%i", i, j, fh);
433    if ( fh > -1 && FD_ISSET(fh, &r) ) {
434     streams_check(c->streams[j]);
435    }
436   }
437  }
438 }
439
440 if ( have_streamless ) {
441   FD_ZERO(&r);
442
443   tv.tv_sec  = 0;
444   tv.tv_usec = 1;
445
446   max_fh = -1;
447
448   for (i = 0; i < have_streamless; i++) {
449    if ( g_clients[j = streamless[i].id] == NULL )
450     continue;
451
452    if ( ROAR_CLIENT(g_clients[j])->execed != -1 )
453     continue;
454
455    fh = streamless[i].fh;
456
457    ROAR_DBG("clients_check_all(void): fh=%i", fh);
458    FD_SET(fh, &r);
459
460    if ( fh > max_fh )
461     max_fh = fh;
462   }
463
464   if ( (ret = select(max_fh + 1, &r, NULL, NULL, &tv)) < 0 ) {
465    return ret;
466   }
467
468   for (i = 0; i < have_streamless; i++) {
469    if ( FD_ISSET(streamless[i].fh, &r) ) {
470     clients_check(streamless[i].id);
471    }
472   }
473 }
474
475 ROAR_DBG("clients_check_all(void) = %i // have value", have);
476 return have;
477#else
478 return -1;
479#endif
480}
481
482int clients_check     (int id) {
483 struct roar_client   * c;
484 struct roar_message    m;
485 struct roar_connection con;
486 char * data = NULL;
487 int oldcmd;
488 int r;
489 int rv = 0;
490 uint32_t flags[2] = {COMMAND_FLAG_NONE, COMMAND_FLAG_NONE};
491 uint32_t event;
492
493 _CHECK_CID(id);
494
495 c = ROAR_CLIENT(g_clients[id]);
496
497 if ( c->fh == -1 )
498  return -1;
499
500 roar_connect_fh(&con, c->fh);
501
502 switch (c->proto) {
503  case ROAR_PROTO_ROARAUDIO:
504    r = roar_recv_message(&con, &m, &data);
505
506    if ( r == -1 ) { // should we drop the client?
507     clients_delete(id);
508     return -1;
509    }
510
511    event = ROAR_NOTIFY_CMD2EVENT(m.cmd);
512
513    roar_debug_message_print(&m);
514
515    oldcmd = m.cmd;
516
517    if ( (r = command_exec(id, &m, &data, flags)) == -1 ) {
518     m.cmd     = ROAR_CMD_ERROR;
519     m.datalen = 0;
520     ROAR_DBG("clients_check(*): Exec of command faild!");
521    } else {
522     if ( m.cmd == oldcmd ) {
523      m.cmd     = ROAR_CMD_OK;
524      m.datalen = 0;
525     } else if ( m.cmd == ROAR_CMD_OK_STOP ) {
526      m.cmd     = ROAR_CMD_OK;
527      rv        = 1;
528     }
529    }
530    ROAR_DBG("clients_check(*): data=%p", data);
531
532    if ( flags[1] & COMMAND_FLAG_OUT_NOSEND ) {
533     roar_notify_core_emit_simple(event, id, -1, -1, -1, -1, NULL, 0);
534    } else {
535     roar_notify_core_emit_simple(event, id, -1, -1, m.cmd, -1, NULL, 0);
536     roar_send_message(&con, &m, flags[1] & COMMAND_FLAG_OUT_LONGDATA ? data : NULL);
537    }
538
539    if ( flags[1] & COMMAND_FLAG_OUT_CLOSECON )
540     clients_close(id, 1);
541
542   break;
543#ifndef ROAR_WITHOUT_DCOMP_EMUL_ESD
544#ifdef ROAR_HAVE_H_ESD
545  case ROAR_PROTO_ESOUND:
546    rv = emul_esd_check_client(id, NULL);
547   break;
548#endif
549#endif
550#ifndef ROAR_WITHOUT_DCOMP_EMUL_RPLAY
551  case ROAR_PROTO_RPLAY:
552    rv = emul_rplay_check_client(id, NULL);
553   break;
554#endif
555#ifndef ROAR_WITHOUT_DCOMP_EMUL_RSOUND
556  case ROAR_PROTO_RSOUND:
557    rv = emul_rsound_check_client(id, NULL);
558    if ( rv == 0 ) { // loop as long as we don't get an error.
559     while (rv == 0)
560      rv = emul_rsound_check_client(id, NULL);
561     rv = 0; // restore
562    } else { // in case of error delete the client
563     if (
564#ifdef EAGAIN
565          errno != EAGAIN      &&
566#endif
567#ifdef EWOULDBLOCK
568          errno != EWOULDBLOCK &&
569#endif
570#ifdef EINTR
571          errno != EINTR       &&
572#endif
573          1 ) {
574      rv = clients_delete(id);
575     } else {
576      rv = 0;
577     }
578    }
579   break;
580#endif
581  default:
582    rv = -1;
583 }
584
585 if ( data != NULL )
586  free(data);
587
588 ROAR_DBG("clients_check(id=%i) = %i", id, rv);
589 return rv;
590}
591
592int clients_send_mon  (struct roar_audio_info * sa, uint32_t pos) {
593 int i;
594// int fh;
595 int j;
596 int keep_going;
597
598 for (i = 0; i < ROAR_CLIENTS_MAX; i++) {
599  if ( g_clients[i] == NULL )
600   continue;
601
602  keep_going = 1;
603
604/*
605  if ( (fh = g_clients[i]->fh) == -1 )
606   continue;
607*/
608
609  ROAR_DBG("clients_send_mon(*): client=%i, execed=%i", i, ROAR_CLIENT(g_clients[i])->execed);
610
611/*
612  if ( g_clients[i]->execed == -1 ) {
613   // TODO: add some code to send a message to the client insetd of the raw data.
614*/
615   for (j = 0; keep_going && j < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; j++) {
616    //if ( (fh = streams_get_fh(g_clients[i]->streams[j])) != -1 ) {
617    ROAR_DBG("clients_send_mon(*): client=%i, stream=%i -> ?", i, j);
618    if ( ROAR_CLIENT(g_clients[i])->streams[j] != -1 ) {
619     ROAR_DBG("clients_send_mon(*): client=%i, stream=%i -> %i", i, j, ROAR_CLIENT(g_clients[i])->streams[j]);
620     streams_send_mon(ROAR_CLIENT(g_clients[i])->streams[j]);
621
622     // the client may be deleted here, check if it still exists:
623     if ( g_clients[i] == NULL )
624      keep_going = 0;
625    }
626   }
627/*
628  } else {
629//   streams_check(g_clients[i]->execed);
630   streams_send_mon(g_clients[i]->execed);
631//   if ( streams_send_mon(g_clients[i]->execed) == -1 )
632//    clients_delete(i); // delete client in case we could not write
633  }
634*/
635 }
636
637 // TODO: FIXME: should this really be -1?
638 return -1;
639}
640
641int clients_send_filter(struct roar_audio_info * sa, uint32_t pos) {
642 struct roar_client * c;
643 int i;
644 int fh;
645
646 for (i = 0; i < ROAR_CLIENTS_MAX; i++) {
647  if ( (c = ROAR_CLIENT(g_clients[i])) == NULL )
648   continue;
649
650  if ( (fh = c->fh) == -1 )
651   continue;
652
653  if ( c->execed == -1 ) {
654   // TODO: add some code to send a message to the client insetd of the raw data.
655  } else {
656//   streams_check(g_clients[i]->execed);
657   streams_send_filter(c->execed);
658//   if ( streams_send_mon(g_clients[i]->execed) == -1 )
659//    clients_delete(i); // delete client in case we could not write
660  }
661 }
662
663 return -1;
664}
665
666int client_stream_exec   (int client, int stream) {
667 struct roar_client * c;
668 int i;
669 int fh;
670
671 _CHECK_CID(client);
672
673#if 0
674 if ( g_clients[client] == NULL ) {
675  ROAR_WARN("client_stream_exec(client=%i, stream=%i) = -1 // client does not exist", client, stream);
676  return -1;
677 }
678#endif
679
680 c = ROAR_CLIENT(g_clients[client]);
681
682 for (i = 0; i < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; i++) {
683  if ( c->streams[i] == stream ) {
684   c->execed = stream;
685   if ( streams_is_ready(stream) == 0 ) {
686    streams_set_fh(stream, c->fh);
687    streams_set_socktype(stream, ROAR_SOCKET_TYPE_GENSTR);
688   } else {
689    ROAR_DBG("client_stream_exec(client=%i, stream=%i): fh=?", client, stream);
690    if ( (fh = c->fh) != -1 ) {
691     close(fh);
692     c->fh = -1;
693    }
694   }
695   ROAR_DBG("client_stream_exec(client=%i, stream=%i) = 0", client, stream);
696   return 0;
697  }
698 }
699
700 ROAR_WARN("client_stream_exec(client=%i, stream=%i) = -1 // client does not own stream", client, stream);
701 return -1;
702}
703
704int client_stream_set_fh (int client, int stream, int fh) {
705 int i;
706
707 ROAR_DBG("client_stream_set_fh(client=%i, stream=%i, fh=%i) = ?", client, stream, fh);
708
709 _CHECK_CID(client);
710
711 for (i = 0; i < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; i++) {
712  if ( ROAR_CLIENT(g_clients[client])->streams[i] == stream ) {
713   ROAR_DBG("client_stream_set_fh(client=%i, stream=%i, fh=%i): stream found, index %i", client, stream, fh, i);
714   return streams_set_fh(stream, fh);
715  }
716 }
717
718 ROAR_WARN("client_stream_set_fh(client=%i, stream=%i, fh=%i) = -1 // client does not own stream", client, stream, fh);
719 return -1;
720}
721
722int client_stream_add    (int client, int stream) {
723 int i;
724
725 _CHECK_CID(client);
726
727 for (i = 0; i < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; i++) {
728  if ( ROAR_CLIENT(g_clients[client])->streams[i] == -1 ) {
729   ROAR_CLIENT(g_clients[client])->streams[i] = stream;
730   streams_set_client(stream, client);
731   return 0;
732  }
733 }
734
735 return -1;
736}
737
738int client_stream_delete (int client, int stream) {
739 int i;
740
741 _CHECK_CID(client);
742
743 for (i = 0; i < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; i++) {
744  if ( ROAR_CLIENT(g_clients[client])->streams[i] == stream ) {
745   ROAR_CLIENT(g_clients[client])->streams[i] = -1;
746
747   if ( stream == ROAR_CLIENT(g_clients[client])->execed ) {
748    ROAR_DBG("client_stream_delete(client=%i, stream=%i): stream is execed one, deleting client!", client, stream);
749    clients_delete(client);
750   }
751
752   ROAR_DBG("client_stream_delete(client=%i, stream=%i) = 0", client, stream);
753   return 0;
754  }
755 }
756
757 ROAR_DBG("client_stream_delete(client=%i, stream=%i) = -1", client, stream);
758 return -1;
759}
760
761int client_stream_move   (int client, int stream) {
762 int old_client = streams_get_client(stream);
763
764 ROAR_DBG("client_stream_move(client=%i, stream=%i): old_client = %i", client, stream, old_client);
765
766 if ( old_client != -1 )
767  if ( client_stream_delete(old_client, stream) == -1 )
768   return -1;
769
770 return client_stream_add(client, stream);
771}
772
773
774// notify thingys
775int clients_wait    (int client, struct roar_event * events, size_t num) {
776 struct roar_client_server * cs;
777 size_t i, c;
778
779 ROAR_DBG("clients_wait(client=%i, events=%p, num=%llu) = ?", client, events, (long long unsigned int)num);
780
781 _CHECK_CID(client);
782
783 cs = g_clients[client];
784
785 if ( cs->waits != NULL )
786  return -1;
787
788 cs->waits = roar_mm_malloc((num+1) * sizeof(struct roar_subscriber *));
789
790 if ( cs->waits == NULL )
791  return -1;
792
793 if ( clients_block(client, 0) != 0 )
794  return -1;
795
796 for (i = 0; i < num; i++) {
797#if defined(DEBUG) && 0
798  dbg_notify_cb(NULL, &(events[i]), cs);
799#endif
800  cs->waits[i] = roar_notify_core_subscribe(NULL, &(events[i]), clients_ncb_wait, cs);
801  if ( cs->waits[i] == NULL ) {
802   for (c = 0; c < i; c++)
803    roar_notify_core_unsubscribe(NULL, cs->waits[c]);
804   roar_mm_free(cs->waits);
805   cs->waits = NULL;
806   clients_block(client, 1);
807   return -1;
808  }
809 }
810
811 cs->waits[num] = NULL;
812
813 ROAR_DBG("clients_wait(client=%i, events=%p, num=%llu) = 0", client, events, (long long unsigned int)num);
814 return 0;
815}
816
817void clients_ncb_wait(struct roar_notify_core * core, struct roar_event * event, void * userdata) {
818 struct roar_client_server * cs = userdata;
819 struct roar_message m;
820 struct roar_connection con;
821 uint16_t * u16 = (uint16_t *) m.data;
822 size_t tmp;
823 size_t i;
824
825 ROAR_DBG("clients_ncb_wait(core=%p, event=%p, userdata=%p) = ?", core, event, userdata);
826
827 for (i = 0; cs->waits[i] != NULL; i++)
828  roar_notify_core_unsubscribe(NULL, cs->waits[i]);
829
830 roar_mm_free(cs->waits);
831 cs->waits = NULL;
832
833 // protocol depended handling...
834 memset(&m, 0, sizeof(m));
835 m.cmd = ROAR_CMD_OK;
836 u16[0] = ROAR_HOST2NET16(0); // Version
837 u16[1] = ROAR_HOST2NET16(0); // flags
838
839 tmp = sizeof(m.data) - 4;
840
841 roar_event_to_blob(event, m.data + 4, &tmp);
842
843 m.datalen = tmp + 4;
844
845 roar_connect_fh(&con, ROAR_CLIENT(cs)->fh);
846 roar_send_message(&con, &m, NULL);
847 // ...end of protocol depended handling.
848
849// clients_block(, 1);
850 // TODO: FIXME: bad hack...
851 cs->blockc--;
852}
853
854
855// acclev:
856static struct {
857 const enum roard_client_acclev acclev;
858 const char *                   name;
859} _g_acclevs[] = {
860 {ACCLEV_NONE,    "none"   },
861 {ACCLEV_IDENTED, "idented"},
862 {ACCLEV_CONCTL,  "conctl" },
863 {ACCLEV_GUEST,   "guest"  },
864 {ACCLEV_USER,    "user"   },
865 {ACCLEV_PWRUSER, "pwruser"},
866 {ACCLEV_ALL,     "all"    },
867 {-1, NULL}
868};
869
870enum roard_client_acclev clients_str2acclev(const char * acclev) {
871 int i;
872
873 for (i = 0; _g_acclevs[i].name != NULL; i++)
874  if ( !strcasecmp(_g_acclevs[i].name, acclev) )
875   return _g_acclevs[i].acclev;
876
877 return -1;
878}
879
880const char * clients_acclev2str(const enum roard_client_acclev acclev) {
881 int i;
882
883 for (i = 0; _g_acclevs[i].name != NULL; i++)
884  if ( _g_acclevs[i].acclev == acclev )
885   return _g_acclevs[i].name;
886
887 return NULL;
888}
889
890//ll
Note: See TracBrowser for help on using the repository browser.