source: roaraudio/roard/clients.c @ 4678:8480af30c884

Last change on this file since 4678:8480af30c884 was 4678:8480af30c884, checked in by phi, 13 years ago

convert select(){} into array looked up with for(){} for protocol in client check rutine

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