source: roaraudio/roard/clients.c @ 1662:a735f98fab9e

Last change on this file since 1662:a735f98fab9e was 1662:a735f98fab9e, checked in by phi, 15 years ago

changed name of fh in con struct to fh, this should all apps requiring the private member to fail to build, added function to get fh, change code to use them both everythere

File size: 10.6 KB
Line 
1//clients.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008
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
21 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 */
24
25#include "roard.h"
26
27int clients_init (void) {
28 int i;
29
30 for (i = 0; i < ROAR_CLIENTS_MAX; i++)
31  g_clients[i] = NULL;
32
33 return 0;
34}
35
36int clients_free (void) {
37 int i;
38
39 for (i = 0; i < ROAR_CLIENTS_MAX; i++)
40  if ( g_clients[i] )
41   clients_delete(i);
42
43 return 0;
44}
45
46int clients_new (void) {
47 int i;
48 int s;
49 struct roar_client * n;
50
51 for (i = 0; i < ROAR_CLIENTS_MAX; i++) {
52  if ( g_clients[i] == NULL ) {
53   n = malloc(sizeof(struct roar_client));
54   if ( n != NULL ) {
55    n->pid    = -1;
56    n->uid    = -1;
57    n->gid    = -1;
58    n->fh     = -1;
59
60    *n->name = 0;
61    *n->host = 0;
62
63    n->acl   = NULL;
64
65    n->execed = -1;
66    for (s = 0; s < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; s++)
67     n->streams[s] = -1;
68
69    g_clients[i] = n;
70
71    ROAR_DBG("clients_new(void) = %i", i);
72    return i;
73   } else {
74    ROAR_ERR("clients_new(void): Can not alloc memory for new client: %s", strerror(errno));
75    ROAR_ERR("clients_new(void) = -1");
76    return -1;
77   }
78  }
79 }
80
81 return -1;
82}
83
84int clients_delete (int id) {
85 int i;
86 int close_client_fh = 1;
87
88 if ( g_clients[id] == NULL )
89  return -1;
90
91 if (g_clients[id]->execed != -1) {
92//  return streams_delete(g_clients[id]->execed);
93  g_clients[id]->execed = -1;
94  close_client_fh = 0;
95 }
96
97 for (i = 0; i < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; i++) {
98  streams_delete(g_clients[id]->streams[i]);
99 }
100
101 if ( g_clients[id]->fh != -1 && close_client_fh )
102  close(g_clients[id]->fh);
103
104 free(g_clients[id]);
105 g_clients[id] = NULL;
106
107 ROAR_DBG("clients_delete(id=%i) = 0", id);
108 return 0;
109}
110
111int clients_get       (int id, struct roar_client ** client) {
112 *client = g_clients[id];
113
114 if ( *client == NULL )
115  return -1;
116
117 return 0;
118}
119
120int clients_set_fh    (int id, int    fh) {
121
122 if ( g_clients[id] == NULL )
123  return -1;
124
125 g_clients[id]->fh = fh;
126
127 return 0;
128}
129
130int clients_get_fh    (int id) {
131 if ( g_clients[id] == NULL )
132  return -1;
133
134 return g_clients[id]->fh;
135}
136
137int clients_set_pid   (int id, int    pid) {
138 if ( g_clients[id] == NULL )
139  return -1;
140
141 g_clients[id]->pid = pid;
142
143 return 0;
144}
145
146int clients_set_uid   (int id, int    uid) {
147 if ( g_clients[id] == NULL )
148  return -1;
149
150 g_clients[id]->uid = uid;
151
152 return 0;
153}
154
155int clients_set_gid   (int id, int    gid) {
156 if ( g_clients[id] == NULL )
157  return -1;
158
159 g_clients[id]->gid = gid;
160
161 return 0;
162}
163
164#define MAX_STREAMLESS 8
165
166int clients_check_all (void) {
167#ifdef ROAR_HAVE_SELECT
168 struct timeval tv;
169 fd_set r, e;
170 int i, j;
171 int ret;
172 int fh;
173 int max_fh = -1;
174 int have = 0;
175 struct {
176  int id;
177  int fh;
178 } streamless[MAX_STREAMLESS];
179 int have_streamless = 0;
180 int have_stream;
181
182 FD_ZERO(&r);
183 FD_ZERO(&e);
184
185 tv.tv_sec  = 0;
186 tv.tv_usec = 1;
187
188 for (i = 0; i < ROAR_CLIENTS_MAX; i++) {
189  if ( g_clients[i] == NULL )
190   continue;
191
192  if ( (fh = g_clients[i]->fh) != -1 ) {
193   have++;
194
195   ROAR_DBG("clients_check_all(*): fh=%i", fh);
196
197   FD_SET(fh, &r);
198   FD_SET(fh, &e);
199
200   if ( fh > max_fh )
201    max_fh = fh;
202  }
203
204  have_stream = 0;
205
206  for (j = 0; j < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; j++) {
207   if ( (fh = streams_get_fh(g_clients[i]->streams[j])) != -1 ) {
208    if ( fh > -1 ) {
209     FD_SET(fh, &r);
210
211     if ( fh > max_fh )
212      max_fh = fh;
213    }
214
215    have_stream = 1;
216   }
217   //printf("D: client=%i, stream=%i, fh=%i\n", i, j, fh);
218  }
219
220  if ( !have_stream && have_streamless < MAX_STREAMLESS ) {
221   streamless[have_streamless  ].id = i;
222   if ( (streamless[have_streamless++].fh = g_clients[i]->fh) == -1 )
223    have_streamless--;
224  }
225 }
226
227 if ( max_fh == -1 )
228  return 0;
229
230 if ( (ret = select(max_fh + 1, &r, NULL, &e, &tv)) < 1 ) {
231  return ret < 0 ? ret : have;
232 }
233
234 for (i = 0; i < ROAR_CLIENTS_MAX; i++) {
235  if ( g_clients[i] == NULL )
236   continue;
237
238  if ( (fh = g_clients[i]->fh) != -1 ) {
239   if ( FD_ISSET(fh, &r) ) {
240    if ( g_clients[i]->execed == -1 ) {
241     clients_check(i);
242/*
243    } else {
244     streams_check(g_clients[i]->execed);
245*/
246    }
247   }
248
249   if ( FD_ISSET(fh, &e) ) {
250    clients_delete(i);
251    continue;
252   }
253  }
254
255  if ( g_clients[i] == NULL )
256   continue;
257
258  for (j = 0; j < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; j++) {
259   ROAR_DBG("clients_check_all(*): D: client=%i, stream=%i, g_clients[i=%i] = %p", i, j, i, g_clients[i]);
260   if ( g_clients[i] == NULL ) // streams_check() bellow can delete our client (why?)
261    break;
262
263   //ROAR_WARN("clients_check_all(*): client=%i: client exists", i);
264   ROAR_DBG("clients_check_all(*): client=%i, stream=%i: id=%i", i, j, g_clients[i]->streams[j]);
265
266   if ( (fh = streams_get_fh(g_clients[i]->streams[j])) != -1 ) {
267    ROAR_DBG("clients_check_all(*): client=%i, stream=%i: fh=%i", i, j, fh);
268    if ( fh == -2 ) {
269     streams_check(g_clients[i]->streams[j]);
270    } else if ( FD_ISSET(fh, &r) ) {
271     streams_check(g_clients[i]->streams[j]);
272    }
273   }
274  }
275 }
276
277 if ( have_streamless ) {
278   FD_ZERO(&r);
279
280   tv.tv_sec  = 0;
281   tv.tv_usec = 1;
282
283   max_fh = -1;
284
285   for (i = 0; i < have_streamless; i++) {
286    if ( ! g_clients[j = streamless[i].id] )
287     continue;
288
289    if ( g_clients[j]->execed != -1 )
290     continue;
291
292    fh = streamless[i].fh;
293
294    ROAR_DBG("clients_check_all(void): fh=%i", fh);
295    FD_SET(fh, &r);
296
297    if ( fh > max_fh )
298     max_fh = fh;
299   }
300
301   if ( (ret = select(max_fh + 1, &r, NULL, NULL, &tv)) < 0 ) {
302    return ret;
303   }
304
305   for (i = 0; i < have_streamless; i++) {
306    if ( FD_ISSET(streamless[i].fh, &r) ) {
307     clients_check(streamless[i].id);
308    }
309   }
310 }
311
312 ROAR_DBG("clients_check_all(void) = %i // have value", have);
313 return have;
314#else
315 return -1;
316#endif
317}
318
319int clients_check     (int id) {
320 struct roar_message    m;
321 struct roar_connection con;
322 char * data = NULL;
323 int oldcmd;
324 int r;
325 int rv = 0;
326
327 if ( g_clients[id] == NULL )
328  return -1;
329 if ( g_clients[id]->fh == -1 )
330  return -1;
331
332 roar_connect_fh(&con, g_clients[id]->fh);
333
334 r = roar_recv_message(&con, &m, &data);
335
336 if ( r == -1 ) { // should we drop the client?
337  clients_delete(id);
338  return -1;
339 }
340
341 roar_debug_message_print(&m);
342
343 oldcmd = m.cmd;
344
345 if ( (r = command_exec(id, &m, data)) == -1 ) {
346  m.cmd     = ROAR_CMD_ERROR;
347  m.datalen = 0;
348  ROAR_DBG("clients_check(*): Exec of command faild!");
349 } else {
350  if ( m.cmd == oldcmd ) {
351   m.cmd     = ROAR_CMD_OK;
352   m.datalen = 0;
353  } else if ( m.cmd == ROAR_CMD_OK_STOP ) {
354   m.cmd     = ROAR_CMD_OK;
355   rv        = 1;
356  }
357 }
358
359 roar_send_message(&con, &m, NULL);
360
361 if ( data )
362  free(data);
363
364 ROAR_DBG("clients_check(id=%i) = 0", id);
365 return rv;
366}
367
368int clients_send_mon  (struct roar_audio_info * sa, uint32_t pos) {
369 int i;
370// int fh;
371 int j;
372
373 for (i = 0; i < ROAR_CLIENTS_MAX; i++) {
374  if ( g_clients[i] == NULL )
375   continue;
376
377/*
378  if ( (fh = g_clients[i]->fh) == -1 )
379   continue;
380*/
381
382  if ( g_clients[i]->execed == -1 ) {
383   // TODO: add some code to send a message to the client insetd of the raw data.
384   for (j = 0; j < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; j++) {
385    //if ( (fh = streams_get_fh(g_clients[i]->streams[j])) != -1 ) {
386    ROAR_DBG("clients_send_mon(*): client=%i, stream=%i -> %i", i, j, g_clients[i]->streams[j]);
387    if ( g_clients[i]->streams[j] != -1 )
388     streams_send_mon(g_clients[i]->streams[j]);
389   }
390  } else {
391//   streams_check(g_clients[i]->execed);
392   streams_send_mon(g_clients[i]->execed);
393//   if ( streams_send_mon(g_clients[i]->execed) == -1 )
394//    clients_delete(i); // delete client in case we could not write
395  }
396 }
397
398 return -1;
399}
400
401int clients_send_filter(struct roar_audio_info * sa, uint32_t pos) {
402 int i;
403 int fh;
404
405 for (i = 0; i < ROAR_CLIENTS_MAX; i++) {
406  if ( g_clients[i] == NULL )
407   continue;
408
409  if ( (fh = g_clients[i]->fh) == -1 )
410   continue;
411
412  if ( g_clients[i]->execed == -1 ) {
413   // TODO: add some code to send a message to the client insetd of the raw data.
414  } else {
415//   streams_check(g_clients[i]->execed);
416   streams_send_filter(g_clients[i]->execed);
417//   if ( streams_send_mon(g_clients[i]->execed) == -1 )
418//    clients_delete(i); // delete client in case we could not write
419  }
420 }
421
422 return -1;
423}
424
425int client_stream_exec   (int client, int stream) {
426 int i;
427
428 if ( g_clients[client] == NULL )
429  return -1;
430
431 for (i = 0; i < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; i++) {
432  if ( g_clients[client]->streams[i] == stream ) {
433   g_clients[client]->execed = stream;
434   streams_set_fh(stream, g_clients[client]->fh);
435   streams_set_socktype(stream, ROAR_SOCKET_TYPE_GENSTR);
436   return 0;
437  }
438 }
439
440 return -1;
441}
442
443int client_stream_set_fh (int client, int stream, int fh) {
444 int i;
445
446 if ( g_clients[client] == NULL )
447  return -1;
448
449 for (i = 0; i < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; i++) {
450  if ( g_clients[client]->streams[i] == stream ) {
451   streams_set_fh(stream, fh);
452   return 0;
453  }
454 }
455
456 return -1;
457}
458
459int client_stream_add    (int client, int stream) {
460 int i;
461
462 if ( g_clients[client] == NULL )
463  return -1;
464
465 for (i = 0; i < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; i++) {
466  if ( g_clients[client]->streams[i] == -1 ) {
467   g_clients[client]->streams[i] = stream;
468   streams_set_client(stream, client);
469   return 0;
470  }
471 }
472
473 return -1;
474}
475
476int client_stream_delete (int client, int stream) {
477 int i;
478
479 if ( g_clients[client] == NULL )
480  return -1;
481
482 for (i = 0; i < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; i++) {
483  if ( g_clients[client]->streams[i] == stream ) {
484   g_clients[client]->streams[i] = -1;
485
486   if ( stream == g_clients[client]->execed ) {
487    ROAR_DBG("client_stream_delete(client=%i, stream=%i): stream is execed one, deleting client!", client, stream);
488    clients_delete(client);
489   }
490
491   ROAR_DBG("client_stream_delete(client=%i, stream=%i) = 0", client, stream);
492   return 0;
493  }
494 }
495
496 ROAR_DBG("client_stream_delete(client=%i, stream=%i) = -1", client, stream);
497 return -1;
498}
499
500int client_stream_move   (int client, int stream) {
501 int old_client = streams_get_client(stream);
502
503 ROAR_DBG("client_stream_move(client=%i, stream=%i): old_client = %i", client, stream, old_client);
504
505 if ( old_client != -1 )
506  if ( client_stream_delete(old_client, stream) == -1 )
507   return -1;
508
509 return client_stream_add(client, stream);
510}
511
512//ll
Note: See TracBrowser for help on using the repository browser.