source: roaraudio/roard/clients.c @ 4347:52d8fa5ac58e

Last change on this file since 4347:52d8fa5ac58e was 4347:52d8fa5ac58e, checked in by phi, 14 years ago

corrected emit for NOSEND commands...

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