source: roaraudio/roard/clients.c @ 4684:90275bd562b4

Last change on this file since 4684:90275bd562b4 was 4684:90275bd562b4, checked in by phi, 13 years ago

added IO buffers for clients, may be used by protocols.

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