2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 2.1 of the License,
10 or (at your option) any later version.
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
30 #include <pulse/rtclock.h>
31 #include <pulse/sample.h>
32 #include <pulse/timeval.h>
33 #include <pulse/utf8.h>
34 #include <pulse/xmalloc.h>
35 #include <pulse/proplist.h>
37 #include <pulsecore/esound.h>
38 #include <pulsecore/memblock.h>
39 #include <pulsecore/client.h>
40 #include <pulsecore/sink-input.h>
41 #include <pulsecore/sink.h>
42 #include <pulsecore/source-output.h>
43 #include <pulsecore/source.h>
44 #include <pulsecore/core-scache.h>
45 #include <pulsecore/sample-util.h>
46 #include <pulsecore/namereg.h>
47 #include <pulsecore/log.h>
48 #include <pulsecore/core-util.h>
49 #include <pulsecore/core-error.h>
50 #include <pulsecore/ipacl.h>
51 #include <pulsecore/macro.h>
52 #include <pulsecore/thread-mq.h>
53 #include <pulsecore/shared.h>
54 #include <pulsecore/endianmacros.h>
56 #include "protocol-esound.h"
58 /* Don't accept more connection than this */
59 #define MAX_CONNECTIONS 64
61 /* Kick a client if it doesn't authenticate within this time */
62 #define AUTH_TIMEOUT (5*PA_USEC_PER_SEC)
64 #define DEFAULT_COOKIE_FILE ".esd_auth"
66 #define PLAYBACK_BUFFER_SECONDS (.25)
67 #define PLAYBACK_BUFFER_FRAGMENTS (10)
68 #define RECORD_BUFFER_SECONDS (5)
70 #define MAX_CACHE_SAMPLE_SIZE (2048000)
72 #define DEFAULT_SINK_LATENCY (150*PA_USEC_PER_MSEC)
73 #define DEFAULT_SOURCE_LATENCY (150*PA_USEC_PER_MSEC)
75 #define SCACHE_PREFIX "esound."
77 /* This is heavily based on esound's code */
79 typedef struct connection {
84 pa_esound_protocol *protocol;
85 pa_esound_options *options;
88 bool authorized, swap_byte_order;
90 size_t write_data_alloc, write_data_index, write_data_length;
92 size_t read_data_alloc, read_data_length;
94 esd_client_state_t state;
95 pa_sink_input *sink_input;
96 pa_source_output *source_output;
97 pa_memblockq *input_memblockq, *output_memblockq;
98 pa_defer_event *defer_event;
103 pa_memblock *current_memblock;
104 size_t memblock_index;
110 pa_memchunk memchunk;
112 pa_sample_spec sample_spec;
115 pa_time_event *auth_timeout_event;
118 PA_DEFINE_PRIVATE_CLASS(connection, pa_msgobject);
119 #define CONNECTION(o) (connection_cast(o))
121 struct pa_esound_protocol {
125 pa_idxset *connections;
130 SINK_INPUT_MESSAGE_POST_DATA = PA_SINK_INPUT_MESSAGE_MAX, /* data from main loop to sink input */
131 SINK_INPUT_MESSAGE_DISABLE_PREBUF
135 CONNECTION_MESSAGE_REQUEST_DATA,
136 CONNECTION_MESSAGE_POST_DATA,
137 CONNECTION_MESSAGE_UNLINK_CONNECTION
140 typedef struct proto_handler {
142 int (*proc)(connection *c, esd_proto_t request, const void *data, size_t length);
143 const char *description;
144 } esd_proto_handler_info_t;
146 static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk);
147 static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes);
148 static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes);
149 static void sink_input_kill_cb(pa_sink_input *i);
150 static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk);
151 static pa_usec_t source_output_get_latency_cb(pa_source_output *o);
153 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk);
154 static void source_output_kill_cb(pa_source_output *o);
156 static int esd_proto_connect(connection *c, esd_proto_t request, const void *data, size_t length);
157 static int esd_proto_stream_play(connection *c, esd_proto_t request, const void *data, size_t length);
158 static int esd_proto_stream_record(connection *c, esd_proto_t request, const void *data, size_t length);
159 static int esd_proto_get_latency(connection *c, esd_proto_t request, const void *data, size_t length);
160 static int esd_proto_server_info(connection *c, esd_proto_t request, const void *data, size_t length);
161 static int esd_proto_all_info(connection *c, esd_proto_t request, const void *data, size_t length);
162 static int esd_proto_stream_pan(connection *c, esd_proto_t request, const void *data, size_t length);
163 static int esd_proto_sample_pan(connection *c, esd_proto_t request, const void *data, size_t length);
164 static int esd_proto_sample_cache(connection *c, esd_proto_t request, const void *data, size_t length);
165 static int esd_proto_sample_free_or_play(connection *c, esd_proto_t request, const void *data, size_t length);
166 static int esd_proto_sample_get_id(connection *c, esd_proto_t request, const void *data, size_t length);
167 static int esd_proto_standby_or_resume(connection *c, esd_proto_t request, const void *data, size_t length);
168 static int esd_proto_standby_mode(connection *c, esd_proto_t request, const void *data, size_t length);
170 /* the big map of protocol handler info */
171 static struct proto_handler proto_map[ESD_PROTO_MAX] = {
172 { ESD_KEY_LEN + sizeof(int), esd_proto_connect, "connect" },
173 { ESD_KEY_LEN + sizeof(int), NULL, "lock" },
174 { ESD_KEY_LEN + sizeof(int), NULL, "unlock" },
176 { ESD_NAME_MAX + 2 * sizeof(int), esd_proto_stream_play, "stream play" },
177 { ESD_NAME_MAX + 2 * sizeof(int), esd_proto_stream_record, "stream rec" },
178 { ESD_NAME_MAX + 2 * sizeof(int), esd_proto_stream_record, "stream mon" },
180 { ESD_NAME_MAX + 3 * sizeof(int), esd_proto_sample_cache, "sample cache" }, /* 6 */
181 { sizeof(int), esd_proto_sample_free_or_play, "sample free" },
182 { sizeof(int), esd_proto_sample_free_or_play, "sample play" }, /* 8 */
183 { sizeof(int), NULL, "sample loop" },
184 { sizeof(int), NULL, "sample stop" },
185 { (size_t) -1, NULL, "TODO: sample kill" },
187 { ESD_KEY_LEN + sizeof(int), esd_proto_standby_or_resume, "standby" },
188 { ESD_KEY_LEN + sizeof(int), esd_proto_standby_or_resume, "resume" }, /* 13 */
190 { ESD_NAME_MAX, esd_proto_sample_get_id, "sample getid" }, /* 14 */
191 { ESD_NAME_MAX + 2 * sizeof(int), NULL, "stream filter" },
193 { sizeof(int), esd_proto_server_info, "server info" },
194 { sizeof(int), esd_proto_all_info, "all info" },
195 { (size_t) -1, NULL, "TODO: subscribe" },
196 { (size_t) -1, NULL, "TODO: unsubscribe" },
198 { 3 * sizeof(int), esd_proto_stream_pan, "stream pan"},
199 { 3 * sizeof(int), esd_proto_sample_pan, "sample pan" },
201 { sizeof(int), esd_proto_standby_mode, "standby mode" },
202 { 0, esd_proto_get_latency, "get latency" }
205 static void connection_unlink(connection *c) {
212 pa_esound_options_unref(c->options);
217 pa_sink_input_unlink(c->sink_input);
218 pa_sink_input_unref(c->sink_input);
219 c->sink_input = NULL;
222 if (c->source_output) {
223 pa_source_output_unlink(c->source_output);
224 pa_source_output_unref(c->source_output);
225 c->source_output = NULL;
229 pa_client_free(c->client);
233 if (c->state == ESD_STREAMING_DATA)
234 c->protocol->n_player--;
237 pa_iochannel_free(c->io);
241 if (c->defer_event) {
242 c->protocol->core->mainloop->defer_free(c->defer_event);
243 c->defer_event = NULL;
246 if (c->auth_timeout_event) {
247 c->protocol->core->mainloop->time_free(c->auth_timeout_event);
248 c->auth_timeout_event = NULL;
251 pa_assert_se(pa_idxset_remove_by_data(c->protocol->connections, c, NULL) == c);
256 static void connection_free(pa_object *obj) {
257 connection *c = CONNECTION(obj);
260 if (c->input_memblockq)
261 pa_memblockq_free(c->input_memblockq);
262 if (c->output_memblockq)
263 pa_memblockq_free(c->output_memblockq);
265 if (c->playback.current_memblock)
266 pa_memblock_unref(c->playback.current_memblock);
268 pa_xfree(c->read_data);
269 pa_xfree(c->write_data);
271 if (c->scache.memchunk.memblock)
272 pa_memblock_unref(c->scache.memchunk.memblock);
273 pa_xfree(c->scache.name);
275 pa_xfree(c->original_name);
279 static void connection_write_prepare(connection *c, size_t length) {
283 t = c->write_data_length+length;
285 if (c->write_data_alloc < t)
286 c->write_data = pa_xrealloc(c->write_data, c->write_data_alloc = t);
288 pa_assert(c->write_data);
291 static void connection_write(connection *c, const void *data, size_t length) {
295 c->protocol->core->mainloop->defer_enable(c->defer_event, 1);
297 connection_write_prepare(c, length);
299 pa_assert(c->write_data);
301 i = c->write_data_length;
302 c->write_data_length += length;
304 memcpy((uint8_t*) c->write_data + i, data, length);
307 static void format_esd2native(int format, bool swap_bytes, pa_sample_spec *ss) {
310 ss->channels = (uint8_t) (((format & ESD_MASK_CHAN) == ESD_STEREO) ? 2 : 1);
311 if ((format & ESD_MASK_BITS) == ESD_BITS16)
312 ss->format = swap_bytes ? PA_SAMPLE_S16RE : PA_SAMPLE_S16NE;
314 ss->format = PA_SAMPLE_U8;
317 static int format_native2esd(pa_sample_spec *ss) {
320 format = (ss->format == PA_SAMPLE_U8) ? ESD_BITS8 : ESD_BITS16;
321 format |= (ss->channels >= 2) ? ESD_STEREO : ESD_MONO;
326 #define CHECK_VALIDITY(expression, ...) do { \
327 if (PA_UNLIKELY(!(expression))) { \
328 pa_log_warn(__FILE__ ": " __VA_ARGS__); \
333 /*** esound commands ***/
335 static int esd_proto_connect(connection *c, esd_proto_t request, const void *data, size_t length) {
339 connection_assert_ref(c);
341 pa_assert(length == (ESD_KEY_LEN + sizeof(uint32_t)));
343 if (!c->authorized && c->options->auth_cookie) {
346 if ((key = pa_auth_cookie_read(c->options->auth_cookie, ESD_KEY_LEN)))
347 if (memcmp(data, key, ESD_KEY_LEN) == 0)
348 c->authorized = true;
351 if (!c->authorized) {
352 pa_log("Kicked client with invalid authentication key.");
356 if (c->auth_timeout_event) {
357 c->protocol->core->mainloop->time_free(c->auth_timeout_event);
358 c->auth_timeout_event = NULL;
361 data = (const char*)data + ESD_KEY_LEN;
363 memcpy(&ekey, data, sizeof(uint32_t));
364 if (ekey == ESD_ENDIAN_KEY)
365 c->swap_byte_order = false;
366 else if (ekey == ESD_SWAP_ENDIAN_KEY)
367 c->swap_byte_order = true;
369 pa_log_warn("Client sent invalid endian key");
373 pa_proplist_sets(c->client->proplist, "esound.byte_order", c->swap_byte_order ? "reverse" : "native");
376 connection_write(c, &ok, sizeof(int));
380 static int esd_proto_stream_play(connection *c, esd_proto_t request, const void *data, size_t length) {
381 char name[ESD_NAME_MAX], *utf8_name;
382 int32_t format, rate;
385 pa_sink *sink = NULL;
386 pa_sink_input_new_data sdata;
389 connection_assert_ref(c);
391 pa_assert(length == (sizeof(int32_t)*2+ESD_NAME_MAX));
393 memcpy(&format, data, sizeof(int32_t));
394 format = PA_MAYBE_INT32_SWAP(c->swap_byte_order, format);
395 data = (const char*) data + sizeof(int32_t);
397 memcpy(&rate, data, sizeof(int32_t));
398 rate = PA_MAYBE_INT32_SWAP(c->swap_byte_order, rate);
399 data = (const char*) data + sizeof(int32_t);
401 ss.rate = (uint32_t) rate;
402 format_esd2native(format, c->swap_byte_order, &ss);
404 CHECK_VALIDITY(pa_sample_spec_valid(&ss), "Invalid sample specification");
406 if (c->options->default_sink) {
407 sink = pa_namereg_get(c->protocol->core, c->options->default_sink, PA_NAMEREG_SINK);
408 CHECK_VALIDITY(sink, "No such sink: %s", pa_strnull(c->options->default_sink));
411 pa_strlcpy(name, data, sizeof(name));
413 utf8_name = pa_utf8_filter(name);
414 pa_client_set_name(c->client, utf8_name);
417 c->original_name = pa_xstrdup(name);
419 pa_assert(!c->sink_input && !c->input_memblockq);
421 pa_sink_input_new_data_init(&sdata);
422 sdata.driver = __FILE__;
423 sdata.module = c->options->module;
424 sdata.client = c->client;
426 pa_sink_input_new_data_set_sink(&sdata, sink, false, true);
427 pa_sink_input_new_data_set_sample_spec(&sdata, &ss);
429 pa_sink_input_new(&c->sink_input, c->protocol->core, &sdata);
430 pa_sink_input_new_data_done(&sdata);
432 CHECK_VALIDITY(c->sink_input, "Failed to create sink input.");
434 l = (size_t) ((double) pa_bytes_per_second(&ss)*PLAYBACK_BUFFER_SECONDS);
435 pa_sink_input_get_silence(c->sink_input, &silence);
436 c->input_memblockq = pa_memblockq_new(
437 "esound protocol connection input_memblockq",
443 l/PLAYBACK_BUFFER_FRAGMENTS,
446 pa_memblock_unref(silence.memblock);
447 pa_iochannel_socket_set_rcvbuf(c->io, l);
449 c->sink_input->parent.process_msg = sink_input_process_msg;
450 c->sink_input->pop = sink_input_pop_cb;
451 c->sink_input->process_rewind = sink_input_process_rewind_cb;
452 c->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;
453 c->sink_input->kill = sink_input_kill_cb;
454 c->sink_input->userdata = c;
456 pa_sink_input_set_requested_latency(c->sink_input, DEFAULT_SINK_LATENCY);
458 c->state = ESD_STREAMING_DATA;
460 c->protocol->n_player++;
462 pa_atomic_store(&c->playback.missing, (int) pa_memblockq_pop_missing(c->input_memblockq));
464 pa_sink_input_put(c->sink_input);
469 static int esd_proto_stream_record(connection *c, esd_proto_t request, const void *data, size_t length) {
470 char name[ESD_NAME_MAX], *utf8_name;
471 int32_t format, rate;
472 pa_source *source = NULL;
475 pa_source_output_new_data sdata;
477 connection_assert_ref(c);
479 pa_assert(length == (sizeof(int32_t)*2+ESD_NAME_MAX));
481 memcpy(&format, data, sizeof(int32_t));
482 format = PA_MAYBE_INT32_SWAP(c->swap_byte_order, format);
483 data = (const char*) data + sizeof(int32_t);
485 memcpy(&rate, data, sizeof(int32_t));
486 rate = PA_MAYBE_INT32_SWAP(c->swap_byte_order, rate);
487 data = (const char*) data + sizeof(int32_t);
489 ss.rate = (uint32_t) rate;
490 format_esd2native(format, c->swap_byte_order, &ss);
492 CHECK_VALIDITY(pa_sample_spec_valid(&ss), "Invalid sample specification.");
494 if (request == ESD_PROTO_STREAM_MON) {
497 sink = pa_namereg_get(c->protocol->core, c->options->default_sink, PA_NAMEREG_SINK);
498 CHECK_VALIDITY(sink, "No such sink: %s", pa_strnull(c->options->default_sink));
500 source = sink->monitor_source;
501 CHECK_VALIDITY(source, "No such source.");
503 pa_assert(request == ESD_PROTO_STREAM_REC);
505 if (c->options->default_source) {
506 source = pa_namereg_get(c->protocol->core, c->options->default_source, PA_NAMEREG_SOURCE);
507 CHECK_VALIDITY(source, "No such source: %s", pa_strnull(c->options->default_source));
511 pa_strlcpy(name, data, sizeof(name));
513 utf8_name = pa_utf8_filter(name);
514 pa_client_set_name(c->client, utf8_name);
517 c->original_name = pa_xstrdup(name);
519 pa_assert(!c->output_memblockq && !c->source_output);
521 pa_source_output_new_data_init(&sdata);
522 sdata.driver = __FILE__;
523 sdata.module = c->options->module;
524 sdata.client = c->client;
526 pa_source_output_new_data_set_source(&sdata, source, false, true);
527 pa_source_output_new_data_set_sample_spec(&sdata, &ss);
529 pa_source_output_new(&c->source_output, c->protocol->core, &sdata);
530 pa_source_output_new_data_done(&sdata);
532 CHECK_VALIDITY(c->source_output, "Failed to create source output.");
534 l = (size_t) (pa_bytes_per_second(&ss)*RECORD_BUFFER_SECONDS);
535 c->output_memblockq = pa_memblockq_new(
536 "esound protocol connection output_memblockq",
545 pa_iochannel_socket_set_sndbuf(c->io, l);
547 c->source_output->push = source_output_push_cb;
548 c->source_output->kill = source_output_kill_cb;
549 c->source_output->get_latency = source_output_get_latency_cb;
550 c->source_output->userdata = c;
552 pa_source_output_set_requested_latency(c->source_output, DEFAULT_SOURCE_LATENCY);
554 c->state = ESD_STREAMING_DATA;
556 c->protocol->n_player++;
558 pa_source_output_put(c->source_output);
563 static int esd_proto_get_latency(connection *c, esd_proto_t request, const void *data, size_t length) {
567 connection_assert_ref(c);
569 pa_assert(length == 0);
571 if (!(sink = pa_namereg_get(c->protocol->core, c->options->default_sink, PA_NAMEREG_SINK)))
574 double usec = (double) pa_sink_get_requested_latency(sink);
575 latency = (int) ((usec*44100)/1000000);
578 latency = PA_MAYBE_INT32_SWAP(c->swap_byte_order, latency);
579 connection_write(c, &latency, sizeof(int32_t));
584 static int esd_proto_server_info(connection *c, esd_proto_t request, const void *data, size_t length) {
585 int32_t rate = 44100, format = ESD_STEREO|ESD_BITS16;
589 connection_assert_ref(c);
591 pa_assert(length == sizeof(int32_t));
593 if ((sink = pa_namereg_get(c->protocol->core, c->options->default_sink, PA_NAMEREG_SINK))) {
594 rate = (int32_t) sink->sample_spec.rate;
595 format = format_native2esd(&sink->sample_spec);
598 connection_write_prepare(c, sizeof(int32_t) * 3);
601 connection_write(c, &response, sizeof(int32_t));
602 rate = PA_MAYBE_INT32_SWAP(c->swap_byte_order, rate);
603 connection_write(c, &rate, sizeof(int32_t));
604 format = PA_MAYBE_INT32_SWAP(c->swap_byte_order, format);
605 connection_write(c, &format, sizeof(int32_t));
610 static int esd_proto_all_info(connection *c, esd_proto_t request, const void *data, size_t length) {
613 uint32_t idx = PA_IDXSET_INVALID;
615 char terminator[sizeof(int32_t)*6+ESD_NAME_MAX];
617 connection_assert_ref(c);
619 pa_assert(length == sizeof(int32_t));
621 if (esd_proto_server_info(c, request, data, length) < 0)
624 k = sizeof(int32_t)*5+ESD_NAME_MAX;
625 s = sizeof(int32_t)*6+ESD_NAME_MAX;
626 nsamples = pa_idxset_size(c->protocol->core->scache);
627 t = s*(nsamples+1) + k*(c->protocol->n_player+1);
629 connection_write_prepare(c, t);
631 memset(terminator, 0, sizeof(terminator));
633 PA_IDXSET_FOREACH(conn, c->protocol->connections, idx) {
634 int32_t id, format = ESD_BITS16 | ESD_STEREO, rate = 44100, lvolume = ESD_VOLUME_BASE, rvolume = ESD_VOLUME_BASE;
635 char name[ESD_NAME_MAX];
637 if (conn->state != ESD_STREAMING_DATA)
640 pa_assert(t >= k*2+s);
642 if (conn->sink_input) {
644 pa_sink_input_get_volume(conn->sink_input, &volume, true);
645 rate = (int32_t) conn->sink_input->sample_spec.rate;
646 lvolume = (int32_t) ((volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM);
647 rvolume = (int32_t) ((volume.values[volume.channels == 2 ? 1 : 0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM);
648 format = format_native2esd(&conn->sink_input->sample_spec);
652 id = PA_MAYBE_INT32_SWAP(c->swap_byte_order, (int32_t) (conn->index+1));
653 connection_write(c, &id, sizeof(int32_t));
656 memset(name, 0, ESD_NAME_MAX); /* don't leak old data */
657 if (conn->original_name)
658 strncpy(name, conn->original_name, ESD_NAME_MAX);
659 else if (conn->client && pa_proplist_gets(conn->client->proplist, PA_PROP_APPLICATION_NAME))
660 strncpy(name, pa_proplist_gets(conn->client->proplist, PA_PROP_APPLICATION_NAME), ESD_NAME_MAX);
661 connection_write(c, name, ESD_NAME_MAX);
664 rate = PA_MAYBE_INT32_SWAP(c->swap_byte_order, rate);
665 connection_write(c, &rate, sizeof(int32_t));
668 lvolume = PA_MAYBE_INT32_SWAP(c->swap_byte_order, lvolume);
669 connection_write(c, &lvolume, sizeof(int32_t));
672 rvolume = PA_MAYBE_INT32_SWAP(c->swap_byte_order, rvolume);
673 connection_write(c, &rvolume, sizeof(int32_t));
676 format = PA_MAYBE_INT32_SWAP(c->swap_byte_order, format);
677 connection_write(c, &format, sizeof(int32_t));
682 pa_assert(t == s*(nsamples+1)+k);
685 connection_write(c, terminator, k);
690 idx = PA_IDXSET_INVALID;
692 PA_IDXSET_FOREACH(ce, c->protocol->core->scache, idx) {
693 int32_t id, rate, lvolume, rvolume, format, len;
694 char name[ESD_NAME_MAX];
695 pa_channel_map stereo = { .channels = 2, .map = { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT } };
701 if (ce->volume_is_set) {
703 pa_cvolume_remap(&volume, &ce->channel_map, &stereo);
705 pa_cvolume_reset(&volume, 2);
707 if (ce->memchunk.memblock)
708 ss = ce->sample_spec;
710 ss.format = PA_SAMPLE_S16NE;
716 id = PA_MAYBE_INT32_SWAP(c->swap_byte_order, (int) (ce->index+1));
717 connection_write(c, &id, sizeof(int32_t));
720 memset(name, 0, ESD_NAME_MAX); /* don't leak old data */
721 if (strncmp(ce->name, SCACHE_PREFIX, sizeof(SCACHE_PREFIX)-1) == 0)
722 strncpy(name, ce->name+sizeof(SCACHE_PREFIX)-1, ESD_NAME_MAX);
724 pa_snprintf(name, ESD_NAME_MAX, "native.%s", ce->name);
725 connection_write(c, name, ESD_NAME_MAX);
728 rate = PA_MAYBE_INT32_SWAP(c->swap_byte_order, (int32_t) ss.rate);
729 connection_write(c, &rate, sizeof(int32_t));
732 lvolume = PA_MAYBE_INT32_SWAP(c->swap_byte_order, (int32_t) ((volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM));
733 connection_write(c, &lvolume, sizeof(int32_t));
736 rvolume = PA_MAYBE_INT32_SWAP(c->swap_byte_order, (int32_t) ((volume.values[1]*ESD_VOLUME_BASE)/PA_VOLUME_NORM));
737 connection_write(c, &rvolume, sizeof(int32_t));
740 format = PA_MAYBE_INT32_SWAP(c->swap_byte_order, format_native2esd(&ss));
741 connection_write(c, &format, sizeof(int32_t));
744 len = PA_MAYBE_INT32_SWAP(c->swap_byte_order, (int) ce->memchunk.length);
745 connection_write(c, &len, sizeof(int32_t));
753 connection_write(c, terminator, s);
758 static int esd_proto_stream_pan(connection *c, esd_proto_t request, const void *data, size_t length) {
760 uint32_t idx, lvolume, rvolume;
763 connection_assert_ref(c);
765 pa_assert(length == sizeof(int32_t)*3);
767 memcpy(&idx, data, sizeof(uint32_t));
768 idx = PA_MAYBE_UINT32_SWAP(c->swap_byte_order, idx) - 1;
769 data = (const char*)data + sizeof(uint32_t);
771 memcpy(&lvolume, data, sizeof(uint32_t));
772 lvolume = PA_MAYBE_UINT32_SWAP(c->swap_byte_order, lvolume);
773 data = (const char*)data + sizeof(uint32_t);
775 memcpy(&rvolume, data, sizeof(uint32_t));
776 rvolume = PA_MAYBE_UINT32_SWAP(c->swap_byte_order, rvolume);
778 if ((conn = pa_idxset_get_by_index(c->protocol->connections, idx)) && conn->sink_input) {
780 volume.values[0] = (lvolume*PA_VOLUME_NORM)/ESD_VOLUME_BASE;
781 volume.values[1] = (rvolume*PA_VOLUME_NORM)/ESD_VOLUME_BASE;
782 volume.channels = conn->sink_input->sample_spec.channels;
784 pa_sink_input_set_volume(conn->sink_input, &volume, true, true);
789 connection_write(c, &ok, sizeof(int32_t));
794 static int esd_proto_sample_pan(connection *c, esd_proto_t request, const void *data, size_t length) {
796 uint32_t idx, lvolume, rvolume;
800 connection_assert_ref(c);
802 pa_assert(length == sizeof(int32_t)*3);
804 memcpy(&idx, data, sizeof(uint32_t));
805 idx = PA_MAYBE_UINT32_SWAP(c->swap_byte_order, idx) - 1;
806 data = (const char*)data + sizeof(uint32_t);
808 memcpy(&lvolume, data, sizeof(uint32_t));
809 lvolume = PA_MAYBE_UINT32_SWAP(c->swap_byte_order, lvolume);
810 data = (const char*)data + sizeof(uint32_t);
812 memcpy(&rvolume, data, sizeof(uint32_t));
813 rvolume = PA_MAYBE_UINT32_SWAP(c->swap_byte_order, rvolume);
815 volume.values[0] = (lvolume*PA_VOLUME_NORM)/ESD_VOLUME_BASE;
816 volume.values[1] = (rvolume*PA_VOLUME_NORM)/ESD_VOLUME_BASE;
819 if ((ce = pa_idxset_get_by_index(c->protocol->core->scache, idx))) {
820 pa_channel_map stereo = { .channels = 2, .map = { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT } };
822 pa_cvolume_remap(&volume, &stereo, &ce->channel_map);
824 ce->volume_is_set = true;
828 connection_write(c, &ok, sizeof(int32_t));
833 static int esd_proto_sample_cache(connection *c, esd_proto_t request, const void *data, size_t length) {
835 int32_t format, rate, sc_length;
837 char name[ESD_NAME_MAX+sizeof(SCACHE_PREFIX)-1];
839 connection_assert_ref(c);
841 pa_assert(length == (ESD_NAME_MAX+3*sizeof(int32_t)));
843 memcpy(&format, data, sizeof(int32_t));
844 format = PA_MAYBE_INT32_SWAP(c->swap_byte_order, format);
845 data = (const char*)data + sizeof(int32_t);
847 memcpy(&rate, data, sizeof(int32_t));
848 rate = PA_MAYBE_INT32_SWAP(c->swap_byte_order, rate);
849 data = (const char*)data + sizeof(int32_t);
851 ss.rate = (uint32_t) rate;
852 format_esd2native(format, c->swap_byte_order, &ss);
854 CHECK_VALIDITY(pa_sample_spec_valid(&ss), "Invalid sample specification.");
856 memcpy(&sc_length, data, sizeof(int32_t));
857 sc_length = PA_MAYBE_INT32_SWAP(c->swap_byte_order, sc_length);
858 data = (const char*)data + sizeof(int32_t);
860 CHECK_VALIDITY(sc_length <= MAX_CACHE_SAMPLE_SIZE, "Sample too large (%d bytes).", (int)sc_length);
862 strcpy(name, SCACHE_PREFIX);
863 pa_strlcpy(name+sizeof(SCACHE_PREFIX)-1, data, ESD_NAME_MAX);
865 CHECK_VALIDITY(pa_utf8_valid(name), "Invalid UTF8 in sample name.");
867 pa_assert(!c->scache.memchunk.memblock);
868 c->scache.memchunk.memblock = pa_memblock_new(c->protocol->core->mempool, (size_t) sc_length);
869 c->scache.memchunk.index = 0;
870 c->scache.memchunk.length = (size_t) sc_length;
871 c->scache.sample_spec = ss;
872 pa_assert(!c->scache.name);
873 c->scache.name = pa_xstrdup(name);
875 c->state = ESD_CACHING_SAMPLE;
877 pa_scache_add_item(c->protocol->core, c->scache.name, NULL, NULL, NULL, c->client->proplist, &idx);
880 connection_write(c, &idx, sizeof(uint32_t));
885 static int esd_proto_sample_get_id(connection *c, esd_proto_t request, const void *data, size_t length) {
888 char name[ESD_NAME_MAX+sizeof(SCACHE_PREFIX)-1];
890 connection_assert_ref(c);
892 pa_assert(length == ESD_NAME_MAX);
894 strcpy(name, SCACHE_PREFIX);
895 pa_strlcpy(name+sizeof(SCACHE_PREFIX)-1, data, ESD_NAME_MAX);
897 CHECK_VALIDITY(pa_utf8_valid(name), "Invalid UTF8 in sample name.");
900 if ((idx = pa_scache_get_id_by_name(c->protocol->core, name)) != PA_IDXSET_INVALID)
901 ok = (int32_t) idx + 1;
903 connection_write(c, &ok, sizeof(int32_t));
908 static int esd_proto_sample_free_or_play(connection *c, esd_proto_t request, const void *data, size_t length) {
913 connection_assert_ref(c);
915 pa_assert(length == sizeof(int32_t));
917 memcpy(&idx, data, sizeof(uint32_t));
918 idx = PA_MAYBE_UINT32_SWAP(c->swap_byte_order, idx) - 1;
922 if ((name = pa_scache_get_name_by_id(c->protocol->core, idx))) {
923 if (request == ESD_PROTO_SAMPLE_PLAY) {
926 if ((sink = pa_namereg_get(c->protocol->core, c->options->default_sink, PA_NAMEREG_SINK)))
927 if (pa_scache_play_item(c->protocol->core, name, sink, PA_VOLUME_NORM, c->client->proplist, NULL) >= 0)
928 ok = (int32_t) idx + 1;
930 pa_assert(request == ESD_PROTO_SAMPLE_FREE);
932 if (pa_scache_remove_item(c->protocol->core, name) >= 0)
933 ok = (int32_t) idx + 1;
937 connection_write(c, &ok, sizeof(int32_t));
942 static int esd_proto_standby_or_resume(connection *c, esd_proto_t request, const void *data, size_t length) {
945 connection_assert_ref(c);
947 connection_write_prepare(c, sizeof(int32_t) * 2);
948 connection_write(c, &ok, sizeof(int32_t));
950 pa_log_debug("%s of all sinks and sources requested by client %" PRIu32 ".",
951 request == ESD_PROTO_STANDBY ? "Suspending" : "Resuming", c->client->index);
953 if (request == ESD_PROTO_STANDBY) {
954 ok = pa_sink_suspend_all(c->protocol->core, true, PA_SUSPEND_USER) >= 0;
955 ok &= pa_source_suspend_all(c->protocol->core, true, PA_SUSPEND_USER) >= 0;
957 pa_assert(request == ESD_PROTO_RESUME);
958 ok = pa_sink_suspend_all(c->protocol->core, false, PA_SUSPEND_USER) >= 0;
959 ok &= pa_source_suspend_all(c->protocol->core, false, PA_SUSPEND_USER) >= 0;
962 connection_write(c, &ok, sizeof(int32_t));
967 static int esd_proto_standby_mode(connection *c, esd_proto_t request, const void *data, size_t length) {
972 connection_assert_ref(c);
976 if ((sink = pa_namereg_get(c->protocol->core, c->options->default_sink, PA_NAMEREG_SINK)))
977 if (sink->state == PA_SINK_SUSPENDED)
978 mode = ESM_ON_STANDBY;
980 if ((source = pa_namereg_get(c->protocol->core, c->options->default_source, PA_NAMEREG_SOURCE)))
981 if (source->state == PA_SOURCE_SUSPENDED)
982 mode = ESM_ON_STANDBY;
984 mode = PA_MAYBE_INT32_SWAP(c->swap_byte_order, mode);
986 connection_write(c, &mode, sizeof(mode));
990 /*** client callbacks ***/
992 static void client_kill_cb(pa_client *c) {
995 connection_unlink(CONNECTION(c->userdata));
998 /*** pa_iochannel callbacks ***/
1000 static int do_read(connection *c) {
1001 connection_assert_ref(c);
1003 /* pa_log("READ"); */
1005 if (c->state == ESD_NEXT_REQUEST) {
1007 pa_assert(c->read_data_length < sizeof(c->request));
1009 if ((r = pa_iochannel_read(c->io,
1010 ((uint8_t*) &c->request) + c->read_data_length,
1011 sizeof(c->request) - c->read_data_length)) <= 0) {
1013 if (r < 0 && errno == EAGAIN)
1016 pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF");
1020 c->read_data_length += (size_t) r;
1022 if (c->read_data_length >= sizeof(c->request)) {
1023 struct proto_handler *handler;
1025 c->request = PA_MAYBE_INT32_SWAP(c->swap_byte_order, c->request);
1027 if (c->request < ESD_PROTO_CONNECT || c->request >= ESD_PROTO_MAX) {
1028 pa_log("received invalid request.");
1032 handler = proto_map+c->request;
1034 /* pa_log("executing request #%u", c->request); */
1036 if (!handler->proc) {
1037 pa_log("received unimplemented request #%u.", c->request);
1041 if (handler->data_length == 0) {
1042 c->read_data_length = 0;
1044 if (handler->proc(c, c->request, NULL, 0) < 0)
1048 if (c->read_data_alloc < handler->data_length)
1049 c->read_data = pa_xrealloc(c->read_data, c->read_data_alloc = handler->data_length);
1050 pa_assert(c->read_data);
1052 c->state = ESD_NEEDS_REQDATA;
1053 c->read_data_length = 0;
1057 } else if (c->state == ESD_NEEDS_REQDATA) {
1059 struct proto_handler *handler = proto_map+c->request;
1061 pa_assert(handler->proc);
1063 pa_assert(c->read_data && c->read_data_length < handler->data_length);
1065 if ((r = pa_iochannel_read(c->io,
1066 (uint8_t*) c->read_data + c->read_data_length,
1067 handler->data_length - c->read_data_length)) <= 0) {
1069 if (r < 0 && errno == EAGAIN)
1072 pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF");
1076 c->read_data_length += (size_t) r;
1077 if (c->read_data_length >= handler->data_length) {
1078 size_t l = c->read_data_length;
1079 pa_assert(handler->proc);
1081 c->state = ESD_NEXT_REQUEST;
1082 c->read_data_length = 0;
1084 if (handler->proc(c, c->request, c->read_data, l) < 0)
1087 } else if (c->state == ESD_CACHING_SAMPLE) {
1091 pa_assert(c->scache.memchunk.memblock);
1092 pa_assert(c->scache.name);
1093 pa_assert(c->scache.memchunk.index < c->scache.memchunk.length);
1095 p = pa_memblock_acquire(c->scache.memchunk.memblock);
1096 r = pa_iochannel_read(c->io, (uint8_t*) p+c->scache.memchunk.index, c->scache.memchunk.length-c->scache.memchunk.index);
1097 pa_memblock_release(c->scache.memchunk.memblock);
1100 if (r < 0 && errno == EAGAIN)
1103 pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF");
1107 c->scache.memchunk.index += (size_t) r;
1108 pa_assert(c->scache.memchunk.index <= c->scache.memchunk.length);
1110 if (c->scache.memchunk.index == c->scache.memchunk.length) {
1113 c->scache.memchunk.index = 0;
1114 pa_scache_add_item(c->protocol->core, c->scache.name, &c->scache.sample_spec, NULL, &c->scache.memchunk, c->client->proplist, &idx);
1116 pa_memblock_unref(c->scache.memchunk.memblock);
1117 pa_memchunk_reset(&c->scache.memchunk);
1119 pa_xfree(c->scache.name);
1120 c->scache.name = NULL;
1122 c->state = ESD_NEXT_REQUEST;
1125 connection_write(c, &idx, sizeof(uint32_t));
1128 } else if (c->state == ESD_STREAMING_DATA && c->sink_input) {
1135 pa_assert(c->input_memblockq);
1137 /* pa_log("STREAMING_DATA"); */
1139 if ((l = (size_t) pa_atomic_load(&c->playback.missing)) <= 0)
1142 if (c->playback.current_memblock) {
1144 space = pa_memblock_get_length(c->playback.current_memblock) - c->playback.memblock_index;
1147 pa_memblock_unref(c->playback.current_memblock);
1148 c->playback.current_memblock = NULL;
1152 if (!c->playback.current_memblock) {
1153 pa_assert_se(c->playback.current_memblock = pa_memblock_new(c->protocol->core->mempool, (size_t) -1));
1154 c->playback.memblock_index = 0;
1156 space = pa_memblock_get_length(c->playback.current_memblock);
1162 p = pa_memblock_acquire(c->playback.current_memblock);
1163 r = pa_iochannel_read(c->io, (uint8_t*) p+c->playback.memblock_index, l);
1164 pa_memblock_release(c->playback.current_memblock);
1168 if (r < 0 && errno == EAGAIN)
1171 pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF");
1175 chunk.memblock = c->playback.current_memblock;
1176 chunk.index = c->playback.memblock_index;
1177 chunk.length = (size_t) r;
1179 c->playback.memblock_index += (size_t) r;
1181 pa_atomic_sub(&c->playback.missing, (int) r);
1182 pa_asyncmsgq_post(c->sink_input->sink->asyncmsgq, PA_MSGOBJECT(c->sink_input), SINK_INPUT_MESSAGE_POST_DATA, NULL, 0, &chunk, NULL);
1188 static int do_write(connection *c) {
1189 connection_assert_ref(c);
1191 /* pa_log("WRITE"); */
1193 if (c->write_data_length) {
1196 pa_assert(c->write_data_index < c->write_data_length);
1197 if ((r = pa_iochannel_write(c->io, (uint8_t*) c->write_data+c->write_data_index, c->write_data_length-c->write_data_index)) < 0) {
1198 pa_log("write(): %s", pa_cstrerror(errno));
1202 c->write_data_index += (size_t) r;
1203 if (c->write_data_index >= c->write_data_length)
1204 c->write_data_length = c->write_data_index = 0;
1208 } else if (c->state == ESD_STREAMING_DATA && c->source_output) {
1213 if (pa_memblockq_peek(c->output_memblockq, &chunk) < 0)
1216 pa_assert(chunk.memblock);
1217 pa_assert(chunk.length);
1219 p = pa_memblock_acquire(chunk.memblock);
1220 r = pa_iochannel_write(c->io, (uint8_t*) p+chunk.index, chunk.length);
1221 pa_memblock_release(chunk.memblock);
1223 pa_memblock_unref(chunk.memblock);
1226 pa_log("write(): %s", pa_cstrerror(errno));
1230 pa_memblockq_drop(c->output_memblockq, (size_t) r);
1237 static void do_work(connection *c) {
1238 connection_assert_ref(c);
1240 c->protocol->core->mainloop->defer_enable(c->defer_event, 0);
1245 if (pa_iochannel_is_readable(c->io))
1249 if (c->state == ESD_STREAMING_DATA && !c->sink_input && pa_iochannel_is_hungup(c->io))
1250 /* In case we are in capture mode we will never call read()
1251 * on the socket, hence we need to detect the hangup manually
1252 * here, instead of simply waiting for read() to return 0. */
1255 while (pa_iochannel_is_writable(c->io)) {
1256 int r = do_write(c);
1267 if (c->state == ESD_STREAMING_DATA && c->sink_input) {
1270 pa_iochannel_free(c->io);
1273 pa_asyncmsgq_post(c->sink_input->sink->asyncmsgq, PA_MSGOBJECT(c->sink_input), SINK_INPUT_MESSAGE_DISABLE_PREBUF, NULL, 0, NULL, NULL);
1275 connection_unlink(c);
1278 static void io_callback(pa_iochannel*io, void *userdata) {
1279 connection *c = CONNECTION(userdata);
1281 connection_assert_ref(c);
1287 static void defer_callback(pa_mainloop_api*a, pa_defer_event *e, void *userdata) {
1288 connection *c = CONNECTION(userdata);
1290 connection_assert_ref(c);
1296 static int connection_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
1297 connection *c = CONNECTION(o);
1298 connection_assert_ref(c);
1304 case CONNECTION_MESSAGE_REQUEST_DATA:
1308 case CONNECTION_MESSAGE_POST_DATA:
1309 /* pa_log("got data %u", chunk->length); */
1310 pa_memblockq_push_align(c->output_memblockq, chunk);
1314 case CONNECTION_MESSAGE_UNLINK_CONNECTION:
1315 connection_unlink(c);
1322 /*** sink_input callbacks ***/
1324 /* Called from thread context */
1325 static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
1326 pa_sink_input *i = PA_SINK_INPUT(o);
1329 pa_sink_input_assert_ref(i);
1330 c = CONNECTION(i->userdata);
1331 connection_assert_ref(c);
1335 case SINK_INPUT_MESSAGE_POST_DATA: {
1338 /* New data from the main loop */
1339 pa_memblockq_push_align(c->input_memblockq, chunk);
1341 if (pa_memblockq_is_readable(c->input_memblockq) && c->playback.underrun) {
1342 pa_log_debug("Requesting rewind due to end of underrun.");
1343 pa_sink_input_request_rewind(c->sink_input, 0, false, true, false);
1346 /* pa_log("got data, %u", pa_memblockq_get_length(c->input_memblockq)); */
1351 case SINK_INPUT_MESSAGE_DISABLE_PREBUF:
1352 pa_memblockq_prebuf_disable(c->input_memblockq);
1355 case PA_SINK_INPUT_MESSAGE_GET_LATENCY: {
1356 pa_usec_t *r = userdata;
1358 /* The default handler will add in the extra latency added by the resampler. */
1359 *r = pa_bytes_to_usec(pa_memblockq_get_length(c->input_memblockq), &c->sink_input->sample_spec);
1364 return pa_sink_input_process_msg(o, code, userdata, offset, chunk);
1368 /* Called from thread context */
1369 static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
1372 pa_sink_input_assert_ref(i);
1373 c = CONNECTION(i->userdata);
1374 connection_assert_ref(c);
1377 if (pa_memblockq_peek(c->input_memblockq, chunk) < 0) {
1379 c->playback.underrun = true;
1381 if (c->dead && pa_sink_input_safe_to_remove(i))
1382 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_UNLINK_CONNECTION, NULL, 0, NULL, NULL);
1388 c->playback.underrun = false;
1390 chunk->length = PA_MIN(length, chunk->length);
1391 pa_memblockq_drop(c->input_memblockq, chunk->length);
1392 m = pa_memblockq_pop_missing(c->input_memblockq);
1395 if (pa_atomic_add(&c->playback.missing, (int) m) <= 0)
1396 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_REQUEST_DATA, NULL, 0, NULL, NULL);
1402 /* Called from thread context */
1403 static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
1406 pa_sink_input_assert_ref(i);
1407 c = CONNECTION(i->userdata);
1408 connection_assert_ref(c);
1410 /* If we are in an underrun, then we don't rewind */
1411 if (i->thread_info.underrun_for > 0)
1414 pa_memblockq_rewind(c->input_memblockq, nbytes);
1417 /* Called from thread context */
1418 static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
1421 pa_sink_input_assert_ref(i);
1422 c = CONNECTION(i->userdata);
1423 connection_assert_ref(c);
1425 pa_memblockq_set_maxrewind(c->input_memblockq, nbytes);
1428 static void sink_input_kill_cb(pa_sink_input *i) {
1429 pa_sink_input_assert_ref(i);
1431 connection_unlink(CONNECTION(i->userdata));
1434 /*** source_output callbacks ***/
1436 /* Called from thread context */
1437 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) {
1440 pa_source_output_assert_ref(o);
1441 c = CONNECTION(o->userdata);
1445 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_POST_DATA, NULL, 0, chunk, NULL);
1448 static void source_output_kill_cb(pa_source_output *o) {
1449 pa_source_output_assert_ref(o);
1451 connection_unlink(CONNECTION(o->userdata));
1454 static pa_usec_t source_output_get_latency_cb(pa_source_output *o) {
1457 pa_source_output_assert_ref(o);
1458 c = CONNECTION(o->userdata);
1461 return pa_bytes_to_usec(pa_memblockq_get_length(c->output_memblockq), &c->source_output->sample_spec);
1464 /*** entry points ***/
1466 static void auth_timeout(pa_mainloop_api *m, pa_time_event *e, const struct timeval *t, void *userdata) {
1467 connection *c = CONNECTION(userdata);
1470 connection_assert_ref(c);
1471 pa_assert(c->auth_timeout_event == e);
1474 connection_unlink(c);
1477 void pa_esound_protocol_connect(pa_esound_protocol *p, pa_iochannel *io, pa_esound_options *o) {
1480 pa_client_new_data data;
1487 if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) {
1488 pa_log("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS);
1489 pa_iochannel_free(io);
1493 pa_client_new_data_init(&data);
1494 data.module = o->module;
1495 data.driver = __FILE__;
1496 pa_iochannel_socket_peer_to_string(io, pname, sizeof(pname));
1497 pa_proplist_setf(data.proplist, PA_PROP_APPLICATION_NAME, "EsounD client (%s)", pname);
1498 pa_proplist_sets(data.proplist, "esound-protocol.peer", pname);
1499 client = pa_client_new(p->core, &data);
1500 pa_client_new_data_done(&data);
1505 c = pa_msgobject_new(connection);
1506 c->parent.parent.free = connection_free;
1507 c->parent.process_msg = connection_process_msg;
1510 pa_iochannel_set_callback(c->io, io_callback, c);
1513 c->client->kill = client_kill_cb;
1514 c->client->userdata = c;
1516 c->options = pa_esound_options_ref(o);
1517 c->authorized = false;
1518 c->swap_byte_order = false;
1521 c->read_data_length = 0;
1522 c->read_data = pa_xmalloc(c->read_data_alloc = proto_map[ESD_PROTO_CONNECT].data_length);
1524 c->write_data_length = c->write_data_index = c->write_data_alloc = 0;
1525 c->write_data = NULL;
1527 c->state = ESD_NEEDS_REQDATA;
1528 c->request = ESD_PROTO_CONNECT;
1530 c->sink_input = NULL;
1531 c->input_memblockq = NULL;
1533 c->source_output = NULL;
1534 c->output_memblockq = NULL;
1536 c->playback.current_memblock = NULL;
1537 c->playback.memblock_index = 0;
1538 c->playback.underrun = true;
1539 pa_atomic_store(&c->playback.missing, 0);
1541 pa_memchunk_reset(&c->scache.memchunk);
1542 c->scache.name = NULL;
1544 c->original_name = NULL;
1546 if (o->auth_anonymous) {
1547 pa_log_info("Client authenticated anonymously.");
1548 c->authorized = true;
1551 if (!c->authorized &&
1553 pa_ip_acl_check(o->auth_ip_acl, pa_iochannel_get_recv_fd(io)) > 0) {
1555 pa_log_info("Client authenticated by IP ACL.");
1556 c->authorized = true;
1560 c->auth_timeout_event = pa_core_rttime_new(p->core, pa_rtclock_now() + AUTH_TIMEOUT, auth_timeout, c);
1562 c->auth_timeout_event = NULL;
1564 c->defer_event = p->core->mainloop->defer_new(p->core->mainloop, defer_callback, c);
1565 p->core->mainloop->defer_enable(c->defer_event, 0);
1567 pa_idxset_put(p->connections, c, &c->index);
1570 void pa_esound_protocol_disconnect(pa_esound_protocol *p, pa_module *m) {
1577 while ((c = pa_idxset_iterate(p->connections, &state, NULL)))
1578 if (c->options->module == m)
1579 connection_unlink(c);
1582 static pa_esound_protocol* esound_protocol_new(pa_core *c) {
1583 pa_esound_protocol *p;
1587 p = pa_xnew(pa_esound_protocol, 1);
1590 p->connections = pa_idxset_new(NULL, NULL);
1593 pa_assert_se(pa_shared_set(c, "esound-protocol", p) >= 0);
1598 pa_esound_protocol* pa_esound_protocol_get(pa_core *c) {
1599 pa_esound_protocol *p;
1601 if ((p = pa_shared_get(c, "esound-protocol")))
1602 return pa_esound_protocol_ref(p);
1604 return esound_protocol_new(c);
1607 pa_esound_protocol* pa_esound_protocol_ref(pa_esound_protocol *p) {
1609 pa_assert(PA_REFCNT_VALUE(p) >= 1);
1616 void pa_esound_protocol_unref(pa_esound_protocol *p) {
1619 pa_assert(PA_REFCNT_VALUE(p) >= 1);
1621 if (PA_REFCNT_DEC(p) > 0)
1624 while ((c = pa_idxset_first(p->connections, NULL)))
1625 connection_unlink(c);
1627 pa_idxset_free(p->connections, NULL);
1629 pa_assert_se(pa_shared_remove(p->core, "esound-protocol") >= 0);
1634 pa_esound_options* pa_esound_options_new(void) {
1635 pa_esound_options *o;
1637 o = pa_xnew0(pa_esound_options, 1);
1643 pa_esound_options* pa_esound_options_ref(pa_esound_options *o) {
1645 pa_assert(PA_REFCNT_VALUE(o) >= 1);
1652 void pa_esound_options_unref(pa_esound_options *o) {
1654 pa_assert(PA_REFCNT_VALUE(o) >= 1);
1656 if (PA_REFCNT_DEC(o) > 0)
1660 pa_ip_acl_free(o->auth_ip_acl);
1663 pa_auth_cookie_unref(o->auth_cookie);
1665 pa_xfree(o->default_sink);
1666 pa_xfree(o->default_source);
1671 int pa_esound_options_parse(pa_esound_options *o, pa_core *c, pa_modargs *ma) {
1676 pa_assert(PA_REFCNT_VALUE(o) >= 1);
1679 if (pa_modargs_get_value_boolean(ma, "auth-anonymous", &o->auth_anonymous) < 0) {
1680 pa_log("auth-anonymous= expects a boolean argument.");
1684 if ((acl = pa_modargs_get_value(ma, "auth-ip-acl", NULL))) {
1687 if (!(ipa = pa_ip_acl_new(acl))) {
1688 pa_log("Failed to parse IP ACL '%s'", acl);
1693 pa_ip_acl_free(o->auth_ip_acl);
1695 o->auth_ip_acl = ipa;
1699 if (pa_modargs_get_value_boolean(ma, "auth-cookie-enabled", &enabled) < 0) {
1700 pa_log("auth-cookie-enabled= expects a boolean argument.");
1705 pa_auth_cookie_unref(o->auth_cookie);
1710 /* The new name for this is 'auth-cookie', for compat reasons
1711 * we check the old name too */
1712 if (!(cn = pa_xstrdup(pa_modargs_get_value(ma, "auth-cookie", NULL)))) {
1713 if (!(cn = pa_xstrdup(pa_modargs_get_value(ma, "cookie", NULL)))) {
1714 if (pa_append_to_home_dir(DEFAULT_COOKIE_FILE, &cn) < 0)
1719 o->auth_cookie = pa_auth_cookie_get(c, cn, true, ESD_KEY_LEN);
1721 if (!o->auth_cookie)
1725 o->auth_cookie = NULL;
1727 pa_xfree(o->default_sink);
1728 o->default_sink = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL));
1730 pa_xfree(o->default_source);
1731 o->default_source = pa_xstrdup(pa_modargs_get_value(ma, "source", NULL));