source: roaraudio/roard/clients.c @ 4395:fd02b170c292

Last change on this file since 4395:fd02b170c292 was 4395:fd02b170c292, checked in by phi, 14 years ago

some cleanup

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