1/*** 2 This file is part of PulseAudio. 3 4 Copyright 2004-2006 Lennart Poettering 5 6 PulseAudio is free software; you can redistribute it and/or modify 7 it under the terms of the GNU Lesser General Public License as published 8 by the Free Software Foundation; either version 2.1 of the License, 9 or (at your option) any later version. 10 11 PulseAudio is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 You should have received a copy of the GNU Lesser General Public License 17 along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. 18***/ 19 20#ifdef HAVE_CONFIG_H 21#include <config.h> 22#endif 23 24#include <stdlib.h> 25 26#include <pulse/xmalloc.h> 27 28#include <pulsecore/cli.h> 29#include <pulsecore/log.h> 30#include <pulsecore/macro.h> 31#include <pulsecore/shared.h> 32 33#include "protocol-cli.h" 34 35/* Don't allow more than this many concurrent connections */ 36#define MAX_CONNECTIONS 25 37 38struct pa_cli_protocol { 39 PA_REFCNT_DECLARE; 40 41 pa_core *core; 42 pa_idxset *connections; 43}; 44 45static void cli_unlink(pa_cli_protocol *p, pa_cli *c) { 46 pa_assert(p); 47 pa_assert(c); 48 49 pa_idxset_remove_by_data(p->connections, c, NULL); 50 pa_cli_free(c); 51} 52 53static void cli_eof_cb(pa_cli*c, void*userdata) { 54 pa_cli_protocol *p = userdata; 55 pa_assert(p); 56 57 cli_unlink(p, c); 58} 59 60void pa_cli_protocol_connect(pa_cli_protocol *p, pa_iochannel *io, pa_module *m) { 61 pa_cli *c; 62 63 pa_assert(p); 64 pa_assert(io); 65 pa_assert(m); 66 67 if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) { 68 pa_log("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS); 69 pa_iochannel_free(io); 70 return; 71 } 72 73 c = pa_cli_new(p->core, io, m); 74 pa_cli_set_eof_callback(c, cli_eof_cb, p); 75 76 pa_idxset_put(p->connections, c, NULL); 77} 78 79void pa_cli_protocol_disconnect(pa_cli_protocol *p, pa_module *m) { 80 pa_cli *c; 81 void *state = NULL; 82 83 pa_assert(p); 84 pa_assert(m); 85 86 while ((c = pa_idxset_iterate(p->connections, &state, NULL))) 87 if (pa_cli_get_module(c) == m) 88 cli_unlink(p, c); 89} 90 91static pa_cli_protocol* cli_protocol_new(pa_core *c) { 92 pa_cli_protocol *p; 93 94 pa_assert(c); 95 96 p = pa_xnew(pa_cli_protocol, 1); 97 PA_REFCNT_INIT(p); 98 p->core = c; 99 p->connections = pa_idxset_new(NULL, NULL); 100 101 pa_assert_se(pa_shared_set(c, "cli-protocol", p) >= 0); 102 103 return p; 104} 105 106pa_cli_protocol* pa_cli_protocol_get(pa_core *c) { 107 pa_cli_protocol *p; 108 109 if ((p = pa_shared_get(c, "cli-protocol"))) 110 return pa_cli_protocol_ref(p); 111 112 return cli_protocol_new(c); 113} 114 115pa_cli_protocol* pa_cli_protocol_ref(pa_cli_protocol *p) { 116 pa_assert(p); 117 pa_assert(PA_REFCNT_VALUE(p) >= 1); 118 119 PA_REFCNT_INC(p); 120 121 return p; 122} 123 124void pa_cli_protocol_unref(pa_cli_protocol *p) { 125 pa_cli *c; 126 pa_assert(p); 127 pa_assert(PA_REFCNT_VALUE(p) >= 1); 128 129 if (PA_REFCNT_DEC(p) > 0) 130 return; 131 132 while ((c = pa_idxset_first(p->connections, NULL))) 133 cli_unlink(p, c); 134 135 pa_idxset_free(p->connections, NULL); 136 137 pa_assert_se(pa_shared_remove(p->core, "cli-protocol") >= 0); 138 139 pa_xfree(p); 140} 141