]> code.delx.au - pulseaudio/blob - src/pulsecore/protocol-native.c
1d294746dfd15b25a27bd47992e7a4e53f1505ab
[pulseaudio] / src / pulsecore / protocol-native.c
1 /* $Id$ */
2
3 /***
4 This file is part of PulseAudio.
5
6 Copyright 2004-2006 Lennart Poettering
7 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
8
9 PulseAudio is free software; you can redistribute it and/or modify
10 it under the terms of the GNU Lesser General Public License as published
11 by the Free Software Foundation; either version 2 of the License,
12 or (at your option) any later version.
13
14 PulseAudio is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public License
20 along with PulseAudio; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22 USA.
23 ***/
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #include <string.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <unistd.h>
33
34 #include <pulse/timeval.h>
35 #include <pulse/version.h>
36 #include <pulse/utf8.h>
37 #include <pulse/util.h>
38 #include <pulse/xmalloc.h>
39
40 #include <pulsecore/native-common.h>
41 #include <pulsecore/packet.h>
42 #include <pulsecore/client.h>
43 #include <pulsecore/source-output.h>
44 #include <pulsecore/sink-input.h>
45 #include <pulsecore/pstream.h>
46 #include <pulsecore/tagstruct.h>
47 #include <pulsecore/pdispatch.h>
48 #include <pulsecore/pstream-util.h>
49 #include <pulsecore/authkey.h>
50 #include <pulsecore/namereg.h>
51 #include <pulsecore/core-scache.h>
52 #include <pulsecore/core-subscribe.h>
53 #include <pulsecore/log.h>
54 #include <pulsecore/autoload.h>
55 #include <pulsecore/authkey-prop.h>
56 #include <pulsecore/strlist.h>
57 #include <pulsecore/props.h>
58 #include <pulsecore/sample-util.h>
59 #include <pulsecore/llist.h>
60 #include <pulsecore/creds.h>
61 #include <pulsecore/core-util.h>
62 #include <pulsecore/ipacl.h>
63 #include <pulsecore/thread-mq.h>
64
65 #include "protocol-native.h"
66
67 /* Kick a client if it doesn't authenticate within this time */
68 #define AUTH_TIMEOUT 60
69
70 /* Don't accept more connection than this */
71 #define MAX_CONNECTIONS 64
72
73 #define MAX_MEMBLOCKQ_LENGTH (4*1024*1024) /* 4MB */
74
75 typedef struct connection connection;
76 struct pa_protocol_native;
77
78 typedef struct record_stream {
79 pa_msgobject parent;
80
81 connection *connection;
82 uint32_t index;
83
84 pa_source_output *source_output;
85 pa_memblockq *memblockq;
86 size_t fragment_size;
87 } record_stream;
88
89 typedef struct output_stream {
90 pa_msgobject parent;
91 } output_stream;
92
93 typedef struct playback_stream {
94 output_stream parent;
95
96 connection *connection;
97 uint32_t index;
98
99 pa_sink_input *sink_input;
100 pa_memblockq *memblockq;
101 int drain_request;
102 uint32_t drain_tag;
103 uint32_t syncid;
104 int underrun;
105
106 pa_atomic_t missing;
107 size_t minreq;
108
109 /* Only updated after SINK_INPUT_MESSAGE_UPDATE_LATENCY */
110 int64_t read_index, write_index;
111 size_t resampled_chunk_length;
112 } playback_stream;
113
114 typedef struct upload_stream {
115 output_stream parent;
116
117 connection *connection;
118 uint32_t index;
119
120 pa_memchunk memchunk;
121 size_t length;
122 char *name;
123 pa_sample_spec sample_spec;
124 pa_channel_map channel_map;
125 } upload_stream;
126
127 struct connection {
128 pa_msgobject parent;
129
130 int authorized;
131 uint32_t version;
132 pa_protocol_native *protocol;
133 pa_client *client;
134 pa_pstream *pstream;
135 pa_pdispatch *pdispatch;
136 pa_idxset *record_streams, *output_streams;
137 uint32_t rrobin_index;
138 pa_subscription *subscription;
139 pa_time_event *auth_timeout_event;
140 };
141
142 PA_DECLARE_CLASS(record_stream);
143 #define RECORD_STREAM(o) (record_stream_cast(o))
144 static PA_DEFINE_CHECK_TYPE(record_stream, pa_msgobject);
145
146 PA_DECLARE_CLASS(output_stream);
147 #define OUTPUT_STREAM(o) (output_stream_cast(o))
148 static PA_DEFINE_CHECK_TYPE(output_stream, pa_msgobject);
149
150 PA_DECLARE_CLASS(playback_stream);
151 #define PLAYBACK_STREAM(o) (playback_stream_cast(o))
152 static PA_DEFINE_CHECK_TYPE(playback_stream, output_stream);
153
154 PA_DECLARE_CLASS(upload_stream);
155 #define UPLOAD_STREAM(o) (upload_stream_cast(o))
156 static PA_DEFINE_CHECK_TYPE(upload_stream, output_stream);
157
158 PA_DECLARE_CLASS(connection);
159 #define CONNECTION(o) (connection_cast(o))
160 static PA_DEFINE_CHECK_TYPE(connection, pa_msgobject);
161
162 struct pa_protocol_native {
163 pa_module *module;
164 pa_core *core;
165 int public;
166 pa_socket_server *server;
167 pa_idxset *connections;
168 uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH];
169 int auth_cookie_in_property;
170 #ifdef HAVE_CREDS
171 char *auth_group;
172 #endif
173 pa_ip_acl *auth_ip_acl;
174 };
175
176 enum {
177 SINK_INPUT_MESSAGE_POST_DATA = PA_SINK_INPUT_MESSAGE_MAX, /* data from main loop to sink input */
178 SINK_INPUT_MESSAGE_DRAIN, /* disabled prebuf, get playback started. */
179 SINK_INPUT_MESSAGE_FLUSH,
180 SINK_INPUT_MESSAGE_TRIGGER,
181 SINK_INPUT_MESSAGE_SEEK,
182 SINK_INPUT_MESSAGE_PREBUF_FORCE,
183 SINK_INPUT_MESSAGE_UPDATE_LATENCY
184 };
185
186 enum {
187 PLAYBACK_STREAM_MESSAGE_REQUEST_DATA, /* data requested from sink input from the main loop */
188 PLAYBACK_STREAM_MESSAGE_UNDERFLOW,
189 PLAYBACK_STREAM_MESSAGE_OVERFLOW,
190 PLAYBACK_STREAM_MESSAGE_DRAIN_ACK
191 };
192
193 enum {
194 RECORD_STREAM_MESSAGE_POST_DATA /* data from source output to main loop */
195 };
196
197 enum {
198 CONNECTION_MESSAGE_RELEASE,
199 CONNECTION_MESSAGE_REVOKE
200 };
201
202 static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk);
203 static void sink_input_drop_cb(pa_sink_input *i, size_t length);
204 static void sink_input_kill_cb(pa_sink_input *i);
205
206 static void send_memblock(connection *c);
207 static void request_bytes(struct playback_stream*s);
208
209 static void source_output_kill_cb(pa_source_output *o);
210 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk);
211 static pa_usec_t source_output_get_latency_cb(pa_source_output *o);
212
213 static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk);
214
215 static void command_exit(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
216 static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
217 static void command_drain_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
218 static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
219 static void command_delete_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
220 static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
221 static void command_set_client_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
222 static void command_lookup(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
223 static void command_stat(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
224 static void command_get_playback_latency(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
225 static void command_get_record_latency(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
226 static void command_create_upload_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
227 static void command_finish_upload_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
228 static void command_play_sample(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
229 static void command_remove_sample(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
230 static void command_get_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
231 static void command_get_info_list(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
232 static void command_get_server_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
233 static void command_subscribe(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
234 static void command_set_volume(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
235 static void command_set_mute(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
236 static void command_cork_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
237 static void command_trigger_or_flush_or_prebuf_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
238 static void command_set_default_sink_or_source(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
239 static void command_set_stream_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
240 static void command_kill(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
241 static void command_load_module(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
242 static void command_unload_module(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
243 static void command_add_autoload(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
244 static void command_remove_autoload(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
245 static void command_get_autoload_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
246 static void command_get_autoload_info_list(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
247 static void command_cork_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
248 static void command_flush_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
249 static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
250 static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
251
252 static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
253 [PA_COMMAND_ERROR] = NULL,
254 [PA_COMMAND_TIMEOUT] = NULL,
255 [PA_COMMAND_REPLY] = NULL,
256 [PA_COMMAND_CREATE_PLAYBACK_STREAM] = command_create_playback_stream,
257 [PA_COMMAND_DELETE_PLAYBACK_STREAM] = command_delete_stream,
258 [PA_COMMAND_DRAIN_PLAYBACK_STREAM] = command_drain_playback_stream,
259 [PA_COMMAND_CREATE_RECORD_STREAM] = command_create_record_stream,
260 [PA_COMMAND_DELETE_RECORD_STREAM] = command_delete_stream,
261 [PA_COMMAND_AUTH] = command_auth,
262 [PA_COMMAND_REQUEST] = NULL,
263 [PA_COMMAND_EXIT] = command_exit,
264 [PA_COMMAND_SET_CLIENT_NAME] = command_set_client_name,
265 [PA_COMMAND_LOOKUP_SINK] = command_lookup,
266 [PA_COMMAND_LOOKUP_SOURCE] = command_lookup,
267 [PA_COMMAND_STAT] = command_stat,
268 [PA_COMMAND_GET_PLAYBACK_LATENCY] = command_get_playback_latency,
269 [PA_COMMAND_GET_RECORD_LATENCY] = command_get_record_latency,
270 [PA_COMMAND_CREATE_UPLOAD_STREAM] = command_create_upload_stream,
271 [PA_COMMAND_DELETE_UPLOAD_STREAM] = command_delete_stream,
272 [PA_COMMAND_FINISH_UPLOAD_STREAM] = command_finish_upload_stream,
273 [PA_COMMAND_PLAY_SAMPLE] = command_play_sample,
274 [PA_COMMAND_REMOVE_SAMPLE] = command_remove_sample,
275 [PA_COMMAND_GET_SINK_INFO] = command_get_info,
276 [PA_COMMAND_GET_SOURCE_INFO] = command_get_info,
277 [PA_COMMAND_GET_CLIENT_INFO] = command_get_info,
278 [PA_COMMAND_GET_MODULE_INFO] = command_get_info,
279 [PA_COMMAND_GET_SINK_INPUT_INFO] = command_get_info,
280 [PA_COMMAND_GET_SOURCE_OUTPUT_INFO] = command_get_info,
281 [PA_COMMAND_GET_SAMPLE_INFO] = command_get_info,
282 [PA_COMMAND_GET_SINK_INFO_LIST] = command_get_info_list,
283 [PA_COMMAND_GET_SOURCE_INFO_LIST] = command_get_info_list,
284 [PA_COMMAND_GET_MODULE_INFO_LIST] = command_get_info_list,
285 [PA_COMMAND_GET_CLIENT_INFO_LIST] = command_get_info_list,
286 [PA_COMMAND_GET_SINK_INPUT_INFO_LIST] = command_get_info_list,
287 [PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST] = command_get_info_list,
288 [PA_COMMAND_GET_SAMPLE_INFO_LIST] = command_get_info_list,
289 [PA_COMMAND_GET_SERVER_INFO] = command_get_server_info,
290 [PA_COMMAND_SUBSCRIBE] = command_subscribe,
291
292 [PA_COMMAND_SET_SINK_VOLUME] = command_set_volume,
293 [PA_COMMAND_SET_SINK_INPUT_VOLUME] = command_set_volume,
294 [PA_COMMAND_SET_SOURCE_VOLUME] = command_set_volume,
295
296 [PA_COMMAND_SET_SINK_MUTE] = command_set_mute,
297 [PA_COMMAND_SET_SINK_INPUT_MUTE] = command_set_mute,
298 [PA_COMMAND_SET_SOURCE_MUTE] = command_set_mute,
299
300 [PA_COMMAND_SUSPEND_SINK] = command_suspend,
301 [PA_COMMAND_SUSPEND_SOURCE] = command_suspend,
302
303 [PA_COMMAND_CORK_PLAYBACK_STREAM] = command_cork_playback_stream,
304 [PA_COMMAND_FLUSH_PLAYBACK_STREAM] = command_trigger_or_flush_or_prebuf_playback_stream,
305 [PA_COMMAND_TRIGGER_PLAYBACK_STREAM] = command_trigger_or_flush_or_prebuf_playback_stream,
306 [PA_COMMAND_PREBUF_PLAYBACK_STREAM] = command_trigger_or_flush_or_prebuf_playback_stream,
307
308 [PA_COMMAND_CORK_RECORD_STREAM] = command_cork_record_stream,
309 [PA_COMMAND_FLUSH_RECORD_STREAM] = command_flush_record_stream,
310
311 [PA_COMMAND_SET_DEFAULT_SINK] = command_set_default_sink_or_source,
312 [PA_COMMAND_SET_DEFAULT_SOURCE] = command_set_default_sink_or_source,
313 [PA_COMMAND_SET_PLAYBACK_STREAM_NAME] = command_set_stream_name,
314 [PA_COMMAND_SET_RECORD_STREAM_NAME] = command_set_stream_name,
315 [PA_COMMAND_KILL_CLIENT] = command_kill,
316 [PA_COMMAND_KILL_SINK_INPUT] = command_kill,
317 [PA_COMMAND_KILL_SOURCE_OUTPUT] = command_kill,
318 [PA_COMMAND_LOAD_MODULE] = command_load_module,
319 [PA_COMMAND_UNLOAD_MODULE] = command_unload_module,
320 [PA_COMMAND_GET_AUTOLOAD_INFO] = command_get_autoload_info,
321 [PA_COMMAND_GET_AUTOLOAD_INFO_LIST] = command_get_autoload_info_list,
322 [PA_COMMAND_ADD_AUTOLOAD] = command_add_autoload,
323 [PA_COMMAND_REMOVE_AUTOLOAD] = command_remove_autoload,
324
325 [PA_COMMAND_MOVE_SINK_INPUT] = command_move_stream,
326 [PA_COMMAND_MOVE_SOURCE_OUTPUT] = command_move_stream
327 };
328
329 /* structure management */
330
331 static void upload_stream_unlink(upload_stream *s) {
332 pa_assert(s);
333
334 if (!s->connection)
335 return;
336
337 pa_assert_se(pa_idxset_remove_by_data(s->connection->output_streams, s, NULL) == s);
338 s->connection = NULL;
339 upload_stream_unref(s);
340 }
341
342 static void upload_stream_free(pa_object *o) {
343 upload_stream *s = UPLOAD_STREAM(o);
344 pa_assert(s);
345
346 upload_stream_unlink(s);
347
348 pa_xfree(s->name);
349
350 if (s->memchunk.memblock)
351 pa_memblock_unref(s->memchunk.memblock);
352
353 pa_xfree(s);
354 }
355
356 static upload_stream* upload_stream_new(
357 connection *c,
358 const pa_sample_spec *ss,
359 const pa_channel_map *map,
360 const char *name, size_t length) {
361
362 upload_stream *s;
363
364 pa_assert(c);
365 pa_assert(ss);
366 pa_assert(name);
367 pa_assert(length > 0);
368
369 s = pa_msgobject_new(upload_stream);
370 s->parent.parent.parent.free = upload_stream_free;
371 s->connection = c;
372 s->sample_spec = *ss;
373 s->channel_map = *map;
374 s->name = pa_xstrdup(name);
375 pa_memchunk_reset(&s->memchunk);
376 s->length = length;
377
378 pa_idxset_put(c->output_streams, s, &s->index);
379
380 return s;
381 }
382
383 static void record_stream_unlink(record_stream *s) {
384 pa_assert(s);
385
386 if (!s->connection)
387 return;
388
389 if (s->source_output) {
390 pa_source_output_unlink(s->source_output);
391 pa_source_output_unref(s->source_output);
392 s->source_output = NULL;
393 }
394
395 pa_assert_se(pa_idxset_remove_by_data(s->connection->record_streams, s, NULL) == s);
396 s->connection = NULL;
397 record_stream_unref(s);
398 }
399
400 static void record_stream_free(pa_object *o) {
401 record_stream *s = RECORD_STREAM(o);
402 pa_assert(s);
403
404 record_stream_unlink(s);
405
406 pa_memblockq_free(s->memblockq);
407 pa_xfree(s);
408 }
409
410 static int record_stream_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
411 record_stream *s = RECORD_STREAM(o);
412 record_stream_assert_ref(s);
413
414 if (!s->connection)
415 return -1;
416
417 switch (code) {
418
419 case RECORD_STREAM_MESSAGE_POST_DATA:
420
421 if (pa_memblockq_push_align(s->memblockq, chunk) < 0) {
422 /* pa_log_warn("Failed to push data into output queue."); */
423 return -1;
424 }
425
426 if (!pa_pstream_is_pending(s->connection->pstream))
427 send_memblock(s->connection);
428
429 break;
430 }
431
432 return 0;
433 }
434
435 static record_stream* record_stream_new(
436 connection *c,
437 pa_source *source,
438 const pa_sample_spec *ss,
439 const pa_channel_map *map,
440 const char *name,
441 uint32_t *maxlength,
442 uint32_t fragment_size,
443 int corked) {
444
445 record_stream *s;
446 pa_source_output *source_output;
447 size_t base;
448 pa_source_output_new_data data;
449
450 pa_assert(c);
451 pa_assert(ss);
452 pa_assert(name);
453 pa_assert(maxlength);
454 pa_assert(*maxlength > 0);
455
456 pa_source_output_new_data_init(&data);
457 data.module = c->protocol->module;
458 data.client = c->client;
459 data.source = source;
460 data.driver = __FILE__;
461 data.name = name;
462 pa_source_output_new_data_set_sample_spec(&data, ss);
463 pa_source_output_new_data_set_channel_map(&data, map);
464
465 if (!(source_output = pa_source_output_new(c->protocol->core, &data, corked ? PA_SOURCE_OUTPUT_START_CORKED : 0)))
466 return NULL;
467
468 s = pa_msgobject_new(record_stream);
469 s->parent.parent.free = record_stream_free;
470 s->parent.process_msg = record_stream_process_msg;
471 s->connection = c;
472 s->source_output = source_output;
473 s->source_output->push = source_output_push_cb;
474 s->source_output->kill = source_output_kill_cb;
475 s->source_output->get_latency = source_output_get_latency_cb;
476 s->source_output->userdata = s;
477
478 s->memblockq = pa_memblockq_new(
479 0,
480 *maxlength,
481 0,
482 base = pa_frame_size(ss),
483 1,
484 0,
485 NULL);
486
487 s->fragment_size = (fragment_size/base)*base;
488 if (s->fragment_size <= 0)
489 s->fragment_size = base;
490 *maxlength = pa_memblockq_get_maxlength(s->memblockq);
491
492 pa_idxset_put(c->record_streams, s, &s->index);
493
494 pa_source_output_put(s->source_output);
495 return s;
496 }
497
498 static void playback_stream_unlink(playback_stream *s) {
499 pa_assert(s);
500
501 if (!s->connection)
502 return;
503
504 if (s->sink_input) {
505 pa_sink_input_unlink(s->sink_input);
506 pa_sink_input_unref(s->sink_input);
507 s->sink_input = NULL;
508 }
509
510 if (s->drain_request)
511 pa_pstream_send_error(s->connection->pstream, s->drain_tag, PA_ERR_NOENTITY);
512
513 pa_assert_se(pa_idxset_remove_by_data(s->connection->output_streams, s, NULL) == s);
514 s->connection = NULL;
515 playback_stream_unref(s);
516 }
517
518 static void playback_stream_free(pa_object* o) {
519 playback_stream *s = PLAYBACK_STREAM(o);
520 pa_assert(s);
521
522 playback_stream_unlink(s);
523
524 pa_memblockq_free(s->memblockq);
525 pa_xfree(s);
526 }
527
528 static int playback_stream_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
529 playback_stream *s = PLAYBACK_STREAM(o);
530 playback_stream_assert_ref(s);
531
532 if (!s->connection)
533 return -1;
534
535 switch (code) {
536 case PLAYBACK_STREAM_MESSAGE_REQUEST_DATA: {
537 pa_tagstruct *t;
538 uint32_t l = 0;
539
540 for (;;) {
541 int32_t k;
542
543 if ((k = pa_atomic_load(&s->missing)) <= 0)
544 break;
545
546 l += k;
547
548 if (l < s->minreq)
549 break;
550
551 if (pa_atomic_sub(&s->missing, k) <= k)
552 break;
553 }
554
555 if (l < s->minreq)
556 break;
557
558 t = pa_tagstruct_new(NULL, 0);
559 pa_tagstruct_putu32(t, PA_COMMAND_REQUEST);
560 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
561 pa_tagstruct_putu32(t, s->index);
562 pa_tagstruct_putu32(t, l);
563 pa_pstream_send_tagstruct(s->connection->pstream, t);
564
565 /* pa_log("Requesting %u bytes", l); */
566 break;
567 }
568
569 case PLAYBACK_STREAM_MESSAGE_UNDERFLOW: {
570 pa_tagstruct *t;
571
572 /* Report that we're empty */
573 t = pa_tagstruct_new(NULL, 0);
574 pa_tagstruct_putu32(t, PA_COMMAND_UNDERFLOW);
575 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
576 pa_tagstruct_putu32(t, s->index);
577 pa_pstream_send_tagstruct(s->connection->pstream, t);
578 break;
579 }
580
581 case PLAYBACK_STREAM_MESSAGE_OVERFLOW: {
582 pa_tagstruct *t;
583
584 /* Notify the user we're overflowed*/
585 t = pa_tagstruct_new(NULL, 0);
586 pa_tagstruct_putu32(t, PA_COMMAND_OVERFLOW);
587 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
588 pa_tagstruct_putu32(t, s->index);
589 pa_pstream_send_tagstruct(s->connection->pstream, t);
590 break;
591 }
592
593 case PLAYBACK_STREAM_MESSAGE_DRAIN_ACK:
594 pa_pstream_send_simple_ack(s->connection->pstream, PA_PTR_TO_UINT(userdata));
595 break;
596
597 }
598
599 return 0;
600 }
601
602 static playback_stream* playback_stream_new(
603 connection *c,
604 pa_sink *sink,
605 const pa_sample_spec *ss,
606 const pa_channel_map *map,
607 const char *name,
608 uint32_t *maxlength,
609 uint32_t *tlength,
610 uint32_t *prebuf,
611 uint32_t *minreq,
612 pa_cvolume *volume,
613 uint32_t syncid,
614 int corked,
615 uint32_t *missing) {
616
617 playback_stream *s, *ssync;
618 pa_sink_input *sink_input;
619 pa_memblock *silence;
620 uint32_t idx;
621 int64_t start_index;
622 pa_sink_input_new_data data;
623
624 pa_assert(c);
625 pa_assert(ss);
626 pa_assert(name);
627 pa_assert(maxlength);
628
629 /* Find syncid group */
630 for (ssync = pa_idxset_first(c->output_streams, &idx); ssync; ssync = pa_idxset_next(c->output_streams, &idx)) {
631
632 if (!playback_stream_isinstance(ssync))
633 continue;
634
635 if (ssync->syncid == syncid)
636 break;
637 }
638
639 /* Synced streams must connect to the same sink */
640 if (ssync) {
641
642 if (!sink)
643 sink = ssync->sink_input->sink;
644 else if (sink != ssync->sink_input->sink)
645 return NULL;
646 }
647
648 pa_sink_input_new_data_init(&data);
649 data.sink = sink;
650 data.driver = __FILE__;
651 data.name = name;
652 pa_sink_input_new_data_set_sample_spec(&data, ss);
653 pa_sink_input_new_data_set_channel_map(&data, map);
654 pa_sink_input_new_data_set_volume(&data, volume);
655 data.module = c->protocol->module;
656 data.client = c->client;
657 data.sync_base = ssync ? ssync->sink_input : NULL;
658
659 if (!(sink_input = pa_sink_input_new(c->protocol->core, &data, corked ? PA_SINK_INPUT_START_CORKED : 0)))
660 return NULL;
661
662 s = pa_msgobject_new(playback_stream);
663 s->parent.parent.parent.free = playback_stream_free;
664 s->parent.parent.process_msg = playback_stream_process_msg;
665 s->connection = c;
666 s->syncid = syncid;
667 s->sink_input = sink_input;
668 s->underrun = 1;
669
670 s->sink_input->parent.process_msg = sink_input_process_msg;
671 s->sink_input->peek = sink_input_peek_cb;
672 s->sink_input->drop = sink_input_drop_cb;
673 s->sink_input->kill = sink_input_kill_cb;
674 s->sink_input->userdata = s;
675
676 start_index = ssync ? pa_memblockq_get_read_index(ssync->memblockq) : 0;
677
678 silence = pa_silence_memblock_new(c->protocol->core->mempool, ss, 0);
679
680 s->memblockq = pa_memblockq_new(
681 start_index,
682 *maxlength,
683 *tlength,
684 pa_frame_size(ss),
685 *prebuf,
686 *minreq,
687 silence);
688
689 pa_memblock_unref(silence);
690
691 *maxlength = (uint32_t) pa_memblockq_get_maxlength(s->memblockq);
692 *tlength = (uint32_t) pa_memblockq_get_tlength(s->memblockq);
693 *prebuf = (uint32_t) pa_memblockq_get_prebuf(s->memblockq);
694 *minreq = (uint32_t) pa_memblockq_get_minreq(s->memblockq);
695 *missing = (uint32_t) pa_memblockq_pop_missing(s->memblockq);
696
697 s->minreq = pa_memblockq_get_minreq(s->memblockq);
698 pa_atomic_store(&s->missing, 0);
699 s->drain_request = 0;
700
701 pa_idxset_put(c->output_streams, s, &s->index);
702
703 pa_sink_input_put(s->sink_input);
704
705 return s;
706 }
707
708 static int connection_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
709 connection *c = CONNECTION(o);
710 connection_assert_ref(c);
711
712 if (!c->protocol)
713 return -1;
714
715 switch (code) {
716
717 case CONNECTION_MESSAGE_REVOKE:
718 pa_pstream_send_revoke(c->pstream, PA_PTR_TO_UINT(userdata));
719 break;
720
721 case CONNECTION_MESSAGE_RELEASE:
722 pa_pstream_send_release(c->pstream, PA_PTR_TO_UINT(userdata));
723 break;
724 }
725
726 return 0;
727 }
728
729 static void connection_unlink(connection *c) {
730 record_stream *r;
731 output_stream *o;
732
733 pa_assert(c);
734
735 if (!c->protocol)
736 return;
737
738 while ((r = pa_idxset_first(c->record_streams, NULL)))
739 record_stream_unlink(r);
740
741 while ((o = pa_idxset_first(c->output_streams, NULL)))
742 if (playback_stream_isinstance(o))
743 playback_stream_unlink(PLAYBACK_STREAM(o));
744 else
745 upload_stream_unlink(UPLOAD_STREAM(o));
746
747 if (c->subscription)
748 pa_subscription_free(c->subscription);
749
750 if (c->pstream)
751 pa_pstream_unlink(c->pstream);
752
753 if (c->auth_timeout_event) {
754 c->protocol->core->mainloop->time_free(c->auth_timeout_event);
755 c->auth_timeout_event = NULL;
756 }
757
758 pa_assert_se(pa_idxset_remove_by_data(c->protocol->connections, c, NULL) == c);
759 c->protocol = NULL;
760 connection_unref(c);
761 }
762
763 static void connection_free(pa_object *o) {
764 connection *c = CONNECTION(o);
765
766 pa_assert(c);
767
768 connection_unlink(c);
769
770 pa_idxset_free(c->record_streams, NULL, NULL);
771 pa_idxset_free(c->output_streams, NULL, NULL);
772
773 pa_pdispatch_unref(c->pdispatch);
774 pa_pstream_unref(c->pstream);
775 pa_client_free(c->client);
776
777 pa_xfree(c);
778 }
779
780 /* Called from thread context */
781 static void request_bytes(playback_stream *s) {
782 size_t m, previous_missing;
783
784 playback_stream_assert_ref(s);
785
786 m = pa_memblockq_pop_missing(s->memblockq);
787
788 if (m <= 0)
789 return;
790
791 /* pa_log("request_bytes(%u)", m); */
792
793 previous_missing = pa_atomic_add(&s->missing, m);
794 if (previous_missing < s->minreq && previous_missing+m >= s->minreq) {
795 pa_assert(pa_thread_mq_get());
796 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_REQUEST_DATA, NULL, 0, NULL, NULL);
797 }
798 }
799
800 static void send_memblock(connection *c) {
801 uint32_t start;
802 record_stream *r;
803
804 start = PA_IDXSET_INVALID;
805 for (;;) {
806 pa_memchunk chunk;
807
808 if (!(r = RECORD_STREAM(pa_idxset_rrobin(c->record_streams, &c->rrobin_index))))
809 return;
810
811 if (start == PA_IDXSET_INVALID)
812 start = c->rrobin_index;
813 else if (start == c->rrobin_index)
814 return;
815
816 if (pa_memblockq_peek(r->memblockq, &chunk) >= 0) {
817 pa_memchunk schunk = chunk;
818
819 if (schunk.length > r->fragment_size)
820 schunk.length = r->fragment_size;
821
822 pa_pstream_send_memblock(c->pstream, r->index, 0, PA_SEEK_RELATIVE, &schunk);
823
824 pa_memblockq_drop(r->memblockq, schunk.length);
825 pa_memblock_unref(schunk.memblock);
826
827 return;
828 }
829 }
830 }
831
832 static void send_playback_stream_killed(playback_stream *p) {
833 pa_tagstruct *t;
834 playback_stream_assert_ref(p);
835
836 t = pa_tagstruct_new(NULL, 0);
837 pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_KILLED);
838 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
839 pa_tagstruct_putu32(t, p->index);
840 pa_pstream_send_tagstruct(p->connection->pstream, t);
841 }
842
843 static void send_record_stream_killed(record_stream *r) {
844 pa_tagstruct *t;
845 record_stream_assert_ref(r);
846
847 t = pa_tagstruct_new(NULL, 0);
848 pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_KILLED);
849 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
850 pa_tagstruct_putu32(t, r->index);
851 pa_pstream_send_tagstruct(r->connection->pstream, t);
852 }
853
854 /*** sink input callbacks ***/
855
856 /* Called from thread context */
857 static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
858 pa_sink_input *i = PA_SINK_INPUT(o);
859 playback_stream *s;
860
861 pa_sink_input_assert_ref(i);
862 s = PLAYBACK_STREAM(i->userdata);
863 playback_stream_assert_ref(s);
864
865 switch (code) {
866
867 case SINK_INPUT_MESSAGE_SEEK:
868 pa_memblockq_seek(s->memblockq, offset, PA_PTR_TO_UINT(userdata));
869 request_bytes(s);
870 return 0;
871
872 case SINK_INPUT_MESSAGE_POST_DATA: {
873 pa_assert(chunk);
874
875 /* pa_log("sink input post: %u", chunk->length); */
876
877 if (pa_memblockq_push_align(s->memblockq, chunk) < 0) {
878
879 pa_log_warn("Failed to push data into queue");
880 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_OVERFLOW, NULL, 0, NULL, NULL);
881 pa_memblockq_seek(s->memblockq, chunk->length, PA_SEEK_RELATIVE);
882 }
883
884 request_bytes(s);
885
886 s->underrun = 0;
887 return 0;
888 }
889
890 case SINK_INPUT_MESSAGE_DRAIN: {
891
892 pa_memblockq_prebuf_disable(s->memblockq);
893
894 if (!pa_memblockq_is_readable(s->memblockq))
895 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_DRAIN_ACK, userdata, 0, NULL, NULL);
896 else {
897 s->drain_tag = PA_PTR_TO_UINT(userdata);
898 s->drain_request = 1;
899 }
900 request_bytes(s);
901
902 return 0;
903 }
904
905 case SINK_INPUT_MESSAGE_FLUSH:
906 case SINK_INPUT_MESSAGE_PREBUF_FORCE:
907 case SINK_INPUT_MESSAGE_TRIGGER: {
908
909 pa_sink_input *isync;
910 void (*func)(pa_memblockq *bq);
911
912 switch (code) {
913 case SINK_INPUT_MESSAGE_FLUSH:
914 func = pa_memblockq_flush;
915 break;
916
917 case SINK_INPUT_MESSAGE_PREBUF_FORCE:
918 func = pa_memblockq_prebuf_force;
919 break;
920
921 case SINK_INPUT_MESSAGE_TRIGGER:
922 func = pa_memblockq_prebuf_disable;
923 break;
924
925 default:
926 pa_assert_not_reached();
927 }
928
929 func(s->memblockq);
930 s->underrun = 0;
931 request_bytes(s);
932
933 /* Do the same for all other members in the sync group */
934 for (isync = i->sync_prev; isync; isync = isync->sync_prev) {
935 playback_stream *ssync = PLAYBACK_STREAM(isync->userdata);
936 func(ssync->memblockq);
937 ssync->underrun = 0;
938 request_bytes(ssync);
939 }
940
941 for (isync = i->sync_next; isync; isync = isync->sync_next) {
942 playback_stream *ssync = PLAYBACK_STREAM(isync->userdata);
943 func(ssync->memblockq);
944 ssync->underrun = 0;
945 request_bytes(ssync);
946 }
947
948 return 0;
949 }
950
951 case SINK_INPUT_MESSAGE_UPDATE_LATENCY:
952
953 s->read_index = pa_memblockq_get_read_index(s->memblockq);
954 s->write_index = pa_memblockq_get_write_index(s->memblockq);
955 s->resampled_chunk_length = s->sink_input->thread_info.resampled_chunk.memblock ? s->sink_input->thread_info.resampled_chunk.length : 0;
956 return 0;
957
958 case PA_SINK_INPUT_MESSAGE_SET_STATE:
959
960 pa_memblockq_prebuf_force(s->memblockq);
961 request_bytes(s);
962 break;
963
964 case PA_SINK_INPUT_MESSAGE_GET_LATENCY: {
965 pa_usec_t *r = userdata;
966
967 *r = pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &i->sample_spec);
968
969 /* Fall through, the default handler will add in the extra
970 * latency added by the resampler */
971 break;
972 }
973 }
974
975 return pa_sink_input_process_msg(o, code, userdata, offset, chunk);
976 }
977
978 /* Called from thread context */
979 static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
980 playback_stream *s;
981
982 pa_sink_input_assert_ref(i);
983 s = PLAYBACK_STREAM(i->userdata);
984 playback_stream_assert_ref(s);
985 pa_assert(chunk);
986
987 if (pa_memblockq_get_length(s->memblockq) <= 0 && !s->underrun) {
988 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_UNDERFLOW, NULL, 0, NULL, NULL);
989 s->underrun = 1;
990 }
991
992 if (pa_memblockq_peek(s->memblockq, chunk) < 0) {
993 /* pa_log("peek: failure"); */
994 return -1;
995 }
996
997 /* pa_log("peek: %u", chunk->length); */
998
999 request_bytes(s);
1000
1001 return 0;
1002 }
1003
1004 /* Called from thread context */
1005 static void sink_input_drop_cb(pa_sink_input *i, size_t length) {
1006 playback_stream *s;
1007
1008 pa_sink_input_assert_ref(i);
1009 s = PLAYBACK_STREAM(i->userdata);
1010 playback_stream_assert_ref(s);
1011 pa_assert(length > 0);
1012
1013 pa_memblockq_drop(s->memblockq, length);
1014
1015 if (s->drain_request && !pa_memblockq_is_readable(s->memblockq)) {
1016 s->drain_request = 0;
1017 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_DRAIN_ACK, PA_UINT_TO_PTR(s->drain_tag), 0, NULL, NULL);
1018 }
1019
1020 request_bytes(s);
1021
1022 /* pa_log("after_drop: %u %u", pa_memblockq_get_length(s->memblockq), pa_memblockq_is_readable(s->memblockq)); */
1023 }
1024
1025 static void sink_input_kill_cb(pa_sink_input *i) {
1026 playback_stream *s;
1027
1028 pa_sink_input_assert_ref(i);
1029 s = PLAYBACK_STREAM(i->userdata);
1030 playback_stream_assert_ref(s);
1031
1032 send_playback_stream_killed(s);
1033 playback_stream_unlink(s);
1034 }
1035
1036 /*** source_output callbacks ***/
1037
1038 /* Called from thread context */
1039 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) {
1040 record_stream *s;
1041
1042 pa_source_output_assert_ref(o);
1043 s = RECORD_STREAM(o->userdata);
1044 record_stream_assert_ref(s);
1045 pa_assert(chunk);
1046
1047 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), RECORD_STREAM_MESSAGE_POST_DATA, NULL, 0, chunk, NULL);
1048 }
1049
1050 static void source_output_kill_cb(pa_source_output *o) {
1051 record_stream *s;
1052
1053 pa_source_output_assert_ref(o);
1054 s = RECORD_STREAM(o->userdata);
1055 record_stream_assert_ref(s);
1056
1057 send_record_stream_killed(s);
1058 record_stream_unlink(s);
1059 }
1060
1061 static pa_usec_t source_output_get_latency_cb(pa_source_output *o) {
1062 record_stream *s;
1063
1064 pa_source_output_assert_ref(o);
1065 s = RECORD_STREAM(o->userdata);
1066 record_stream_assert_ref(s);
1067
1068 /*pa_log("get_latency: %u", pa_memblockq_get_length(s->memblockq));*/
1069
1070 return pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &o->sample_spec);
1071 }
1072
1073 /*** pdispatch callbacks ***/
1074
1075 static void protocol_error(connection *c) {
1076 pa_log("protocol error, kicking client");
1077 connection_unlink(c);
1078 }
1079
1080 #define CHECK_VALIDITY(pstream, expression, tag, error) do { \
1081 if (!(expression)) { \
1082 pa_pstream_send_error((pstream), (tag), (error)); \
1083 return; \
1084 } \
1085 } while(0);
1086
1087 static pa_tagstruct *reply_new(uint32_t tag) {
1088 pa_tagstruct *reply;
1089
1090 reply = pa_tagstruct_new(NULL, 0);
1091 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
1092 pa_tagstruct_putu32(reply, tag);
1093 return reply;
1094 }
1095
1096 static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1097 connection *c = CONNECTION(userdata);
1098 playback_stream *s;
1099 uint32_t maxlength, tlength, prebuf, minreq, sink_index, syncid, missing;
1100 const char *name, *sink_name;
1101 pa_sample_spec ss;
1102 pa_channel_map map;
1103 pa_tagstruct *reply;
1104 pa_sink *sink = NULL;
1105 pa_cvolume volume;
1106 int corked;
1107
1108 connection_assert_ref(c);
1109 pa_assert(t);
1110
1111 if (pa_tagstruct_get(
1112 t,
1113 PA_TAG_STRING, &name,
1114 PA_TAG_SAMPLE_SPEC, &ss,
1115 PA_TAG_CHANNEL_MAP, &map,
1116 PA_TAG_U32, &sink_index,
1117 PA_TAG_STRING, &sink_name,
1118 PA_TAG_U32, &maxlength,
1119 PA_TAG_BOOLEAN, &corked,
1120 PA_TAG_U32, &tlength,
1121 PA_TAG_U32, &prebuf,
1122 PA_TAG_U32, &minreq,
1123 PA_TAG_U32, &syncid,
1124 PA_TAG_CVOLUME, &volume,
1125 PA_TAG_INVALID) < 0 ||
1126 !pa_tagstruct_eof(t) ||
1127 !name) {
1128 protocol_error(c);
1129 return;
1130 }
1131
1132 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1133 CHECK_VALIDITY(c->pstream, name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
1134 CHECK_VALIDITY(c->pstream, sink_index != PA_INVALID_INDEX || !sink_name || (*sink_name && pa_utf8_valid(name)), tag, PA_ERR_INVALID);
1135 CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID);
1136 CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID);
1137 CHECK_VALIDITY(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID);
1138 CHECK_VALIDITY(c->pstream, map.channels == ss.channels && volume.channels == ss.channels, tag, PA_ERR_INVALID);
1139 CHECK_VALIDITY(c->pstream, maxlength > 0 && maxlength <= MAX_MEMBLOCKQ_LENGTH, tag, PA_ERR_INVALID);
1140 CHECK_VALIDITY(c->pstream, maxlength >= pa_frame_size(&ss), tag, PA_ERR_INVALID);
1141
1142 if (sink_index != PA_INVALID_INDEX) {
1143 sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index);
1144 CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
1145 } else if (sink_name) {
1146 sink = pa_namereg_get(c->protocol->core, sink_name, PA_NAMEREG_SINK, 1);
1147 CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
1148 }
1149
1150 s = playback_stream_new(c, sink, &ss, &map, name, &maxlength, &tlength, &prebuf, &minreq, &volume, syncid, corked, &missing);
1151 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID);
1152
1153 reply = reply_new(tag);
1154 pa_tagstruct_putu32(reply, s->index);
1155 pa_assert(s->sink_input);
1156 pa_tagstruct_putu32(reply, s->sink_input->index);
1157 pa_tagstruct_putu32(reply, missing);
1158
1159 /* pa_log("initial request is %u", missing); */
1160
1161 if (c->version >= 9) {
1162 /* Since 0.9 we support sending the buffer metrics back to the client */
1163
1164 pa_tagstruct_putu32(reply, (uint32_t) maxlength);
1165 pa_tagstruct_putu32(reply, (uint32_t) tlength);
1166 pa_tagstruct_putu32(reply, (uint32_t) prebuf);
1167 pa_tagstruct_putu32(reply, (uint32_t) minreq);
1168 }
1169
1170 pa_pstream_send_tagstruct(c->pstream, reply);
1171 }
1172
1173 static void command_delete_stream(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1174 connection *c = CONNECTION(userdata);
1175 uint32_t channel;
1176
1177 connection_assert_ref(c);
1178 pa_assert(t);
1179
1180 if (pa_tagstruct_getu32(t, &channel) < 0 ||
1181 !pa_tagstruct_eof(t)) {
1182 protocol_error(c);
1183 return;
1184 }
1185
1186 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1187
1188 switch (command) {
1189
1190 case PA_COMMAND_DELETE_PLAYBACK_STREAM: {
1191 playback_stream *s;
1192 if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || !playback_stream_isinstance(s)) {
1193 pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST);
1194 return;
1195 }
1196
1197 playback_stream_unlink(s);
1198 break;
1199 }
1200
1201 case PA_COMMAND_DELETE_RECORD_STREAM: {
1202 record_stream *s;
1203 if (!(s = pa_idxset_get_by_index(c->record_streams, channel))) {
1204 pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST);
1205 return;
1206 }
1207
1208 record_stream_unlink(s);
1209 break;
1210 }
1211
1212 case PA_COMMAND_DELETE_UPLOAD_STREAM: {
1213 upload_stream *s;
1214
1215 if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || !upload_stream_isinstance(s)) {
1216 pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST);
1217 return;
1218 }
1219
1220 upload_stream_unlink(s);
1221 break;
1222 }
1223
1224 default:
1225 pa_assert_not_reached();
1226 }
1227
1228 pa_pstream_send_simple_ack(c->pstream, tag);
1229 }
1230
1231 static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1232 connection *c = CONNECTION(userdata);
1233 record_stream *s;
1234 uint32_t maxlength, fragment_size;
1235 uint32_t source_index;
1236 const char *name, *source_name;
1237 pa_sample_spec ss;
1238 pa_channel_map map;
1239 pa_tagstruct *reply;
1240 pa_source *source = NULL;
1241 int corked;
1242
1243 connection_assert_ref(c);
1244 pa_assert(t);
1245
1246 if (pa_tagstruct_gets(t, &name) < 0 ||
1247 pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
1248 pa_tagstruct_get_channel_map(t, &map) < 0 ||
1249 pa_tagstruct_getu32(t, &source_index) < 0 ||
1250 pa_tagstruct_gets(t, &source_name) < 0 ||
1251 pa_tagstruct_getu32(t, &maxlength) < 0 ||
1252 pa_tagstruct_get_boolean(t, &corked) < 0 ||
1253 pa_tagstruct_getu32(t, &fragment_size) < 0 ||
1254 !pa_tagstruct_eof(t)) {
1255 protocol_error(c);
1256 return;
1257 }
1258
1259 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1260 CHECK_VALIDITY(c->pstream, name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
1261 CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID);
1262 CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID);
1263 CHECK_VALIDITY(c->pstream, source_index != PA_INVALID_INDEX || !source_name || (*source_name && pa_utf8_valid(source_name)), tag, PA_ERR_INVALID);
1264 CHECK_VALIDITY(c->pstream, map.channels == ss.channels, tag, PA_ERR_INVALID);
1265 CHECK_VALIDITY(c->pstream, maxlength <= MAX_MEMBLOCKQ_LENGTH, tag, PA_ERR_INVALID);
1266
1267 if (source_index != PA_INVALID_INDEX) {
1268 source = pa_idxset_get_by_index(c->protocol->core->sources, source_index);
1269 CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY);
1270 } else if (source_name) {
1271 source = pa_namereg_get(c->protocol->core, source_name, PA_NAMEREG_SOURCE, 1);
1272 CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY);
1273 }
1274
1275 s = record_stream_new(c, source, &ss, &map, name, &maxlength, fragment_size, corked);
1276 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID);
1277
1278 reply = reply_new(tag);
1279 pa_tagstruct_putu32(reply, s->index);
1280 pa_assert(s->source_output);
1281 pa_tagstruct_putu32(reply, s->source_output->index);
1282
1283 if (c->version >= 9) {
1284 /* Since 0.9 we support sending the buffer metrics back to the client */
1285
1286 pa_tagstruct_putu32(reply, (uint32_t) maxlength);
1287 pa_tagstruct_putu32(reply, (uint32_t) s->fragment_size);
1288 }
1289
1290 pa_pstream_send_tagstruct(c->pstream, reply);
1291 }
1292
1293 static void command_exit(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1294 connection *c = CONNECTION(userdata);
1295
1296 connection_assert_ref(c);
1297 pa_assert(t);
1298
1299 if (!pa_tagstruct_eof(t)) {
1300 protocol_error(c);
1301 return;
1302 }
1303
1304 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1305
1306 c->protocol->core->mainloop->quit(c->protocol->core->mainloop, 0);
1307 pa_pstream_send_simple_ack(c->pstream, tag); /* nonsense */
1308 }
1309
1310 static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1311 connection *c = CONNECTION(userdata);
1312 const void*cookie;
1313 pa_tagstruct *reply;
1314
1315 connection_assert_ref(c);
1316 pa_assert(t);
1317
1318 if (pa_tagstruct_getu32(t, &c->version) < 0 ||
1319 pa_tagstruct_get_arbitrary(t, &cookie, PA_NATIVE_COOKIE_LENGTH) < 0 ||
1320 !pa_tagstruct_eof(t)) {
1321 protocol_error(c);
1322 return;
1323 }
1324
1325 /* Minimum supported version */
1326 if (c->version < 8) {
1327 pa_pstream_send_error(c->pstream, tag, PA_ERR_VERSION);
1328 return;
1329 }
1330
1331 if (!c->authorized) {
1332 int success = 0;
1333
1334 #ifdef HAVE_CREDS
1335 const pa_creds *creds;
1336
1337 if ((creds = pa_pdispatch_creds(pd))) {
1338 if (creds->uid == getuid())
1339 success = 1;
1340 else if (c->protocol->auth_group) {
1341 int r;
1342 gid_t gid;
1343
1344 if ((gid = pa_get_gid_of_group(c->protocol->auth_group)) == (gid_t) -1)
1345 pa_log_warn("failed to get GID of group '%s'", c->protocol->auth_group);
1346 else if (gid == creds->gid)
1347 success = 1;
1348
1349 if (!success) {
1350 if ((r = pa_uid_in_group(creds->uid, c->protocol->auth_group)) < 0)
1351 pa_log_warn("failed to check group membership.");
1352 else if (r > 0)
1353 success = 1;
1354 }
1355 }
1356
1357 pa_log_info("Got credentials: uid=%lu gid=%lu success=%i",
1358 (unsigned long) creds->uid,
1359 (unsigned long) creds->gid,
1360 success);
1361
1362 if (c->version >= 10 &&
1363 pa_mempool_is_shared(c->protocol->core->mempool) &&
1364 creds->uid == getuid()) {
1365
1366 pa_pstream_use_shm(c->pstream, 1);
1367 pa_log_info("Enabled SHM for new connection");
1368 }
1369
1370 }
1371 #endif
1372
1373 if (!success && memcmp(c->protocol->auth_cookie, cookie, PA_NATIVE_COOKIE_LENGTH) == 0)
1374 success = 1;
1375
1376 if (!success) {
1377 pa_log_warn("Denied access to client with invalid authorization data.");
1378 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
1379 return;
1380 }
1381
1382 c->authorized = 1;
1383 if (c->auth_timeout_event) {
1384 c->protocol->core->mainloop->time_free(c->auth_timeout_event);
1385 c->auth_timeout_event = NULL;
1386 }
1387 }
1388
1389 reply = reply_new(tag);
1390 pa_tagstruct_putu32(reply, PA_PROTOCOL_VERSION);
1391
1392 #ifdef HAVE_CREDS
1393 {
1394 /* SHM support is only enabled after both sides made sure they are the same user. */
1395
1396 pa_creds ucred;
1397
1398 ucred.uid = getuid();
1399 ucred.gid = getgid();
1400
1401 pa_pstream_send_tagstruct_with_creds(c->pstream, reply, &ucred);
1402 }
1403 #else
1404 pa_pstream_send_tagstruct(c->pstream, reply);
1405 #endif
1406 }
1407
1408 static void command_set_client_name(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1409 connection *c = CONNECTION(userdata);
1410 const char *name;
1411
1412 connection_assert_ref(c);
1413 pa_assert(t);
1414
1415 if (pa_tagstruct_gets(t, &name) < 0 ||
1416 !pa_tagstruct_eof(t)) {
1417 protocol_error(c);
1418 return;
1419 }
1420
1421 CHECK_VALIDITY(c->pstream, name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
1422
1423 pa_client_set_name(c->client, name);
1424 pa_pstream_send_simple_ack(c->pstream, tag);
1425 }
1426
1427 static void command_lookup(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1428 connection *c = CONNECTION(userdata);
1429 const char *name;
1430 uint32_t idx = PA_IDXSET_INVALID;
1431
1432 connection_assert_ref(c);
1433 pa_assert(t);
1434
1435 if (pa_tagstruct_gets(t, &name) < 0 ||
1436 !pa_tagstruct_eof(t)) {
1437 protocol_error(c);
1438 return;
1439 }
1440
1441 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1442 CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
1443
1444 if (command == PA_COMMAND_LOOKUP_SINK) {
1445 pa_sink *sink;
1446 if ((sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1)))
1447 idx = sink->index;
1448 } else {
1449 pa_source *source;
1450 pa_assert(command == PA_COMMAND_LOOKUP_SOURCE);
1451 if ((source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1)))
1452 idx = source->index;
1453 }
1454
1455 if (idx == PA_IDXSET_INVALID)
1456 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1457 else {
1458 pa_tagstruct *reply;
1459 reply = reply_new(tag);
1460 pa_tagstruct_putu32(reply, idx);
1461 pa_pstream_send_tagstruct(c->pstream, reply);
1462 }
1463 }
1464
1465 static void command_drain_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1466 connection *c = CONNECTION(userdata);
1467 uint32_t idx;
1468 playback_stream *s;
1469
1470 connection_assert_ref(c);
1471 pa_assert(t);
1472
1473 if (pa_tagstruct_getu32(t, &idx) < 0 ||
1474 !pa_tagstruct_eof(t)) {
1475 protocol_error(c);
1476 return;
1477 }
1478
1479 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1480 s = pa_idxset_get_by_index(c->output_streams, idx);
1481 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
1482 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
1483
1484 pa_asyncmsgq_post(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_DRAIN, PA_UINT_TO_PTR(tag), 0, NULL, NULL);
1485 }
1486
1487 static void command_stat(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1488 connection *c = CONNECTION(userdata);
1489 pa_tagstruct *reply;
1490 const pa_mempool_stat *stat;
1491
1492 connection_assert_ref(c);
1493 pa_assert(t);
1494
1495 if (!pa_tagstruct_eof(t)) {
1496 protocol_error(c);
1497 return;
1498 }
1499
1500 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1501
1502 stat = pa_mempool_get_stat(c->protocol->core->mempool);
1503
1504 reply = reply_new(tag);
1505 pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->n_allocated));
1506 pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->allocated_size));
1507 pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->n_accumulated));
1508 pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->accumulated_size));
1509 pa_tagstruct_putu32(reply, pa_scache_total_size(c->protocol->core));
1510 pa_pstream_send_tagstruct(c->pstream, reply);
1511 }
1512
1513 static void command_get_playback_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1514 connection *c = CONNECTION(userdata);
1515 pa_tagstruct *reply;
1516 playback_stream *s;
1517 struct timeval tv, now;
1518 uint32_t idx;
1519 pa_usec_t latency;
1520
1521 connection_assert_ref(c);
1522 pa_assert(t);
1523
1524 if (pa_tagstruct_getu32(t, &idx) < 0 ||
1525 pa_tagstruct_get_timeval(t, &tv) < 0 ||
1526 !pa_tagstruct_eof(t)) {
1527 protocol_error(c);
1528 return;
1529 }
1530
1531 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1532 s = pa_idxset_get_by_index(c->output_streams, idx);
1533 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
1534 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
1535 CHECK_VALIDITY(c->pstream, pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_UPDATE_LATENCY, s, 0, NULL) == 0, tag, PA_ERR_NOENTITY)
1536
1537 reply = reply_new(tag);
1538
1539 latency = pa_sink_get_latency(s->sink_input->sink);
1540 latency += pa_bytes_to_usec(s->resampled_chunk_length, &s->sink_input->sample_spec);
1541
1542 pa_tagstruct_put_usec(reply, latency);
1543
1544 pa_tagstruct_put_usec(reply, 0);
1545 pa_tagstruct_put_boolean(reply, pa_sink_input_get_state(s->sink_input) == PA_SINK_INPUT_RUNNING);
1546 pa_tagstruct_put_timeval(reply, &tv);
1547 pa_tagstruct_put_timeval(reply, pa_gettimeofday(&now));
1548 pa_tagstruct_puts64(reply, s->write_index);
1549 pa_tagstruct_puts64(reply, s->read_index);
1550 pa_pstream_send_tagstruct(c->pstream, reply);
1551 }
1552
1553 static void command_get_record_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1554 connection *c = CONNECTION(userdata);
1555 pa_tagstruct *reply;
1556 record_stream *s;
1557 struct timeval tv, now;
1558 uint32_t idx;
1559
1560 connection_assert_ref(c);
1561 pa_assert(t);
1562
1563 if (pa_tagstruct_getu32(t, &idx) < 0 ||
1564 pa_tagstruct_get_timeval(t, &tv) < 0 ||
1565 !pa_tagstruct_eof(t)) {
1566 protocol_error(c);
1567 return;
1568 }
1569
1570 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1571 s = pa_idxset_get_by_index(c->record_streams, idx);
1572 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
1573
1574 reply = reply_new(tag);
1575 pa_tagstruct_put_usec(reply, s->source_output->source->monitor_of ? pa_sink_get_latency(s->source_output->source->monitor_of) : 0);
1576 pa_tagstruct_put_usec(reply, pa_source_get_latency(s->source_output->source));
1577 pa_tagstruct_put_boolean(reply, 0);
1578 pa_tagstruct_put_timeval(reply, &tv);
1579 pa_tagstruct_put_timeval(reply, pa_gettimeofday(&now));
1580 pa_tagstruct_puts64(reply, pa_memblockq_get_write_index(s->memblockq));
1581 pa_tagstruct_puts64(reply, pa_memblockq_get_read_index(s->memblockq));
1582 pa_pstream_send_tagstruct(c->pstream, reply);
1583 }
1584
1585 static void command_create_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1586 connection *c = CONNECTION(userdata);
1587 upload_stream *s;
1588 uint32_t length;
1589 const char *name;
1590 pa_sample_spec ss;
1591 pa_channel_map map;
1592 pa_tagstruct *reply;
1593
1594 connection_assert_ref(c);
1595 pa_assert(t);
1596
1597 if (pa_tagstruct_gets(t, &name) < 0 ||
1598 pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
1599 pa_tagstruct_get_channel_map(t, &map) < 0 ||
1600 pa_tagstruct_getu32(t, &length) < 0 ||
1601 !pa_tagstruct_eof(t)) {
1602 protocol_error(c);
1603 return;
1604 }
1605
1606 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1607 CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID);
1608 CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID);
1609 CHECK_VALIDITY(c->pstream, map.channels == ss.channels, tag, PA_ERR_INVALID);
1610 CHECK_VALIDITY(c->pstream, (length % pa_frame_size(&ss)) == 0 && length > 0, tag, PA_ERR_INVALID);
1611 CHECK_VALIDITY(c->pstream, length <= PA_SCACHE_ENTRY_SIZE_MAX, tag, PA_ERR_TOOLARGE);
1612 CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
1613
1614 s = upload_stream_new(c, &ss, &map, name, length);
1615 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID);
1616
1617 reply = reply_new(tag);
1618 pa_tagstruct_putu32(reply, s->index);
1619 pa_tagstruct_putu32(reply, length);
1620 pa_pstream_send_tagstruct(c->pstream, reply);
1621 }
1622
1623 static void command_finish_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1624 connection *c = CONNECTION(userdata);
1625 uint32_t channel;
1626 upload_stream *s;
1627 uint32_t idx;
1628
1629 connection_assert_ref(c);
1630 pa_assert(t);
1631
1632 if (pa_tagstruct_getu32(t, &channel) < 0 ||
1633 !pa_tagstruct_eof(t)) {
1634 protocol_error(c);
1635 return;
1636 }
1637
1638 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1639
1640 s = pa_idxset_get_by_index(c->output_streams, channel);
1641 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
1642 CHECK_VALIDITY(c->pstream, upload_stream_isinstance(s), tag, PA_ERR_NOENTITY);
1643
1644 if (pa_scache_add_item(c->protocol->core, s->name, &s->sample_spec, &s->channel_map, &s->memchunk, &idx) < 0)
1645 pa_pstream_send_error(c->pstream, tag, PA_ERR_INTERNAL);
1646 else
1647 pa_pstream_send_simple_ack(c->pstream, tag);
1648
1649 upload_stream_unlink(s);
1650 }
1651
1652 static void command_play_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1653 connection *c = CONNECTION(userdata);
1654 uint32_t sink_index;
1655 pa_volume_t volume;
1656 pa_sink *sink;
1657 const char *name, *sink_name;
1658
1659 connection_assert_ref(c);
1660 pa_assert(t);
1661
1662 if (pa_tagstruct_getu32(t, &sink_index) < 0 ||
1663 pa_tagstruct_gets(t, &sink_name) < 0 ||
1664 pa_tagstruct_getu32(t, &volume) < 0 ||
1665 pa_tagstruct_gets(t, &name) < 0 ||
1666 !pa_tagstruct_eof(t)) {
1667 protocol_error(c);
1668 return;
1669 }
1670
1671 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1672 CHECK_VALIDITY(c->pstream, sink_index != PA_INVALID_INDEX || !sink_name || (*sink_name && pa_utf8_valid(name)), tag, PA_ERR_INVALID);
1673 CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
1674
1675 if (sink_index != PA_INVALID_INDEX)
1676 sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index);
1677 else
1678 sink = pa_namereg_get(c->protocol->core, sink_name, PA_NAMEREG_SINK, 1);
1679
1680 CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
1681
1682 if (pa_scache_play_item(c->protocol->core, name, sink, volume) < 0) {
1683 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1684 return;
1685 }
1686
1687 pa_pstream_send_simple_ack(c->pstream, tag);
1688 }
1689
1690 static void command_remove_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1691 connection *c = CONNECTION(userdata);
1692 const char *name;
1693
1694 connection_assert_ref(c);
1695 pa_assert(t);
1696
1697 if (pa_tagstruct_gets(t, &name) < 0 ||
1698 !pa_tagstruct_eof(t)) {
1699 protocol_error(c);
1700 return;
1701 }
1702
1703 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1704 CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
1705
1706 if (pa_scache_remove_item(c->protocol->core, name) < 0) {
1707 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1708 return;
1709 }
1710
1711 pa_pstream_send_simple_ack(c->pstream, tag);
1712 }
1713
1714 static void sink_fill_tagstruct(pa_tagstruct *t, pa_sink *sink) {
1715 pa_assert(t);
1716 pa_sink_assert_ref(sink);
1717
1718 pa_tagstruct_put(
1719 t,
1720 PA_TAG_U32, sink->index,
1721 PA_TAG_STRING, sink->name,
1722 PA_TAG_STRING, sink->description,
1723 PA_TAG_SAMPLE_SPEC, &sink->sample_spec,
1724 PA_TAG_CHANNEL_MAP, &sink->channel_map,
1725 PA_TAG_U32, sink->module ? sink->module->index : PA_INVALID_INDEX,
1726 PA_TAG_CVOLUME, pa_sink_get_volume(sink),
1727 PA_TAG_BOOLEAN, pa_sink_get_mute(sink),
1728 PA_TAG_U32, sink->monitor_source ? sink->monitor_source->index : PA_INVALID_INDEX,
1729 PA_TAG_STRING, sink->monitor_source ? sink->monitor_source->name : NULL,
1730 PA_TAG_USEC, pa_sink_get_latency(sink),
1731 PA_TAG_STRING, sink->driver,
1732 PA_TAG_U32, sink->flags,
1733 PA_TAG_INVALID);
1734 }
1735
1736 static void source_fill_tagstruct(pa_tagstruct *t, pa_source *source) {
1737 pa_assert(t);
1738 pa_source_assert_ref(source);
1739
1740 pa_tagstruct_put(
1741 t,
1742 PA_TAG_U32, source->index,
1743 PA_TAG_STRING, source->name,
1744 PA_TAG_STRING, source->description,
1745 PA_TAG_SAMPLE_SPEC, &source->sample_spec,
1746 PA_TAG_CHANNEL_MAP, &source->channel_map,
1747 PA_TAG_U32, source->module ? source->module->index : PA_INVALID_INDEX,
1748 PA_TAG_CVOLUME, pa_source_get_volume(source),
1749 PA_TAG_BOOLEAN, pa_source_get_mute(source),
1750 PA_TAG_U32, source->monitor_of ? source->monitor_of->index : PA_INVALID_INDEX,
1751 PA_TAG_STRING, source->monitor_of ? source->monitor_of->name : NULL,
1752 PA_TAG_USEC, pa_source_get_latency(source),
1753 PA_TAG_STRING, source->driver,
1754 PA_TAG_U32, source->flags,
1755 PA_TAG_INVALID);
1756 }
1757
1758 static void client_fill_tagstruct(pa_tagstruct *t, pa_client *client) {
1759 pa_assert(t);
1760 pa_assert(client);
1761
1762 pa_tagstruct_putu32(t, client->index);
1763 pa_tagstruct_puts(t, client->name);
1764 pa_tagstruct_putu32(t, client->owner ? client->owner->index : PA_INVALID_INDEX);
1765 pa_tagstruct_puts(t, client->driver);
1766 }
1767
1768 static void module_fill_tagstruct(pa_tagstruct *t, pa_module *module) {
1769 pa_assert(t);
1770 pa_assert(module);
1771
1772 pa_tagstruct_putu32(t, module->index);
1773 pa_tagstruct_puts(t, module->name);
1774 pa_tagstruct_puts(t, module->argument);
1775 pa_tagstruct_putu32(t, module->n_used);
1776 pa_tagstruct_put_boolean(t, module->auto_unload);
1777 }
1778
1779 static void sink_input_fill_tagstruct(connection *c, pa_tagstruct *t, pa_sink_input *s) {
1780 pa_assert(t);
1781 pa_sink_input_assert_ref(s);
1782
1783 pa_tagstruct_putu32(t, s->index);
1784 pa_tagstruct_puts(t, s->name);
1785 pa_tagstruct_putu32(t, s->module ? s->module->index : PA_INVALID_INDEX);
1786 pa_tagstruct_putu32(t, s->client ? s->client->index : PA_INVALID_INDEX);
1787 pa_tagstruct_putu32(t, s->sink->index);
1788 pa_tagstruct_put_sample_spec(t, &s->sample_spec);
1789 pa_tagstruct_put_channel_map(t, &s->channel_map);
1790 pa_tagstruct_put_cvolume(t, &s->volume);
1791 pa_tagstruct_put_usec(t, pa_sink_input_get_latency(s));
1792 pa_tagstruct_put_usec(t, pa_sink_get_latency(s->sink));
1793 pa_tagstruct_puts(t, pa_resample_method_to_string(pa_sink_input_get_resample_method(s)));
1794 pa_tagstruct_puts(t, s->driver);
1795 if (c->version >= 11)
1796 pa_tagstruct_put_boolean(t, pa_sink_input_get_mute(s));
1797 }
1798
1799 static void source_output_fill_tagstruct(pa_tagstruct *t, pa_source_output *s) {
1800 pa_assert(t);
1801 pa_source_output_assert_ref(s);
1802
1803 pa_tagstruct_putu32(t, s->index);
1804 pa_tagstruct_puts(t, s->name);
1805 pa_tagstruct_putu32(t, s->module ? s->module->index : PA_INVALID_INDEX);
1806 pa_tagstruct_putu32(t, s->client ? s->client->index : PA_INVALID_INDEX);
1807 pa_tagstruct_putu32(t, s->source->index);
1808 pa_tagstruct_put_sample_spec(t, &s->sample_spec);
1809 pa_tagstruct_put_channel_map(t, &s->channel_map);
1810 pa_tagstruct_put_usec(t, pa_source_output_get_latency(s));
1811 pa_tagstruct_put_usec(t, pa_source_get_latency(s->source));
1812 pa_tagstruct_puts(t, pa_resample_method_to_string(pa_source_output_get_resample_method(s)));
1813 pa_tagstruct_puts(t, s->driver);
1814 }
1815
1816 static void scache_fill_tagstruct(pa_tagstruct *t, pa_scache_entry *e) {
1817 pa_assert(t);
1818 pa_assert(e);
1819
1820 pa_tagstruct_putu32(t, e->index);
1821 pa_tagstruct_puts(t, e->name);
1822 pa_tagstruct_put_cvolume(t, &e->volume);
1823 pa_tagstruct_put_usec(t, pa_bytes_to_usec(e->memchunk.length, &e->sample_spec));
1824 pa_tagstruct_put_sample_spec(t, &e->sample_spec);
1825 pa_tagstruct_put_channel_map(t, &e->channel_map);
1826 pa_tagstruct_putu32(t, e->memchunk.length);
1827 pa_tagstruct_put_boolean(t, e->lazy);
1828 pa_tagstruct_puts(t, e->filename);
1829 }
1830
1831 static void command_get_info(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1832 connection *c = CONNECTION(userdata);
1833 uint32_t idx;
1834 pa_sink *sink = NULL;
1835 pa_source *source = NULL;
1836 pa_client *client = NULL;
1837 pa_module *module = NULL;
1838 pa_sink_input *si = NULL;
1839 pa_source_output *so = NULL;
1840 pa_scache_entry *sce = NULL;
1841 const char *name;
1842 pa_tagstruct *reply;
1843
1844 connection_assert_ref(c);
1845 pa_assert(t);
1846
1847 if (pa_tagstruct_getu32(t, &idx) < 0 ||
1848 (command != PA_COMMAND_GET_CLIENT_INFO &&
1849 command != PA_COMMAND_GET_MODULE_INFO &&
1850 command != PA_COMMAND_GET_SINK_INPUT_INFO &&
1851 command != PA_COMMAND_GET_SOURCE_OUTPUT_INFO &&
1852 pa_tagstruct_gets(t, &name) < 0) ||
1853 !pa_tagstruct_eof(t)) {
1854 protocol_error(c);
1855 return;
1856 }
1857
1858 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1859 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || !name || (*name && pa_utf8_valid(name)), tag, PA_ERR_INVALID);
1860
1861 if (command == PA_COMMAND_GET_SINK_INFO) {
1862 if (idx != PA_INVALID_INDEX)
1863 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
1864 else
1865 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1);
1866 } else if (command == PA_COMMAND_GET_SOURCE_INFO) {
1867 if (idx != PA_INVALID_INDEX)
1868 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
1869 else
1870 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1);
1871 } else if (command == PA_COMMAND_GET_CLIENT_INFO)
1872 client = pa_idxset_get_by_index(c->protocol->core->clients, idx);
1873 else if (command == PA_COMMAND_GET_MODULE_INFO)
1874 module = pa_idxset_get_by_index(c->protocol->core->modules, idx);
1875 else if (command == PA_COMMAND_GET_SINK_INPUT_INFO)
1876 si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
1877 else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO)
1878 so = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
1879 else {
1880 pa_assert(command == PA_COMMAND_GET_SAMPLE_INFO);
1881 if (idx != PA_INVALID_INDEX)
1882 sce = pa_idxset_get_by_index(c->protocol->core->scache, idx);
1883 else
1884 sce = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SAMPLE, 0);
1885 }
1886
1887 if (!sink && !source && !client && !module && !si && !so && !sce) {
1888 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1889 return;
1890 }
1891
1892 reply = reply_new(tag);
1893 if (sink)
1894 sink_fill_tagstruct(reply, sink);
1895 else if (source)
1896 source_fill_tagstruct(reply, source);
1897 else if (client)
1898 client_fill_tagstruct(reply, client);
1899 else if (module)
1900 module_fill_tagstruct(reply, module);
1901 else if (si)
1902 sink_input_fill_tagstruct(c, reply, si);
1903 else if (so)
1904 source_output_fill_tagstruct(reply, so);
1905 else
1906 scache_fill_tagstruct(reply, sce);
1907 pa_pstream_send_tagstruct(c->pstream, reply);
1908 }
1909
1910 static void command_get_info_list(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1911 connection *c = CONNECTION(userdata);
1912 pa_idxset *i;
1913 uint32_t idx;
1914 void *p;
1915 pa_tagstruct *reply;
1916
1917 connection_assert_ref(c);
1918 pa_assert(t);
1919
1920 if (!pa_tagstruct_eof(t)) {
1921 protocol_error(c);
1922 return;
1923 }
1924
1925 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1926
1927 reply = reply_new(tag);
1928
1929 if (command == PA_COMMAND_GET_SINK_INFO_LIST)
1930 i = c->protocol->core->sinks;
1931 else if (command == PA_COMMAND_GET_SOURCE_INFO_LIST)
1932 i = c->protocol->core->sources;
1933 else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST)
1934 i = c->protocol->core->clients;
1935 else if (command == PA_COMMAND_GET_MODULE_INFO_LIST)
1936 i = c->protocol->core->modules;
1937 else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST)
1938 i = c->protocol->core->sink_inputs;
1939 else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST)
1940 i = c->protocol->core->source_outputs;
1941 else {
1942 pa_assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST);
1943 i = c->protocol->core->scache;
1944 }
1945
1946 if (i) {
1947 for (p = pa_idxset_first(i, &idx); p; p = pa_idxset_next(i, &idx)) {
1948 if (command == PA_COMMAND_GET_SINK_INFO_LIST)
1949 sink_fill_tagstruct(reply, p);
1950 else if (command == PA_COMMAND_GET_SOURCE_INFO_LIST)
1951 source_fill_tagstruct(reply, p);
1952 else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST)
1953 client_fill_tagstruct(reply, p);
1954 else if (command == PA_COMMAND_GET_MODULE_INFO_LIST)
1955 module_fill_tagstruct(reply, p);
1956 else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST)
1957 sink_input_fill_tagstruct(c, reply, p);
1958 else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST)
1959 source_output_fill_tagstruct(reply, p);
1960 else {
1961 pa_assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST);
1962 scache_fill_tagstruct(reply, p);
1963 }
1964 }
1965 }
1966
1967 pa_pstream_send_tagstruct(c->pstream, reply);
1968 }
1969
1970 static void command_get_server_info(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1971 connection *c = CONNECTION(userdata);
1972 pa_tagstruct *reply;
1973 char txt[256];
1974 const char *n;
1975
1976 connection_assert_ref(c);
1977 pa_assert(t);
1978
1979 if (!pa_tagstruct_eof(t)) {
1980 protocol_error(c);
1981 return;
1982 }
1983
1984 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1985
1986 reply = reply_new(tag);
1987 pa_tagstruct_puts(reply, PACKAGE_NAME);
1988 pa_tagstruct_puts(reply, PACKAGE_VERSION);
1989 pa_tagstruct_puts(reply, pa_get_user_name(txt, sizeof(txt)));
1990 pa_tagstruct_puts(reply, pa_get_fqdn(txt, sizeof(txt)));
1991 pa_tagstruct_put_sample_spec(reply, &c->protocol->core->default_sample_spec);
1992
1993 n = pa_namereg_get_default_sink_name(c->protocol->core);
1994 pa_tagstruct_puts(reply, n);
1995 n = pa_namereg_get_default_source_name(c->protocol->core);
1996 pa_tagstruct_puts(reply, n);
1997
1998 pa_tagstruct_putu32(reply, c->protocol->core->cookie);
1999
2000 pa_pstream_send_tagstruct(c->pstream, reply);
2001 }
2002
2003 static void subscription_cb(pa_core *core, pa_subscription_event_type_t e, uint32_t idx, void *userdata) {
2004 pa_tagstruct *t;
2005 connection *c = CONNECTION(userdata);
2006
2007 connection_assert_ref(c);
2008
2009 t = pa_tagstruct_new(NULL, 0);
2010 pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE_EVENT);
2011 pa_tagstruct_putu32(t, (uint32_t) -1);
2012 pa_tagstruct_putu32(t, e);
2013 pa_tagstruct_putu32(t, idx);
2014 pa_pstream_send_tagstruct(c->pstream, t);
2015 }
2016
2017 static void command_subscribe(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2018 connection *c = CONNECTION(userdata);
2019 pa_subscription_mask_t m;
2020
2021 connection_assert_ref(c);
2022 pa_assert(t);
2023
2024 if (pa_tagstruct_getu32(t, &m) < 0 ||
2025 !pa_tagstruct_eof(t)) {
2026 protocol_error(c);
2027 return;
2028 }
2029
2030 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2031 CHECK_VALIDITY(c->pstream, (m & ~PA_SUBSCRIPTION_MASK_ALL) == 0, tag, PA_ERR_INVALID);
2032
2033 if (c->subscription)
2034 pa_subscription_free(c->subscription);
2035
2036 if (m != 0) {
2037 c->subscription = pa_subscription_new(c->protocol->core, m, subscription_cb, c);
2038 pa_assert(c->subscription);
2039 } else
2040 c->subscription = NULL;
2041
2042 pa_pstream_send_simple_ack(c->pstream, tag);
2043 }
2044
2045 static void command_set_volume(
2046 PA_GCC_UNUSED pa_pdispatch *pd,
2047 uint32_t command,
2048 uint32_t tag,
2049 pa_tagstruct *t,
2050 void *userdata) {
2051
2052 connection *c = CONNECTION(userdata);
2053 uint32_t idx;
2054 pa_cvolume volume;
2055 pa_sink *sink = NULL;
2056 pa_source *source = NULL;
2057 pa_sink_input *si = NULL;
2058 const char *name = NULL;
2059
2060 connection_assert_ref(c);
2061 pa_assert(t);
2062
2063 if (pa_tagstruct_getu32(t, &idx) < 0 ||
2064 (command == PA_COMMAND_SET_SINK_VOLUME && pa_tagstruct_gets(t, &name) < 0) ||
2065 (command == PA_COMMAND_SET_SOURCE_VOLUME && pa_tagstruct_gets(t, &name) < 0) ||
2066 pa_tagstruct_get_cvolume(t, &volume) ||
2067 !pa_tagstruct_eof(t)) {
2068 protocol_error(c);
2069 return;
2070 }
2071
2072 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2073 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || !name || (*name && pa_utf8_valid(name)), tag, PA_ERR_INVALID);
2074 CHECK_VALIDITY(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID);
2075
2076 switch (command) {
2077
2078 case PA_COMMAND_SET_SINK_VOLUME:
2079 if (idx != PA_INVALID_INDEX)
2080 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
2081 else
2082 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1);
2083 break;
2084
2085 case PA_COMMAND_SET_SOURCE_VOLUME:
2086 if (idx != PA_INVALID_INDEX)
2087 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
2088 else
2089 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1);
2090 break;
2091
2092 case PA_COMMAND_SET_SINK_INPUT_VOLUME:
2093 si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
2094 break;
2095
2096 default:
2097 pa_assert_not_reached();
2098 }
2099
2100 CHECK_VALIDITY(c->pstream, si || sink || source, tag, PA_ERR_NOENTITY);
2101
2102 if (sink)
2103 pa_sink_set_volume(sink, &volume);
2104 else if (source)
2105 pa_source_set_volume(source, &volume);
2106 else if (si)
2107 pa_sink_input_set_volume(si, &volume);
2108
2109 pa_pstream_send_simple_ack(c->pstream, tag);
2110 }
2111
2112 static void command_set_mute(
2113 PA_GCC_UNUSED pa_pdispatch *pd,
2114 uint32_t command,
2115 uint32_t tag,
2116 pa_tagstruct *t,
2117 void *userdata) {
2118
2119 connection *c = CONNECTION(userdata);
2120 uint32_t idx;
2121 int mute;
2122 pa_sink *sink = NULL;
2123 pa_source *source = NULL;
2124 pa_sink_input *si = NULL;
2125 const char *name = NULL;
2126
2127 connection_assert_ref(c);
2128 pa_assert(t);
2129
2130 if (pa_tagstruct_getu32(t, &idx) < 0 ||
2131 (command == PA_COMMAND_SET_SINK_MUTE && pa_tagstruct_gets(t, &name) < 0) ||
2132 (command == PA_COMMAND_SET_SOURCE_MUTE && pa_tagstruct_gets(t, &name) < 0) ||
2133 pa_tagstruct_get_boolean(t, &mute) ||
2134 !pa_tagstruct_eof(t)) {
2135 protocol_error(c);
2136 return;
2137 }
2138
2139 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2140 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || !name || (*name && pa_utf8_valid(name)), tag, PA_ERR_INVALID);
2141
2142 switch (command) {
2143
2144 case PA_COMMAND_SET_SINK_MUTE:
2145
2146 if (idx != PA_INVALID_INDEX)
2147 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
2148 else
2149 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1);
2150
2151 break;
2152
2153 case PA_COMMAND_SET_SOURCE_MUTE:
2154 if (idx != PA_INVALID_INDEX)
2155 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
2156 else
2157 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1);
2158
2159 break;
2160
2161 case PA_COMMAND_SET_SINK_INPUT_MUTE:
2162 si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
2163 break;
2164
2165 default:
2166 pa_assert_not_reached();
2167 }
2168
2169 CHECK_VALIDITY(c->pstream, si || sink || source, tag, PA_ERR_NOENTITY);
2170
2171 if (sink)
2172 pa_sink_set_mute(sink, mute);
2173 else if (source)
2174 pa_source_set_mute(source, mute);
2175 else if (si)
2176 pa_sink_input_set_mute(si, mute);
2177
2178 pa_pstream_send_simple_ack(c->pstream, tag);
2179 }
2180
2181 static void command_cork_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2182 connection *c = CONNECTION(userdata);
2183 uint32_t idx;
2184 int b;
2185 playback_stream *s;
2186
2187 connection_assert_ref(c);
2188 pa_assert(t);
2189
2190 if (pa_tagstruct_getu32(t, &idx) < 0 ||
2191 pa_tagstruct_get_boolean(t, &b) < 0 ||
2192 !pa_tagstruct_eof(t)) {
2193 protocol_error(c);
2194 return;
2195 }
2196
2197 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2198 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
2199 s = pa_idxset_get_by_index(c->output_streams, idx);
2200 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2201 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
2202
2203 pa_sink_input_cork(s->sink_input, b);
2204 pa_pstream_send_simple_ack(c->pstream, tag);
2205 }
2206
2207 static void command_trigger_or_flush_or_prebuf_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2208 connection *c = CONNECTION(userdata);
2209 uint32_t idx;
2210 playback_stream *s;
2211
2212 connection_assert_ref(c);
2213 pa_assert(t);
2214
2215 if (pa_tagstruct_getu32(t, &idx) < 0 ||
2216 !pa_tagstruct_eof(t)) {
2217 protocol_error(c);
2218 return;
2219 }
2220
2221 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2222 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
2223 s = pa_idxset_get_by_index(c->output_streams, idx);
2224 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2225 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
2226
2227 switch (command) {
2228 case PA_COMMAND_FLUSH_PLAYBACK_STREAM:
2229 pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_FLUSH, NULL, 0, NULL);
2230 break;
2231
2232 case PA_COMMAND_PREBUF_PLAYBACK_STREAM:
2233 pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_PREBUF_FORCE, NULL, 0, NULL);
2234 break;
2235
2236 case PA_COMMAND_TRIGGER_PLAYBACK_STREAM:
2237 pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_TRIGGER, NULL, 0, NULL);
2238 break;
2239
2240 default:
2241 pa_assert_not_reached();
2242 }
2243
2244 pa_pstream_send_simple_ack(c->pstream, tag);
2245 }
2246
2247 static void command_cork_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2248 connection *c = CONNECTION(userdata);
2249 uint32_t idx;
2250 record_stream *s;
2251 int b;
2252
2253 connection_assert_ref(c);
2254 pa_assert(t);
2255
2256 if (pa_tagstruct_getu32(t, &idx) < 0 ||
2257 pa_tagstruct_get_boolean(t, &b) < 0 ||
2258 !pa_tagstruct_eof(t)) {
2259 protocol_error(c);
2260 return;
2261 }
2262
2263 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2264 s = pa_idxset_get_by_index(c->record_streams, idx);
2265 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2266
2267 pa_source_output_cork(s->source_output, b);
2268 pa_memblockq_prebuf_force(s->memblockq);
2269 pa_pstream_send_simple_ack(c->pstream, tag);
2270 }
2271
2272 static void command_flush_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2273 connection *c = CONNECTION(userdata);
2274 uint32_t idx;
2275 record_stream *s;
2276
2277 connection_assert_ref(c);
2278 pa_assert(t);
2279
2280 if (pa_tagstruct_getu32(t, &idx) < 0 ||
2281 !pa_tagstruct_eof(t)) {
2282 protocol_error(c);
2283 return;
2284 }
2285
2286 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2287 s = pa_idxset_get_by_index(c->record_streams, idx);
2288 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2289
2290 pa_memblockq_flush(s->memblockq);
2291 pa_pstream_send_simple_ack(c->pstream, tag);
2292 }
2293
2294 static void command_set_default_sink_or_source(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2295 connection *c = CONNECTION(userdata);
2296 const char *s;
2297
2298 connection_assert_ref(c);
2299 pa_assert(t);
2300
2301 if (pa_tagstruct_gets(t, &s) < 0 ||
2302 !pa_tagstruct_eof(t)) {
2303 protocol_error(c);
2304 return;
2305 }
2306
2307 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2308 CHECK_VALIDITY(c->pstream, !s || (*s && pa_utf8_valid(s)), tag, PA_ERR_INVALID);
2309
2310 pa_namereg_set_default(c->protocol->core, s, command == PA_COMMAND_SET_DEFAULT_SOURCE ? PA_NAMEREG_SOURCE : PA_NAMEREG_SINK);
2311 pa_pstream_send_simple_ack(c->pstream, tag);
2312 }
2313
2314 static void command_set_stream_name(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2315 connection *c = CONNECTION(userdata);
2316 uint32_t idx;
2317 const char *name;
2318
2319 connection_assert_ref(c);
2320 pa_assert(t);
2321
2322 if (pa_tagstruct_getu32(t, &idx) < 0 ||
2323 pa_tagstruct_gets(t, &name) < 0 ||
2324 !pa_tagstruct_eof(t)) {
2325 protocol_error(c);
2326 return;
2327 }
2328
2329 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2330 CHECK_VALIDITY(c->pstream, name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
2331
2332 if (command == PA_COMMAND_SET_PLAYBACK_STREAM_NAME) {
2333 playback_stream *s;
2334
2335 s = pa_idxset_get_by_index(c->output_streams, idx);
2336 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2337 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
2338
2339 pa_sink_input_set_name(s->sink_input, name);
2340
2341 } else {
2342 record_stream *s;
2343
2344 s = pa_idxset_get_by_index(c->record_streams, idx);
2345 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2346
2347 pa_source_output_set_name(s->source_output, name);
2348 }
2349
2350 pa_pstream_send_simple_ack(c->pstream, tag);
2351 }
2352
2353 static void command_kill(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2354 connection *c = CONNECTION(userdata);
2355 uint32_t idx;
2356
2357 connection_assert_ref(c);
2358 pa_assert(t);
2359
2360 if (pa_tagstruct_getu32(t, &idx) < 0 ||
2361 !pa_tagstruct_eof(t)) {
2362 protocol_error(c);
2363 return;
2364 }
2365
2366 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2367
2368 if (command == PA_COMMAND_KILL_CLIENT) {
2369 pa_client *client;
2370
2371 client = pa_idxset_get_by_index(c->protocol->core->clients, idx);
2372 CHECK_VALIDITY(c->pstream, client, tag, PA_ERR_NOENTITY);
2373
2374 connection_ref(c);
2375 pa_client_kill(client);
2376
2377 } else if (command == PA_COMMAND_KILL_SINK_INPUT) {
2378 pa_sink_input *s;
2379
2380 s = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
2381 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2382
2383 connection_ref(c);
2384 pa_sink_input_kill(s);
2385 } else {
2386 pa_source_output *s;
2387
2388 pa_assert(command == PA_COMMAND_KILL_SOURCE_OUTPUT);
2389
2390 s = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
2391 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2392
2393 connection_ref(c);
2394 pa_source_output_kill(s);
2395 }
2396
2397 pa_pstream_send_simple_ack(c->pstream, tag);
2398 connection_unref(c);
2399 }
2400
2401 static void command_load_module(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2402 connection *c = CONNECTION(userdata);
2403 pa_module *m;
2404 const char *name, *argument;
2405 pa_tagstruct *reply;
2406
2407 connection_assert_ref(c);
2408 pa_assert(t);
2409
2410 if (pa_tagstruct_gets(t, &name) < 0 ||
2411 pa_tagstruct_gets(t, &argument) < 0 ||
2412 !pa_tagstruct_eof(t)) {
2413 protocol_error(c);
2414 return;
2415 }
2416
2417 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2418 CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name) && !strchr(name, '/'), tag, PA_ERR_INVALID);
2419 CHECK_VALIDITY(c->pstream, !argument || pa_utf8_valid(argument), tag, PA_ERR_INVALID);
2420
2421 if (!(m = pa_module_load(c->protocol->core, name, argument))) {
2422 pa_pstream_send_error(c->pstream, tag, PA_ERR_MODINITFAILED);
2423 return;
2424 }
2425
2426 reply = reply_new(tag);
2427 pa_tagstruct_putu32(reply, m->index);
2428 pa_pstream_send_tagstruct(c->pstream, reply);
2429 }
2430
2431 static void command_unload_module(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2432 connection *c = CONNECTION(userdata);
2433 uint32_t idx;
2434 pa_module *m;
2435
2436 connection_assert_ref(c);
2437 pa_assert(t);
2438
2439 if (pa_tagstruct_getu32(t, &idx) < 0 ||
2440 !pa_tagstruct_eof(t)) {
2441 protocol_error(c);
2442 return;
2443 }
2444
2445 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2446 m = pa_idxset_get_by_index(c->protocol->core->modules, idx);
2447 CHECK_VALIDITY(c->pstream, m, tag, PA_ERR_NOENTITY);
2448
2449 pa_module_unload_request(m);
2450 pa_pstream_send_simple_ack(c->pstream, tag);
2451 }
2452
2453 static void command_add_autoload(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2454 connection *c = CONNECTION(userdata);
2455 const char *name, *module, *argument;
2456 uint32_t type;
2457 uint32_t idx;
2458 pa_tagstruct *reply;
2459
2460 connection_assert_ref(c);
2461 pa_assert(t);
2462
2463 if (pa_tagstruct_gets(t, &name) < 0 ||
2464 pa_tagstruct_getu32(t, &type) < 0 ||
2465 pa_tagstruct_gets(t, &module) < 0 ||
2466 pa_tagstruct_gets(t, &argument) < 0 ||
2467 !pa_tagstruct_eof(t)) {
2468 protocol_error(c);
2469 return;
2470 }
2471
2472 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2473 CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
2474 CHECK_VALIDITY(c->pstream, type == 0 || type == 1, tag, PA_ERR_INVALID);
2475 CHECK_VALIDITY(c->pstream, module && *module && pa_utf8_valid(module), tag, PA_ERR_INVALID);
2476 CHECK_VALIDITY(c->pstream, !argument || pa_utf8_valid(argument), tag, PA_ERR_INVALID);
2477
2478 if (pa_autoload_add(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE, module, argument, &idx) < 0) {
2479 pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST);
2480 return;
2481 }
2482
2483 reply = reply_new(tag);
2484 pa_tagstruct_putu32(reply, idx);
2485 pa_pstream_send_tagstruct(c->pstream, reply);
2486 }
2487
2488 static void command_remove_autoload(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2489 connection *c = CONNECTION(userdata);
2490 const char *name = NULL;
2491 uint32_t type, idx = PA_IDXSET_INVALID;
2492 int r;
2493
2494 connection_assert_ref(c);
2495 pa_assert(t);
2496
2497 if ((pa_tagstruct_getu32(t, &idx) < 0 &&
2498 (pa_tagstruct_gets(t, &name) < 0 ||
2499 pa_tagstruct_getu32(t, &type) < 0)) ||
2500 !pa_tagstruct_eof(t)) {
2501 protocol_error(c);
2502 return;
2503 }
2504
2505 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2506 CHECK_VALIDITY(c->pstream, name || idx != PA_IDXSET_INVALID, tag, PA_ERR_INVALID);
2507 CHECK_VALIDITY(c->pstream, !name || (*name && pa_utf8_valid(name) && (type == 0 || type == 1)), tag, PA_ERR_INVALID);
2508
2509 if (name)
2510 r = pa_autoload_remove_by_name(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE);
2511 else
2512 r = pa_autoload_remove_by_index(c->protocol->core, idx);
2513
2514 CHECK_VALIDITY(c->pstream, r >= 0, tag, PA_ERR_NOENTITY);
2515
2516 pa_pstream_send_simple_ack(c->pstream, tag);
2517 }
2518
2519 static void autoload_fill_tagstruct(pa_tagstruct *t, const pa_autoload_entry *e) {
2520 pa_assert(t && e);
2521
2522 pa_tagstruct_putu32(t, e->index);
2523 pa_tagstruct_puts(t, e->name);
2524 pa_tagstruct_putu32(t, e->type == PA_NAMEREG_SINK ? 0 : 1);
2525 pa_tagstruct_puts(t, e->module);
2526 pa_tagstruct_puts(t, e->argument);
2527 }
2528
2529 static void command_get_autoload_info(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2530 connection *c = CONNECTION(userdata);
2531 const pa_autoload_entry *a = NULL;
2532 uint32_t type, idx;
2533 const char *name;
2534 pa_tagstruct *reply;
2535
2536 connection_assert_ref(c);
2537 pa_assert(t);
2538
2539 if ((pa_tagstruct_getu32(t, &idx) < 0 &&
2540 (pa_tagstruct_gets(t, &name) < 0 ||
2541 pa_tagstruct_getu32(t, &type) < 0)) ||
2542 !pa_tagstruct_eof(t)) {
2543 protocol_error(c);
2544 return;
2545 }
2546
2547 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2548 CHECK_VALIDITY(c->pstream, name || idx != PA_IDXSET_INVALID, tag, PA_ERR_INVALID);
2549 CHECK_VALIDITY(c->pstream, !name || (*name && (type == 0 || type == 1) && pa_utf8_valid(name)), tag, PA_ERR_INVALID);
2550
2551 if (name)
2552 a = pa_autoload_get_by_name(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE);
2553 else
2554 a = pa_autoload_get_by_index(c->protocol->core, idx);
2555
2556 CHECK_VALIDITY(c->pstream, a, tag, PA_ERR_NOENTITY);
2557
2558 reply = reply_new(tag);
2559 autoload_fill_tagstruct(reply, a);
2560 pa_pstream_send_tagstruct(c->pstream, reply);
2561 }
2562
2563 static void command_get_autoload_info_list(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2564 connection *c = CONNECTION(userdata);
2565 pa_tagstruct *reply;
2566
2567 connection_assert_ref(c);
2568 pa_assert(t);
2569
2570 if (!pa_tagstruct_eof(t)) {
2571 protocol_error(c);
2572 return;
2573 }
2574
2575 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2576
2577 reply = reply_new(tag);
2578
2579 if (c->protocol->core->autoload_hashmap) {
2580 pa_autoload_entry *a;
2581 void *state = NULL;
2582
2583 while ((a = pa_hashmap_iterate(c->protocol->core->autoload_hashmap, &state, NULL)))
2584 autoload_fill_tagstruct(reply, a);
2585 }
2586
2587 pa_pstream_send_tagstruct(c->pstream, reply);
2588 }
2589
2590 static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2591 connection *c = CONNECTION(userdata);
2592 uint32_t idx = PA_INVALID_INDEX, idx_device = PA_INVALID_INDEX;
2593 const char *name = NULL;
2594
2595 connection_assert_ref(c);
2596 pa_assert(t);
2597
2598 if (pa_tagstruct_getu32(t, &idx) < 0 ||
2599 pa_tagstruct_getu32(t, &idx_device) < 0 ||
2600 pa_tagstruct_gets(t, &name) < 0 ||
2601 !pa_tagstruct_eof(t)) {
2602 protocol_error(c);
2603 return;
2604 }
2605
2606 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2607 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
2608 CHECK_VALIDITY(c->pstream, idx_device != PA_INVALID_INDEX || !name || (*name && pa_utf8_valid(name)), tag, PA_ERR_INVALID);
2609
2610 if (command == PA_COMMAND_MOVE_SINK_INPUT) {
2611 pa_sink_input *si = NULL;
2612 pa_sink *sink = NULL;
2613
2614 si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
2615
2616 if (idx_device != PA_INVALID_INDEX)
2617 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx_device);
2618 else
2619 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1);
2620
2621 CHECK_VALIDITY(c->pstream, si && sink, tag, PA_ERR_NOENTITY);
2622
2623 if (pa_sink_input_move_to(si, sink, 0) < 0) {
2624 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
2625 return;
2626 }
2627 } else {
2628 pa_source_output *so = NULL;
2629 pa_source *source;
2630
2631 pa_assert(command == PA_COMMAND_MOVE_SOURCE_OUTPUT);
2632
2633 so = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
2634
2635 if (idx_device != PA_INVALID_INDEX)
2636 source = pa_idxset_get_by_index(c->protocol->core->sources, idx_device);
2637 else
2638 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1);
2639
2640 CHECK_VALIDITY(c->pstream, so && source, tag, PA_ERR_NOENTITY);
2641
2642 if (pa_source_output_move_to(so, source) < 0) {
2643 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
2644 return;
2645 }
2646 }
2647
2648 pa_pstream_send_simple_ack(c->pstream, tag);
2649 }
2650
2651 static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2652 connection *c = CONNECTION(userdata);
2653 uint32_t idx = PA_INVALID_INDEX;
2654 const char *name = NULL;
2655 int b;
2656
2657 connection_assert_ref(c);
2658 pa_assert(t);
2659
2660 if (pa_tagstruct_getu32(t, &idx) < 0 ||
2661 pa_tagstruct_gets(t, &name) < 0 ||
2662 pa_tagstruct_get_boolean(t, &b) < 0 ||
2663 !pa_tagstruct_eof(t)) {
2664 protocol_error(c);
2665 return;
2666 }
2667
2668 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2669 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || !name || !*name || pa_utf8_valid(name), tag, PA_ERR_INVALID);
2670
2671 if (command == PA_COMMAND_SUSPEND_SINK) {
2672
2673 if (idx == PA_INVALID_INDEX && name && !*name) {
2674
2675 if (pa_sink_suspend_all(c->protocol->core, b) < 0) {
2676 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
2677 return;
2678 }
2679 } else {
2680 pa_sink *sink = NULL;
2681
2682 if (idx != PA_INVALID_INDEX)
2683 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
2684 else
2685 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1);
2686
2687 CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
2688
2689 if (pa_sink_suspend(sink, b) < 0) {
2690 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
2691 return;
2692 }
2693 }
2694 } else {
2695
2696 pa_assert(command == PA_COMMAND_SUSPEND_SOURCE);
2697
2698 if (idx == PA_INVALID_INDEX && name && !*name) {
2699
2700 if (pa_source_suspend_all(c->protocol->core, b) < 0) {
2701 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
2702 return;
2703 }
2704
2705 } else {
2706 pa_source *source;
2707
2708 if (idx != PA_INVALID_INDEX)
2709 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
2710 else
2711 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1);
2712
2713 CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY);
2714
2715 if (pa_source_suspend(source, b) < 0) {
2716 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
2717 return;
2718 }
2719 }
2720 }
2721
2722 pa_pstream_send_simple_ack(c->pstream, tag);
2723 }
2724
2725 /*** pstream callbacks ***/
2726
2727 static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata) {
2728 connection *c = CONNECTION(userdata);
2729
2730 pa_assert(p);
2731 pa_assert(packet);
2732 connection_assert_ref(c);
2733
2734 if (pa_pdispatch_run(c->pdispatch, packet, creds, c) < 0) {
2735 pa_log("invalid packet.");
2736 connection_unlink(c);
2737 }
2738 }
2739
2740 static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk, void *userdata) {
2741 connection *c = CONNECTION(userdata);
2742 output_stream *stream;
2743
2744 pa_assert(p);
2745 pa_assert(chunk);
2746 connection_assert_ref(c);
2747
2748 if (!(stream = OUTPUT_STREAM(pa_idxset_get_by_index(c->output_streams, channel)))) {
2749 pa_log("client sent block for invalid stream.");
2750 /* Ignoring */
2751 return;
2752 }
2753
2754 if (playback_stream_isinstance(stream)) {
2755 playback_stream *ps = PLAYBACK_STREAM(stream);
2756
2757 if (seek != PA_SEEK_RELATIVE || offset != 0)
2758 pa_asyncmsgq_post(ps->sink_input->sink->asyncmsgq, PA_MSGOBJECT(ps->sink_input), SINK_INPUT_MESSAGE_SEEK, PA_UINT_TO_PTR(seek), offset, NULL, NULL);
2759
2760 pa_asyncmsgq_post(ps->sink_input->sink->asyncmsgq, PA_MSGOBJECT(ps->sink_input), SINK_INPUT_MESSAGE_POST_DATA, NULL, 0, chunk, NULL);
2761
2762 } else {
2763 upload_stream *u = UPLOAD_STREAM(stream);
2764 size_t l;
2765
2766 if (!u->memchunk.memblock) {
2767 if (u->length == chunk->length) {
2768 u->memchunk = *chunk;
2769 pa_memblock_ref(u->memchunk.memblock);
2770 u->length = 0;
2771 } else {
2772 u->memchunk.memblock = pa_memblock_new(c->protocol->core->mempool, u->length);
2773 u->memchunk.index = u->memchunk.length = 0;
2774 }
2775 }
2776
2777 pa_assert(u->memchunk.memblock);
2778
2779 l = u->length;
2780 if (l > chunk->length)
2781 l = chunk->length;
2782
2783
2784 if (l > 0) {
2785 void *src, *dst;
2786 dst = pa_memblock_acquire(u->memchunk.memblock);
2787 src = pa_memblock_acquire(chunk->memblock);
2788
2789 memcpy((uint8_t*) dst + u->memchunk.index + u->memchunk.length,
2790 (uint8_t*) src+chunk->index, l);
2791
2792 pa_memblock_release(u->memchunk.memblock);
2793 pa_memblock_release(chunk->memblock);
2794
2795 u->memchunk.length += l;
2796 u->length -= l;
2797 }
2798 }
2799 }
2800
2801 static void pstream_die_callback(pa_pstream *p, void *userdata) {
2802 connection *c = CONNECTION(userdata);
2803
2804 pa_assert(p);
2805 connection_assert_ref(c);
2806
2807 connection_unlink(c);
2808 pa_log_info("connection died.");
2809 }
2810
2811 static void pstream_drain_callback(pa_pstream *p, void *userdata) {
2812 connection *c = CONNECTION(userdata);
2813
2814 pa_assert(p);
2815 connection_assert_ref(c);
2816
2817 send_memblock(c);
2818 }
2819
2820 static void pstream_revoke_callback(pa_pstream *p, uint32_t block_id, void *userdata) {
2821 pa_thread_mq *q;
2822
2823 if (!(q = pa_thread_mq_get()))
2824 pa_pstream_send_revoke(p, block_id);
2825 else
2826 pa_asyncmsgq_post(q->outq, PA_MSGOBJECT(userdata), CONNECTION_MESSAGE_REVOKE, PA_UINT_TO_PTR(block_id), 0, NULL, NULL);
2827 }
2828
2829 static void pstream_release_callback(pa_pstream *p, uint32_t block_id, void *userdata) {
2830 pa_thread_mq *q;
2831
2832 if (!(q = pa_thread_mq_get()))
2833 pa_pstream_send_release(p, block_id);
2834 else
2835 pa_asyncmsgq_post(q->outq, PA_MSGOBJECT(userdata), CONNECTION_MESSAGE_RELEASE, PA_UINT_TO_PTR(block_id), 0, NULL, NULL);
2836 }
2837
2838 /*** client callbacks ***/
2839
2840 static void client_kill_cb(pa_client *c) {
2841 pa_assert(c);
2842
2843 connection_unlink(CONNECTION(c->userdata));
2844 }
2845
2846 /*** socket server callbacks ***/
2847
2848 static void auth_timeout(pa_mainloop_api*m, pa_time_event *e, const struct timeval *tv, void *userdata) {
2849 connection *c = CONNECTION(userdata);
2850
2851 pa_assert(m);
2852 pa_assert(tv);
2853 connection_assert_ref(c);
2854 pa_assert(c->auth_timeout_event == e);
2855
2856 if (!c->authorized)
2857 connection_unlink(c);
2858 }
2859
2860 static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, void *userdata) {
2861 pa_protocol_native *p = userdata;
2862 connection *c;
2863 char cname[256], pname[128];
2864
2865 pa_assert(s);
2866 pa_assert(io);
2867 pa_assert(p);
2868
2869 if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) {
2870 pa_log_warn("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS);
2871 pa_iochannel_free(io);
2872 return;
2873 }
2874
2875 c = pa_msgobject_new(connection);
2876 c->parent.parent.free = connection_free;
2877 c->parent.process_msg = connection_process_msg;
2878
2879 c->authorized = !!p->public;
2880
2881 if (!c->authorized && p->auth_ip_acl && pa_ip_acl_check(p->auth_ip_acl, pa_iochannel_get_recv_fd(io)) > 0) {
2882 pa_log_info("Client authenticated by IP ACL.");
2883 c->authorized = 1;
2884 }
2885
2886 if (!c->authorized) {
2887 struct timeval tv;
2888 pa_gettimeofday(&tv);
2889 tv.tv_sec += AUTH_TIMEOUT;
2890 c->auth_timeout_event = p->core->mainloop->time_new(p->core->mainloop, &tv, auth_timeout, c);
2891 } else
2892 c->auth_timeout_event = NULL;
2893
2894 c->version = 8;
2895 c->protocol = p;
2896 pa_iochannel_socket_peer_to_string(io, pname, sizeof(pname));
2897 pa_snprintf(cname, sizeof(cname), "Native client (%s)", pname);
2898 c->client = pa_client_new(p->core, __FILE__, cname);
2899 c->client->kill = client_kill_cb;
2900 c->client->userdata = c;
2901 c->client->owner = p->module;
2902
2903 c->pstream = pa_pstream_new(p->core->mainloop, io, p->core->mempool);
2904
2905 pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c);
2906 pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c);
2907 pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c);
2908 pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c);
2909 pa_pstream_set_revoke_callback(c->pstream, pstream_revoke_callback, c);
2910 pa_pstream_set_release_callback(c->pstream, pstream_release_callback, c);
2911
2912 c->pdispatch = pa_pdispatch_new(p->core->mainloop, command_table, PA_COMMAND_MAX);
2913
2914 c->record_streams = pa_idxset_new(NULL, NULL);
2915 c->output_streams = pa_idxset_new(NULL, NULL);
2916
2917 c->rrobin_index = PA_IDXSET_INVALID;
2918 c->subscription = NULL;
2919
2920 pa_idxset_put(p->connections, c, NULL);
2921
2922 #ifdef HAVE_CREDS
2923 if (pa_iochannel_creds_supported(io))
2924 pa_iochannel_creds_enable(io);
2925
2926 #endif
2927 }
2928
2929 /*** module entry points ***/
2930
2931 static int load_key(pa_protocol_native*p, const char*fn) {
2932 pa_assert(p);
2933
2934 p->auth_cookie_in_property = 0;
2935
2936 if (!fn && pa_authkey_prop_get(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME, p->auth_cookie, sizeof(p->auth_cookie)) >= 0) {
2937 pa_log_info("using already loaded auth cookie.");
2938 pa_authkey_prop_ref(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME);
2939 p->auth_cookie_in_property = 1;
2940 return 0;
2941 }
2942
2943 if (!fn)
2944 fn = PA_NATIVE_COOKIE_FILE;
2945
2946 if (pa_authkey_load_auto(fn, p->auth_cookie, sizeof(p->auth_cookie)) < 0)
2947 return -1;
2948
2949 pa_log_info("loading cookie from disk.");
2950
2951 if (pa_authkey_prop_put(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME, p->auth_cookie, sizeof(p->auth_cookie)) >= 0)
2952 p->auth_cookie_in_property = 1;
2953
2954 return 0;
2955 }
2956
2957 static pa_protocol_native* protocol_new_internal(pa_core *c, pa_module *m, pa_modargs *ma) {
2958 pa_protocol_native *p;
2959 pa_bool_t public = FALSE;
2960 const char *acl;
2961
2962 pa_assert(c);
2963 pa_assert(ma);
2964
2965 if (pa_modargs_get_value_boolean(ma, "auth-anonymous", &public) < 0) {
2966 pa_log("auth-anonymous= expects a boolean argument.");
2967 return NULL;
2968 }
2969
2970 p = pa_xnew(pa_protocol_native, 1);
2971 p->core = c;
2972 p->module = m;
2973 p->public = public;
2974 p->server = NULL;
2975 p->auth_ip_acl = NULL;
2976
2977 #ifdef HAVE_CREDS
2978 {
2979 pa_bool_t a = 1;
2980 if (pa_modargs_get_value_boolean(ma, "auth-group-enabled", &a) < 0) {
2981 pa_log("auth-group-enabled= expects a boolean argument.");
2982 return NULL;
2983 }
2984 p->auth_group = a ? pa_xstrdup(pa_modargs_get_value(ma, "auth-group", c->is_system_instance ? PA_ACCESS_GROUP : NULL)) : NULL;
2985
2986 if (p->auth_group)
2987 pa_log_info("Allowing access to group '%s'.", p->auth_group);
2988 }
2989 #endif
2990
2991
2992 if ((acl = pa_modargs_get_value(ma, "auth-ip-acl", NULL))) {
2993
2994 if (!(p->auth_ip_acl = pa_ip_acl_new(acl))) {
2995 pa_log("Failed to parse IP ACL '%s'", acl);
2996 goto fail;
2997 }
2998 }
2999
3000 if (load_key(p, pa_modargs_get_value(ma, "cookie", NULL)) < 0)
3001 goto fail;
3002
3003 p->connections = pa_idxset_new(NULL, NULL);
3004
3005 return p;
3006
3007 fail:
3008 #ifdef HAVE_CREDS
3009 pa_xfree(p->auth_group);
3010 #endif
3011 if (p->auth_ip_acl)
3012 pa_ip_acl_free(p->auth_ip_acl);
3013 pa_xfree(p);
3014 return NULL;
3015 }
3016
3017 pa_protocol_native* pa_protocol_native_new(pa_core *core, pa_socket_server *server, pa_module *m, pa_modargs *ma) {
3018 char t[256];
3019 pa_protocol_native *p;
3020
3021 if (!(p = protocol_new_internal(core, m, ma)))
3022 return NULL;
3023
3024 p->server = server;
3025 pa_socket_server_set_callback(p->server, on_connection, p);
3026
3027 if (pa_socket_server_get_address(p->server, t, sizeof(t))) {
3028 pa_strlist *l;
3029 l = pa_property_get(core, PA_NATIVE_SERVER_PROPERTY_NAME);
3030 l = pa_strlist_prepend(l, t);
3031 pa_property_replace(core, PA_NATIVE_SERVER_PROPERTY_NAME, l);
3032 }
3033
3034 return p;
3035 }
3036
3037 void pa_protocol_native_free(pa_protocol_native *p) {
3038 connection *c;
3039 pa_assert(p);
3040
3041 while ((c = pa_idxset_first(p->connections, NULL)))
3042 connection_unlink(c);
3043 pa_idxset_free(p->connections, NULL, NULL);
3044
3045 if (p->server) {
3046 char t[256];
3047
3048 if (pa_socket_server_get_address(p->server, t, sizeof(t))) {
3049 pa_strlist *l;
3050 l = pa_property_get(p->core, PA_NATIVE_SERVER_PROPERTY_NAME);
3051 l = pa_strlist_remove(l, t);
3052
3053 if (l)
3054 pa_property_replace(p->core, PA_NATIVE_SERVER_PROPERTY_NAME, l);
3055 else
3056 pa_property_remove(p->core, PA_NATIVE_SERVER_PROPERTY_NAME);
3057 }
3058
3059 pa_socket_server_unref(p->server);
3060 }
3061
3062 if (p->auth_cookie_in_property)
3063 pa_authkey_prop_unref(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME);
3064
3065 if (p->auth_ip_acl)
3066 pa_ip_acl_free(p->auth_ip_acl);
3067
3068 #ifdef HAVE_CREDS
3069 pa_xfree(p->auth_group);
3070 #endif
3071 pa_xfree(p);
3072 }
3073
3074 pa_protocol_native* pa_protocol_native_new_iochannel(
3075 pa_core*core,
3076 pa_iochannel *io,
3077 pa_module *m,
3078 pa_modargs *ma) {
3079
3080 pa_protocol_native *p;
3081
3082 if (!(p = protocol_new_internal(core, m, ma)))
3083 return NULL;
3084
3085 on_connection(NULL, io, p);
3086
3087 return p;
3088 }