source: roaraudio/roard/clients.c @ 4468:f8d2cccafc74

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

do very basic auth stuff

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