source: roaraudio/roard/clients.c @ 4467:74702c84db56

Last change on this file since 4467:74702c84db56 was 4467:74702c84db56, checked in by phi, 14 years ago

implement acclevs like rpld does, check them on command proc however still need to set them correctly.

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