1 /***
2   This file is part of PulseAudio.
3 
4   Copyright 2004-2006 Lennart Poettering
5   Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
6 
7   PulseAudio is free software; you can redistribute it and/or modify
8   it under the terms of the GNU Lesser General Public License as published
9   by the Free Software Foundation; either version 2.1 of the License,
10   or (at your option) any later version.
11 
12   PulseAudio is distributed in the hope that it will be useful, but
13   WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   General Public License for more details.
16 
17   You should have received a copy of the GNU Lesser General Public License
18   along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
19 ***/
20 
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24 
25 #ifndef LOG_TAG
26 #define LOG_TAG "ProtocolNative"
27 #endif
28 
29 #include <string.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <unistd.h>
33 
34 #include <pulse/rtclock.h>
35 #include <pulse/timeval.h>
36 #include <pulse/version.h>
37 #include <pulse/utf8.h>
38 #include <pulse/util.h>
39 #include <pulse/xmalloc.h>
40 #include <pulse/internal.h>
41 
42 #include <pulsecore/native-common.h>
43 #include <pulsecore/packet.h>
44 #include <pulsecore/client.h>
45 #include <pulsecore/source-output.h>
46 #include <pulsecore/sink-input.h>
47 #include <pulsecore/pstream.h>
48 #include <pulsecore/tagstruct.h>
49 #include <pulsecore/pdispatch.h>
50 #include <pulsecore/pstream-util.h>
51 #include <pulsecore/namereg.h>
52 #include <pulsecore/core-scache.h>
53 #include <pulsecore/core-subscribe.h>
54 #include <pulsecore/message-handler.h>
55 #include <pulsecore/log.h>
56 #include <pulsecore/mem.h>
57 #include <pulsecore/strlist.h>
58 #include <pulsecore/shared.h>
59 #include <pulsecore/sample-util.h>
60 #include <pulsecore/creds.h>
61 #include <pulsecore/core-util.h>
62 #include <pulsecore/ipacl.h>
63 #include <pulsecore/thread-mq.h>
64 #include <pulsecore/mem.h>
65 
66 #include "protocol-native.h"
67 
68 /* #define PROTOCOL_NATIVE_DEBUG */
69 
70 /* Kick a client if it doesn't authenticate within this time */
71 #define AUTH_TIMEOUT (60 * PA_USEC_PER_SEC)
72 
73 /* Don't accept more connection than this */
74 #define MAX_CONNECTIONS 128
75 
76 #define MAX_MEMBLOCKQ_LENGTH (4*1024*1024) /* 4MB */
77 #define DEFAULT_TLENGTH_MSEC 2000 /* 2s */
78 #define DEFAULT_PROCESS_MSEC 20   /* 20ms */
79 #define DEFAULT_FRAGSIZE_MSEC DEFAULT_TLENGTH_MSEC
80 
81 static bool sink_input_process_underrun_cb(pa_sink_input *i);
82 static bool sink_input_process_underrun_ohos_cb(pa_sink_input *i);
83 static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk);
84 static void sink_input_kill_cb(pa_sink_input *i);
85 static void sink_input_suspend_cb(pa_sink_input *i, pa_sink_state_t old_state, pa_suspend_cause_t old_suspend_cause);
86 static void sink_input_moving_cb(pa_sink_input *i, pa_sink *dest);
87 static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes);
88 static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes);
89 static void sink_input_update_max_request_cb(pa_sink_input *i, size_t nbytes);
90 static void sink_input_send_event_cb(pa_sink_input *i, const char *event, pa_proplist *pl);
91 
92 static void native_connection_send_memblock(pa_native_connection *c);
93 
94 static void source_output_kill_cb(pa_source_output *o);
95 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk);
96 static void source_output_suspend_cb(pa_source_output *o, pa_source_state_t old_state, pa_suspend_cause_t old_suspend_cause);
97 static void source_output_moving_cb(pa_source_output *o, pa_source *dest);
98 static pa_usec_t source_output_get_latency_cb(pa_source_output *o);
99 static void source_output_send_event_cb(pa_source_output *o, const char *event, pa_proplist *pl);
100 
101 static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk);
102 static int source_output_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk);
103 
104 /* structure management */
105 
106 /* Called from main context */
upload_stream_unlink(upload_stream *s)107 static void upload_stream_unlink(upload_stream *s) {
108     pa_assert(s);
109 
110     if (!s->connection)
111         return;
112 
113     pa_assert_se(pa_idxset_remove_by_data(s->connection->output_streams, s, NULL) == s);
114     s->connection = NULL;
115     upload_stream_unref(s);
116 }
117 
118 /* Called from main context */
upload_stream_free(pa_object *o)119 static void upload_stream_free(pa_object *o) {
120     upload_stream *s = UPLOAD_STREAM(o);
121     pa_assert(s);
122 
123     upload_stream_unlink(s);
124 
125     pa_xfree(s->name);
126 
127     if (s->proplist)
128         pa_proplist_free(s->proplist);
129 
130     if (s->memchunk.memblock)
131         pa_memblock_unref(s->memchunk.memblock);
132 
133     pa_xfree(s);
134 }
135 
136 /* Called from main context */
upload_stream_new( pa_native_connection *c, const pa_sample_spec *ss, const pa_channel_map *map, const char *name, size_t length, pa_proplist *p)137 static upload_stream* upload_stream_new(
138         pa_native_connection *c,
139         const pa_sample_spec *ss,
140         const pa_channel_map *map,
141         const char *name,
142         size_t length,
143         pa_proplist *p) {
144 
145     upload_stream *s;
146 
147     pa_assert(c);
148     pa_assert(ss);
149     pa_assert(name);
150     pa_assert(length > 0);
151     pa_assert(p);
152 
153     s = pa_msgobject_new(upload_stream);
154     s->parent.parent.parent.free = upload_stream_free;
155     s->connection = c;
156     s->sample_spec = *ss;
157     s->channel_map = *map;
158     s->name = pa_xstrdup(name);
159     pa_memchunk_reset(&s->memchunk);
160     s->length = length;
161     s->proplist = pa_proplist_copy(p);
162     pa_proplist_update(s->proplist, PA_UPDATE_MERGE, c->client->proplist);
163 
164     pa_idxset_put(c->output_streams, s, &s->index);
165 
166     return s;
167 }
168 
169 /* Called from main context */
record_stream_unlink(record_stream *s)170 static void record_stream_unlink(record_stream *s) {
171     pa_assert(s);
172 
173     if (!s->connection)
174         return;
175 
176     if (s->source_output) {
177         pa_source_output_unlink(s->source_output);
178         pa_source_output_unref(s->source_output);
179         s->source_output = NULL;
180     }
181 
182     pa_assert_se(pa_idxset_remove_by_data(s->connection->record_streams, s, NULL) == s);
183     s->connection = NULL;
184     record_stream_unref(s);
185 }
186 
187 /* Called from main context */
record_stream_free(pa_object *o)188 static void record_stream_free(pa_object *o) {
189     record_stream *s = RECORD_STREAM(o);
190     pa_assert(s);
191 
192     record_stream_unlink(s);
193 
194     pa_memblockq_free(s->memblockq);
195     pa_xfree(s);
196 }
197 
198 /* Called from main context */
record_stream_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk)199 static int record_stream_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
200     record_stream *s = RECORD_STREAM(o);
201     record_stream_assert_ref(s);
202 
203     if (!s->connection)
204         return -1;
205 
206     switch (code) {
207 
208         case RECORD_STREAM_MESSAGE_POST_DATA:
209 
210             /* We try to keep up to date with how many bytes are
211              * currently on the fly */
212             pa_atomic_sub(&s->on_the_fly, chunk->length);
213 
214             if (pa_memblockq_push_align(s->memblockq, chunk) < 0) {
215 /*                 pa_log_warn("Failed to push data into output queue."); */
216                 return -1;
217             }
218 
219             if (!pa_pstream_is_pending(s->connection->pstream))
220                 native_connection_send_memblock(s->connection);
221 
222             break;
223     }
224 
225     return 0;
226 }
227 
228 /* Called from main context */
fix_record_buffer_attr_pre(record_stream *s)229 static void fix_record_buffer_attr_pre(record_stream *s) {
230 
231     size_t frame_size;
232     pa_usec_t orig_fragsize_usec, fragsize_usec, source_usec;
233 
234     pa_assert(s);
235 
236     /* This function will be called from the main thread, before as
237      * well as after the source output has been activated using
238      * pa_source_output_put()! That means it may not touch any
239      * ->thread_info data! */
240 
241     frame_size = pa_frame_size(&s->source_output->sample_spec);
242     s->buffer_attr = s->buffer_attr_req;
243 
244     if (s->buffer_attr.maxlength == (uint32_t) -1 || s->buffer_attr.maxlength > MAX_MEMBLOCKQ_LENGTH)
245         s->buffer_attr.maxlength = MAX_MEMBLOCKQ_LENGTH;
246     if (s->buffer_attr.maxlength <= 0)
247         s->buffer_attr.maxlength = (uint32_t) frame_size;
248 
249     if (s->buffer_attr.fragsize == (uint32_t) -1)
250         s->buffer_attr.fragsize = (uint32_t) pa_usec_to_bytes(DEFAULT_FRAGSIZE_MSEC*PA_USEC_PER_MSEC, &s->source_output->sample_spec);
251     if (s->buffer_attr.fragsize <= 0)
252         s->buffer_attr.fragsize = (uint32_t) frame_size;
253 
254     orig_fragsize_usec = fragsize_usec = pa_bytes_to_usec(s->buffer_attr.fragsize, &s->source_output->sample_spec);
255 
256     if (s->early_requests) {
257 
258         /* In early request mode we need to emulate the classic
259          * fragment-based playback model. Unfortunately we have no
260          * mechanism to tell the source how often we want it to send us
261          * data. The next best thing we can do is to set the source's
262          * total buffer (i.e. its latency) to the fragment size. That
263          * way it will have to send data at least that often. */
264 
265         source_usec = fragsize_usec;
266 
267     } else if (s->adjust_latency) {
268 
269         /* So, the user asked us to adjust the latency according to
270          * what the source can provide. We set the source to whatever
271          * latency it can provide that is closest to what we want, and
272          * let the client buffer be equally large. This does NOT mean
273          * that we are doing (2 * fragsize) bytes of buffering, since
274          * the client-side buffer is only data that is on the way to
275          * the client. */
276 
277         source_usec = fragsize_usec;
278 
279     } else {
280 
281         /* Ok, the user didn't ask us to adjust the latency, hence we
282          * don't */
283 
284         source_usec = (pa_usec_t) -1;
285     }
286 
287     if (source_usec != (pa_usec_t) -1)
288         s->configured_source_latency = pa_source_output_set_requested_latency(s->source_output, source_usec);
289     else
290         s->configured_source_latency = 0;
291 
292     if (s->early_requests) {
293 
294         /* Ok, we didn't necessarily get what we were asking for. We
295          * might still get the proper fragment interval, we just can't
296          * guarantee it. */
297 
298         if (fragsize_usec != s->configured_source_latency)
299             pa_log_debug("Could not configure a sufficiently low latency. Early requests might not be satisfied.");
300 
301     } else if (s->adjust_latency) {
302 
303         /* We keep the client buffer large enough to transfer one
304          * hardware-buffer-sized chunk at a time to the client. */
305 
306         fragsize_usec = s->configured_source_latency;
307     }
308 
309     if (pa_usec_to_bytes(orig_fragsize_usec, &s->source_output->sample_spec) !=
310         pa_usec_to_bytes(fragsize_usec, &s->source_output->sample_spec))
311 
312         s->buffer_attr.fragsize = (uint32_t) pa_usec_to_bytes(fragsize_usec, &s->source_output->sample_spec);
313 
314     if (s->buffer_attr.fragsize <= 0)
315         s->buffer_attr.fragsize = (uint32_t) frame_size;
316 }
317 
318 /* Called from main context */
fix_record_buffer_attr_post(record_stream *s)319 static void fix_record_buffer_attr_post(record_stream *s) {
320     size_t base;
321 
322     pa_assert(s);
323 
324     /* This function will be called from the main thread, before as
325      * well as after the source output has been activated using
326      * pa_source_output_put()! That means it may not touch and
327      * ->thread_info data! */
328 
329     base = pa_frame_size(&s->source_output->sample_spec);
330 
331     s->buffer_attr.fragsize = (s->buffer_attr.fragsize/base)*base;
332     if (s->buffer_attr.fragsize <= 0)
333         s->buffer_attr.fragsize = base;
334 
335     if (s->buffer_attr.fragsize > s->buffer_attr.maxlength)
336         s->buffer_attr.fragsize = s->buffer_attr.maxlength;
337 }
338 
339 /* Called from main context */
record_stream_new( pa_native_connection *c, pa_source *source, pa_sample_spec *ss, pa_channel_map *map, pa_idxset *formats, pa_buffer_attr *attr, pa_cvolume *volume, bool muted, bool muted_set, pa_source_output_flags_t flags, pa_proplist *p, bool adjust_latency, bool early_requests, bool relative_volume, bool peak_detect, pa_sink_input *direct_on_input, int *ret)340 static record_stream* record_stream_new(
341         pa_native_connection *c,
342         pa_source *source,
343         pa_sample_spec *ss,
344         pa_channel_map *map,
345         pa_idxset *formats,
346         pa_buffer_attr *attr,
347         pa_cvolume *volume,
348         bool muted,
349         bool muted_set,
350         pa_source_output_flags_t flags,
351         pa_proplist *p,
352         bool adjust_latency,
353         bool early_requests,
354         bool relative_volume,
355         bool peak_detect,
356         pa_sink_input *direct_on_input,
357         int *ret) {
358 
359     /* Note: This function takes ownership of the 'formats' param, so we need
360      * to take extra care to not leak it */
361 
362     record_stream *s;
363     pa_source_output *source_output = NULL;
364     pa_source_output_new_data data;
365     char *memblockq_name;
366 
367     pa_assert(c);
368     pa_assert(ss);
369     pa_assert(p);
370     pa_assert(ret);
371 
372     pa_source_output_new_data_init(&data);
373 
374     pa_proplist_update(data.proplist, PA_UPDATE_REPLACE, p);
375     data.driver = __FILE__;
376     data.module = c->options->module;
377     data.client = c->client;
378     if (source)
379         pa_source_output_new_data_set_source(&data, source, false, true);
380     if (pa_sample_spec_valid(ss))
381         pa_source_output_new_data_set_sample_spec(&data, ss);
382     if (pa_channel_map_valid(map))
383         pa_source_output_new_data_set_channel_map(&data, map);
384     if (formats)
385         pa_source_output_new_data_set_formats(&data, formats);
386     data.direct_on_input = direct_on_input;
387     if (volume) {
388         pa_source_output_new_data_set_volume(&data, volume);
389         data.volume_is_absolute = !relative_volume;
390         data.save_volume = false;
391     }
392     if (muted_set) {
393         pa_source_output_new_data_set_muted(&data, muted);
394         data.save_muted = false;
395     }
396     if (peak_detect)
397         data.resample_method = PA_RESAMPLER_PEAKS;
398     data.flags = flags;
399 
400     *ret = -pa_source_output_new(&source_output, c->protocol->core, &data);
401 
402     pa_source_output_new_data_done(&data);
403 
404     if (!source_output)
405         return NULL;
406 
407     s = pa_msgobject_new(record_stream);
408     s->parent.parent.free = record_stream_free;
409     s->parent.process_msg = record_stream_process_msg;
410     s->connection = c;
411     s->source_output = source_output;
412     s->buffer_attr_req = *attr;
413     s->adjust_latency = adjust_latency;
414     s->early_requests = early_requests;
415     pa_atomic_store(&s->on_the_fly, 0);
416 
417     s->source_output->parent.process_msg = source_output_process_msg;
418     s->source_output->push = source_output_push_cb;
419     s->source_output->kill = source_output_kill_cb;
420     s->source_output->get_latency = source_output_get_latency_cb;
421     s->source_output->moving = source_output_moving_cb;
422     s->source_output->suspend = source_output_suspend_cb;
423     s->source_output->send_event = source_output_send_event_cb;
424     s->source_output->userdata = s;
425 
426     fix_record_buffer_attr_pre(s);
427 
428     memblockq_name = pa_sprintf_malloc("native protocol record stream memblockq [%u]", s->source_output->index);
429     s->memblockq = pa_memblockq_new(
430             memblockq_name,
431             0,
432             s->buffer_attr.maxlength,
433             0,
434             &source_output->sample_spec,
435             1,
436             0,
437             0,
438             NULL);
439     pa_xfree(memblockq_name);
440 
441     pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
442     fix_record_buffer_attr_post(s);
443 
444     *ss = s->source_output->sample_spec;
445     *map = s->source_output->channel_map;
446 
447     pa_idxset_put(c->record_streams, s, &s->index);
448 
449     pa_log_debug("Final latency %0.2f ms = %0.2f ms + %0.2f ms",
450                 ((double) pa_bytes_to_usec(s->buffer_attr.fragsize, &source_output->sample_spec) + (double) s->configured_source_latency) / PA_USEC_PER_MSEC,
451                 (double) pa_bytes_to_usec(s->buffer_attr.fragsize, &source_output->sample_spec) / PA_USEC_PER_MSEC,
452                 (double) s->configured_source_latency / PA_USEC_PER_MSEC);
453 
454     pa_source_output_put(s->source_output);
455     return s;
456 }
457 
458 /* Called from main context */
record_stream_send_killed(record_stream *r)459 static void record_stream_send_killed(record_stream *r) {
460     pa_tagstruct *t;
461     record_stream_assert_ref(r);
462 
463     t = pa_tagstruct_new();
464     pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_KILLED);
465     pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
466     pa_tagstruct_putu32(t, r->index);
467     pa_pstream_send_tagstruct(r->connection->pstream, t);
468 }
469 
470 /* Called from main context */
playback_stream_unlink(playback_stream *s)471 static void playback_stream_unlink(playback_stream *s) {
472     pa_assert(s);
473 
474     if (!s->connection)
475         return;
476 
477     if (s->sink_input) {
478         pa_sink_input_unlink(s->sink_input);
479         pa_sink_input_unref(s->sink_input);
480         s->sink_input = NULL;
481     }
482 
483     if (s->drain_request)
484         pa_pstream_send_error(s->connection->pstream, s->drain_tag, PA_ERR_NOENTITY);
485 
486     pa_assert_se(pa_idxset_remove_by_data(s->connection->output_streams, s, NULL) == s);
487     s->connection = NULL;
488     playback_stream_unref(s);
489 }
490 
491 /* Called from main context */
playback_stream_free(pa_object* o)492 static void playback_stream_free(pa_object* o) {
493     playback_stream *s = PLAYBACK_STREAM(o);
494     pa_assert(s);
495 
496     playback_stream_unlink(s);
497 
498     pa_memblockq_free(s->memblockq);
499     pa_xfree(s);
500 }
501 
502 /* Called from main context */
playback_stream_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk)503 static int playback_stream_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
504     playback_stream *s = PLAYBACK_STREAM(o);
505     playback_stream_assert_ref(s);
506 
507     if (!s->connection)
508         return -1;
509 
510     switch (code) {
511 
512         case PLAYBACK_STREAM_MESSAGE_REQUEST_DATA: {
513             pa_tagstruct *t;
514             int l = 0;
515 
516             for (;;) {
517                 if ((l = pa_atomic_load(&s->missing)) <= 0)
518                     return 0;
519 
520                 if (pa_atomic_cmpxchg(&s->missing, l, 0))
521                     break;
522             }
523 
524             t = pa_tagstruct_new();
525             pa_tagstruct_putu32(t, PA_COMMAND_REQUEST);
526             pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
527             pa_tagstruct_putu32(t, s->index);
528             pa_tagstruct_putu32(t, (uint32_t) l);
529             pa_pstream_send_tagstruct(s->connection->pstream, t);
530 
531 #ifdef PROTOCOL_NATIVE_DEBUG
532             pa_log("Requesting %lu bytes", (unsigned long) l);
533 #endif
534             break;
535         }
536 
537         case PLAYBACK_STREAM_MESSAGE_UNDERFLOW: {
538             pa_tagstruct *t;
539 
540 #ifdef PROTOCOL_NATIVE_DEBUG
541             pa_log("signalling underflow");
542 #endif
543 
544             /* Report that we're empty */
545             t = pa_tagstruct_new();
546             pa_tagstruct_putu32(t, PA_COMMAND_UNDERFLOW);
547             pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
548             pa_tagstruct_putu32(t, s->index);
549             if (s->connection->version >= 23)
550                 pa_tagstruct_puts64(t, offset);
551             pa_pstream_send_tagstruct(s->connection->pstream, t);
552             break;
553         }
554 
555         case PLAYBACK_STREAM_MESSAGE_OVERFLOW: {
556             pa_tagstruct *t;
557 
558             /* Notify the user we're overflowed*/
559             t = pa_tagstruct_new();
560             pa_tagstruct_putu32(t, PA_COMMAND_OVERFLOW);
561             pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
562             pa_tagstruct_putu32(t, s->index);
563             pa_pstream_send_tagstruct(s->connection->pstream, t);
564             break;
565         }
566 
567         case PLAYBACK_STREAM_MESSAGE_STARTED:
568 
569             if (s->connection->version >= 13) {
570                 pa_tagstruct *t;
571 
572                 /* Notify the user we started playback */
573                 t = pa_tagstruct_new();
574                 pa_tagstruct_putu32(t, PA_COMMAND_STARTED);
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             }
579 
580             break;
581 
582         case PLAYBACK_STREAM_MESSAGE_DRAIN_ACK:
583             pa_pstream_send_simple_ack(s->connection->pstream, PA_PTR_TO_UINT(userdata));
584             break;
585 
586         case PLAYBACK_STREAM_MESSAGE_UPDATE_TLENGTH:
587 
588             s->buffer_attr.tlength = (uint32_t) offset;
589 
590             if (s->connection->version >= 15) {
591                 pa_tagstruct *t;
592 
593                 t = pa_tagstruct_new();
594                 pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED);
595                 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
596                 pa_tagstruct_putu32(t, s->index);
597                 pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
598                 pa_tagstruct_putu32(t, s->buffer_attr.tlength);
599                 pa_tagstruct_putu32(t, s->buffer_attr.prebuf);
600                 pa_tagstruct_putu32(t, s->buffer_attr.minreq);
601                 pa_tagstruct_put_usec(t, s->configured_sink_latency);
602                 pa_pstream_send_tagstruct(s->connection->pstream, t);
603             }
604 
605         case PLAYBACK_STREAM_MESSAGE_UNDERFLOW_OHOS: {
606             pa_tagstruct *t;
607 
608             /* Notify the user we're overflowed*/
609             t = pa_tagstruct_new();
610             pa_tagstruct_putu32(t, PA_COMMAND_UNDERFLOW_OHOS);
611             pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
612             pa_tagstruct_putu32(t, s->index);
613             pa_pstream_send_tagstruct(s->connection->pstream, t);
614             break;
615         }
616 
617             break;
618     }
619 
620     return 0;
621 }
622 
623 /* Called from main context */
fix_playback_buffer_attr(playback_stream *s)624 static void fix_playback_buffer_attr(playback_stream *s) {
625     size_t frame_size, max_prebuf;
626     pa_usec_t orig_tlength_usec, tlength_usec, orig_minreq_usec, minreq_usec, sink_usec;
627 
628     pa_assert(s);
629 
630 #ifdef PROTOCOL_NATIVE_DEBUG
631     pa_log_debug("Client requested: maxlength=%li bytes tlength=%li bytes minreq=%li bytes prebuf=%li bytes",
632            (long) s->buffer_attr_req.maxlength,
633            (long) s->buffer_attr_req.tlength,
634            (long) s->buffer_attr_req.minreq,
635            (long) s->buffer_attr_req.prebuf);
636 
637     pa_log("Client requested: maxlength=%lu ms tlength=%lu ms minreq=%lu ms prebuf=%lu ms",
638            (unsigned long) (pa_bytes_to_usec(s->buffer_attr_req.maxlength, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC),
639            (unsigned long) (pa_bytes_to_usec(s->buffer_attr_req.tlength, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC),
640            (unsigned long) (pa_bytes_to_usec(s->buffer_attr_req.minreq, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC),
641            (unsigned long) (pa_bytes_to_usec(s->buffer_attr_req.prebuf, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC));
642 #endif
643 
644     /* This function will be called from the main thread, before as
645      * well as after the sink input has been activated using
646      * pa_sink_input_put()! That means it may not touch any
647      * ->thread_info data, such as the memblockq! */
648 
649     frame_size = pa_frame_size(&s->sink_input->sample_spec);
650     s->buffer_attr = s->buffer_attr_req;
651 
652     if (s->buffer_attr.maxlength == (uint32_t) -1 || s->buffer_attr.maxlength > MAX_MEMBLOCKQ_LENGTH)
653         s->buffer_attr.maxlength = MAX_MEMBLOCKQ_LENGTH;
654     if (s->buffer_attr.maxlength <= 0)
655         s->buffer_attr.maxlength = (uint32_t) frame_size;
656 
657     if (s->buffer_attr.tlength == (uint32_t) -1)
658         s->buffer_attr.tlength = (uint32_t) pa_usec_to_bytes_round_up(DEFAULT_TLENGTH_MSEC*PA_USEC_PER_MSEC, &s->sink_input->sample_spec);
659     if (s->buffer_attr.tlength <= 0)
660         s->buffer_attr.tlength = (uint32_t) frame_size;
661     if (s->buffer_attr.tlength > s->buffer_attr.maxlength)
662         s->buffer_attr.tlength = s->buffer_attr.maxlength;
663 
664     if (s->buffer_attr.minreq == (uint32_t) -1) {
665         uint32_t process = (uint32_t) pa_usec_to_bytes_round_up(DEFAULT_PROCESS_MSEC*PA_USEC_PER_MSEC, &s->sink_input->sample_spec);
666         /* With low-latency, tlength/4 gives a decent default in all of traditional, adjust latency and early request modes. */
667         uint32_t m = s->buffer_attr.tlength / 4;
668         if (frame_size)
669             m -= m % frame_size;
670         s->buffer_attr.minreq = PA_MIN(process, m);
671     }
672     if (s->buffer_attr.minreq <= 0)
673         s->buffer_attr.minreq = (uint32_t) frame_size;
674 
675     if (s->buffer_attr.tlength < s->buffer_attr.minreq+frame_size)
676         s->buffer_attr.tlength = s->buffer_attr.minreq+(uint32_t) frame_size;
677 
678     orig_tlength_usec = tlength_usec = pa_bytes_to_usec(s->buffer_attr.tlength, &s->sink_input->sample_spec);
679     orig_minreq_usec = minreq_usec = pa_bytes_to_usec(s->buffer_attr.minreq, &s->sink_input->sample_spec);
680 
681     pa_log_info("Requested tlength=%0.2f ms, minreq=%0.2f ms",
682                 (double) tlength_usec / PA_USEC_PER_MSEC,
683                 (double) minreq_usec / PA_USEC_PER_MSEC);
684 
685     if (s->early_requests) {
686 
687         /* In early request mode we need to emulate the classic
688          * fragment-based playback model. Unfortunately we have no
689          * mechanism to tell the sink how often we want to be queried
690          * for data. The next best thing we can do is to set the sink's
691          * total buffer (i.e. its latency) to the fragment size. That
692          * way it will have to query us at least that often. */
693 
694         sink_usec = minreq_usec;
695         pa_log_debug("Early requests mode enabled, configuring sink latency to minreq.");
696 
697     } else if (s->adjust_latency) {
698 
699         /* So, the user asked us to adjust the latency of the stream
700          * buffer according to the what the sink can provide. The
701          * tlength passed in shall be the overall latency. Roughly
702          * half the latency will be spent on the hw buffer, the other
703          * half of it in the async buffer queue we maintain for each
704          * client. In between we'll have a safety space of size
705          * 2*minreq. Why the 2*minreq? When the hw buffer is completely
706          * empty and needs to be filled, then our buffer must have
707          * enough data to fulfill this request immediately and thus
708          * have at least the same tlength as the size of the hw
709          * buffer. It additionally needs space for 2 times minreq
710          * because if the buffer ran empty and a partial fillup
711          * happens immediately on the next iteration we need to be
712          * able to fulfill it and give the application also minreq
713          * time to fill it up again for the next request Makes 2 times
714          * minreq in plus.. */
715 
716         if (tlength_usec > minreq_usec*2)
717             sink_usec = (tlength_usec - minreq_usec*2)/2;
718         else
719             sink_usec = 0;
720 
721         pa_log_debug("Adjust latency mode enabled, configuring sink latency to half of overall latency.");
722 
723     } else {
724 
725         /* Ok, the user didn't ask us to adjust the latency, but we
726          * still need to make sure that the parameters from the user
727          * do make sense. */
728 
729         if (tlength_usec > minreq_usec*2)
730             sink_usec = (tlength_usec - minreq_usec*2);
731         else
732             sink_usec = 0;
733 
734         pa_log_debug("Traditional mode enabled, modifying sink usec only for compat with minreq.");
735     }
736 
737     s->configured_sink_latency = pa_sink_input_set_requested_latency(s->sink_input, sink_usec);
738 
739     if (s->early_requests) {
740 
741         /* Ok, we didn't necessarily get what we were asking for. We
742          * might still get the proper fragment interval, we just can't
743          * guarantee it. */
744 
745         if (minreq_usec != s->configured_sink_latency)
746             pa_log_debug("Could not configure a sufficiently low latency. Early requests might not be satisfied.");
747 
748     } else if (s->adjust_latency) {
749 
750         /* Ok, we didn't necessarily get what we were asking for, so
751          * let's subtract from what we asked for for the remaining
752          * buffer space */
753 
754         if (tlength_usec >= s->configured_sink_latency)
755             tlength_usec -= s->configured_sink_latency;
756     }
757 
758     pa_log_debug("Requested latency=%0.2f ms, Received latency=%0.2f ms",
759                  (double) sink_usec / PA_USEC_PER_MSEC,
760                  (double) s->configured_sink_latency / PA_USEC_PER_MSEC);
761 
762     /* FIXME: This is actually larger than necessary, since not all of
763      * the sink latency is actually rewritable. */
764     if (tlength_usec < s->configured_sink_latency + 2*minreq_usec)
765         tlength_usec = s->configured_sink_latency + 2*minreq_usec;
766 
767     if (pa_usec_to_bytes_round_up(orig_tlength_usec, &s->sink_input->sample_spec) !=
768         pa_usec_to_bytes_round_up(tlength_usec, &s->sink_input->sample_spec))
769         s->buffer_attr.tlength = (uint32_t) pa_usec_to_bytes_round_up(tlength_usec, &s->sink_input->sample_spec);
770 
771     if (pa_usec_to_bytes(orig_minreq_usec, &s->sink_input->sample_spec) !=
772         pa_usec_to_bytes(minreq_usec, &s->sink_input->sample_spec))
773         s->buffer_attr.minreq = (uint32_t) pa_usec_to_bytes(minreq_usec, &s->sink_input->sample_spec);
774 
775     if (s->buffer_attr.minreq <= 0) {
776         s->buffer_attr.minreq = (uint32_t) frame_size;
777         s->buffer_attr.tlength += (uint32_t) frame_size*2;
778     }
779 
780     if (s->buffer_attr.tlength <= s->buffer_attr.minreq)
781         s->buffer_attr.tlength = s->buffer_attr.minreq*2 + (uint32_t) frame_size;
782 
783     max_prebuf = s->buffer_attr.tlength + (uint32_t)frame_size - s->buffer_attr.minreq;
784 
785     if (s->buffer_attr.prebuf == (uint32_t) -1 ||
786         s->buffer_attr.prebuf > max_prebuf)
787         s->buffer_attr.prebuf = max_prebuf;
788 
789 #ifdef PROTOCOL_NATIVE_DEBUG
790     pa_log("Client accepted: maxlength=%lu ms tlength=%lu ms minreq=%lu ms prebuf=%lu ms",
791            (unsigned long) (pa_bytes_to_usec(s->buffer_attr.maxlength, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC),
792            (unsigned long) (pa_bytes_to_usec(s->buffer_attr.tlength, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC),
793            (unsigned long) (pa_bytes_to_usec(s->buffer_attr.minreq, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC),
794            (unsigned long) (pa_bytes_to_usec(s->buffer_attr.prebuf, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC));
795 #endif
796 }
797 
798 /* Called from main context */
playback_stream_new( pa_native_connection *c, pa_sink *sink, pa_sample_spec *ss, pa_channel_map *map, pa_idxset *formats, pa_buffer_attr *a, pa_cvolume *volume, bool muted, bool muted_set, pa_sink_input_flags_t flags, pa_proplist *p, bool adjust_latency, bool early_requests, bool relative_volume, uint32_t syncid, uint32_t *missing, int *ret)799 static playback_stream* playback_stream_new(
800         pa_native_connection *c,
801         pa_sink *sink,
802         pa_sample_spec *ss,
803         pa_channel_map *map,
804         pa_idxset *formats,
805         pa_buffer_attr *a,
806         pa_cvolume *volume,
807         bool muted,
808         bool muted_set,
809         pa_sink_input_flags_t flags,
810         pa_proplist *p,
811         bool adjust_latency,
812         bool early_requests,
813         bool relative_volume,
814         uint32_t syncid,
815         uint32_t *missing,
816         int *ret) {
817 
818     /* Note: This function takes ownership of the 'formats' param, so we need
819      * to take extra care to not leak it */
820 
821     playback_stream *ssync;
822     playback_stream *s = NULL;
823     pa_sink_input *sink_input = NULL;
824     pa_memchunk silence;
825     uint32_t idx;
826     int64_t start_index;
827     pa_sink_input_new_data data;
828     char *memblockq_name;
829 
830     pa_assert(c);
831     pa_assert(ss);
832     pa_assert(missing);
833     pa_assert(p);
834     pa_assert(ret);
835 
836     /* Find syncid group */
837     PA_IDXSET_FOREACH(ssync, c->output_streams, idx) {
838 
839         if (!playback_stream_isinstance(ssync))
840             continue;
841 
842         if (ssync->syncid == syncid)
843             break;
844     }
845 
846     /* Synced streams must connect to the same sink */
847     if (ssync) {
848 
849         if (!sink)
850             sink = ssync->sink_input->sink;
851         else if (sink != ssync->sink_input->sink) {
852             *ret = PA_ERR_INVALID;
853             goto out;
854         }
855     }
856 
857     pa_sink_input_new_data_init(&data);
858 
859     pa_proplist_update(data.proplist, PA_UPDATE_REPLACE, p);
860     data.driver = __FILE__;
861     data.module = c->options->module;
862     data.client = c->client;
863     if (sink)
864         pa_sink_input_new_data_set_sink(&data, sink, false, true);
865     if (pa_sample_spec_valid(ss))
866         pa_sink_input_new_data_set_sample_spec(&data, ss);
867     if (pa_channel_map_valid(map))
868         pa_sink_input_new_data_set_channel_map(&data, map);
869     if (formats) {
870         pa_sink_input_new_data_set_formats(&data, formats);
871         /* Ownership transferred to new_data, so we don't free it ourselves */
872         formats = NULL;
873     }
874     if (volume) {
875         pa_sink_input_new_data_set_volume(&data, volume);
876         data.volume_is_absolute = !relative_volume;
877         data.save_volume = false;
878     }
879     if (muted_set) {
880         pa_sink_input_new_data_set_muted(&data, muted);
881         data.save_muted = false;
882     }
883     data.sync_base = ssync ? ssync->sink_input : NULL;
884     data.flags = flags;
885 
886     *ret = -pa_sink_input_new(&sink_input, c->protocol->core, &data);
887 
888     pa_sink_input_new_data_done(&data);
889 
890     if (!sink_input)
891         goto out;
892 
893     s = pa_msgobject_new(playback_stream);
894     s->parent.parent.parent.free = playback_stream_free;
895     s->parent.parent.process_msg = playback_stream_process_msg;
896     s->connection = c;
897     s->syncid = syncid;
898     s->sink_input = sink_input;
899     s->is_underrun = true;
900     s->drain_request = false;
901     pa_atomic_store(&s->missing, 0);
902     s->buffer_attr_req = *a;
903     s->adjust_latency = adjust_latency;
904     s->early_requests = early_requests;
905     pa_atomic_store(&s->seek_or_post_in_queue, 0);
906     s->seek_windex = -1;
907 
908     s->sink_input->parent.process_msg = sink_input_process_msg;
909     s->sink_input->pop = sink_input_pop_cb;
910     s->sink_input->process_underrun = sink_input_process_underrun_cb;
911     s->sink_input->process_rewind = sink_input_process_rewind_cb;
912     s->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;
913     s->sink_input->update_max_request = sink_input_update_max_request_cb;
914     s->sink_input->kill = sink_input_kill_cb;
915     s->sink_input->moving = sink_input_moving_cb;
916     s->sink_input->suspend = sink_input_suspend_cb;
917     s->sink_input->send_event = sink_input_send_event_cb;
918     s->sink_input->userdata = s;
919 
920     s->sink_input->process_underrun_ohos = sink_input_process_underrun_ohos_cb;
921 
922     start_index = ssync ? pa_memblockq_get_read_index(ssync->memblockq) : 0;
923 
924     fix_playback_buffer_attr(s);
925 
926     pa_sink_input_get_silence(sink_input, &silence);
927     memblockq_name = pa_sprintf_malloc("native protocol playback stream memblockq [%u]", s->sink_input->index);
928     s->memblockq = pa_memblockq_new(
929             memblockq_name,
930             start_index,
931             s->buffer_attr.maxlength,
932             s->buffer_attr.tlength,
933             &sink_input->sample_spec,
934             s->buffer_attr.prebuf,
935             s->buffer_attr.minreq,
936             0,
937             &silence);
938     pa_xfree(memblockq_name);
939     pa_memblock_unref(silence.memblock);
940 
941     pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
942 
943     *missing = (uint32_t) pa_memblockq_pop_missing(s->memblockq);
944 
945 #ifdef PROTOCOL_NATIVE_DEBUG
946     pa_log("missing original: %li", (long int) *missing);
947 #endif
948 
949     *ss = s->sink_input->sample_spec;
950     *map = s->sink_input->channel_map;
951 
952     pa_idxset_put(c->output_streams, s, &s->index);
953 
954     pa_log_debug("Final latency %0.2f ms = %0.2f ms + 2*%0.2f ms + %0.2f ms",
955                 ((double) pa_bytes_to_usec(s->buffer_attr.tlength, &sink_input->sample_spec) + (double) s->configured_sink_latency) / PA_USEC_PER_MSEC,
956                 (double) pa_bytes_to_usec(s->buffer_attr.tlength-s->buffer_attr.minreq*2, &sink_input->sample_spec) / PA_USEC_PER_MSEC,
957                 (double) pa_bytes_to_usec(s->buffer_attr.minreq, &sink_input->sample_spec) / PA_USEC_PER_MSEC,
958                 (double) s->configured_sink_latency / PA_USEC_PER_MSEC);
959 
960     pa_sink_input_put(s->sink_input);
961 
962 out:
963     if (formats)
964         pa_idxset_free(formats, (pa_free_cb_t) pa_format_info_free);
965 
966     return s;
967 }
968 
969 /* Called from main context */
playback_stream_send_killed(playback_stream *p)970 static void playback_stream_send_killed(playback_stream *p) {
971     pa_tagstruct *t;
972     playback_stream_assert_ref(p);
973 
974     t = pa_tagstruct_new();
975     pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_KILLED);
976     pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
977     pa_tagstruct_putu32(t, p->index);
978     pa_pstream_send_tagstruct(p->connection->pstream, t);
979 }
980 
981 /* Called from main context */
native_connection_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk)982 static int native_connection_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
983     pa_native_connection *c = PA_NATIVE_CONNECTION(o);
984     pa_native_connection_assert_ref(c);
985 
986     if (!c->protocol)
987         return -1;
988 
989     switch (code) {
990 
991         case CONNECTION_MESSAGE_REVOKE:
992             pa_pstream_send_revoke(c->pstream, PA_PTR_TO_UINT(userdata));
993             break;
994 
995         case CONNECTION_MESSAGE_RELEASE:
996             pa_pstream_send_release(c->pstream, PA_PTR_TO_UINT(userdata));
997             break;
998     }
999 
1000     return 0;
1001 }
1002 
1003 /* Called from main context */
native_connection_unlink(pa_native_connection *c)1004 static void native_connection_unlink(pa_native_connection *c) {
1005     record_stream *r;
1006     output_stream *o;
1007 
1008     pa_assert(c);
1009 
1010     if (!c->protocol)
1011         return;
1012 
1013     pa_hook_fire(&c->protocol->hooks[PA_NATIVE_HOOK_CONNECTION_UNLINK], c);
1014 
1015     if (c->options)
1016         pa_native_options_unref(c->options);
1017 
1018     if (c->srbpending)
1019         pa_srbchannel_free(c->srbpending);
1020 
1021     while ((r = pa_idxset_first(c->record_streams, NULL)))
1022         record_stream_unlink(r);
1023 
1024     while ((o = pa_idxset_first(c->output_streams, NULL)))
1025         if (playback_stream_isinstance(o))
1026             playback_stream_unlink(PLAYBACK_STREAM(o));
1027         else
1028             upload_stream_unlink(UPLOAD_STREAM(o));
1029 
1030     if (c->subscription)
1031         pa_subscription_free(c->subscription);
1032 
1033     if (c->pstream)
1034         pa_pstream_unlink(c->pstream);
1035 
1036     if (c->auth_timeout_event) {
1037         c->protocol->core->mainloop->time_free(c->auth_timeout_event);
1038         c->auth_timeout_event = NULL;
1039     }
1040 
1041     pa_assert_se(pa_idxset_remove_by_data(c->protocol->connections, c, NULL) == c);
1042     c->protocol = NULL;
1043     pa_native_connection_unref(c);
1044 }
1045 
1046 /* Called from main context */
native_connection_free(pa_object *o)1047 static void native_connection_free(pa_object *o) {
1048     pa_native_connection *c = PA_NATIVE_CONNECTION(o);
1049 
1050     pa_assert(c);
1051 
1052     native_connection_unlink(c);
1053 
1054     pa_idxset_free(c->record_streams, NULL);
1055     pa_idxset_free(c->output_streams, NULL);
1056 
1057     pa_pdispatch_unref(c->pdispatch);
1058     pa_pstream_unref(c->pstream);
1059     if (c->rw_mempool)
1060         pa_mempool_unref(c->rw_mempool);
1061 
1062     pa_client_free(c->client);
1063 
1064     pa_xfree(c);
1065 }
1066 
1067 /* Called from main context */
native_connection_send_memblock(pa_native_connection *c)1068 static void native_connection_send_memblock(pa_native_connection *c) {
1069     uint32_t start;
1070     record_stream *r;
1071 
1072     start = PA_IDXSET_INVALID;
1073     for (;;) {
1074         pa_memchunk chunk;
1075 
1076         if (!(r = RECORD_STREAM(pa_idxset_rrobin(c->record_streams, &c->rrobin_index))))
1077             return;
1078 
1079         if (start == PA_IDXSET_INVALID)
1080             start = c->rrobin_index;
1081         else if (start == c->rrobin_index)
1082             return;
1083 
1084         if (pa_memblockq_peek(r->memblockq, &chunk) >= 0) {
1085             pa_memchunk schunk = chunk;
1086 
1087             if (schunk.length > r->buffer_attr.fragsize)
1088                 schunk.length = r->buffer_attr.fragsize;
1089 
1090             pa_pstream_send_memblock(c->pstream, r->index, 0, PA_SEEK_RELATIVE, &schunk);
1091 
1092             pa_memblockq_drop(r->memblockq, schunk.length);
1093             pa_memblock_unref(schunk.memblock);
1094 
1095             return;
1096         }
1097     }
1098 }
1099 
1100 /*** sink input callbacks ***/
1101 
1102 /* Called from thread context */
handle_seek(playback_stream *s, int64_t indexw)1103 static void handle_seek(playback_stream *s, int64_t indexw) {
1104     playback_stream_assert_ref(s);
1105 
1106 /*     pa_log("handle_seek: %llu -- %i", (unsigned long long) s->sink_input->thread_info.underrun_for, pa_memblockq_is_readable(s->memblockq)); */
1107 
1108     if (s->sink_input->thread_info.underrun_for > 0) {
1109 
1110 /*         pa_log("%lu vs. %lu", (unsigned long) pa_memblockq_get_length(s->memblockq), (unsigned long) pa_memblockq_get_prebuf(s->memblockq)); */
1111 
1112         if (pa_memblockq_is_readable(s->memblockq)) {
1113 
1114             /* We just ended an underrun, let's ask the sink
1115              * for a complete rewind rewrite */
1116 
1117             pa_log_debug("Requesting rewind due to end of underrun.");
1118             pa_sink_input_request_rewind(s->sink_input,
1119                                          (size_t) (s->sink_input->thread_info.underrun_for == (uint64_t) -1 ? 0 :
1120                                                    s->sink_input->thread_info.underrun_for),
1121                                          false, true, false);
1122         }
1123 
1124     } else {
1125         int64_t indexr;
1126 
1127         indexr = pa_memblockq_get_read_index(s->memblockq);
1128 
1129         if (indexw < indexr) {
1130             /* OK, the sink already asked for this data, so
1131              * let's have it ask us again */
1132 
1133             pa_log_debug("Requesting rewind due to rewrite.");
1134             pa_sink_input_request_rewind(s->sink_input, (size_t) (indexr - indexw), true, false, false);
1135         }
1136     }
1137 
1138     playback_stream_request_bytes(s);
1139 }
1140 
flush_write_no_account(pa_memblockq *q)1141 static void flush_write_no_account(pa_memblockq *q) {
1142     pa_memblockq_flush_write(q, false);
1143 }
1144 
1145 /* Called from thread context */
sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk)1146 static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
1147     pa_sink_input *i = PA_SINK_INPUT(o);
1148     playback_stream *s;
1149 
1150     pa_sink_input_assert_ref(i);
1151     s = PLAYBACK_STREAM(i->userdata);
1152     playback_stream_assert_ref(s);
1153 
1154     switch (code) {
1155 
1156         case SINK_INPUT_MESSAGE_SEEK:
1157         case SINK_INPUT_MESSAGE_POST_DATA: {
1158             int64_t windex = pa_memblockq_get_write_index(s->memblockq);
1159 
1160             if (code == SINK_INPUT_MESSAGE_SEEK) {
1161                 /* The client side is incapable of accounting correctly
1162                  * for seeks of a type != PA_SEEK_RELATIVE. We need to be
1163                  * able to deal with that. */
1164 
1165                 pa_memblockq_seek(s->memblockq, offset, PA_PTR_TO_UINT(userdata), PA_PTR_TO_UINT(userdata) == PA_SEEK_RELATIVE);
1166                 windex = PA_MIN(windex, pa_memblockq_get_write_index(s->memblockq));
1167             }
1168 
1169             if (chunk && pa_memblockq_push_align(s->memblockq, chunk) < 0) {
1170                 if (pa_log_ratelimit(PA_LOG_WARN))
1171                     pa_log_warn("Failed to push data into queue");
1172                 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_OVERFLOW, NULL, 0, NULL, NULL);
1173                 pa_memblockq_seek(s->memblockq, (int64_t) chunk->length, PA_SEEK_RELATIVE, true);
1174             }
1175 
1176             /* If more data is in queue, we rewind later instead. */
1177             if (s->seek_windex != -1)
1178                 windex = PA_MIN(windex, s->seek_windex);
1179             if (pa_atomic_dec(&s->seek_or_post_in_queue) > 1)
1180                 s->seek_windex = windex;
1181             else {
1182                 s->seek_windex = -1;
1183                 handle_seek(s, windex);
1184             }
1185             return 0;
1186         }
1187 
1188         case SINK_INPUT_MESSAGE_DRAIN:
1189         case SINK_INPUT_MESSAGE_FLUSH:
1190         case SINK_INPUT_MESSAGE_PREBUF_FORCE:
1191         case SINK_INPUT_MESSAGE_TRIGGER: {
1192 
1193             int64_t windex;
1194             pa_sink_input *isync;
1195             void (*func)(pa_memblockq *bq);
1196 
1197             switch (code) {
1198                 case SINK_INPUT_MESSAGE_FLUSH:
1199                     func = flush_write_no_account;
1200                     break;
1201 
1202                 case SINK_INPUT_MESSAGE_PREBUF_FORCE:
1203                     func = pa_memblockq_prebuf_force;
1204                     break;
1205 
1206                 case SINK_INPUT_MESSAGE_DRAIN:
1207                 case SINK_INPUT_MESSAGE_TRIGGER:
1208                     func = pa_memblockq_prebuf_disable;
1209                     break;
1210 
1211                 default:
1212                     pa_assert_not_reached();
1213             }
1214 
1215             windex = pa_memblockq_get_write_index(s->memblockq);
1216             func(s->memblockq);
1217             handle_seek(s, windex);
1218 
1219             /* Do the same for all other members in the sync group */
1220             for (isync = i->sync_prev; isync; isync = isync->sync_prev) {
1221                 playback_stream *ssync = PLAYBACK_STREAM(isync->userdata);
1222                 windex = pa_memblockq_get_write_index(ssync->memblockq);
1223                 func(ssync->memblockq);
1224                 handle_seek(ssync, windex);
1225             }
1226 
1227             for (isync = i->sync_next; isync; isync = isync->sync_next) {
1228                 playback_stream *ssync = PLAYBACK_STREAM(isync->userdata);
1229                 windex = pa_memblockq_get_write_index(ssync->memblockq);
1230                 func(ssync->memblockq);
1231                 handle_seek(ssync, windex);
1232             }
1233 
1234             if (code == SINK_INPUT_MESSAGE_DRAIN) {
1235                 if (!pa_memblockq_is_readable(s->memblockq))
1236                     pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_DRAIN_ACK, userdata, 0, NULL, NULL);
1237                 else {
1238                     s->drain_tag = PA_PTR_TO_UINT(userdata);
1239                     s->drain_request = true;
1240                 }
1241             }
1242 
1243             return 0;
1244         }
1245 
1246         case SINK_INPUT_MESSAGE_UPDATE_LATENCY:
1247             /* Atomically get a snapshot of all timing parameters... */
1248             s->read_index = pa_memblockq_get_read_index(s->memblockq);
1249             s->write_index = pa_memblockq_get_write_index(s->memblockq);
1250             s->render_memblockq_length = pa_memblockq_get_length(s->sink_input->thread_info.render_memblockq);
1251             s->current_sink_latency = pa_sink_get_latency_within_thread(s->sink_input->sink, false);
1252             /* Add resampler latency */
1253             s->current_sink_latency += pa_resampler_get_delay_usec(i->thread_info.resampler);
1254             s->underrun_for = s->sink_input->thread_info.underrun_for;
1255             s->playing_for = s->sink_input->thread_info.playing_for;
1256 
1257             return 0;
1258 
1259         case PA_SINK_INPUT_MESSAGE_SET_STATE: {
1260             int64_t windex;
1261 
1262             windex = pa_memblockq_get_write_index(s->memblockq);
1263 
1264             /* We enable prebuffering so that after CORKED -> RUNNING
1265              * transitions we don't have trouble with underruns in case the
1266              * buffer has too little data. This must not be done when draining
1267              * has been requested, however, otherwise the buffered audio would
1268              * never play. */
1269             if (!s->drain_request)
1270                 pa_memblockq_prebuf_force(s->memblockq);
1271 
1272             handle_seek(s, windex);
1273 
1274             /* Fall through to the default handler */
1275             break;
1276         }
1277 
1278         case PA_SINK_INPUT_MESSAGE_GET_LATENCY: {
1279             pa_usec_t *r = userdata;
1280 
1281             *r = pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &i->sample_spec);
1282 
1283             /* Fall through, the default handler will add in the extra
1284              * latency added by the resampler */
1285             break;
1286         }
1287 
1288         case SINK_INPUT_MESSAGE_UPDATE_BUFFER_ATTR: {
1289             pa_memblockq_apply_attr(s->memblockq, &s->buffer_attr);
1290             pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
1291             return 0;
1292         }
1293     }
1294 
1295     return pa_sink_input_process_msg(o, code, userdata, offset, chunk);
1296 }
1297 
handle_input_underrun(playback_stream *s, bool force)1298 static bool handle_input_underrun(playback_stream *s, bool force) {
1299     bool send_drain;
1300 
1301     if (pa_memblockq_is_readable(s->memblockq))
1302         return false;
1303 
1304     if (!s->is_underrun)
1305         pa_log_debug("%s %s of '%s'", force ? "Actual" : "Implicit",
1306             s->drain_request ? "drain" : "underrun", pa_strnull(pa_proplist_gets(s->sink_input->proplist, PA_PROP_MEDIA_NAME)));
1307 
1308     send_drain = s->drain_request && (force || pa_sink_input_safe_to_remove(s->sink_input));
1309 
1310     if (send_drain) {
1311          s->drain_request = false;
1312          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);
1313          pa_log_debug("Drain acknowledged of '%s'", pa_strnull(pa_proplist_gets(s->sink_input->proplist, PA_PROP_MEDIA_NAME)));
1314     } else if (!s->is_underrun) {
1315          pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_UNDERFLOW, NULL, pa_memblockq_get_read_index(s->memblockq), NULL, NULL);
1316     }
1317     s->is_underrun = true;
1318     playback_stream_request_bytes(s);
1319     return true;
1320 }
1321 
1322 /* Called from thread context */
sink_input_process_underrun_cb(pa_sink_input *i)1323 static bool sink_input_process_underrun_cb(pa_sink_input *i) {
1324     playback_stream *s;
1325 
1326     pa_sink_input_assert_ref(i);
1327     s = PLAYBACK_STREAM(i->userdata);
1328     playback_stream_assert_ref(s);
1329 
1330     return handle_input_underrun(s, true);
1331 }
1332 
handle_input_underrun_ohos(playback_stream *s, bool force)1333 static bool handle_input_underrun_ohos(playback_stream *s, bool force) {
1334     bool send_drain;
1335 
1336     if (pa_memblockq_is_readable(s->memblockq))
1337         return false;
1338 
1339     if (!s->is_underrun)
1340         pa_log_debug("%s %s of '%s'", force ? "Actual" : "Implicit",
1341             s->drain_request ? "drain" : "underrun",
1342             pa_strnull(pa_proplist_gets(s->sink_input->proplist, PA_PROP_MEDIA_NAME)));
1343 
1344     send_drain = s->drain_request && (force || pa_sink_input_safe_to_remove(s->sink_input));
1345     if (!send_drain) {
1346         pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_UNDERFLOW_OHOS,
1347             NULL, pa_memblockq_get_read_index(s->memblockq), NULL, NULL);
1348     }
1349     return true;
1350 }
1351 
sink_input_process_underrun_ohos_cb(pa_sink_input *i)1352 static bool sink_input_process_underrun_ohos_cb(pa_sink_input *i) {
1353     playback_stream *s;
1354 
1355     pa_sink_input_assert_ref(i);
1356     s = PLAYBACK_STREAM(i->userdata);
1357     playback_stream_assert_ref(s);
1358 
1359     return handle_input_underrun_ohos(s, true);
1360 }
1361 
1362 /* Called from thread context */
sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk)1363 static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) {
1364     playback_stream *s;
1365 
1366     pa_sink_input_assert_ref(i);
1367     s = PLAYBACK_STREAM(i->userdata);
1368     playback_stream_assert_ref(s);
1369     pa_assert(chunk);
1370 
1371 #ifdef PROTOCOL_NATIVE_DEBUG
1372     pa_log("%s, pop(): %lu", pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME), (unsigned long) pa_memblockq_get_length(s->memblockq));
1373 #endif
1374 
1375     if (!handle_input_underrun(s, false))
1376         s->is_underrun = false;
1377 
1378     /* This call will not fail with prebuf=0, hence we check for
1379        underrun explicitly in handle_input_underrun */
1380     if (pa_memblockq_peek(s->memblockq, chunk) < 0)
1381         return -1;
1382 
1383     chunk->length = PA_MIN(nbytes, chunk->length);
1384 
1385     if (i->thread_info.underrun_for > 0)
1386         pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_STARTED, NULL, 0, NULL, NULL);
1387 
1388     pa_memblockq_drop(s->memblockq, chunk->length);
1389     playback_stream_request_bytes(s);
1390 
1391     return 0;
1392 }
1393 
1394 /* Called from thread context */
sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes)1395 static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
1396     playback_stream *s;
1397 
1398     pa_sink_input_assert_ref(i);
1399     s = PLAYBACK_STREAM(i->userdata);
1400     playback_stream_assert_ref(s);
1401 
1402     /* If we are in an underrun, then we don't rewind */
1403     if (i->thread_info.underrun_for > 0)
1404         return;
1405 
1406     pa_memblockq_rewind(s->memblockq, nbytes);
1407 }
1408 
1409 /* Called from thread context */
sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes)1410 static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
1411     playback_stream *s;
1412 
1413     pa_sink_input_assert_ref(i);
1414     s = PLAYBACK_STREAM(i->userdata);
1415     playback_stream_assert_ref(s);
1416 
1417     pa_memblockq_set_maxrewind(s->memblockq, nbytes);
1418 }
1419 
1420 /* Called from thread context */
sink_input_update_max_request_cb(pa_sink_input *i, size_t nbytes)1421 static void sink_input_update_max_request_cb(pa_sink_input *i, size_t nbytes) {
1422     playback_stream *s;
1423     size_t new_tlength, old_tlength;
1424 
1425     pa_sink_input_assert_ref(i);
1426     s = PLAYBACK_STREAM(i->userdata);
1427     playback_stream_assert_ref(s);
1428 
1429     old_tlength = pa_memblockq_get_tlength(s->memblockq);
1430     new_tlength = nbytes+2*pa_memblockq_get_minreq(s->memblockq);
1431 
1432     if (old_tlength < new_tlength) {
1433         pa_log_debug("max_request changed, trying to update from %zu to %zu.", old_tlength,
1434             new_tlength);
1435         pa_memblockq_set_tlength(s->memblockq, new_tlength);
1436         new_tlength = pa_memblockq_get_tlength(s->memblockq);
1437 
1438         if (new_tlength == old_tlength)
1439             pa_log_debug("Failed to increase tlength");
1440         else {
1441             pa_log_debug("Notifying client about increased tlength");
1442             pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_UPDATE_TLENGTH, NULL, pa_memblockq_get_tlength(s->memblockq), NULL, NULL);
1443         }
1444     }
1445 }
1446 
1447 /* Called from main context */
sink_input_kill_cb(pa_sink_input *i)1448 static void sink_input_kill_cb(pa_sink_input *i) {
1449     playback_stream *s;
1450 
1451     pa_sink_input_assert_ref(i);
1452     s = PLAYBACK_STREAM(i->userdata);
1453     playback_stream_assert_ref(s);
1454 
1455     playback_stream_send_killed(s);
1456     playback_stream_unlink(s);
1457 }
1458 
1459 /* Called from main context */
sink_input_send_event_cb(pa_sink_input *i, const char *event, pa_proplist *pl)1460 static void sink_input_send_event_cb(pa_sink_input *i, const char *event, pa_proplist *pl) {
1461     playback_stream *s;
1462     pa_tagstruct *t;
1463 
1464     pa_sink_input_assert_ref(i);
1465     s = PLAYBACK_STREAM(i->userdata);
1466     playback_stream_assert_ref(s);
1467 
1468     if (s->connection->version < 15)
1469       return;
1470 
1471     t = pa_tagstruct_new();
1472     pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_EVENT);
1473     pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1474     pa_tagstruct_putu32(t, s->index);
1475     pa_tagstruct_puts(t, event);
1476     pa_tagstruct_put_proplist(t, pl);
1477     pa_pstream_send_tagstruct(s->connection->pstream, t);
1478 }
1479 
1480 /* Called from main context */
sink_input_suspend_cb(pa_sink_input *i, pa_sink_state_t old_state, pa_suspend_cause_t old_suspend_cause)1481 static void sink_input_suspend_cb(pa_sink_input *i, pa_sink_state_t old_state, pa_suspend_cause_t old_suspend_cause) {
1482     playback_stream *s;
1483     pa_tagstruct *t;
1484     bool suspend;
1485 
1486     pa_sink_input_assert_ref(i);
1487 
1488     /* State has not changed, nothing to do */
1489     if (old_state == i->sink->state)
1490         return;
1491 
1492     suspend = (i->sink->state == PA_SINK_SUSPENDED);
1493 
1494     s = PLAYBACK_STREAM(i->userdata);
1495     playback_stream_assert_ref(s);
1496 
1497     if (s->connection->version < 12)
1498       return;
1499 
1500     t = pa_tagstruct_new();
1501     pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_SUSPENDED);
1502     pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1503     pa_tagstruct_putu32(t, s->index);
1504     pa_tagstruct_put_boolean(t, suspend);
1505     pa_pstream_send_tagstruct(s->connection->pstream, t);
1506 }
1507 
1508 /* Called from main context */
sink_input_moving_cb(pa_sink_input *i, pa_sink *dest)1509 static void sink_input_moving_cb(pa_sink_input *i, pa_sink *dest) {
1510     playback_stream *s;
1511     pa_tagstruct *t;
1512 
1513     pa_sink_input_assert_ref(i);
1514     s = PLAYBACK_STREAM(i->userdata);
1515     playback_stream_assert_ref(s);
1516 
1517     if (!dest)
1518         return;
1519 
1520     fix_playback_buffer_attr(s);
1521     pa_memblockq_apply_attr(s->memblockq, &s->buffer_attr);
1522     pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
1523 
1524     if (s->connection->version < 12)
1525       return;
1526 
1527     t = pa_tagstruct_new();
1528     pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_MOVED);
1529     pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1530     pa_tagstruct_putu32(t, s->index);
1531     pa_tagstruct_putu32(t, dest->index);
1532     pa_tagstruct_puts(t, dest->name);
1533     pa_tagstruct_put_boolean(t, dest->state == PA_SINK_SUSPENDED);
1534 
1535     if (s->connection->version >= 13) {
1536         pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
1537         pa_tagstruct_putu32(t, s->buffer_attr.tlength);
1538         pa_tagstruct_putu32(t, s->buffer_attr.prebuf);
1539         pa_tagstruct_putu32(t, s->buffer_attr.minreq);
1540         pa_tagstruct_put_usec(t, s->configured_sink_latency);
1541     }
1542 
1543     pa_pstream_send_tagstruct(s->connection->pstream, t);
1544 }
1545 
1546 /*** source_output callbacks ***/
1547 
1548 /* Called from thread context */
source_output_process_msg(pa_msgobject *_o, int code, void *userdata, int64_t offset, pa_memchunk *chunk)1549 static int source_output_process_msg(pa_msgobject *_o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
1550     pa_source_output *o = PA_SOURCE_OUTPUT(_o);
1551     record_stream *s;
1552 
1553     pa_source_output_assert_ref(o);
1554     s = RECORD_STREAM(o->userdata);
1555     record_stream_assert_ref(s);
1556 
1557     switch (code) {
1558         case SOURCE_OUTPUT_MESSAGE_UPDATE_LATENCY:
1559             /* Atomically get a snapshot of all timing parameters... */
1560             s->current_monitor_latency = o->source->monitor_of ? pa_sink_get_latency_within_thread(o->source->monitor_of, false) : 0;
1561             s->current_source_latency = pa_source_get_latency_within_thread(o->source, false);
1562             /* Add resampler latency */
1563             s->current_source_latency += pa_resampler_get_delay_usec(o->thread_info.resampler);
1564             s->on_the_fly_snapshot = pa_atomic_load(&s->on_the_fly);
1565             return 0;
1566     }
1567 
1568     return pa_source_output_process_msg(_o, code, userdata, offset, chunk);
1569 }
1570 
1571 /* Called from thread context */
source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk)1572 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) {
1573     record_stream *s;
1574 
1575     pa_source_output_assert_ref(o);
1576     s = RECORD_STREAM(o->userdata);
1577     record_stream_assert_ref(s);
1578     pa_assert(chunk);
1579 
1580     pa_atomic_add(&s->on_the_fly, chunk->length);
1581     pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), RECORD_STREAM_MESSAGE_POST_DATA, NULL, 0, chunk, NULL);
1582 }
1583 
source_output_kill_cb(pa_source_output *o)1584 static void source_output_kill_cb(pa_source_output *o) {
1585     record_stream *s;
1586 
1587     pa_source_output_assert_ref(o);
1588     s = RECORD_STREAM(o->userdata);
1589     record_stream_assert_ref(s);
1590 
1591     record_stream_send_killed(s);
1592     record_stream_unlink(s);
1593 }
1594 
source_output_get_latency_cb(pa_source_output *o)1595 static pa_usec_t source_output_get_latency_cb(pa_source_output *o) {
1596     record_stream *s;
1597 
1598     pa_source_output_assert_ref(o);
1599     s = RECORD_STREAM(o->userdata);
1600     record_stream_assert_ref(s);
1601 
1602     /*pa_log("get_latency: %u", pa_memblockq_get_length(s->memblockq));*/
1603 
1604     return pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &o->sample_spec);
1605 }
1606 
1607 /* Called from main context */
source_output_send_event_cb(pa_source_output *o, const char *event, pa_proplist *pl)1608 static void source_output_send_event_cb(pa_source_output *o, const char *event, pa_proplist *pl) {
1609     record_stream *s;
1610     pa_tagstruct *t;
1611 
1612     pa_source_output_assert_ref(o);
1613     s = RECORD_STREAM(o->userdata);
1614     record_stream_assert_ref(s);
1615 
1616     if (s->connection->version < 15)
1617       return;
1618 
1619     t = pa_tagstruct_new();
1620     pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_EVENT);
1621     pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1622     pa_tagstruct_putu32(t, s->index);
1623     pa_tagstruct_puts(t, event);
1624     pa_tagstruct_put_proplist(t, pl);
1625     pa_pstream_send_tagstruct(s->connection->pstream, t);
1626 }
1627 
1628 /* Called from main context */
source_output_suspend_cb(pa_source_output *o, pa_source_state_t old_state, pa_suspend_cause_t old_suspend_cause)1629 static void source_output_suspend_cb(pa_source_output *o, pa_source_state_t old_state, pa_suspend_cause_t old_suspend_cause) {
1630     record_stream *s;
1631     pa_tagstruct *t;
1632     bool suspend;
1633 
1634     pa_source_output_assert_ref(o);
1635 
1636     /* State has not changed, nothing to do */
1637     if (old_state == o->source->state)
1638         return;
1639 
1640     suspend = (o->source->state == PA_SOURCE_SUSPENDED);
1641 
1642     s = RECORD_STREAM(o->userdata);
1643     record_stream_assert_ref(s);
1644 
1645     if (s->connection->version < 12)
1646       return;
1647 
1648     t = pa_tagstruct_new();
1649     pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_SUSPENDED);
1650     pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1651     pa_tagstruct_putu32(t, s->index);
1652     pa_tagstruct_put_boolean(t, suspend);
1653     pa_pstream_send_tagstruct(s->connection->pstream, t);
1654 }
1655 
1656 /* Called from main context */
source_output_moving_cb(pa_source_output *o, pa_source *dest)1657 static void source_output_moving_cb(pa_source_output *o, pa_source *dest) {
1658     record_stream *s;
1659     pa_tagstruct *t;
1660 
1661     pa_source_output_assert_ref(o);
1662     s = RECORD_STREAM(o->userdata);
1663     record_stream_assert_ref(s);
1664 
1665     if (!dest)
1666         return;
1667 
1668     fix_record_buffer_attr_pre(s);
1669     pa_memblockq_set_maxlength(s->memblockq, s->buffer_attr.maxlength);
1670     pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
1671     fix_record_buffer_attr_post(s);
1672 
1673     if (s->connection->version < 12)
1674       return;
1675 
1676     t = pa_tagstruct_new();
1677     pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_MOVED);
1678     pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1679     pa_tagstruct_putu32(t, s->index);
1680     pa_tagstruct_putu32(t, dest->index);
1681     pa_tagstruct_puts(t, dest->name);
1682     pa_tagstruct_put_boolean(t, dest->state == PA_SOURCE_SUSPENDED);
1683 
1684     if (s->connection->version >= 13) {
1685         pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
1686         pa_tagstruct_putu32(t, s->buffer_attr.fragsize);
1687         pa_tagstruct_put_usec(t, s->configured_source_latency);
1688     }
1689 
1690     pa_pstream_send_tagstruct(s->connection->pstream, t);
1691 }
1692 
1693 /*** pdispatch callbacks ***/
1694 
protocol_error(pa_native_connection *c)1695 static void protocol_error(pa_native_connection *c) {
1696     pa_log("protocol error, kicking client");
1697     native_connection_unlink(c);
1698 }
1699 
1700 #define CHECK_VALIDITY(pstream, expression, tag, error) do { \
1701 if (!(expression)) { \
1702     pa_pstream_send_error((pstream), (tag), (error)); \
1703     return; \
1704 } \
1705 } while(0);
1706 
1707 #define CHECK_VALIDITY_GOTO(pstream, expression, tag, error, label) do { \
1708 if (!(expression)) { \
1709     pa_pstream_send_error((pstream), (tag), (error)); \
1710     goto label; \
1711 } \
1712 } while(0);
1713 
reply_new(uint32_t tag)1714 static pa_tagstruct *reply_new(uint32_t tag) {
1715     pa_tagstruct *reply;
1716 
1717     reply = pa_tagstruct_new();
1718     pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
1719     pa_tagstruct_putu32(reply, tag);
1720     return reply;
1721 }
1722 
command_create_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)1723 static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1724     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
1725     playback_stream *s;
1726     uint32_t sink_index, syncid, missing = 0;
1727     pa_buffer_attr attr;
1728     const char *name = NULL, *sink_name;
1729     pa_sample_spec ss;
1730     pa_channel_map map;
1731     pa_tagstruct *reply;
1732     pa_sink *sink = NULL;
1733     pa_cvolume volume;
1734     bool
1735         corked = false,
1736         no_remap = false,
1737         no_remix = false,
1738         fix_format = false,
1739         fix_rate = false,
1740         fix_channels = false,
1741         no_move = false,
1742         variable_rate = false,
1743         muted = false,
1744         adjust_latency = false,
1745         early_requests = false,
1746         dont_inhibit_auto_suspend = false,
1747         volume_set = true,
1748         muted_set = false,
1749         fail_on_suspend = false,
1750         relative_volume = false,
1751         passthrough = false;
1752 
1753     pa_sink_input_flags_t flags = 0;
1754     pa_proplist *p = NULL;
1755     int ret = PA_ERR_INVALID;
1756     uint8_t n_formats = 0;
1757     pa_format_info *format;
1758     pa_idxset *formats = NULL;
1759     uint32_t i;
1760 
1761     pa_native_connection_assert_ref(c);
1762     pa_assert(t);
1763     memset(&attr, 0, sizeof(attr));
1764 
1765     if ((c->version < 13 && (pa_tagstruct_gets(t, &name) < 0 || !name)) ||
1766         pa_tagstruct_get(
1767                 t,
1768                 PA_TAG_SAMPLE_SPEC, &ss,
1769                 PA_TAG_CHANNEL_MAP, &map,
1770                 PA_TAG_U32, &sink_index,
1771                 PA_TAG_STRING, &sink_name,
1772                 PA_TAG_U32, &attr.maxlength,
1773                 PA_TAG_BOOLEAN, &corked,
1774                 PA_TAG_U32, &attr.tlength,
1775                 PA_TAG_U32, &attr.prebuf,
1776                 PA_TAG_U32, &attr.minreq,
1777                 PA_TAG_U32, &syncid,
1778                 PA_TAG_CVOLUME, &volume,
1779                 PA_TAG_INVALID) < 0) {
1780 
1781         protocol_error(c);
1782         goto finish;
1783     }
1784 
1785     CHECK_VALIDITY_GOTO(c->pstream, c->authorized, tag, PA_ERR_ACCESS, finish);
1786     CHECK_VALIDITY_GOTO(c->pstream, !sink_name || pa_namereg_is_valid_name_or_wildcard(sink_name, PA_NAMEREG_SINK), tag, PA_ERR_INVALID, finish);
1787     CHECK_VALIDITY_GOTO(c->pstream, sink_index == PA_INVALID_INDEX || !sink_name, tag, PA_ERR_INVALID, finish);
1788     CHECK_VALIDITY_GOTO(c->pstream, !sink_name || sink_index == PA_INVALID_INDEX, tag, PA_ERR_INVALID, finish);
1789     CHECK_VALIDITY_GOTO(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID, finish);
1790 
1791     p = pa_proplist_new();
1792 
1793     if (name)
1794         pa_proplist_sets(p, PA_PROP_MEDIA_NAME, name);
1795 
1796     if (c->version >= 12) {
1797         /* Since 0.9.8 the user can ask for a couple of additional flags */
1798 
1799         if (pa_tagstruct_get_boolean(t, &no_remap) < 0 ||
1800             pa_tagstruct_get_boolean(t, &no_remix) < 0 ||
1801             pa_tagstruct_get_boolean(t, &fix_format) < 0 ||
1802             pa_tagstruct_get_boolean(t, &fix_rate) < 0 ||
1803             pa_tagstruct_get_boolean(t, &fix_channels) < 0 ||
1804             pa_tagstruct_get_boolean(t, &no_move) < 0 ||
1805             pa_tagstruct_get_boolean(t, &variable_rate) < 0) {
1806 
1807             protocol_error(c);
1808             goto finish;
1809         }
1810     }
1811 
1812     if (c->version >= 13) {
1813 
1814         if (pa_tagstruct_get_boolean(t, &muted) < 0 ||
1815             pa_tagstruct_get_boolean(t, &adjust_latency) < 0 ||
1816             pa_tagstruct_get_proplist(t, p) < 0) {
1817 
1818             protocol_error(c);
1819             goto finish;
1820         }
1821     }
1822 
1823     if (c->version >= 14) {
1824 
1825         if (pa_tagstruct_get_boolean(t, &volume_set) < 0 ||
1826             pa_tagstruct_get_boolean(t, &early_requests) < 0) {
1827 
1828             protocol_error(c);
1829             goto finish;
1830         }
1831     }
1832 
1833     if (c->version >= 15) {
1834 
1835         if (pa_tagstruct_get_boolean(t, &muted_set) < 0 ||
1836             pa_tagstruct_get_boolean(t, &dont_inhibit_auto_suspend) < 0 ||
1837             pa_tagstruct_get_boolean(t, &fail_on_suspend) < 0) {
1838 
1839             protocol_error(c);
1840             goto finish;
1841         }
1842     }
1843 
1844     if (c->version >= 17) {
1845 
1846         if (pa_tagstruct_get_boolean(t, &relative_volume) < 0) {
1847 
1848             protocol_error(c);
1849             goto finish;
1850         }
1851     }
1852 
1853     if (c->version >= 18) {
1854 
1855         if (pa_tagstruct_get_boolean(t, &passthrough) < 0 ) {
1856             protocol_error(c);
1857             goto finish;
1858         }
1859     }
1860 
1861     if (c->version >= 21) {
1862 
1863         if (pa_tagstruct_getu8(t, &n_formats) < 0) {
1864             protocol_error(c);
1865             goto finish;
1866         }
1867 
1868         if (n_formats)
1869             formats = pa_idxset_new(NULL, NULL);
1870 
1871         for (i = 0; i < n_formats; i++) {
1872             format = pa_format_info_new();
1873             if (pa_tagstruct_get_format_info(t, format) < 0) {
1874                 protocol_error(c);
1875                 goto finish;
1876             }
1877             pa_idxset_put(formats, format, NULL);
1878         }
1879     }
1880 
1881     if (n_formats == 0) {
1882         CHECK_VALIDITY_GOTO(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID, finish);
1883         CHECK_VALIDITY_GOTO(c->pstream, map.channels == ss.channels && volume.channels == ss.channels, tag, PA_ERR_INVALID, finish);
1884         CHECK_VALIDITY_GOTO(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID, finish);
1885     } else {
1886         PA_IDXSET_FOREACH(format, formats, i) {
1887             CHECK_VALIDITY_GOTO(c->pstream, pa_format_info_valid(format), tag, PA_ERR_INVALID, finish);
1888         }
1889     }
1890 
1891     if (!pa_tagstruct_eof(t)) {
1892         protocol_error(c);
1893         goto finish;
1894     }
1895 
1896     if (sink_index != PA_INVALID_INDEX) {
1897 
1898         if (!(sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index))) {
1899             pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1900             goto finish;
1901         }
1902 
1903     } else if (sink_name) {
1904 
1905         if (!(sink = pa_namereg_get(c->protocol->core, sink_name, PA_NAMEREG_SINK))) {
1906             pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1907             goto finish;
1908         }
1909     }
1910 
1911     flags =
1912         (corked ? PA_SINK_INPUT_START_CORKED : 0) |
1913         (no_remap ? PA_SINK_INPUT_NO_REMAP : 0) |
1914         (no_remix ? PA_SINK_INPUT_NO_REMIX : 0) |
1915         (fix_format ? PA_SINK_INPUT_FIX_FORMAT : 0) |
1916         (fix_rate ? PA_SINK_INPUT_FIX_RATE : 0) |
1917         (fix_channels ? PA_SINK_INPUT_FIX_CHANNELS : 0) |
1918         (no_move ? PA_SINK_INPUT_DONT_MOVE : 0) |
1919         (variable_rate ? PA_SINK_INPUT_VARIABLE_RATE : 0) |
1920         (dont_inhibit_auto_suspend ? PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND : 0) |
1921         (fail_on_suspend ? PA_SINK_INPUT_NO_CREATE_ON_SUSPEND|PA_SINK_INPUT_KILL_ON_SUSPEND : 0) |
1922         (passthrough ? PA_SINK_INPUT_PASSTHROUGH : 0);
1923 
1924     /* Only since protocol version 15 there's a separate muted_set
1925      * flag. For older versions we synthesize it here */
1926     muted_set = muted_set || muted;
1927 
1928     s = playback_stream_new(c, sink, &ss, &map, formats, &attr, volume_set ? &volume : NULL, muted, muted_set, flags, p, adjust_latency, early_requests, relative_volume, syncid, &missing, &ret);
1929     /* We no longer own the formats idxset */
1930     formats = NULL;
1931 
1932     CHECK_VALIDITY_GOTO(c->pstream, s, tag, ret, finish);
1933 
1934     reply = reply_new(tag);
1935     pa_tagstruct_putu32(reply, s->index);
1936     pa_assert(s->sink_input);
1937     pa_tagstruct_putu32(reply, s->sink_input->index);
1938     pa_tagstruct_putu32(reply, missing);
1939 
1940 #ifdef PROTOCOL_NATIVE_DEBUG
1941     pa_log("initial request is %u", missing);
1942 #endif
1943 
1944     if (c->version >= 9) {
1945         /* Since 0.9.0 we support sending the buffer metrics back to the client */
1946 
1947         pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.maxlength);
1948         pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.tlength);
1949         pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.prebuf);
1950         pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.minreq);
1951     }
1952 
1953     if (c->version >= 12) {
1954         /* Since 0.9.8 we support sending the chosen sample
1955          * spec/channel map/device/suspend status back to the
1956          * client */
1957 
1958         pa_tagstruct_put_sample_spec(reply, &ss);
1959         pa_tagstruct_put_channel_map(reply, &map);
1960 
1961         pa_tagstruct_putu32(reply, s->sink_input->sink->index);
1962         pa_tagstruct_puts(reply, s->sink_input->sink->name);
1963 
1964         pa_tagstruct_put_boolean(reply, s->sink_input->sink->state == PA_SINK_SUSPENDED);
1965     }
1966 
1967     if (c->version >= 13)
1968         pa_tagstruct_put_usec(reply, s->configured_sink_latency);
1969 
1970     if (c->version >= 21) {
1971         /* Send back the format we negotiated */
1972         if (s->sink_input->format)
1973             pa_tagstruct_put_format_info(reply, s->sink_input->format);
1974         else {
1975             pa_format_info *f = pa_format_info_new();
1976             pa_tagstruct_put_format_info(reply, f);
1977             pa_format_info_free(f);
1978         }
1979     }
1980 
1981     pa_pstream_send_tagstruct(c->pstream, reply);
1982 
1983 finish:
1984     if (p)
1985         pa_proplist_free(p);
1986     if (formats)
1987         pa_idxset_free(formats, (pa_free_cb_t) pa_format_info_free);
1988 }
1989 
command_delete_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)1990 static void command_delete_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1991     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
1992     uint32_t channel;
1993 
1994     pa_native_connection_assert_ref(c);
1995     pa_assert(t);
1996 
1997     if (pa_tagstruct_getu32(t, &channel) < 0 ||
1998         !pa_tagstruct_eof(t)) {
1999         protocol_error(c);
2000         return;
2001     }
2002 
2003     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2004 
2005     switch (command) {
2006 
2007         case PA_COMMAND_DELETE_PLAYBACK_STREAM: {
2008             playback_stream *s;
2009             if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || !playback_stream_isinstance(s)) {
2010                 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2011                 return;
2012             }
2013 
2014             playback_stream_unlink(s);
2015             break;
2016         }
2017 
2018         case PA_COMMAND_DELETE_RECORD_STREAM: {
2019             record_stream *s;
2020             if (!(s = pa_idxset_get_by_index(c->record_streams, channel))) {
2021                 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2022                 return;
2023             }
2024 
2025             record_stream_unlink(s);
2026             break;
2027         }
2028 
2029         case PA_COMMAND_DELETE_UPLOAD_STREAM: {
2030             upload_stream *s;
2031 
2032             if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || !upload_stream_isinstance(s)) {
2033                 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2034                 return;
2035             }
2036 
2037             upload_stream_unlink(s);
2038             break;
2039         }
2040 
2041         default:
2042             pa_assert_not_reached();
2043     }
2044 
2045     pa_pstream_send_simple_ack(c->pstream, tag);
2046 }
2047 
command_create_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)2048 static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2049     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2050     record_stream *s;
2051     pa_buffer_attr attr;
2052     uint32_t source_index;
2053     const char *name = NULL, *source_name;
2054     pa_sample_spec ss;
2055     pa_channel_map map;
2056     pa_tagstruct *reply;
2057     pa_source *source = NULL;
2058     pa_cvolume volume;
2059     bool
2060         corked = false,
2061         no_remap = false,
2062         no_remix = false,
2063         fix_format = false,
2064         fix_rate = false,
2065         fix_channels = false,
2066         no_move = false,
2067         variable_rate = false,
2068         muted = false,
2069         adjust_latency = false,
2070         peak_detect = false,
2071         early_requests = false,
2072         dont_inhibit_auto_suspend = false,
2073         volume_set = false,
2074         muted_set = false,
2075         fail_on_suspend = false,
2076         relative_volume = false,
2077         passthrough = false;
2078 
2079     pa_source_output_flags_t flags = 0;
2080     pa_proplist *p = NULL;
2081     uint32_t direct_on_input_idx = PA_INVALID_INDEX;
2082     pa_sink_input *direct_on_input = NULL;
2083     int ret = PA_ERR_INVALID;
2084     uint8_t n_formats = 0;
2085     pa_format_info *format;
2086     pa_idxset *formats = NULL;
2087     uint32_t i;
2088 
2089     pa_native_connection_assert_ref(c);
2090     pa_assert(t);
2091 
2092     memset(&attr, 0, sizeof(attr));
2093 
2094     if ((c->version < 13 && (pa_tagstruct_gets(t, &name) < 0 || !name)) ||
2095         pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
2096         pa_tagstruct_get_channel_map(t, &map) < 0 ||
2097         pa_tagstruct_getu32(t, &source_index) < 0 ||
2098         pa_tagstruct_gets(t, &source_name) < 0 ||
2099         pa_tagstruct_getu32(t, &attr.maxlength) < 0 ||
2100         pa_tagstruct_get_boolean(t, &corked) < 0 ||
2101         pa_tagstruct_getu32(t, &attr.fragsize) < 0) {
2102 
2103         protocol_error(c);
2104         goto finish;
2105     }
2106 
2107     CHECK_VALIDITY_GOTO(c->pstream, c->authorized, tag, PA_ERR_ACCESS, finish);
2108     CHECK_VALIDITY_GOTO(c->pstream, !source_name || pa_namereg_is_valid_name_or_wildcard(source_name, PA_NAMEREG_SOURCE), tag, PA_ERR_INVALID, finish);
2109     CHECK_VALIDITY_GOTO(c->pstream, source_index == PA_INVALID_INDEX || !source_name, tag, PA_ERR_INVALID, finish);
2110     CHECK_VALIDITY_GOTO(c->pstream, !source_name || source_index == PA_INVALID_INDEX, tag, PA_ERR_INVALID, finish);
2111 
2112     p = pa_proplist_new();
2113 
2114     if (name)
2115         pa_proplist_sets(p, PA_PROP_MEDIA_NAME, name);
2116 
2117     if (c->version >= 12) {
2118         /* Since 0.9.8 the user can ask for a couple of additional flags */
2119 
2120         if (pa_tagstruct_get_boolean(t, &no_remap) < 0 ||
2121             pa_tagstruct_get_boolean(t, &no_remix) < 0 ||
2122             pa_tagstruct_get_boolean(t, &fix_format) < 0 ||
2123             pa_tagstruct_get_boolean(t, &fix_rate) < 0 ||
2124             pa_tagstruct_get_boolean(t, &fix_channels) < 0 ||
2125             pa_tagstruct_get_boolean(t, &no_move) < 0 ||
2126             pa_tagstruct_get_boolean(t, &variable_rate) < 0) {
2127 
2128             protocol_error(c);
2129             goto finish;
2130         }
2131     }
2132 
2133     if (c->version >= 13) {
2134 
2135         if (pa_tagstruct_get_boolean(t, &peak_detect) < 0 ||
2136             pa_tagstruct_get_boolean(t, &adjust_latency) < 0 ||
2137             pa_tagstruct_get_proplist(t, p) < 0 ||
2138             pa_tagstruct_getu32(t, &direct_on_input_idx) < 0) {
2139 
2140             protocol_error(c);
2141             goto finish;
2142         }
2143     }
2144 
2145     if (c->version >= 14) {
2146 
2147         if (pa_tagstruct_get_boolean(t, &early_requests) < 0) {
2148             protocol_error(c);
2149             goto finish;
2150         }
2151     }
2152 
2153     if (c->version >= 15) {
2154 
2155         if (pa_tagstruct_get_boolean(t, &dont_inhibit_auto_suspend) < 0 ||
2156             pa_tagstruct_get_boolean(t, &fail_on_suspend) < 0) {
2157 
2158             protocol_error(c);
2159             goto finish;
2160         }
2161     }
2162 
2163     if (c->version >= 22) {
2164         /* For newer client versions (with per-source-output volumes), we try
2165          * to make the behaviour for playback and record streams the same. */
2166         volume_set = true;
2167 
2168         if (pa_tagstruct_getu8(t, &n_formats) < 0) {
2169             protocol_error(c);
2170             goto finish;
2171         }
2172 
2173         if (n_formats)
2174             formats = pa_idxset_new(NULL, NULL);
2175 
2176         for (i = 0; i < n_formats; i++) {
2177             format = pa_format_info_new();
2178             if (pa_tagstruct_get_format_info(t, format) < 0) {
2179                 protocol_error(c);
2180                 goto finish;
2181             }
2182             pa_idxset_put(formats, format, NULL);
2183         }
2184 
2185         if (pa_tagstruct_get_cvolume(t, &volume) < 0 ||
2186             pa_tagstruct_get_boolean(t, &muted) < 0 ||
2187             pa_tagstruct_get_boolean(t, &volume_set) < 0 ||
2188             pa_tagstruct_get_boolean(t, &muted_set) < 0 ||
2189             pa_tagstruct_get_boolean(t, &relative_volume) < 0 ||
2190             pa_tagstruct_get_boolean(t, &passthrough) < 0) {
2191 
2192             protocol_error(c);
2193             goto finish;
2194         }
2195 
2196         CHECK_VALIDITY_GOTO(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID, finish);
2197     }
2198 
2199     if (n_formats == 0) {
2200         CHECK_VALIDITY_GOTO(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID, finish);
2201         CHECK_VALIDITY_GOTO(c->pstream, map.channels == ss.channels, tag, PA_ERR_INVALID, finish);
2202         CHECK_VALIDITY_GOTO(c->pstream, c->version < 22 || (volume.channels == ss.channels), tag, PA_ERR_INVALID, finish);
2203         CHECK_VALIDITY_GOTO(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID, finish);
2204     } else {
2205         PA_IDXSET_FOREACH(format, formats, i) {
2206             CHECK_VALIDITY_GOTO(c->pstream, pa_format_info_valid(format), tag, PA_ERR_INVALID, finish);
2207         }
2208     }
2209 
2210     if (!pa_tagstruct_eof(t)) {
2211         protocol_error(c);
2212         goto finish;
2213     }
2214 
2215     if (source_index != PA_INVALID_INDEX) {
2216 
2217         if (!(source = pa_idxset_get_by_index(c->protocol->core->sources, source_index))) {
2218             pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2219             goto finish;
2220         }
2221 
2222     } else if (source_name) {
2223 
2224         if (!(source = pa_namereg_get(c->protocol->core, source_name, PA_NAMEREG_SOURCE))) {
2225             pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2226             goto finish;
2227         }
2228     }
2229 
2230     if (direct_on_input_idx != PA_INVALID_INDEX) {
2231 
2232         if (!(direct_on_input = pa_idxset_get_by_index(c->protocol->core->sink_inputs, direct_on_input_idx))) {
2233             pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2234             goto finish;
2235         }
2236     }
2237 
2238     flags =
2239         (corked ? PA_SOURCE_OUTPUT_START_CORKED : 0) |
2240         (no_remap ? PA_SOURCE_OUTPUT_NO_REMAP : 0) |
2241         (no_remix ? PA_SOURCE_OUTPUT_NO_REMIX : 0) |
2242         (fix_format ? PA_SOURCE_OUTPUT_FIX_FORMAT : 0) |
2243         (fix_rate ? PA_SOURCE_OUTPUT_FIX_RATE : 0) |
2244         (fix_channels ? PA_SOURCE_OUTPUT_FIX_CHANNELS : 0) |
2245         (no_move ? PA_SOURCE_OUTPUT_DONT_MOVE : 0) |
2246         (variable_rate ? PA_SOURCE_OUTPUT_VARIABLE_RATE : 0) |
2247         (dont_inhibit_auto_suspend ? PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND : 0) |
2248         (fail_on_suspend ? PA_SOURCE_OUTPUT_NO_CREATE_ON_SUSPEND|PA_SOURCE_OUTPUT_KILL_ON_SUSPEND : 0) |
2249         (passthrough ? PA_SOURCE_OUTPUT_PASSTHROUGH : 0);
2250 
2251     s = record_stream_new(c, source, &ss, &map, formats, &attr, volume_set ? &volume : NULL, muted, muted_set, flags, p, adjust_latency, early_requests, relative_volume, peak_detect, direct_on_input, &ret);
2252     /* We no longer own the formats idxset */
2253     formats = NULL;
2254 
2255     CHECK_VALIDITY_GOTO(c->pstream, s, tag, ret, finish);
2256 
2257     reply = reply_new(tag);
2258     pa_tagstruct_putu32(reply, s->index);
2259     pa_assert(s->source_output);
2260     pa_tagstruct_putu32(reply, s->source_output->index);
2261 
2262     if (c->version >= 9) {
2263         /* Since 0.9 we support sending the buffer metrics back to the client */
2264 
2265         pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.maxlength);
2266         pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.fragsize);
2267     }
2268 
2269     if (c->version >= 12) {
2270         /* Since 0.9.8 we support sending the chosen sample
2271          * spec/channel map/device/suspend status back to the
2272          * client */
2273 
2274         pa_tagstruct_put_sample_spec(reply, &ss);
2275         pa_tagstruct_put_channel_map(reply, &map);
2276 
2277         pa_tagstruct_putu32(reply, s->source_output->source->index);
2278         pa_tagstruct_puts(reply, s->source_output->source->name);
2279 
2280         pa_tagstruct_put_boolean(reply, s->source_output->source->state == PA_SOURCE_SUSPENDED);
2281     }
2282 
2283     if (c->version >= 13)
2284         pa_tagstruct_put_usec(reply, s->configured_source_latency);
2285 
2286     if (c->version >= 22) {
2287         /* Send back the format we negotiated */
2288         if (s->source_output->format)
2289             pa_tagstruct_put_format_info(reply, s->source_output->format);
2290         else {
2291             pa_format_info *f = pa_format_info_new();
2292             pa_tagstruct_put_format_info(reply, f);
2293             pa_format_info_free(f);
2294         }
2295     }
2296 
2297     pa_pstream_send_tagstruct(c->pstream, reply);
2298 
2299 finish:
2300     if (p)
2301         pa_proplist_free(p);
2302     if (formats)
2303         pa_idxset_free(formats, (pa_free_cb_t) pa_format_info_free);
2304 }
2305 
command_exit(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)2306 static void command_exit(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2307     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2308     int ret;
2309 
2310     pa_native_connection_assert_ref(c);
2311     pa_assert(t);
2312 
2313     if (!pa_tagstruct_eof(t)) {
2314         protocol_error(c);
2315         return;
2316     }
2317 
2318     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2319     ret = pa_core_exit(c->protocol->core, false, 0);
2320     CHECK_VALIDITY(c->pstream, ret >= 0, tag, PA_ERR_ACCESS);
2321 
2322     pa_log_debug("Client %s asks us to terminate.", pa_strnull(pa_proplist_gets(c->client->proplist,
2323         PA_PROP_APPLICATION_PROCESS_BINARY)));
2324 
2325     pa_pstream_send_simple_ack(c->pstream, tag); /* nonsense */
2326 }
2327 
setup_srbchannel(pa_native_connection *c, pa_mem_type_t shm_type)2328 static void setup_srbchannel(pa_native_connection *c, pa_mem_type_t shm_type) {
2329     pa_srbchannel_template srbt;
2330     pa_srbchannel *srb;
2331     pa_memchunk mc;
2332     pa_tagstruct *t;
2333     int fdlist[2];
2334     pa_log_info("start setup_srbchannel, shm_type: %d", shm_type);
2335 #ifndef HAVE_CREDS
2336     pa_log_debug("Disabling srbchannel, reason: No fd passing support");
2337     return;
2338 #endif
2339 
2340     if (!c->options->srbchannel) {
2341         pa_log_debug("Disabling srbchannel, reason: Must be enabled by module parameter");
2342         return;
2343     }
2344 
2345     if (c->version < 30) {
2346         pa_log_debug("Disabling srbchannel, reason: Protocol too old");
2347         return;
2348     }
2349 
2350     if (!pa_pstream_get_shm(c->pstream)) {
2351         pa_log_debug("Disabling srbchannel, reason: No SHM support");
2352         return;
2353     }
2354 
2355     if (c->rw_mempool) {
2356         pa_log_debug("Ignoring srbchannel setup, reason: received COMMAND_AUTH "
2357                      "more than once");
2358         return;
2359     }
2360 
2361     if (!(c->rw_mempool = pa_mempool_new(shm_type, c->protocol->core->shm_size, true))) {
2362         pa_log_debug("Disabling srbchannel, reason: Failed to allocate shared "
2363                     "writable memory pool.");
2364         return;
2365     }
2366 
2367     if (shm_type == PA_MEM_TYPE_SHARED_MEMFD) {
2368         const char *reason;
2369         if (pa_pstream_register_memfd_mempool(c->pstream, c->rw_mempool, &reason)) {
2370             pa_log_warn("Disabling srbchannel, reason: Failed to register memfd mempool: %s", reason);
2371             goto fail;
2372         }
2373     }
2374     pa_mempool_set_is_remote_writable(c->rw_mempool, true);
2375 
2376     srb = pa_srbchannel_new(c->protocol->core->mainloop, c->rw_mempool);
2377     if (!srb) {
2378         pa_log_debug("Failed to create srbchannel");
2379         goto fail;
2380     }
2381     pa_log_debug("Enabling srbchannel...");
2382     pa_srbchannel_export(srb, &srbt);
2383 
2384     /* Send enable command to client */
2385     t = pa_tagstruct_new();
2386     pa_tagstruct_putu32(t, PA_COMMAND_ENABLE_SRBCHANNEL);
2387     pa_tagstruct_putu32(t, (size_t) srb); /* tag */
2388     fdlist[0] = srbt.readfd;
2389     fdlist[1] = srbt.writefd;
2390     pa_pstream_send_tagstruct_with_fds(c->pstream, t, 2, fdlist, false);
2391 
2392     /* Send ringbuffer memblock to client */
2393     mc.memblock = srbt.memblock;
2394     mc.index = 0;
2395     mc.length = pa_memblock_get_length(srbt.memblock);
2396     pa_pstream_send_memblock(c->pstream, 0, 0, 0, &mc);
2397 
2398     c->srbpending = srb;
2399     return;
2400 
2401 fail:
2402     if (c->rw_mempool) {
2403         pa_mempool_unref(c->rw_mempool);
2404         c->rw_mempool = NULL;
2405     }
2406 }
2407 
command_enable_srbchannel(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)2408 static void command_enable_srbchannel(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2409     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2410 
2411     if (tag != (uint32_t) (size_t) c->srbpending) {
2412         protocol_error(c);
2413         return;
2414     }
2415 
2416     pa_log_debug("Client enabled srbchannel.");
2417     pa_pstream_set_srbchannel(c->pstream, c->srbpending);
2418     c->srbpending = NULL;
2419 }
2420 
command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)2421 static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2422     pa_log_info("start command_authd");
2423     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2424     const void*cookie;
2425     bool memfd_on_remote = false, do_memfd = false;
2426     pa_tagstruct *reply;
2427     pa_mem_type_t shm_type;
2428     bool shm_on_remote = false, do_shm;
2429 
2430     pa_native_connection_assert_ref(c);
2431     pa_assert(t);
2432 
2433     if (pa_tagstruct_getu32(t, &c->version) < 0 ||
2434         pa_tagstruct_get_arbitrary(t, &cookie, PA_NATIVE_COOKIE_LENGTH) < 0 ||
2435         !pa_tagstruct_eof(t)) {
2436         protocol_error(c);
2437         return;
2438     }
2439 
2440     /* Minimum supported version */
2441     if (c->version < 8) {
2442         pa_pstream_send_error(c->pstream, tag, PA_ERR_VERSION);
2443         return;
2444     }
2445 
2446     /* Starting with protocol version 13 the MSB of the version tag
2447        reflects if shm is available for this pa_native_connection or
2448        not. */
2449     if ((c->version & PA_PROTOCOL_VERSION_MASK) >= 13) {
2450         shm_on_remote = !!(c->version & PA_PROTOCOL_FLAG_SHM);
2451 
2452         /* Starting with protocol version 31, the second MSB of the version
2453          * tag reflects whether memfd is supported on the other PA end. */
2454         if ((c->version & PA_PROTOCOL_VERSION_MASK) >= 31)
2455             memfd_on_remote = !!(c->version & PA_PROTOCOL_FLAG_MEMFD);
2456 
2457         /* Reserve the two most-significant _bytes_ of the version tag
2458          * for flags. */
2459         c->version &= PA_PROTOCOL_VERSION_MASK;
2460     }
2461 
2462     pa_log_debug("Protocol version: remote %u, local %u", c->version, PA_PROTOCOL_VERSION);
2463 
2464     pa_proplist_setf(c->client->proplist, "native-protocol.version", "%u", c->version);
2465 
2466     if (!c->authorized) {
2467         bool success = false;
2468 
2469 #ifdef HAVE_CREDS
2470         const pa_creds *creds;
2471 
2472         if ((creds = pa_pdispatch_creds(pd))) {
2473             if (creds->uid == getuid())
2474                 success = true;
2475             else if (c->options->auth_group) {
2476                 int r;
2477                 gid_t gid;
2478 
2479                 if ((gid = pa_get_gid_of_group(c->options->auth_group)) == (gid_t) -1)
2480                     pa_log_warn("Failed to get GID of group '%s'", c->options->auth_group);
2481                 else if (gid == creds->gid)
2482                     success = true;
2483 
2484                 if (!success) {
2485                     if ((r = pa_uid_in_group(creds->uid, c->options->auth_group)) < 0)
2486                         pa_log_warn("Failed to check group membership.");
2487                     else if (r > 0)
2488                         success = true;
2489                 }
2490             }
2491 
2492             pa_log_debug("Got credentials: uid=%lu gid=%lu success=%i",
2493                         (unsigned long) creds->uid,
2494                         (unsigned long) creds->gid,
2495                         (int) success);
2496         }
2497 #endif
2498 
2499         if (!success && c->options->auth_cookie) {
2500             const uint8_t *ac;
2501 
2502             if ((ac = pa_auth_cookie_read(c->options->auth_cookie, PA_NATIVE_COOKIE_LENGTH)))
2503                 if (memcmp(ac, cookie, PA_NATIVE_COOKIE_LENGTH) == 0)
2504                     success = true;
2505 
2506             /* All user process need to have the capability to connect and create pa stream,
2507              * so all of them can get the right cookie through ipc, cookie file check is useless.
2508              * We plan to use other way to protect some of the functions, instead of preventing
2509              * connection.
2510              */
2511             success = true;
2512         }
2513 
2514         if (!success) {
2515             pa_log_warn("Denied access to client with invalid authentication data.");
2516             pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
2517             return;
2518         }
2519 
2520         c->authorized = true;
2521         if (c->auth_timeout_event) {
2522             c->protocol->core->mainloop->time_free(c->auth_timeout_event);
2523             c->auth_timeout_event = NULL;
2524         }
2525     }
2526 
2527     /* Enable shared memory and memfd support if possible */
2528     do_shm =
2529         pa_mempool_is_shared(c->protocol->core->mempool) &&
2530         c->is_local;
2531 
2532     pa_log_debug("SHM possible: %s", pa_yes_no(do_shm));
2533 
2534     if (do_shm)
2535         if (c->version < 10 || (c->version >= 13 && !shm_on_remote))
2536             do_shm = false;
2537 
2538 #ifdef HAVE_CREDS
2539     if (do_shm) {
2540         /* Only enable SHM if both sides are owned by the same
2541          * user. This is a security measure because otherwise data
2542          * private to the user might leak. */
2543 
2544         const pa_creds *creds;
2545         if (!(creds = pa_pdispatch_creds(pd)) || getuid() != creds->uid)
2546             do_shm = false;
2547     }
2548 #endif
2549 
2550     pa_log_debug("Negotiated SHM: %s", pa_yes_no(do_shm));
2551     pa_pstream_enable_shm(c->pstream, do_shm);
2552 
2553     /* Do not declare memfd support for 9.0 client libraries (protocol v31).
2554      *
2555      * Although they support memfd transport, such 9.0 clients has an iochannel
2556      * bug that would break memfd audio if they're run in 32-bit mode over a
2557      * 64-bit kernel. Thus influence them to use the POSIX shared memory model
2558      * instead. Check commit 451d1d676237c81 for further details. */
2559     do_memfd =
2560         c->version >= 32 && do_shm && pa_mempool_is_memfd_backed(c->protocol->core->mempool);
2561 
2562     shm_type = PA_MEM_TYPE_PRIVATE;
2563     if (do_shm) {
2564         if (do_memfd && memfd_on_remote) {
2565             pa_pstream_enable_memfd(c->pstream);
2566             shm_type = PA_MEM_TYPE_SHARED_MEMFD;
2567         } else
2568             shm_type = PA_MEM_TYPE_SHARED_POSIX;
2569 
2570         pa_log_info("Memfd possible: %s", pa_yes_no(pa_memfd_is_locally_supported()));
2571         pa_log_info("Negotiated SHM type: %s", pa_mem_type_to_string(shm_type));
2572     }
2573 
2574     reply = reply_new(tag);
2575     pa_tagstruct_putu32(reply, PA_PROTOCOL_VERSION | (do_shm ? 0x80000000 : 0) |
2576                         (do_memfd ? 0x40000000 : 0));
2577 
2578 #ifdef HAVE_CREDS
2579 {
2580     /* SHM support is only enabled after both sides made sure they are the same user. */
2581 
2582     pa_creds ucred;
2583 
2584     ucred.uid = getuid();
2585     ucred.gid = getgid();
2586 
2587     pa_pstream_send_tagstruct_with_creds(c->pstream, reply, &ucred);
2588 }
2589 #else
2590     pa_pstream_send_tagstruct(c->pstream, reply);
2591 #endif
2592 
2593     /* The client enables memfd transport on its pstream only after
2594      * inspecting our version flags to see if we support memfds too.
2595      *
2596      * Thus register any pools after sending the server's version
2597      * flags and _never_ before it. */
2598     if (shm_type == PA_MEM_TYPE_SHARED_MEMFD) {
2599         const char *reason;
2600 
2601         if (pa_pstream_register_memfd_mempool(c->pstream, c->protocol->core->mempool, &reason))
2602             pa_log("Failed to register memfd mempool. Reason: %s", reason);
2603     }
2604 
2605     setup_srbchannel(c, shm_type);
2606 }
2607 
command_register_memfd_shmid(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)2608 static void command_register_memfd_shmid(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2609     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2610 
2611     pa_native_connection_assert_ref(c);
2612     pa_assert(t);
2613 
2614     if (pa_common_command_register_memfd_shmid(c->pstream, pd, c->version, command, t))
2615         protocol_error(c);
2616 }
2617 
command_set_client_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)2618 static void command_set_client_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2619     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2620     const char *name = NULL;
2621     pa_proplist *p;
2622     pa_tagstruct *reply;
2623 
2624     pa_native_connection_assert_ref(c);
2625     pa_assert(t);
2626 
2627     p = pa_proplist_new();
2628 
2629     if ((c->version < 13 && pa_tagstruct_gets(t, &name) < 0) ||
2630         (c->version >= 13 && pa_tagstruct_get_proplist(t, p) < 0) ||
2631         !pa_tagstruct_eof(t)) {
2632 
2633         protocol_error(c);
2634         pa_proplist_free(p);
2635         return;
2636     }
2637 
2638     if (name)
2639         if (pa_proplist_sets(p, PA_PROP_APPLICATION_NAME, name) < 0) {
2640             pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
2641             pa_proplist_free(p);
2642             return;
2643         }
2644 
2645     pa_client_update_proplist(c->client, PA_UPDATE_REPLACE, p);
2646     pa_proplist_free(p);
2647 
2648     reply = reply_new(tag);
2649 
2650     if (c->version >= 13)
2651         pa_tagstruct_putu32(reply, c->client->index);
2652 
2653     pa_pstream_send_tagstruct(c->pstream, reply);
2654 }
2655 
command_lookup(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)2656 static void command_lookup(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2657     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2658     const char *name;
2659     uint32_t idx = PA_IDXSET_INVALID;
2660 
2661     pa_native_connection_assert_ref(c);
2662     pa_assert(t);
2663 
2664     if (pa_tagstruct_gets(t, &name) < 0 ||
2665         !pa_tagstruct_eof(t)) {
2666         protocol_error(c);
2667         return;
2668     }
2669 
2670     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2671     CHECK_VALIDITY(c->pstream, name && pa_namereg_is_valid_name_or_wildcard(name, command == PA_COMMAND_LOOKUP_SINK ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE), tag, PA_ERR_INVALID);
2672 
2673     if (command == PA_COMMAND_LOOKUP_SINK) {
2674         pa_sink *sink;
2675         if ((sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK)))
2676             idx = sink->index;
2677     } else {
2678         pa_source *source;
2679         pa_assert(command == PA_COMMAND_LOOKUP_SOURCE);
2680         if ((source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE)))
2681             idx = source->index;
2682     }
2683 
2684     if (idx == PA_IDXSET_INVALID)
2685         pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2686     else {
2687         pa_tagstruct *reply;
2688         reply = reply_new(tag);
2689         pa_tagstruct_putu32(reply, idx);
2690         pa_pstream_send_tagstruct(c->pstream, reply);
2691     }
2692 }
2693 
command_drain_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)2694 static void command_drain_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2695     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2696     uint32_t idx;
2697     playback_stream *s;
2698 
2699     pa_native_connection_assert_ref(c);
2700     pa_assert(t);
2701 
2702     if (pa_tagstruct_getu32(t, &idx) < 0 ||
2703         !pa_tagstruct_eof(t)) {
2704         protocol_error(c);
2705         return;
2706     }
2707 
2708     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2709     s = pa_idxset_get_by_index(c->output_streams, idx);
2710     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2711     CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
2712 
2713     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);
2714 }
2715 
command_stat(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)2716 static void command_stat(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2717     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2718     pa_tagstruct *reply;
2719     const pa_mempool_stat *stat;
2720 
2721     pa_native_connection_assert_ref(c);
2722     pa_assert(t);
2723 
2724     if (!pa_tagstruct_eof(t)) {
2725         protocol_error(c);
2726         return;
2727     }
2728 
2729     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2730 
2731     stat = pa_mempool_get_stat(c->protocol->core->mempool);
2732 
2733     reply = reply_new(tag);
2734     pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->n_allocated));
2735     pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->allocated_size));
2736     pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->n_accumulated));
2737     pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->accumulated_size));
2738     pa_tagstruct_putu32(reply, (uint32_t) pa_scache_total_size(c->protocol->core));
2739     pa_pstream_send_tagstruct(c->pstream, reply);
2740 }
2741 
command_get_playback_latency(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)2742 static void command_get_playback_latency(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2743     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2744     pa_tagstruct *reply;
2745     playback_stream *s;
2746     struct timeval tv, now;
2747     uint32_t idx;
2748 
2749     pa_native_connection_assert_ref(c);
2750     pa_assert(t);
2751 
2752     if (pa_tagstruct_getu32(t, &idx) < 0 ||
2753         pa_tagstruct_get_timeval(t, &tv) < 0 ||
2754         !pa_tagstruct_eof(t)) {
2755         protocol_error(c);
2756         return;
2757     }
2758 
2759     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2760     s = pa_idxset_get_by_index(c->output_streams, idx);
2761     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2762     CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
2763 
2764     /* Get an atomic snapshot of all timing parameters */
2765     pa_assert_se(pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_UPDATE_LATENCY, s, 0, NULL) == 0);
2766 
2767     reply = reply_new(tag);
2768     pa_tagstruct_put_usec(reply,
2769                           s->current_sink_latency +
2770                           pa_bytes_to_usec(s->render_memblockq_length, &s->sink_input->sink->sample_spec));
2771     pa_tagstruct_put_usec(reply, 0);
2772     pa_tagstruct_put_boolean(reply,
2773                              s->playing_for > 0 &&
2774                              s->sink_input->sink->state == PA_SINK_RUNNING &&
2775                              s->sink_input->state == PA_SINK_INPUT_RUNNING);
2776     pa_tagstruct_put_timeval(reply, &tv);
2777     pa_tagstruct_put_timeval(reply, pa_gettimeofday(&now));
2778     pa_tagstruct_puts64(reply, s->write_index);
2779     pa_tagstruct_puts64(reply, s->read_index);
2780 
2781     if (c->version >= 13) {
2782         pa_tagstruct_putu64(reply, s->underrun_for);
2783         pa_tagstruct_putu64(reply, s->playing_for);
2784     }
2785 
2786     pa_pstream_send_tagstruct(c->pstream, reply);
2787 }
2788 
command_get_record_latency(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)2789 static void command_get_record_latency(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2790     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2791     pa_tagstruct *reply;
2792     record_stream *s;
2793     struct timeval tv, now;
2794     uint32_t idx;
2795 
2796     pa_native_connection_assert_ref(c);
2797     pa_assert(t);
2798 
2799     if (pa_tagstruct_getu32(t, &idx) < 0 ||
2800         pa_tagstruct_get_timeval(t, &tv) < 0 ||
2801         !pa_tagstruct_eof(t)) {
2802         protocol_error(c);
2803         return;
2804     }
2805 
2806     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2807     s = pa_idxset_get_by_index(c->record_streams, idx);
2808     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2809 
2810     /* Get an atomic snapshot of all timing parameters */
2811     pa_assert_se(pa_asyncmsgq_send(s->source_output->source->asyncmsgq, PA_MSGOBJECT(s->source_output), SOURCE_OUTPUT_MESSAGE_UPDATE_LATENCY, s, 0, NULL) == 0);
2812 
2813     reply = reply_new(tag);
2814     pa_tagstruct_put_usec(reply, s->current_monitor_latency);
2815     pa_tagstruct_put_usec(reply,
2816                           s->current_source_latency +
2817                           pa_bytes_to_usec(s->on_the_fly_snapshot, &s->source_output->sample_spec));
2818     pa_tagstruct_put_boolean(reply,
2819                              s->source_output->source->state == PA_SOURCE_RUNNING &&
2820                              s->source_output->state == PA_SOURCE_OUTPUT_RUNNING);
2821     pa_tagstruct_put_timeval(reply, &tv);
2822     pa_tagstruct_put_timeval(reply, pa_gettimeofday(&now));
2823     pa_tagstruct_puts64(reply, pa_memblockq_get_write_index(s->memblockq));
2824     pa_tagstruct_puts64(reply, pa_memblockq_get_read_index(s->memblockq));
2825     pa_pstream_send_tagstruct(c->pstream, reply);
2826 }
2827 
command_create_upload_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)2828 static void command_create_upload_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2829     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2830     upload_stream *s;
2831     uint32_t length;
2832     const char *name = NULL;
2833     pa_sample_spec ss;
2834     pa_channel_map map;
2835     pa_tagstruct *reply;
2836     pa_proplist *p;
2837 
2838     pa_native_connection_assert_ref(c);
2839     pa_assert(t);
2840 
2841     if (pa_tagstruct_gets(t, &name) < 0 ||
2842         pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
2843         pa_tagstruct_get_channel_map(t, &map) < 0 ||
2844         pa_tagstruct_getu32(t, &length) < 0) {
2845         protocol_error(c);
2846         return;
2847     }
2848 
2849     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2850     CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID);
2851     CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID);
2852     CHECK_VALIDITY(c->pstream, map.channels == ss.channels, tag, PA_ERR_INVALID);
2853     CHECK_VALIDITY(c->pstream, (length % pa_frame_size(&ss)) == 0 && length > 0, tag, PA_ERR_INVALID);
2854     CHECK_VALIDITY(c->pstream, length <= PA_SCACHE_ENTRY_SIZE_MAX, tag, PA_ERR_TOOLARGE);
2855 
2856     p = pa_proplist_new();
2857 
2858     if ((c->version >= 13 && pa_tagstruct_get_proplist(t, p) < 0) ||
2859         !pa_tagstruct_eof(t)) {
2860 
2861         protocol_error(c);
2862         pa_proplist_free(p);
2863         return;
2864     }
2865 
2866     if (c->version < 13)
2867         pa_proplist_sets(p, PA_PROP_MEDIA_NAME, name);
2868     else if (!name)
2869         if (!(name = pa_proplist_gets(p, PA_PROP_EVENT_ID)))
2870             name = pa_proplist_gets(p, PA_PROP_MEDIA_NAME);
2871 
2872     if (!name || !pa_namereg_is_valid_name(name)) {
2873         pa_proplist_free(p);
2874         CHECK_VALIDITY(c->pstream, false, tag, PA_ERR_INVALID);
2875     }
2876 
2877     s = upload_stream_new(c, &ss, &map, name, length, p);
2878     pa_proplist_free(p);
2879 
2880     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID);
2881 
2882     reply = reply_new(tag);
2883     pa_tagstruct_putu32(reply, s->index);
2884     pa_tagstruct_putu32(reply, length);
2885     pa_pstream_send_tagstruct(c->pstream, reply);
2886 }
2887 
command_finish_upload_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)2888 static void command_finish_upload_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2889     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2890     uint32_t channel;
2891     upload_stream *s;
2892     uint32_t idx;
2893 
2894     pa_native_connection_assert_ref(c);
2895     pa_assert(t);
2896 
2897     if (pa_tagstruct_getu32(t, &channel) < 0 ||
2898         !pa_tagstruct_eof(t)) {
2899         protocol_error(c);
2900         return;
2901     }
2902 
2903     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2904 
2905     s = pa_idxset_get_by_index(c->output_streams, channel);
2906     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2907     CHECK_VALIDITY(c->pstream, upload_stream_isinstance(s), tag, PA_ERR_NOENTITY);
2908 
2909     if (!s->memchunk.memblock)
2910         pa_pstream_send_error(c->pstream, tag, PA_ERR_TOOLARGE);
2911     else if (pa_scache_add_item(c->protocol->core, s->name, &s->sample_spec, &s->channel_map, &s->memchunk, s->proplist, &idx) < 0)
2912         pa_pstream_send_error(c->pstream, tag, PA_ERR_INTERNAL);
2913     else
2914         pa_pstream_send_simple_ack(c->pstream, tag);
2915 
2916     upload_stream_unlink(s);
2917 }
2918 
command_play_sample(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)2919 static void command_play_sample(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2920     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2921     uint32_t sink_index;
2922     pa_volume_t volume;
2923     pa_sink *sink;
2924     const char *name, *sink_name;
2925     uint32_t idx;
2926     pa_proplist *p;
2927     pa_tagstruct *reply;
2928 
2929     pa_native_connection_assert_ref(c);
2930     pa_assert(t);
2931 
2932     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2933 
2934     if (pa_tagstruct_getu32(t, &sink_index) < 0 ||
2935         pa_tagstruct_gets(t, &sink_name) < 0 ||
2936         pa_tagstruct_getu32(t, &volume) < 0 ||
2937         pa_tagstruct_gets(t, &name) < 0) {
2938         protocol_error(c);
2939         return;
2940     }
2941 
2942     CHECK_VALIDITY(c->pstream, !sink_name || pa_namereg_is_valid_name_or_wildcard(sink_name, PA_NAMEREG_SINK), tag, PA_ERR_INVALID);
2943     CHECK_VALIDITY(c->pstream, sink_index == PA_INVALID_INDEX || !sink_name, tag, PA_ERR_INVALID);
2944     CHECK_VALIDITY(c->pstream, !sink_name || sink_index == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
2945     CHECK_VALIDITY(c->pstream, name && pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
2946 
2947     if (sink_index != PA_INVALID_INDEX)
2948         sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index);
2949     else
2950         sink = pa_namereg_get(c->protocol->core, sink_name, PA_NAMEREG_SINK);
2951 
2952     CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
2953 
2954     p = pa_proplist_new();
2955 
2956     if ((c->version >= 13 && pa_tagstruct_get_proplist(t, p) < 0) ||
2957         !pa_tagstruct_eof(t)) {
2958         protocol_error(c);
2959         pa_proplist_free(p);
2960         return;
2961     }
2962 
2963     pa_proplist_update(p, PA_UPDATE_MERGE, c->client->proplist);
2964 
2965     if (pa_scache_play_item(c->protocol->core, name, sink, volume, p, &idx) < 0) {
2966         pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2967         pa_proplist_free(p);
2968         return;
2969     }
2970 
2971     pa_proplist_free(p);
2972 
2973     reply = reply_new(tag);
2974 
2975     if (c->version >= 13)
2976         pa_tagstruct_putu32(reply, idx);
2977 
2978     pa_pstream_send_tagstruct(c->pstream, reply);
2979 }
2980 
command_remove_sample(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)2981 static void command_remove_sample(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2982     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2983     const char *name;
2984 
2985     pa_native_connection_assert_ref(c);
2986     pa_assert(t);
2987 
2988     if (pa_tagstruct_gets(t, &name) < 0 ||
2989         !pa_tagstruct_eof(t)) {
2990         protocol_error(c);
2991         return;
2992     }
2993 
2994     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2995     CHECK_VALIDITY(c->pstream, name && pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
2996 
2997     if (pa_scache_remove_item(c->protocol->core, name) < 0) {
2998         pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2999         return;
3000     }
3001 
3002     pa_pstream_send_simple_ack(c->pstream, tag);
3003 }
3004 
fixup_sample_spec(pa_native_connection *c, pa_sample_spec *fixed, const pa_sample_spec *original)3005 static void fixup_sample_spec(pa_native_connection *c, pa_sample_spec *fixed, const pa_sample_spec *original) {
3006     pa_assert(c);
3007     pa_assert(fixed);
3008     pa_assert(original);
3009 
3010     *fixed = *original;
3011 
3012     if (c->version < 12) {
3013         /* Before protocol version 12 we didn't support S32 samples,
3014          * so we need to lie about this to the client */
3015 
3016         if (fixed->format == PA_SAMPLE_S32LE)
3017             fixed->format = PA_SAMPLE_FLOAT32LE;
3018         if (fixed->format == PA_SAMPLE_S32BE)
3019             fixed->format = PA_SAMPLE_FLOAT32BE;
3020     }
3021 
3022     if (c->version < 15) {
3023         if (fixed->format == PA_SAMPLE_S24LE || fixed->format == PA_SAMPLE_S24_32LE)
3024             fixed->format = PA_SAMPLE_FLOAT32LE;
3025         if (fixed->format == PA_SAMPLE_S24BE || fixed->format == PA_SAMPLE_S24_32BE)
3026             fixed->format = PA_SAMPLE_FLOAT32BE;
3027     }
3028 }
3029 
sink_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_sink *sink)3030 static void sink_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_sink *sink) {
3031     pa_sample_spec fixed_ss;
3032 
3033     pa_assert(t);
3034     pa_sink_assert_ref(sink);
3035 
3036     fixup_sample_spec(c, &fixed_ss, &sink->sample_spec);
3037 
3038     pa_tagstruct_put(
3039         t,
3040         PA_TAG_U32, sink->index,
3041         PA_TAG_STRING, sink->name,
3042         PA_TAG_STRING, pa_strnull(pa_proplist_gets(sink->proplist, PA_PROP_DEVICE_DESCRIPTION)),
3043         PA_TAG_SAMPLE_SPEC, &fixed_ss,
3044         PA_TAG_CHANNEL_MAP, &sink->channel_map,
3045         PA_TAG_U32, sink->module ? sink->module->index : PA_INVALID_INDEX,
3046         PA_TAG_CVOLUME, pa_sink_get_volume(sink, false),
3047         PA_TAG_BOOLEAN, pa_sink_get_mute(sink, false),
3048         PA_TAG_U32, sink->monitor_source ? sink->monitor_source->index : PA_INVALID_INDEX,
3049         PA_TAG_STRING, sink->monitor_source ? sink->monitor_source->name : NULL,
3050         PA_TAG_USEC, pa_sink_get_latency(sink),
3051         PA_TAG_STRING, sink->driver,
3052         PA_TAG_U32, sink->flags & PA_SINK_CLIENT_FLAGS_MASK,
3053         PA_TAG_INVALID);
3054 
3055     if (c->version >= 13) {
3056         pa_tagstruct_put_proplist(t, sink->proplist);
3057         pa_tagstruct_put_usec(t, pa_sink_get_requested_latency(sink));
3058     }
3059 
3060     if (c->version >= 15) {
3061         pa_tagstruct_put_volume(t, sink->base_volume);
3062         if (PA_UNLIKELY(sink->state == PA_SINK_INVALID_STATE))
3063             pa_log_error("Internal sink state is invalid.");
3064         pa_tagstruct_putu32(t, sink->state);
3065         pa_tagstruct_putu32(t, sink->n_volume_steps);
3066         pa_tagstruct_putu32(t, sink->card ? sink->card->index : PA_INVALID_INDEX);
3067     }
3068 
3069     if (c->version >= 16) {
3070         void *state;
3071         pa_device_port *p;
3072 
3073         pa_tagstruct_putu32(t, pa_hashmap_size(sink->ports));
3074 
3075         PA_HASHMAP_FOREACH(p, sink->ports, state) {
3076             pa_tagstruct_puts(t, p->name);
3077             pa_tagstruct_puts(t, p->description);
3078             pa_tagstruct_putu32(t, p->priority);
3079             if (c->version >= 24) {
3080                 pa_tagstruct_putu32(t, p->available);
3081                 if (c->version >= 34) {
3082                     pa_tagstruct_puts(t, p->availability_group);
3083                     pa_tagstruct_putu32(t, p->type);
3084                 }
3085             }
3086         }
3087 
3088         pa_tagstruct_puts(t, sink->active_port ? sink->active_port->name : NULL);
3089     }
3090 
3091     if (c->version >= 21) {
3092         uint32_t i;
3093         pa_format_info *f;
3094         pa_idxset *formats = pa_sink_get_formats(sink);
3095 
3096         pa_tagstruct_putu8(t, (uint8_t) pa_idxset_size(formats));
3097         PA_IDXSET_FOREACH(f, formats, i) {
3098             pa_tagstruct_put_format_info(t, f);
3099         }
3100 
3101         pa_idxset_free(formats, (pa_free_cb_t) pa_format_info_free);
3102     }
3103 }
3104 
source_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_source *source)3105 static void source_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_source *source) {
3106     pa_sample_spec fixed_ss;
3107 
3108     pa_assert(t);
3109     pa_source_assert_ref(source);
3110 
3111     fixup_sample_spec(c, &fixed_ss, &source->sample_spec);
3112 
3113     pa_tagstruct_put(
3114         t,
3115         PA_TAG_U32, source->index,
3116         PA_TAG_STRING, source->name,
3117         PA_TAG_STRING, pa_strnull(pa_proplist_gets(source->proplist, PA_PROP_DEVICE_DESCRIPTION)),
3118         PA_TAG_SAMPLE_SPEC, &fixed_ss,
3119         PA_TAG_CHANNEL_MAP, &source->channel_map,
3120         PA_TAG_U32, source->module ? source->module->index : PA_INVALID_INDEX,
3121         PA_TAG_CVOLUME, pa_source_get_volume(source, false),
3122         PA_TAG_BOOLEAN, pa_source_get_mute(source, false),
3123         PA_TAG_U32, source->monitor_of ? source->monitor_of->index : PA_INVALID_INDEX,
3124         PA_TAG_STRING, source->monitor_of ? source->monitor_of->name : NULL,
3125         PA_TAG_USEC, pa_source_get_latency(source),
3126         PA_TAG_STRING, source->driver,
3127         PA_TAG_U32, source->flags & PA_SOURCE_CLIENT_FLAGS_MASK,
3128         PA_TAG_INVALID);
3129 
3130     if (c->version >= 13) {
3131         pa_tagstruct_put_proplist(t, source->proplist);
3132         pa_tagstruct_put_usec(t, pa_source_get_requested_latency(source));
3133     }
3134 
3135     if (c->version >= 15) {
3136         pa_tagstruct_put_volume(t, source->base_volume);
3137         if (PA_UNLIKELY(source->state == PA_SOURCE_INVALID_STATE))
3138             pa_log_error("Internal source state is invalid.");
3139         pa_tagstruct_putu32(t, source->state);
3140         pa_tagstruct_putu32(t, source->n_volume_steps);
3141         pa_tagstruct_putu32(t, source->card ? source->card->index : PA_INVALID_INDEX);
3142     }
3143 
3144     if (c->version >= 16) {
3145         void *state;
3146         pa_device_port *p;
3147 
3148         pa_tagstruct_putu32(t, pa_hashmap_size(source->ports));
3149 
3150         PA_HASHMAP_FOREACH(p, source->ports, state) {
3151             pa_tagstruct_puts(t, p->name);
3152             pa_tagstruct_puts(t, p->description);
3153             pa_tagstruct_putu32(t, p->priority);
3154             if (c->version >= 24) {
3155                 pa_tagstruct_putu32(t, p->available);
3156                 if (c->version >= 34) {
3157                     pa_tagstruct_puts(t, p->availability_group);
3158                     pa_tagstruct_putu32(t, p->type);
3159                 }
3160             }
3161         }
3162 
3163         pa_tagstruct_puts(t, source->active_port ? source->active_port->name : NULL);
3164     }
3165 
3166     if (c->version >= 22) {
3167         uint32_t i;
3168         pa_format_info *f;
3169         pa_idxset *formats = pa_source_get_formats(source);
3170 
3171         pa_tagstruct_putu8(t, (uint8_t) pa_idxset_size(formats));
3172         PA_IDXSET_FOREACH(f, formats, i) {
3173             pa_tagstruct_put_format_info(t, f);
3174         }
3175 
3176         pa_idxset_free(formats, (pa_free_cb_t) pa_format_info_free);
3177     }
3178 }
3179 
client_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_client *client)3180 static void client_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_client *client) {
3181     pa_assert(t);
3182     pa_assert(client);
3183 
3184     pa_tagstruct_putu32(t, client->index);
3185     pa_tagstruct_puts(t, pa_strnull(pa_proplist_gets(client->proplist, PA_PROP_APPLICATION_NAME)));
3186     pa_tagstruct_putu32(t, client->module ? client->module->index : PA_INVALID_INDEX);
3187     pa_tagstruct_puts(t, client->driver);
3188 
3189     if (c->version >= 13)
3190         pa_tagstruct_put_proplist(t, client->proplist);
3191 }
3192 
card_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_card *card)3193 static void card_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_card *card) {
3194     void *state = NULL;
3195     pa_card_profile *p;
3196     pa_device_port *port;
3197 
3198     pa_assert(t);
3199     pa_assert(card);
3200 
3201     pa_tagstruct_putu32(t, card->index);
3202     pa_tagstruct_puts(t, card->name);
3203     pa_tagstruct_putu32(t, card->module ? card->module->index : PA_INVALID_INDEX);
3204     pa_tagstruct_puts(t, card->driver);
3205 
3206     pa_tagstruct_putu32(t, pa_hashmap_size(card->profiles));
3207 
3208     PA_HASHMAP_FOREACH(p, card->profiles, state) {
3209         pa_tagstruct_puts(t, p->name);
3210         pa_tagstruct_puts(t, p->description);
3211         pa_tagstruct_putu32(t, p->n_sinks);
3212         pa_tagstruct_putu32(t, p->n_sources);
3213         pa_tagstruct_putu32(t, p->priority);
3214 
3215         if (c->version >= 29)
3216             pa_tagstruct_putu32(t, (p->available != PA_AVAILABLE_NO));
3217     }
3218 
3219     pa_tagstruct_puts(t, card->active_profile->name);
3220     pa_tagstruct_put_proplist(t, card->proplist);
3221 
3222     if (c->version < 26)
3223         return;
3224 
3225     pa_tagstruct_putu32(t, pa_hashmap_size(card->ports));
3226 
3227     PA_HASHMAP_FOREACH(port, card->ports, state) {
3228         void *state2;
3229 
3230         pa_tagstruct_puts(t, port->name);
3231         pa_tagstruct_puts(t, port->description);
3232         pa_tagstruct_putu32(t, port->priority);
3233         pa_tagstruct_putu32(t, port->available);
3234         pa_tagstruct_putu8(t, port->direction);
3235         pa_tagstruct_put_proplist(t, port->proplist);
3236 
3237         pa_tagstruct_putu32(t, pa_hashmap_size(port->profiles));
3238 
3239         PA_HASHMAP_FOREACH(p, port->profiles, state2)
3240             pa_tagstruct_puts(t, p->name);
3241 
3242         if (c->version >= 27) {
3243             pa_tagstruct_puts64(t, port->latency_offset);
3244             if (c->version >= 34) {
3245                 pa_tagstruct_puts(t, port->availability_group);
3246                 pa_tagstruct_putu32(t, port->type);
3247             }
3248         }
3249     }
3250 }
3251 
module_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_module *module)3252 static void module_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_module *module) {
3253     pa_assert(t);
3254     pa_assert(module);
3255 
3256     pa_tagstruct_putu32(t, module->index);
3257     pa_tagstruct_puts(t, module->name);
3258     pa_tagstruct_puts(t, module->argument);
3259     pa_tagstruct_putu32(t, (uint32_t) pa_module_get_n_used(module));
3260 
3261     if (c->version < 15)
3262         pa_tagstruct_put_boolean(t, false); /* autoload is obsolete */
3263 
3264     if (c->version >= 15)
3265         pa_tagstruct_put_proplist(t, module->proplist);
3266 }
3267 
sink_input_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_sink_input *s)3268 static void sink_input_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_sink_input *s) {
3269     pa_sample_spec fixed_ss;
3270     pa_usec_t sink_latency;
3271     pa_cvolume v;
3272     bool has_volume = false;
3273 
3274     pa_assert(t);
3275     pa_sink_input_assert_ref(s);
3276 
3277     fixup_sample_spec(c, &fixed_ss, &s->sample_spec);
3278 
3279     has_volume = pa_sink_input_is_volume_readable(s);
3280     if (has_volume)
3281         pa_sink_input_get_volume(s, &v, true);
3282     else
3283         pa_cvolume_reset(&v, fixed_ss.channels);
3284 
3285     pa_tagstruct_putu32(t, s->index);
3286     pa_tagstruct_puts(t, pa_strnull(pa_proplist_gets(s->proplist, PA_PROP_MEDIA_NAME)));
3287     pa_tagstruct_putu32(t, s->module ? s->module->index : PA_INVALID_INDEX);
3288     pa_tagstruct_putu32(t, s->client ? s->client->index : PA_INVALID_INDEX);
3289     pa_tagstruct_putu32(t, s->sink->index);
3290     pa_tagstruct_put_sample_spec(t, &fixed_ss);
3291     pa_tagstruct_put_channel_map(t, &s->channel_map);
3292     pa_tagstruct_put_cvolume(t, &v);
3293     pa_tagstruct_put_usec(t, pa_sink_input_get_latency(s, &sink_latency));
3294     pa_tagstruct_put_usec(t, sink_latency);
3295     pa_tagstruct_puts(t, pa_resample_method_to_string(pa_sink_input_get_resample_method(s)));
3296     pa_tagstruct_puts(t, s->driver);
3297     if (c->version >= 11)
3298         pa_tagstruct_put_boolean(t, s->muted);
3299     if (c->version >= 13)
3300         pa_tagstruct_put_proplist(t, s->proplist);
3301     if (c->version >= 19)
3302         pa_tagstruct_put_boolean(t, s->state == PA_SINK_INPUT_CORKED);
3303     if (c->version >= 20) {
3304         pa_tagstruct_put_boolean(t, has_volume);
3305         pa_tagstruct_put_boolean(t, s->volume_writable);
3306     }
3307     if (c->version >= 21)
3308         pa_tagstruct_put_format_info(t, s->format);
3309 }
3310 
source_output_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_source_output *s)3311 static void source_output_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_source_output *s) {
3312     pa_sample_spec fixed_ss;
3313     pa_usec_t source_latency;
3314     pa_cvolume v;
3315     bool has_volume = false;
3316 
3317     pa_assert(t);
3318     pa_source_output_assert_ref(s);
3319 
3320     fixup_sample_spec(c, &fixed_ss, &s->sample_spec);
3321 
3322     has_volume = pa_source_output_is_volume_readable(s);
3323     if (has_volume)
3324         pa_source_output_get_volume(s, &v, true);
3325     else
3326         pa_cvolume_reset(&v, fixed_ss.channels);
3327 
3328     pa_tagstruct_putu32(t, s->index);
3329     pa_tagstruct_puts(t, pa_strnull(pa_proplist_gets(s->proplist, PA_PROP_MEDIA_NAME)));
3330     pa_tagstruct_putu32(t, s->module ? s->module->index : PA_INVALID_INDEX);
3331     pa_tagstruct_putu32(t, s->client ? s->client->index : PA_INVALID_INDEX);
3332     pa_tagstruct_putu32(t, s->source->index);
3333     pa_tagstruct_put_sample_spec(t, &fixed_ss);
3334     pa_tagstruct_put_channel_map(t, &s->channel_map);
3335     pa_tagstruct_put_usec(t, pa_source_output_get_latency(s, &source_latency));
3336     pa_tagstruct_put_usec(t, source_latency);
3337     pa_tagstruct_puts(t, pa_resample_method_to_string(pa_source_output_get_resample_method(s)));
3338     pa_tagstruct_puts(t, s->driver);
3339     if (c->version >= 13)
3340         pa_tagstruct_put_proplist(t, s->proplist);
3341     if (c->version >= 19)
3342         pa_tagstruct_put_boolean(t, s->state == PA_SOURCE_OUTPUT_CORKED);
3343     if (c->version >= 22) {
3344         pa_tagstruct_put_cvolume(t, &v);
3345         pa_tagstruct_put_boolean(t, s->muted);
3346         pa_tagstruct_put_boolean(t, has_volume);
3347         pa_tagstruct_put_boolean(t, s->volume_writable);
3348         pa_tagstruct_put_format_info(t, s->format);
3349     }
3350 }
3351 
scache_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_scache_entry *e)3352 static void scache_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_scache_entry *e) {
3353     pa_sample_spec fixed_ss;
3354     pa_cvolume v;
3355 
3356     pa_assert(t);
3357     pa_assert(e);
3358 
3359     if (e->memchunk.memblock)
3360         fixup_sample_spec(c, &fixed_ss, &e->sample_spec);
3361     else
3362         memset(&fixed_ss, 0, sizeof(fixed_ss));
3363 
3364     pa_tagstruct_putu32(t, e->index);
3365     pa_tagstruct_puts(t, e->name);
3366 
3367     if (e->volume_is_set)
3368         v = e->volume;
3369     else
3370         pa_cvolume_init(&v);
3371 
3372     pa_tagstruct_put_cvolume(t, &v);
3373     pa_tagstruct_put_usec(t, e->memchunk.memblock ? pa_bytes_to_usec(e->memchunk.length, &e->sample_spec) : 0);
3374     pa_tagstruct_put_sample_spec(t, &fixed_ss);
3375     pa_tagstruct_put_channel_map(t, &e->channel_map);
3376     pa_tagstruct_putu32(t, (uint32_t) e->memchunk.length);
3377     pa_tagstruct_put_boolean(t, e->lazy);
3378     pa_tagstruct_puts(t, e->filename);
3379 
3380     if (c->version >= 13)
3381         pa_tagstruct_put_proplist(t, e->proplist);
3382 }
3383 
command_get_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)3384 static void command_get_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3385     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3386     uint32_t idx;
3387     pa_sink *sink = NULL;
3388     pa_source *source = NULL;
3389     pa_client *client = NULL;
3390     pa_card *card = NULL;
3391     pa_module *module = NULL;
3392     pa_sink_input *si = NULL;
3393     pa_source_output *so = NULL;
3394     pa_scache_entry *sce = NULL;
3395     const char *name = NULL;
3396     pa_tagstruct *reply;
3397 
3398     pa_native_connection_assert_ref(c);
3399     pa_assert(t);
3400 
3401     if (pa_tagstruct_getu32(t, &idx) < 0 ||
3402         (command != PA_COMMAND_GET_CLIENT_INFO &&
3403          command != PA_COMMAND_GET_MODULE_INFO &&
3404          command != PA_COMMAND_GET_SINK_INPUT_INFO &&
3405          command != PA_COMMAND_GET_SOURCE_OUTPUT_INFO &&
3406          pa_tagstruct_gets(t, &name) < 0) ||
3407         !pa_tagstruct_eof(t)) {
3408         protocol_error(c);
3409         return;
3410     }
3411 
3412     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3413     CHECK_VALIDITY(c->pstream, !name ||
3414                    (command == PA_COMMAND_GET_SINK_INFO &&
3415                     pa_namereg_is_valid_name_or_wildcard(name, PA_NAMEREG_SINK)) ||
3416                    (command == PA_COMMAND_GET_SOURCE_INFO &&
3417                     pa_namereg_is_valid_name_or_wildcard(name, PA_NAMEREG_SOURCE)) ||
3418                    pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
3419     CHECK_VALIDITY(c->pstream, command == PA_COMMAND_GET_SINK_INFO ||
3420                    command == PA_COMMAND_GET_SOURCE_INFO ||
3421                    (idx != PA_INVALID_INDEX || name), tag, PA_ERR_INVALID);
3422     CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
3423 
3424     if (command == PA_COMMAND_GET_SINK_INFO) {
3425         if (idx != PA_INVALID_INDEX)
3426             sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
3427         else
3428             sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK);
3429     } else if (command == PA_COMMAND_GET_SOURCE_INFO) {
3430         if (idx != PA_INVALID_INDEX)
3431             source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
3432         else
3433             source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
3434     } else if (command == PA_COMMAND_GET_CARD_INFO) {
3435         if (idx != PA_INVALID_INDEX)
3436             card = pa_idxset_get_by_index(c->protocol->core->cards, idx);
3437         else
3438             card = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_CARD);
3439     } else if (command == PA_COMMAND_GET_CLIENT_INFO)
3440         client = pa_idxset_get_by_index(c->protocol->core->clients, idx);
3441     else if (command == PA_COMMAND_GET_MODULE_INFO)
3442         module = pa_idxset_get_by_index(c->protocol->core->modules, idx);
3443     else if (command == PA_COMMAND_GET_SINK_INPUT_INFO)
3444         si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
3445     else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO)
3446         so = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
3447     else {
3448         pa_assert(command == PA_COMMAND_GET_SAMPLE_INFO);
3449         if (idx != PA_INVALID_INDEX)
3450             sce = pa_idxset_get_by_index(c->protocol->core->scache, idx);
3451         else
3452             sce = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SAMPLE);
3453     }
3454 
3455     if (!sink && !source && !client && !card && !module && !si && !so && !sce) {
3456         pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
3457         return;
3458     }
3459 
3460     reply = reply_new(tag);
3461     if (sink)
3462         sink_fill_tagstruct(c, reply, sink);
3463     else if (source)
3464         source_fill_tagstruct(c, reply, source);
3465     else if (client)
3466         client_fill_tagstruct(c, reply, client);
3467     else if (card)
3468         card_fill_tagstruct(c, reply, card);
3469     else if (module)
3470         module_fill_tagstruct(c, reply, module);
3471     else if (si)
3472         sink_input_fill_tagstruct(c, reply, si);
3473     else if (so)
3474         source_output_fill_tagstruct(c, reply, so);
3475     else
3476         scache_fill_tagstruct(c, reply, sce);
3477     pa_pstream_send_tagstruct(c->pstream, reply);
3478 }
3479 
command_get_info_list(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)3480 static void command_get_info_list(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3481     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3482     pa_idxset *i;
3483     uint32_t idx;
3484     void *p;
3485     pa_tagstruct *reply;
3486 
3487     pa_native_connection_assert_ref(c);
3488     pa_assert(t);
3489 
3490     if (!pa_tagstruct_eof(t)) {
3491         protocol_error(c);
3492         return;
3493     }
3494 
3495     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3496 
3497     reply = reply_new(tag);
3498 
3499     if (command == PA_COMMAND_GET_SINK_INFO_LIST)
3500         i = c->protocol->core->sinks;
3501     else if (command == PA_COMMAND_GET_SOURCE_INFO_LIST)
3502         i = c->protocol->core->sources;
3503     else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST)
3504         i = c->protocol->core->clients;
3505     else if (command == PA_COMMAND_GET_CARD_INFO_LIST)
3506         i = c->protocol->core->cards;
3507     else if (command == PA_COMMAND_GET_MODULE_INFO_LIST)
3508         i = c->protocol->core->modules;
3509     else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST)
3510         i = c->protocol->core->sink_inputs;
3511     else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST)
3512         i = c->protocol->core->source_outputs;
3513     else {
3514         pa_assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST);
3515         i = c->protocol->core->scache;
3516     }
3517 
3518     if (i) {
3519         PA_IDXSET_FOREACH(p, i, idx) {
3520             if (command == PA_COMMAND_GET_SINK_INFO_LIST)
3521                 sink_fill_tagstruct(c, reply, p);
3522             else if (command == PA_COMMAND_GET_SOURCE_INFO_LIST)
3523                 source_fill_tagstruct(c, reply, p);
3524             else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST)
3525                 client_fill_tagstruct(c, reply, p);
3526             else if (command == PA_COMMAND_GET_CARD_INFO_LIST)
3527                 card_fill_tagstruct(c, reply, p);
3528             else if (command == PA_COMMAND_GET_MODULE_INFO_LIST)
3529                 module_fill_tagstruct(c, reply, p);
3530             else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST)
3531                 sink_input_fill_tagstruct(c, reply, p);
3532             else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST)
3533                 source_output_fill_tagstruct(c, reply, p);
3534             else {
3535                 pa_assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST);
3536                 scache_fill_tagstruct(c, reply, p);
3537             }
3538         }
3539     }
3540 
3541     pa_pstream_send_tagstruct(c->pstream, reply);
3542 }
3543 
command_get_server_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)3544 static void command_get_server_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3545     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3546     pa_tagstruct *reply;
3547     pa_sample_spec fixed_ss;
3548     char *h, *u;
3549     pa_core *core;
3550 
3551     pa_native_connection_assert_ref(c);
3552     pa_assert(t);
3553 
3554     if (!pa_tagstruct_eof(t)) {
3555         protocol_error(c);
3556         return;
3557     }
3558 
3559     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3560 
3561     reply = reply_new(tag);
3562     pa_tagstruct_puts(reply, PACKAGE_NAME);
3563     pa_tagstruct_puts(reply, PACKAGE_VERSION);
3564 
3565     u = pa_get_user_name_malloc();
3566     pa_tagstruct_puts(reply, u);
3567     pa_xfree(u);
3568 
3569     h = pa_get_host_name_malloc();
3570     pa_tagstruct_puts(reply, h);
3571     pa_xfree(h);
3572 
3573     core = c->protocol->core;
3574 
3575     fixup_sample_spec(c, &fixed_ss, &core->default_sample_spec);
3576     pa_tagstruct_put_sample_spec(reply, &fixed_ss);
3577 
3578     pa_tagstruct_puts(reply, core->default_sink ? core->default_sink->name : NULL);
3579     pa_tagstruct_puts(reply, core->default_source ? core->default_source->name : NULL);
3580 
3581     pa_tagstruct_putu32(reply, c->protocol->core->cookie);
3582 
3583     if (c->version >= 15)
3584         pa_tagstruct_put_channel_map(reply, &core->default_channel_map);
3585 
3586     pa_pstream_send_tagstruct(c->pstream, reply);
3587 }
3588 
subscription_cb(pa_core *core, pa_subscription_event_type_t e, uint32_t idx, void *userdata)3589 static void subscription_cb(pa_core *core, pa_subscription_event_type_t e, uint32_t idx, void *userdata) {
3590     pa_tagstruct *t;
3591     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3592 
3593     pa_native_connection_assert_ref(c);
3594 
3595     t = pa_tagstruct_new();
3596     pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE_EVENT);
3597     pa_tagstruct_putu32(t, (uint32_t) -1);
3598     pa_tagstruct_putu32(t, e);
3599     pa_tagstruct_putu32(t, idx);
3600     pa_pstream_send_tagstruct(c->pstream, t);
3601 }
3602 
command_subscribe(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)3603 static void command_subscribe(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3604     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3605     pa_subscription_mask_t m;
3606 
3607     pa_native_connection_assert_ref(c);
3608     pa_assert(t);
3609 
3610     if (pa_tagstruct_getu32(t, &m) < 0 ||
3611         !pa_tagstruct_eof(t)) {
3612         protocol_error(c);
3613         return;
3614     }
3615 
3616     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3617     CHECK_VALIDITY(c->pstream, (m & ~PA_SUBSCRIPTION_MASK_ALL) == 0, tag, PA_ERR_INVALID);
3618 
3619     if (c->subscription)
3620         pa_subscription_free(c->subscription);
3621 
3622     if (m != 0) {
3623         c->subscription = pa_subscription_new(c->protocol->core, m, subscription_cb, c);
3624         pa_assert(c->subscription);
3625     } else
3626         c->subscription = NULL;
3627 
3628     pa_pstream_send_simple_ack(c->pstream, tag);
3629 }
3630 
command_set_volume( pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)3631 static void command_set_volume(
3632         pa_pdispatch *pd,
3633         uint32_t command,
3634         uint32_t tag,
3635         pa_tagstruct *t,
3636         void *userdata) {
3637 
3638     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3639     uint32_t idx;
3640     pa_cvolume volume;
3641     pa_sink *sink = NULL;
3642     pa_source *source = NULL;
3643     pa_sink_input *si = NULL;
3644     pa_source_output *so = NULL;
3645     const char *name = NULL;
3646     const char *client_name;
3647 
3648     pa_native_connection_assert_ref(c);
3649     pa_assert(t);
3650 
3651     if (pa_tagstruct_getu32(t, &idx) < 0 ||
3652         (command == PA_COMMAND_SET_SINK_VOLUME && pa_tagstruct_gets(t, &name) < 0) ||
3653         (command == PA_COMMAND_SET_SOURCE_VOLUME && pa_tagstruct_gets(t, &name) < 0) ||
3654         pa_tagstruct_get_cvolume(t, &volume) ||
3655         !pa_tagstruct_eof(t)) {
3656         protocol_error(c);
3657         return;
3658     }
3659 
3660     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3661     CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name_or_wildcard(name, command == PA_COMMAND_SET_SINK_VOLUME ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE), tag, PA_ERR_INVALID);
3662     CHECK_VALIDITY(c->pstream, (idx != PA_INVALID_INDEX) ^ (name != NULL), tag, PA_ERR_INVALID);
3663     CHECK_VALIDITY(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID);
3664 
3665     switch (command) {
3666 
3667         case PA_COMMAND_SET_SINK_VOLUME:
3668             if (idx != PA_INVALID_INDEX)
3669                 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
3670             else
3671                 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK);
3672             break;
3673 
3674         case PA_COMMAND_SET_SOURCE_VOLUME:
3675             if (idx != PA_INVALID_INDEX)
3676                 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
3677             else
3678                 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
3679             break;
3680 
3681         case PA_COMMAND_SET_SINK_INPUT_VOLUME:
3682             si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
3683             break;
3684 
3685         case PA_COMMAND_SET_SOURCE_OUTPUT_VOLUME:
3686             so = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
3687             break;
3688 
3689         default:
3690             pa_assert_not_reached();
3691     }
3692 
3693     CHECK_VALIDITY(c->pstream, si || so || sink || source, tag, PA_ERR_NOENTITY);
3694 
3695     client_name = pa_strnull(pa_proplist_gets(c->client->proplist, PA_PROP_APPLICATION_PROCESS_BINARY));
3696 
3697     if (sink) {
3698         CHECK_VALIDITY(c->pstream, volume.channels == 1 || pa_cvolume_compatible(&volume, &sink->sample_spec), tag, PA_ERR_INVALID);
3699 
3700         pa_log_debug("Client %s changes volume of sink %s.", client_name, sink->name);
3701         pa_sink_set_volume(sink, &volume, true, true);
3702     } else if (source) {
3703         CHECK_VALIDITY(c->pstream, volume.channels == 1 || pa_cvolume_compatible(&volume, &source->sample_spec), tag, PA_ERR_INVALID);
3704 
3705         pa_log_debug("Client %s changes volume of source %s.", client_name, source->name);
3706         pa_source_set_volume(source, &volume, true, true);
3707     } else if (si) {
3708         CHECK_VALIDITY(c->pstream, si->volume_writable, tag, PA_ERR_BADSTATE);
3709         CHECK_VALIDITY(c->pstream, volume.channels == 1 || pa_cvolume_compatible(&volume, &si->sample_spec), tag, PA_ERR_INVALID);
3710 
3711         pa_log_debug("Client %s changes volume of sink input %s.",
3712                      client_name,
3713                      pa_strnull(pa_proplist_gets(si->proplist, PA_PROP_MEDIA_NAME)));
3714         pa_sink_input_set_volume(si, &volume, true, true);
3715     } else if (so) {
3716         CHECK_VALIDITY(c->pstream, so->volume_writable, tag, PA_ERR_BADSTATE);
3717         CHECK_VALIDITY(c->pstream, volume.channels == 1 || pa_cvolume_compatible(&volume, &so->sample_spec), tag, PA_ERR_INVALID);
3718 
3719         pa_log_debug("Client %s changes volume of source output %s.",
3720                      client_name,
3721                      pa_strnull(pa_proplist_gets(so->proplist, PA_PROP_MEDIA_NAME)));
3722         pa_source_output_set_volume(so, &volume, true, true);
3723     }
3724 
3725     pa_pstream_send_simple_ack(c->pstream, tag);
3726 }
3727 
command_set_mute( pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)3728 static void command_set_mute(
3729         pa_pdispatch *pd,
3730         uint32_t command,
3731         uint32_t tag,
3732         pa_tagstruct *t,
3733         void *userdata) {
3734 
3735     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3736     uint32_t idx;
3737     bool mute;
3738     pa_sink *sink = NULL;
3739     pa_source *source = NULL;
3740     pa_sink_input *si = NULL;
3741     pa_source_output *so = NULL;
3742     const char *name = NULL, *client_name;
3743 
3744     pa_native_connection_assert_ref(c);
3745     pa_assert(t);
3746 
3747     if (pa_tagstruct_getu32(t, &idx) < 0 ||
3748         (command == PA_COMMAND_SET_SINK_MUTE && pa_tagstruct_gets(t, &name) < 0) ||
3749         (command == PA_COMMAND_SET_SOURCE_MUTE && pa_tagstruct_gets(t, &name) < 0) ||
3750         pa_tagstruct_get_boolean(t, &mute) ||
3751         !pa_tagstruct_eof(t)) {
3752         protocol_error(c);
3753         return;
3754     }
3755 
3756     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3757     CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name_or_wildcard(name, command == PA_COMMAND_SET_SINK_MUTE ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE), tag, PA_ERR_INVALID);
3758     CHECK_VALIDITY(c->pstream, (idx != PA_INVALID_INDEX) ^ (name != NULL), tag, PA_ERR_INVALID);
3759 
3760     switch (command) {
3761 
3762         case PA_COMMAND_SET_SINK_MUTE:
3763             if (idx != PA_INVALID_INDEX)
3764                 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
3765             else
3766                 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK);
3767 
3768             break;
3769 
3770         case PA_COMMAND_SET_SOURCE_MUTE:
3771             if (idx != PA_INVALID_INDEX)
3772                 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
3773             else
3774                 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
3775 
3776             break;
3777 
3778         case PA_COMMAND_SET_SINK_INPUT_MUTE:
3779             si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
3780             break;
3781 
3782         case PA_COMMAND_SET_SOURCE_OUTPUT_MUTE:
3783             so = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
3784             break;
3785 
3786         default:
3787             pa_assert_not_reached();
3788     }
3789 
3790     CHECK_VALIDITY(c->pstream, si || so || sink || source, tag, PA_ERR_NOENTITY);
3791 
3792     client_name = pa_strnull(pa_proplist_gets(c->client->proplist, PA_PROP_APPLICATION_PROCESS_BINARY));
3793 
3794     if (sink) {
3795         pa_log_debug("Client %s changes mute of sink %s.", client_name, sink->name);
3796         pa_sink_set_mute(sink, mute, true);
3797     } else if (source) {
3798         pa_log_debug("Client %s changes mute of source %s.", client_name, source->name);
3799         pa_source_set_mute(source, mute, true);
3800     } else if (si) {
3801         pa_log_debug("Client %s changes mute of sink input %s.",
3802                      client_name,
3803                      pa_strnull(pa_proplist_gets(si->proplist, PA_PROP_MEDIA_NAME)));
3804         pa_sink_input_set_mute(si, mute, true);
3805     } else if (so) {
3806         pa_log_debug("Client %s changes mute of source output %s.",
3807                      client_name,
3808                      pa_strnull(pa_proplist_gets(so->proplist, PA_PROP_MEDIA_NAME)));
3809         pa_source_output_set_mute(so, mute, true);
3810     }
3811 
3812     pa_pstream_send_simple_ack(c->pstream, tag);
3813 }
3814 
command_cork_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)3815 static void command_cork_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3816     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3817     uint32_t idx;
3818     bool b;
3819     playback_stream *s;
3820 
3821     pa_native_connection_assert_ref(c);
3822     pa_assert(t);
3823 
3824     if (pa_tagstruct_getu32(t, &idx) < 0 ||
3825         pa_tagstruct_get_boolean(t, &b) < 0 ||
3826         !pa_tagstruct_eof(t)) {
3827         protocol_error(c);
3828         return;
3829     }
3830 
3831     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3832     CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
3833     s = pa_idxset_get_by_index(c->output_streams, idx);
3834     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3835     CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3836 
3837     pa_sink_input_cork(s->sink_input, b);
3838 
3839     if (b)
3840         s->is_underrun = true;
3841 
3842     pa_pstream_send_simple_ack(c->pstream, tag);
3843 }
3844 
command_trigger_or_flush_or_prebuf_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)3845 static void command_trigger_or_flush_or_prebuf_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3846     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3847     uint32_t idx;
3848     playback_stream *s;
3849 
3850     pa_native_connection_assert_ref(c);
3851     pa_assert(t);
3852 
3853     if (pa_tagstruct_getu32(t, &idx) < 0 ||
3854         !pa_tagstruct_eof(t)) {
3855         protocol_error(c);
3856         return;
3857     }
3858 
3859     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3860     CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
3861     s = pa_idxset_get_by_index(c->output_streams, idx);
3862     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3863     CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3864 
3865     switch (command) {
3866         case PA_COMMAND_FLUSH_PLAYBACK_STREAM:
3867             pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_FLUSH, NULL, 0, NULL);
3868             break;
3869 
3870         case PA_COMMAND_PREBUF_PLAYBACK_STREAM:
3871             pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_PREBUF_FORCE, NULL, 0, NULL);
3872             break;
3873 
3874         case PA_COMMAND_TRIGGER_PLAYBACK_STREAM:
3875             pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_TRIGGER, NULL, 0, NULL);
3876             break;
3877 
3878         default:
3879             pa_assert_not_reached();
3880     }
3881 
3882     pa_pstream_send_simple_ack(c->pstream, tag);
3883 }
3884 
command_cork_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)3885 static void command_cork_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3886     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3887     uint32_t idx;
3888     record_stream *s;
3889     bool b;
3890 
3891     pa_native_connection_assert_ref(c);
3892     pa_assert(t);
3893 
3894     if (pa_tagstruct_getu32(t, &idx) < 0 ||
3895         pa_tagstruct_get_boolean(t, &b) < 0 ||
3896         !pa_tagstruct_eof(t)) {
3897         protocol_error(c);
3898         return;
3899     }
3900 
3901     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3902     s = pa_idxset_get_by_index(c->record_streams, idx);
3903     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3904 
3905     pa_source_output_cork(s->source_output, b);
3906     pa_memblockq_prebuf_force(s->memblockq);
3907     pa_pstream_send_simple_ack(c->pstream, tag);
3908 }
3909 
command_flush_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)3910 static void command_flush_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3911     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3912     uint32_t idx;
3913     record_stream *s;
3914 
3915     pa_native_connection_assert_ref(c);
3916     pa_assert(t);
3917 
3918     if (pa_tagstruct_getu32(t, &idx) < 0 ||
3919         !pa_tagstruct_eof(t)) {
3920         protocol_error(c);
3921         return;
3922     }
3923 
3924     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3925     s = pa_idxset_get_by_index(c->record_streams, idx);
3926     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3927 
3928     pa_memblockq_flush_read(s->memblockq);
3929     pa_pstream_send_simple_ack(c->pstream, tag);
3930 }
3931 
command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)3932 static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3933     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3934     uint32_t idx;
3935     pa_buffer_attr a;
3936     pa_tagstruct *reply;
3937 
3938     pa_native_connection_assert_ref(c);
3939     pa_assert(t);
3940 
3941     memset(&a, 0, sizeof(a));
3942 
3943     if (pa_tagstruct_getu32(t, &idx) < 0) {
3944         protocol_error(c);
3945         return;
3946     }
3947 
3948     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3949 
3950     if (command == PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR) {
3951         playback_stream *s;
3952         bool adjust_latency = false, early_requests = false;
3953 
3954         s = pa_idxset_get_by_index(c->output_streams, idx);
3955         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3956         CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3957 
3958         if (pa_tagstruct_get(
3959                     t,
3960                     PA_TAG_U32, &a.maxlength,
3961                     PA_TAG_U32, &a.tlength,
3962                     PA_TAG_U32, &a.prebuf,
3963                     PA_TAG_U32, &a.minreq,
3964                     PA_TAG_INVALID) < 0 ||
3965             (c->version >= 13 && pa_tagstruct_get_boolean(t, &adjust_latency) < 0) ||
3966             (c->version >= 14 && pa_tagstruct_get_boolean(t, &early_requests) < 0) ||
3967             !pa_tagstruct_eof(t)) {
3968             protocol_error(c);
3969             return;
3970         }
3971 
3972         s->adjust_latency = adjust_latency;
3973         s->early_requests = early_requests;
3974         s->buffer_attr_req = a;
3975 
3976         fix_playback_buffer_attr(s);
3977         pa_assert_se(pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_UPDATE_BUFFER_ATTR, NULL, 0, NULL) == 0);
3978 
3979         reply = reply_new(tag);
3980         pa_tagstruct_putu32(reply, s->buffer_attr.maxlength);
3981         pa_tagstruct_putu32(reply, s->buffer_attr.tlength);
3982         pa_tagstruct_putu32(reply, s->buffer_attr.prebuf);
3983         pa_tagstruct_putu32(reply, s->buffer_attr.minreq);
3984 
3985         if (c->version >= 13)
3986             pa_tagstruct_put_usec(reply, s->configured_sink_latency);
3987 
3988     } else {
3989         record_stream *s;
3990         bool adjust_latency = false, early_requests = false;
3991         pa_assert(command == PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR);
3992 
3993         s = pa_idxset_get_by_index(c->record_streams, idx);
3994         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3995 
3996         if (pa_tagstruct_get(
3997                     t,
3998                     PA_TAG_U32, &a.maxlength,
3999                     PA_TAG_U32, &a.fragsize,
4000                     PA_TAG_INVALID) < 0 ||
4001             (c->version >= 13 && pa_tagstruct_get_boolean(t, &adjust_latency) < 0) ||
4002             (c->version >= 14 && pa_tagstruct_get_boolean(t, &early_requests) < 0) ||
4003             !pa_tagstruct_eof(t)) {
4004             protocol_error(c);
4005             return;
4006         }
4007 
4008         s->adjust_latency = adjust_latency;
4009         s->early_requests = early_requests;
4010         s->buffer_attr_req = a;
4011 
4012         fix_record_buffer_attr_pre(s);
4013         pa_memblockq_set_maxlength(s->memblockq, s->buffer_attr.maxlength);
4014         pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
4015         fix_record_buffer_attr_post(s);
4016 
4017         reply = reply_new(tag);
4018         pa_tagstruct_putu32(reply, s->buffer_attr.maxlength);
4019         pa_tagstruct_putu32(reply, s->buffer_attr.fragsize);
4020 
4021         if (c->version >= 13)
4022             pa_tagstruct_put_usec(reply, s->configured_source_latency);
4023     }
4024 
4025     pa_pstream_send_tagstruct(c->pstream, reply);
4026 }
4027 
command_update_stream_sample_rate(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)4028 static void command_update_stream_sample_rate(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4029     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4030     uint32_t idx;
4031     uint32_t rate;
4032 
4033     pa_native_connection_assert_ref(c);
4034     pa_assert(t);
4035 
4036     if (pa_tagstruct_getu32(t, &idx) < 0 ||
4037         pa_tagstruct_getu32(t, &rate) < 0 ||
4038         !pa_tagstruct_eof(t)) {
4039         protocol_error(c);
4040         return;
4041     }
4042 
4043     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4044     CHECK_VALIDITY(c->pstream, pa_sample_rate_valid(rate), tag, PA_ERR_INVALID);
4045 
4046     if (command == PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE) {
4047         playback_stream *s;
4048 
4049         s = pa_idxset_get_by_index(c->output_streams, idx);
4050         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
4051         CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
4052 
4053         pa_sink_input_set_rate(s->sink_input, rate);
4054 
4055     } else {
4056         record_stream *s;
4057         pa_assert(command == PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE);
4058 
4059         s = pa_idxset_get_by_index(c->record_streams, idx);
4060         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
4061 
4062         pa_source_output_set_rate(s->source_output, rate);
4063     }
4064 
4065     pa_pstream_send_simple_ack(c->pstream, tag);
4066 }
4067 
command_update_proplist(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)4068 static void command_update_proplist(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4069     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4070     uint32_t idx;
4071     uint32_t mode;
4072     pa_proplist *p;
4073 
4074     pa_native_connection_assert_ref(c);
4075     pa_assert(t);
4076 
4077     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4078 
4079     p = pa_proplist_new();
4080 
4081     if (command == PA_COMMAND_UPDATE_CLIENT_PROPLIST) {
4082 
4083         if (pa_tagstruct_getu32(t, &mode) < 0 ||
4084             pa_tagstruct_get_proplist(t, p) < 0 ||
4085             !pa_tagstruct_eof(t)) {
4086             protocol_error(c);
4087             pa_proplist_free(p);
4088             return;
4089         }
4090 
4091     } else {
4092 
4093         if (pa_tagstruct_getu32(t, &idx) < 0 ||
4094             pa_tagstruct_getu32(t, &mode) < 0 ||
4095             pa_tagstruct_get_proplist(t, p) < 0 ||
4096             !pa_tagstruct_eof(t)) {
4097             protocol_error(c);
4098             pa_proplist_free(p);
4099             return;
4100         }
4101     }
4102 
4103     if (!(mode == PA_UPDATE_SET || mode == PA_UPDATE_MERGE || mode == PA_UPDATE_REPLACE)) {
4104         pa_proplist_free(p);
4105         CHECK_VALIDITY(c->pstream, false, tag, PA_ERR_INVALID);
4106     }
4107 
4108     if (command == PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST) {
4109         playback_stream *s;
4110 
4111         s = pa_idxset_get_by_index(c->output_streams, idx);
4112         if (!s || !playback_stream_isinstance(s)) {
4113             pa_proplist_free(p);
4114             CHECK_VALIDITY(c->pstream, false, tag, PA_ERR_NOENTITY);
4115         }
4116         pa_sink_input_update_proplist(s->sink_input, mode, p);
4117 
4118     } else if (command == PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST) {
4119         record_stream *s;
4120 
4121         if (!(s = pa_idxset_get_by_index(c->record_streams, idx))) {
4122             pa_proplist_free(p);
4123             CHECK_VALIDITY(c->pstream, false, tag, PA_ERR_NOENTITY);
4124         }
4125         pa_source_output_update_proplist(s->source_output, mode, p);
4126 
4127     } else {
4128         pa_assert(command == PA_COMMAND_UPDATE_CLIENT_PROPLIST);
4129 
4130         pa_client_update_proplist(c->client, mode, p);
4131     }
4132 
4133     pa_pstream_send_simple_ack(c->pstream, tag);
4134     pa_proplist_free(p);
4135 }
4136 
command_remove_proplist(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)4137 static void command_remove_proplist(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4138     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4139     uint32_t idx;
4140     unsigned changed = 0;
4141     pa_proplist *p;
4142     pa_strlist *l = NULL;
4143 
4144     pa_native_connection_assert_ref(c);
4145     pa_assert(t);
4146 
4147     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4148 
4149     if (command != PA_COMMAND_REMOVE_CLIENT_PROPLIST) {
4150 
4151         if (pa_tagstruct_getu32(t, &idx) < 0) {
4152             protocol_error(c);
4153             return;
4154         }
4155     }
4156 
4157     if (command == PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST) {
4158         playback_stream *s;
4159 
4160         s = pa_idxset_get_by_index(c->output_streams, idx);
4161         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
4162         CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
4163 
4164         p = s->sink_input->proplist;
4165 
4166     } else if (command == PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST) {
4167         record_stream *s;
4168 
4169         s = pa_idxset_get_by_index(c->record_streams, idx);
4170         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
4171 
4172         p = s->source_output->proplist;
4173     } else {
4174         pa_assert(command == PA_COMMAND_REMOVE_CLIENT_PROPLIST);
4175 
4176         p = c->client->proplist;
4177     }
4178 
4179     for (;;) {
4180         const char *k;
4181 
4182         if (pa_tagstruct_gets(t, &k) < 0) {
4183             protocol_error(c);
4184             pa_strlist_free(l);
4185             return;
4186         }
4187 
4188         if (!k)
4189             break;
4190 
4191         l = pa_strlist_prepend(l, k);
4192     }
4193 
4194     if (!pa_tagstruct_eof(t)) {
4195         protocol_error(c);
4196         pa_strlist_free(l);
4197         return;
4198     }
4199 
4200     for (;;) {
4201         char *z;
4202 
4203         l = pa_strlist_pop(l, &z);
4204 
4205         if (!z)
4206             break;
4207 
4208         changed += (unsigned) (pa_proplist_unset(p, z) >= 0);
4209         pa_xfree(z);
4210     }
4211 
4212     pa_pstream_send_simple_ack(c->pstream, tag);
4213 
4214     if (changed) {
4215         if (command == PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST) {
4216             playback_stream *s;
4217 
4218             s = pa_idxset_get_by_index(c->output_streams, idx);
4219             pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, s->sink_input->index);
4220 
4221         } else if (command == PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST) {
4222             record_stream *s;
4223 
4224             s = pa_idxset_get_by_index(c->record_streams, idx);
4225             pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, s->source_output->index);
4226 
4227         } else {
4228             pa_assert(command == PA_COMMAND_REMOVE_CLIENT_PROPLIST);
4229             pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_CHANGE, c->client->index);
4230         }
4231     }
4232 }
4233 
command_set_default_sink_or_source(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)4234 static void command_set_default_sink_or_source(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4235     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4236     const char *s;
4237 
4238     pa_native_connection_assert_ref(c);
4239     pa_assert(t);
4240 
4241     if (pa_tagstruct_gets(t, &s) < 0 ||
4242         !pa_tagstruct_eof(t)) {
4243         protocol_error(c);
4244         return;
4245     }
4246 
4247     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4248     CHECK_VALIDITY(c->pstream, !s || pa_namereg_is_valid_name(s), tag, PA_ERR_INVALID);
4249 
4250     if (command == PA_COMMAND_SET_DEFAULT_SOURCE) {
4251         pa_source *source;
4252 
4253         source = pa_namereg_get(c->protocol->core, s, PA_NAMEREG_SOURCE);
4254         CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY);
4255 
4256         pa_core_set_configured_default_source(c->protocol->core, source->name);
4257     } else {
4258         pa_sink *sink;
4259         pa_assert(command == PA_COMMAND_SET_DEFAULT_SINK);
4260 
4261         sink = pa_namereg_get(c->protocol->core, s, PA_NAMEREG_SINK);
4262         CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
4263 
4264         pa_core_set_configured_default_sink(c->protocol->core, sink->name);
4265     }
4266 
4267     pa_pstream_send_simple_ack(c->pstream, tag);
4268 }
4269 
command_set_stream_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)4270 static void command_set_stream_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4271     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4272     uint32_t idx;
4273     const char *name;
4274 
4275     pa_native_connection_assert_ref(c);
4276     pa_assert(t);
4277 
4278     if (pa_tagstruct_getu32(t, &idx) < 0 ||
4279         pa_tagstruct_gets(t, &name) < 0 ||
4280         !pa_tagstruct_eof(t)) {
4281         protocol_error(c);
4282         return;
4283     }
4284 
4285     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4286     CHECK_VALIDITY(c->pstream, name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
4287 
4288     if (command == PA_COMMAND_SET_PLAYBACK_STREAM_NAME) {
4289         playback_stream *s;
4290 
4291         s = pa_idxset_get_by_index(c->output_streams, idx);
4292         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
4293         CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
4294 
4295         pa_sink_input_set_property(s->sink_input, PA_PROP_MEDIA_NAME, name);
4296 
4297     } else {
4298         record_stream *s;
4299         pa_assert(command == PA_COMMAND_SET_RECORD_STREAM_NAME);
4300 
4301         s = pa_idxset_get_by_index(c->record_streams, idx);
4302         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
4303 
4304         pa_source_output_set_property(s->source_output, PA_PROP_MEDIA_NAME, name);
4305     }
4306 
4307     pa_pstream_send_simple_ack(c->pstream, tag);
4308 }
4309 
command_kill(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)4310 static void command_kill(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4311     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4312     uint32_t idx;
4313 
4314     pa_native_connection_assert_ref(c);
4315     pa_assert(t);
4316 
4317     if (pa_tagstruct_getu32(t, &idx) < 0 ||
4318         !pa_tagstruct_eof(t)) {
4319         protocol_error(c);
4320         return;
4321     }
4322 
4323     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4324 
4325     if (command == PA_COMMAND_KILL_CLIENT) {
4326         pa_client *client;
4327 
4328         client = pa_idxset_get_by_index(c->protocol->core->clients, idx);
4329         CHECK_VALIDITY(c->pstream, client, tag, PA_ERR_NOENTITY);
4330 
4331         pa_native_connection_ref(c);
4332         pa_client_kill(client);
4333 
4334     } else if (command == PA_COMMAND_KILL_SINK_INPUT) {
4335         pa_sink_input *s;
4336 
4337         s = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
4338         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
4339 
4340         pa_native_connection_ref(c);
4341         pa_sink_input_kill(s);
4342     } else {
4343         pa_source_output *s;
4344 
4345         pa_assert(command == PA_COMMAND_KILL_SOURCE_OUTPUT);
4346 
4347         s = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
4348         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
4349 
4350         pa_native_connection_ref(c);
4351         pa_source_output_kill(s);
4352     }
4353 
4354     pa_pstream_send_simple_ack(c->pstream, tag);
4355     pa_native_connection_unref(c);
4356 }
4357 
command_load_module(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)4358 static void command_load_module(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4359     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4360     pa_module *m;
4361     const char *name, *argument;
4362     pa_tagstruct *reply;
4363 
4364     pa_native_connection_assert_ref(c);
4365     pa_assert(t);
4366 
4367     if (pa_tagstruct_gets(t, &name) < 0 ||
4368         pa_tagstruct_gets(t, &argument) < 0 ||
4369         !pa_tagstruct_eof(t)) {
4370         protocol_error(c);
4371         return;
4372     }
4373 
4374     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4375     CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name) && !strchr(name, '/'), tag, PA_ERR_INVALID);
4376     CHECK_VALIDITY(c->pstream, !argument || pa_utf8_valid(argument), tag, PA_ERR_INVALID);
4377 
4378     if (pa_module_load(&m, c->protocol->core, name, argument) < 0) {
4379         pa_pstream_send_error(c->pstream, tag, PA_ERR_MODINITFAILED);
4380         return;
4381     }
4382 
4383     reply = reply_new(tag);
4384     pa_tagstruct_putu32(reply, m->index);
4385     pa_pstream_send_tagstruct(c->pstream, reply);
4386 }
4387 
command_unload_module(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)4388 static void command_unload_module(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4389     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4390     uint32_t idx;
4391     pa_module *m;
4392 
4393     pa_native_connection_assert_ref(c);
4394     pa_assert(t);
4395 
4396     if (pa_tagstruct_getu32(t, &idx) < 0 ||
4397         !pa_tagstruct_eof(t)) {
4398         protocol_error(c);
4399         return;
4400     }
4401 
4402     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4403     m = pa_idxset_get_by_index(c->protocol->core->modules, idx);
4404     CHECK_VALIDITY(c->pstream, m, tag, PA_ERR_NOENTITY);
4405 
4406     pa_module_unload_request(m, false);
4407     pa_pstream_send_simple_ack(c->pstream, tag);
4408 }
4409 
command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)4410 static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4411     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4412     uint32_t idx = PA_INVALID_INDEX, idx_device = PA_INVALID_INDEX;
4413     const char *name_device = NULL;
4414 
4415     pa_native_connection_assert_ref(c);
4416     pa_assert(t);
4417 
4418     if (pa_tagstruct_getu32(t, &idx) < 0 ||
4419         pa_tagstruct_getu32(t, &idx_device) < 0 ||
4420         pa_tagstruct_gets(t, &name_device) < 0 ||
4421         !pa_tagstruct_eof(t)) {
4422         protocol_error(c);
4423         return;
4424     }
4425 
4426     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4427     CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4428 
4429     CHECK_VALIDITY(c->pstream, !name_device || pa_namereg_is_valid_name_or_wildcard(name_device, command == PA_COMMAND_MOVE_SINK_INPUT ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE), tag, PA_ERR_INVALID);
4430     CHECK_VALIDITY(c->pstream, (idx_device != PA_INVALID_INDEX) ^ (name_device != NULL), tag, PA_ERR_INVALID);
4431 
4432     if (command == PA_COMMAND_MOVE_SINK_INPUT) {
4433         pa_sink_input *si = NULL;
4434         pa_sink *sink = NULL;
4435 
4436         si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
4437 
4438         if (idx_device != PA_INVALID_INDEX)
4439             sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx_device);
4440         else
4441             sink = pa_namereg_get(c->protocol->core, name_device, PA_NAMEREG_SINK);
4442 
4443         CHECK_VALIDITY(c->pstream, si && sink, tag, PA_ERR_NOENTITY);
4444 
4445         if (pa_sink_input_move_to(si, sink, true) < 0) {
4446             pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4447             return;
4448         }
4449     } else {
4450         pa_source_output *so = NULL;
4451         pa_source *source;
4452 
4453         pa_assert(command == PA_COMMAND_MOVE_SOURCE_OUTPUT);
4454 
4455         so = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
4456 
4457         if (idx_device != PA_INVALID_INDEX)
4458             source = pa_idxset_get_by_index(c->protocol->core->sources, idx_device);
4459         else
4460             source = pa_namereg_get(c->protocol->core, name_device, PA_NAMEREG_SOURCE);
4461 
4462         CHECK_VALIDITY(c->pstream, so && source, tag, PA_ERR_NOENTITY);
4463 
4464         if (pa_source_output_move_to(so, source, true) < 0) {
4465             pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4466             return;
4467         }
4468     }
4469 
4470     pa_pstream_send_simple_ack(c->pstream, tag);
4471 }
4472 
command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)4473 static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4474     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4475     uint32_t idx = PA_INVALID_INDEX;
4476     const char *name = NULL;
4477     bool b;
4478 
4479     pa_native_connection_assert_ref(c);
4480     pa_assert(t);
4481 
4482     if (pa_tagstruct_getu32(t, &idx) < 0 ||
4483         pa_tagstruct_gets(t, &name) < 0 ||
4484         pa_tagstruct_get_boolean(t, &b) < 0 ||
4485         !pa_tagstruct_eof(t)) {
4486         protocol_error(c);
4487         return;
4488     }
4489 
4490     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4491     CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name_or_wildcard(name, command == PA_COMMAND_SUSPEND_SINK ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE) || *name == 0, tag, PA_ERR_INVALID);
4492     CHECK_VALIDITY(c->pstream, (idx != PA_INVALID_INDEX) ^ (name != NULL), tag, PA_ERR_INVALID);
4493 
4494     if (command == PA_COMMAND_SUSPEND_SINK) {
4495 
4496         if (idx == PA_INVALID_INDEX && name && !*name) {
4497 
4498             pa_log_debug("%s all sinks", b ? "Suspending" : "Resuming");
4499 
4500             if (pa_sink_suspend_all(c->protocol->core, b, PA_SUSPEND_USER) < 0) {
4501                 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4502                 return;
4503             }
4504         } else {
4505             pa_sink *sink = NULL;
4506 
4507             if (idx != PA_INVALID_INDEX)
4508                 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
4509             else
4510                 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK);
4511 
4512             CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
4513 
4514             pa_log_debug("%s of sink %s requested by client %" PRIu32 ".",
4515                          b ? "Suspending" : "Resuming", sink->name, c->client->index);
4516 
4517             if (pa_sink_suspend(sink, b, PA_SUSPEND_USER) < 0) {
4518                 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4519                 return;
4520             }
4521         }
4522     } else {
4523 
4524         pa_assert(command == PA_COMMAND_SUSPEND_SOURCE);
4525 
4526         if (idx == PA_INVALID_INDEX && name && !*name) {
4527 
4528             pa_log_debug("%s all sources", b ? "Suspending" : "Resuming");
4529 
4530             if (pa_source_suspend_all(c->protocol->core, b, PA_SUSPEND_USER) < 0) {
4531                 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4532                 return;
4533             }
4534 
4535         } else {
4536             pa_source *source;
4537 
4538             if (idx != PA_INVALID_INDEX)
4539                 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
4540             else
4541                 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
4542 
4543             CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY);
4544 
4545             pa_log_debug("%s of source %s requested by client %" PRIu32 ".",
4546                          b ? "Suspending" : "Resuming", source->name, c->client->index);
4547 
4548             if (pa_source_suspend(source, b, PA_SUSPEND_USER) < 0) {
4549                 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4550                 return;
4551             }
4552         }
4553     }
4554 
4555     pa_pstream_send_simple_ack(c->pstream, tag);
4556 }
4557 
command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)4558 static void command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4559     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4560     uint32_t idx = PA_INVALID_INDEX;
4561     const char *name = NULL;
4562     pa_module *m;
4563     pa_native_protocol_ext_cb_t cb;
4564 
4565     pa_native_connection_assert_ref(c);
4566     pa_assert(t);
4567 
4568     if (pa_tagstruct_getu32(t, &idx) < 0 ||
4569         pa_tagstruct_gets(t, &name) < 0) {
4570         protocol_error(c);
4571         return;
4572     }
4573 
4574     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4575     CHECK_VALIDITY(c->pstream, !name || pa_utf8_valid(name), tag, PA_ERR_INVALID);
4576     CHECK_VALIDITY(c->pstream, (idx != PA_INVALID_INDEX) ^ (name != NULL), tag, PA_ERR_INVALID);
4577 
4578     if (idx != PA_INVALID_INDEX)
4579         m = pa_idxset_get_by_index(c->protocol->core->modules, idx);
4580     else
4581         PA_IDXSET_FOREACH(m, c->protocol->core->modules, idx)
4582             if (pa_streq(name, m->name))
4583                 break;
4584 
4585     CHECK_VALIDITY(c->pstream, m, tag, PA_ERR_NOEXTENSION);
4586     CHECK_VALIDITY(c->pstream, m->load_once || idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4587 
4588     cb = pa_hashmap_get(c->protocol->extensions, m);
4589     CHECK_VALIDITY(c->pstream, cb, tag, PA_ERR_NOEXTENSION);
4590 
4591     if (cb(c->protocol, m, c, tag, t) < 0)
4592         protocol_error(c);
4593 }
4594 
4595 /* Send message to an object which registered a handler. Result must be returned as string. */
command_send_object_message(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)4596 static void command_send_object_message(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4597     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4598     const char *object_path = NULL;
4599     const char *message = NULL;
4600     const char *message_parameters = NULL;
4601     const char *client_name;
4602     char *response = NULL;
4603     int ret;
4604     pa_tagstruct *reply;
4605 
4606     pa_native_connection_assert_ref(c);
4607     pa_assert(t);
4608 
4609     if (pa_tagstruct_gets(t, &object_path) < 0 ||
4610         pa_tagstruct_gets(t, &message) < 0 ||
4611         pa_tagstruct_gets(t, &message_parameters) < 0 ||
4612         !pa_tagstruct_eof(t)) {
4613         protocol_error(c);
4614         return;
4615     }
4616 
4617     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4618     CHECK_VALIDITY(c->pstream, object_path != NULL, tag, PA_ERR_INVALID);
4619     CHECK_VALIDITY(c->pstream, pa_utf8_valid(object_path), tag, PA_ERR_INVALID);
4620     CHECK_VALIDITY(c->pstream, message != NULL, tag, PA_ERR_INVALID);
4621     CHECK_VALIDITY(c->pstream, pa_utf8_valid(message), tag, PA_ERR_INVALID);
4622     if (message_parameters)
4623         CHECK_VALIDITY(c->pstream, pa_utf8_valid(message_parameters), tag, PA_ERR_INVALID);
4624 
4625     client_name = pa_strnull(pa_proplist_gets(c->client->proplist, PA_PROP_APPLICATION_PROCESS_BINARY));
4626     pa_log_debug("Client %s sent message %s to path %s", client_name, message, object_path);
4627     if (message_parameters)
4628         pa_log_debug("Message parameters: %s", message_parameters);
4629 
4630     ret = pa_message_handler_send_message(c->protocol->core, object_path, message, message_parameters, &response);
4631 
4632     if (ret < 0) {
4633         pa_pstream_send_error(c->pstream, tag, -ret);
4634         return;
4635     }
4636 
4637     reply = reply_new(tag);
4638     pa_tagstruct_puts(reply, response);
4639     pa_xfree(response);
4640 
4641     pa_pstream_send_tagstruct(c->pstream, reply);
4642 }
4643 
command_set_card_profile(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)4644 static void command_set_card_profile(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4645     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4646     uint32_t idx = PA_INVALID_INDEX;
4647     const char *name = NULL, *profile_name = NULL;
4648     pa_card *card = NULL;
4649     pa_card_profile *profile;
4650     int ret;
4651 
4652     pa_native_connection_assert_ref(c);
4653     pa_assert(t);
4654 
4655     if (pa_tagstruct_getu32(t, &idx) < 0 ||
4656         pa_tagstruct_gets(t, &name) < 0 ||
4657         pa_tagstruct_gets(t, &profile_name) < 0 ||
4658         !pa_tagstruct_eof(t)) {
4659         protocol_error(c);
4660         return;
4661     }
4662 
4663     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4664     CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
4665     CHECK_VALIDITY(c->pstream, (idx != PA_INVALID_INDEX) ^ (name != NULL), tag, PA_ERR_INVALID);
4666     CHECK_VALIDITY(c->pstream, profile_name, tag, PA_ERR_INVALID);
4667 
4668     if (idx != PA_INVALID_INDEX)
4669         card = pa_idxset_get_by_index(c->protocol->core->cards, idx);
4670     else
4671         card = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_CARD);
4672 
4673     CHECK_VALIDITY(c->pstream, card, tag, PA_ERR_NOENTITY);
4674 
4675     profile = pa_hashmap_get(card->profiles, profile_name);
4676 
4677     CHECK_VALIDITY(c->pstream, profile, tag, PA_ERR_NOENTITY);
4678 
4679     pa_log_info("Application \"%s\" requests card profile change. card = %s, profile = %s",
4680                 pa_strnull(pa_proplist_gets(c->client->proplist, PA_PROP_APPLICATION_NAME)),
4681                 card->name,
4682                 profile->name);
4683 
4684     if ((ret = pa_card_set_profile(card, profile, true)) < 0) {
4685         pa_pstream_send_error(c->pstream, tag, -ret);
4686         return;
4687     }
4688 
4689     pa_pstream_send_simple_ack(c->pstream, tag);
4690 }
4691 
command_set_sink_or_source_port(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)4692 static void command_set_sink_or_source_port(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4693     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4694     uint32_t idx = PA_INVALID_INDEX;
4695     const char *name = NULL, *port = NULL;
4696     int ret;
4697 
4698     pa_native_connection_assert_ref(c);
4699     pa_assert(t);
4700 
4701     if (pa_tagstruct_getu32(t, &idx) < 0 ||
4702         pa_tagstruct_gets(t, &name) < 0 ||
4703         pa_tagstruct_gets(t, &port) < 0 ||
4704         !pa_tagstruct_eof(t)) {
4705         protocol_error(c);
4706         return;
4707     }
4708 
4709     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4710     CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name_or_wildcard(name, command == PA_COMMAND_SET_SINK_PORT ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE), tag, PA_ERR_INVALID);
4711     CHECK_VALIDITY(c->pstream, (idx != PA_INVALID_INDEX) ^ (name != NULL), tag, PA_ERR_INVALID);
4712     CHECK_VALIDITY(c->pstream, port, tag, PA_ERR_INVALID);
4713 
4714     if (command == PA_COMMAND_SET_SINK_PORT) {
4715         pa_sink *sink;
4716 
4717         if (idx != PA_INVALID_INDEX)
4718             sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
4719         else
4720             sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK);
4721 
4722         CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
4723 
4724         if ((ret = pa_sink_set_port(sink, port, true)) < 0) {
4725             pa_pstream_send_error(c->pstream, tag, -ret);
4726             return;
4727         }
4728     } else {
4729         pa_source *source;
4730 
4731         pa_assert(command == PA_COMMAND_SET_SOURCE_PORT);
4732 
4733         if (idx != PA_INVALID_INDEX)
4734             source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
4735         else
4736             source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
4737 
4738         CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY);
4739 
4740         if ((ret = pa_source_set_port(source, port, true)) < 0) {
4741             pa_pstream_send_error(c->pstream, tag, -ret);
4742             return;
4743         }
4744     }
4745 
4746     pa_pstream_send_simple_ack(c->pstream, tag);
4747 }
4748 
command_set_port_latency_offset(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata)4749 static void command_set_port_latency_offset(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4750     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4751     const char *port_name, *card_name;
4752     uint32_t idx = PA_INVALID_INDEX;
4753     int64_t offset;
4754     pa_card *card = NULL;
4755     pa_device_port *port = NULL;
4756 
4757     pa_native_connection_assert_ref(c);
4758     pa_assert(t);
4759 
4760     if (pa_tagstruct_getu32(t, &idx) < 0 ||
4761         pa_tagstruct_gets(t, &card_name) < 0 ||
4762         pa_tagstruct_gets(t, &port_name) < 0 ||
4763         pa_tagstruct_gets64(t, &offset) < 0 ||
4764         !pa_tagstruct_eof(t)) {
4765         protocol_error(c);
4766         return;
4767     }
4768 
4769     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4770     CHECK_VALIDITY(c->pstream, !card_name || pa_namereg_is_valid_name(card_name), tag, PA_ERR_INVALID);
4771     CHECK_VALIDITY(c->pstream, (idx != PA_INVALID_INDEX) ^ (card_name != NULL), tag, PA_ERR_INVALID);
4772     CHECK_VALIDITY(c->pstream, port_name, tag, PA_ERR_INVALID);
4773 
4774     if (idx != PA_INVALID_INDEX)
4775         card = pa_idxset_get_by_index(c->protocol->core->cards, idx);
4776     else
4777         card = pa_namereg_get(c->protocol->core, card_name, PA_NAMEREG_CARD);
4778 
4779     CHECK_VALIDITY(c->pstream, card, tag, PA_ERR_NOENTITY);
4780 
4781     port = pa_hashmap_get(card->ports, port_name);
4782     CHECK_VALIDITY(c->pstream, port, tag, PA_ERR_NOENTITY);
4783 
4784     pa_device_port_set_latency_offset(port, offset);
4785 
4786     pa_pstream_send_simple_ack(c->pstream, tag);
4787 }
4788 
4789 static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
4790     [PA_COMMAND_ERROR] = NULL,
4791     [PA_COMMAND_TIMEOUT] = NULL,
4792     [PA_COMMAND_REPLY] = NULL,
4793     [PA_COMMAND_CREATE_PLAYBACK_STREAM] = command_create_playback_stream,
4794     [PA_COMMAND_DELETE_PLAYBACK_STREAM] = command_delete_stream,
4795     [PA_COMMAND_DRAIN_PLAYBACK_STREAM] = command_drain_playback_stream,
4796     [PA_COMMAND_CREATE_RECORD_STREAM] = command_create_record_stream,
4797     [PA_COMMAND_DELETE_RECORD_STREAM] = command_delete_stream,
4798     [PA_COMMAND_AUTH] = command_auth,
4799     [PA_COMMAND_REQUEST] = NULL,
4800     [PA_COMMAND_EXIT] = command_exit,
4801     [PA_COMMAND_SET_CLIENT_NAME] = command_set_client_name,
4802     [PA_COMMAND_LOOKUP_SINK] = command_lookup,
4803     [PA_COMMAND_LOOKUP_SOURCE] = command_lookup,
4804     [PA_COMMAND_STAT] = command_stat,
4805     [PA_COMMAND_GET_PLAYBACK_LATENCY] = command_get_playback_latency,
4806     [PA_COMMAND_GET_RECORD_LATENCY] = command_get_record_latency,
4807     [PA_COMMAND_CREATE_UPLOAD_STREAM] = command_create_upload_stream,
4808     [PA_COMMAND_DELETE_UPLOAD_STREAM] = command_delete_stream,
4809     [PA_COMMAND_FINISH_UPLOAD_STREAM] = command_finish_upload_stream,
4810     [PA_COMMAND_PLAY_SAMPLE] = command_play_sample,
4811     [PA_COMMAND_REMOVE_SAMPLE] = command_remove_sample,
4812     [PA_COMMAND_GET_SINK_INFO] = command_get_info,
4813     [PA_COMMAND_GET_SOURCE_INFO] = command_get_info,
4814     [PA_COMMAND_GET_CLIENT_INFO] = command_get_info,
4815     [PA_COMMAND_GET_CARD_INFO] = command_get_info,
4816     [PA_COMMAND_GET_MODULE_INFO] = command_get_info,
4817     [PA_COMMAND_GET_SINK_INPUT_INFO] = command_get_info,
4818     [PA_COMMAND_GET_SOURCE_OUTPUT_INFO] = command_get_info,
4819     [PA_COMMAND_GET_SAMPLE_INFO] = command_get_info,
4820     [PA_COMMAND_GET_SINK_INFO_LIST] = command_get_info_list,
4821     [PA_COMMAND_GET_SOURCE_INFO_LIST] = command_get_info_list,
4822     [PA_COMMAND_GET_MODULE_INFO_LIST] = command_get_info_list,
4823     [PA_COMMAND_GET_CLIENT_INFO_LIST] = command_get_info_list,
4824     [PA_COMMAND_GET_CARD_INFO_LIST] = command_get_info_list,
4825     [PA_COMMAND_GET_SINK_INPUT_INFO_LIST] = command_get_info_list,
4826     [PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST] = command_get_info_list,
4827     [PA_COMMAND_GET_SAMPLE_INFO_LIST] = command_get_info_list,
4828     [PA_COMMAND_GET_SERVER_INFO] = command_get_server_info,
4829     [PA_COMMAND_SUBSCRIBE] = command_subscribe,
4830 
4831     [PA_COMMAND_SET_SINK_VOLUME] = command_set_volume,
4832     [PA_COMMAND_SET_SINK_INPUT_VOLUME] = command_set_volume,
4833     [PA_COMMAND_SET_SOURCE_VOLUME] = command_set_volume,
4834     [PA_COMMAND_SET_SOURCE_OUTPUT_VOLUME] = command_set_volume,
4835 
4836     [PA_COMMAND_SET_SINK_MUTE] = command_set_mute,
4837     [PA_COMMAND_SET_SINK_INPUT_MUTE] = command_set_mute,
4838     [PA_COMMAND_SET_SOURCE_MUTE] = command_set_mute,
4839     [PA_COMMAND_SET_SOURCE_OUTPUT_MUTE] = command_set_mute,
4840 
4841     [PA_COMMAND_SUSPEND_SINK] = command_suspend,
4842     [PA_COMMAND_SUSPEND_SOURCE] = command_suspend,
4843 
4844     [PA_COMMAND_CORK_PLAYBACK_STREAM] = command_cork_playback_stream,
4845     [PA_COMMAND_FLUSH_PLAYBACK_STREAM] = command_trigger_or_flush_or_prebuf_playback_stream,
4846     [PA_COMMAND_TRIGGER_PLAYBACK_STREAM] = command_trigger_or_flush_or_prebuf_playback_stream,
4847     [PA_COMMAND_PREBUF_PLAYBACK_STREAM] = command_trigger_or_flush_or_prebuf_playback_stream,
4848 
4849     [PA_COMMAND_CORK_RECORD_STREAM] = command_cork_record_stream,
4850     [PA_COMMAND_FLUSH_RECORD_STREAM] = command_flush_record_stream,
4851 
4852     [PA_COMMAND_SET_DEFAULT_SINK] = command_set_default_sink_or_source,
4853     [PA_COMMAND_SET_DEFAULT_SOURCE] = command_set_default_sink_or_source,
4854     [PA_COMMAND_SET_PLAYBACK_STREAM_NAME] = command_set_stream_name,
4855     [PA_COMMAND_SET_RECORD_STREAM_NAME] = command_set_stream_name,
4856     [PA_COMMAND_KILL_CLIENT] = command_kill,
4857     [PA_COMMAND_KILL_SINK_INPUT] = command_kill,
4858     [PA_COMMAND_KILL_SOURCE_OUTPUT] = command_kill,
4859     [PA_COMMAND_LOAD_MODULE] = command_load_module,
4860     [PA_COMMAND_UNLOAD_MODULE] = command_unload_module,
4861 
4862     [PA_COMMAND_GET_AUTOLOAD_INFO___OBSOLETE] = NULL,
4863     [PA_COMMAND_GET_AUTOLOAD_INFO_LIST___OBSOLETE] = NULL,
4864     [PA_COMMAND_ADD_AUTOLOAD___OBSOLETE] = NULL,
4865     [PA_COMMAND_REMOVE_AUTOLOAD___OBSOLETE] = NULL,
4866 
4867     [PA_COMMAND_MOVE_SINK_INPUT] = command_move_stream,
4868     [PA_COMMAND_MOVE_SOURCE_OUTPUT] = command_move_stream,
4869 
4870     [PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR] = command_set_stream_buffer_attr,
4871     [PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR] = command_set_stream_buffer_attr,
4872 
4873     [PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE] = command_update_stream_sample_rate,
4874     [PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE] = command_update_stream_sample_rate,
4875 
4876     [PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST] = command_update_proplist,
4877     [PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST] = command_update_proplist,
4878     [PA_COMMAND_UPDATE_CLIENT_PROPLIST] = command_update_proplist,
4879 
4880     [PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST] = command_remove_proplist,
4881     [PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST] = command_remove_proplist,
4882     [PA_COMMAND_REMOVE_CLIENT_PROPLIST] = command_remove_proplist,
4883 
4884     [PA_COMMAND_SET_CARD_PROFILE] = command_set_card_profile,
4885 
4886     [PA_COMMAND_SET_SINK_PORT] = command_set_sink_or_source_port,
4887     [PA_COMMAND_SET_SOURCE_PORT] = command_set_sink_or_source_port,
4888 
4889     [PA_COMMAND_SET_PORT_LATENCY_OFFSET] = command_set_port_latency_offset,
4890 
4891     [PA_COMMAND_ENABLE_SRBCHANNEL] = command_enable_srbchannel,
4892 
4893     [PA_COMMAND_REGISTER_MEMFD_SHMID] = command_register_memfd_shmid,
4894 
4895     [PA_COMMAND_SEND_OBJECT_MESSAGE] = command_send_object_message,
4896 
4897     [PA_COMMAND_EXTENSION] = command_extension
4898 };
4899 
4900 /*** pstream callbacks ***/
4901 
pstream_packet_callback(pa_pstream *p, pa_packet *packet, pa_cmsg_ancil_data *ancil_data, void *userdata)4902 static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, pa_cmsg_ancil_data *ancil_data, void *userdata) {
4903     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4904 
4905     pa_assert(p);
4906     pa_assert(packet);
4907     pa_native_connection_assert_ref(c);
4908 
4909     if (pa_pdispatch_run(c->pdispatch, packet, ancil_data, c) < 0) {
4910         pa_log("invalid packet.");
4911         native_connection_unlink(c);
4912     }
4913 }
4914 
pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk, void *userdata)4915 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) {
4916     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4917     output_stream *stream;
4918 
4919     pa_assert(p);
4920     pa_assert(chunk);
4921     pa_native_connection_assert_ref(c);
4922 
4923     if (!(stream = OUTPUT_STREAM(pa_idxset_get_by_index(c->output_streams, channel)))) {
4924         pa_log_debug("Client sent block for invalid stream.");
4925         /* Ignoring */
4926         return;
4927     }
4928 
4929 #ifdef PROTOCOL_NATIVE_DEBUG
4930     pa_log("got %lu bytes from client", (unsigned long) chunk->length);
4931 #endif
4932 
4933     if (playback_stream_isinstance(stream)) {
4934         playback_stream *ps = PLAYBACK_STREAM(stream);
4935 
4936         size_t frame_size = pa_frame_size(&ps->sink_input->sample_spec);
4937         if (chunk->index % frame_size != 0 || chunk->length % frame_size != 0) {
4938             pa_log_warn("Client sent non-aligned memblock: index %d, length %d, frame size:"
4939                 "%d", (int) chunk->index, (int) chunk->length, (int) frame_size);
4940             return;
4941         }
4942 
4943         pa_atomic_inc(&ps->seek_or_post_in_queue);
4944         if (chunk->memblock) {
4945             if (seek != PA_SEEK_RELATIVE || offset != 0)
4946                 pa_asyncmsgq_post(ps->sink_input->sink->asyncmsgq, PA_MSGOBJECT(ps->sink_input), SINK_INPUT_MESSAGE_SEEK, PA_UINT_TO_PTR(seek), offset, chunk, NULL);
4947             else
4948                 pa_asyncmsgq_post(ps->sink_input->sink->asyncmsgq, PA_MSGOBJECT(ps->sink_input), SINK_INPUT_MESSAGE_POST_DATA, NULL, 0, chunk, NULL);
4949         } else
4950             pa_asyncmsgq_post(ps->sink_input->sink->asyncmsgq, PA_MSGOBJECT(ps->sink_input), SINK_INPUT_MESSAGE_SEEK, PA_UINT_TO_PTR(seek), offset+chunk->length, NULL, NULL);
4951 
4952     } else {
4953         upload_stream *u = UPLOAD_STREAM(stream);
4954         size_t l;
4955 
4956         if (!u->memchunk.memblock) {
4957             if (u->length == chunk->length && chunk->memblock) {
4958                 u->memchunk = *chunk;
4959                 pa_memblock_ref(u->memchunk.memblock);
4960                 u->length = 0;
4961             } else {
4962                 u->memchunk.memblock = pa_memblock_new(c->protocol->core->mempool, u->length);
4963                 u->memchunk.index = u->memchunk.length = 0;
4964             }
4965         }
4966 
4967         pa_assert(u->memchunk.memblock);
4968 
4969         l = u->length;
4970         if (l > chunk->length)
4971             l = chunk->length;
4972 
4973         if (l > 0) {
4974             void *dst;
4975             dst = pa_memblock_acquire(u->memchunk.memblock);
4976 
4977             if (chunk->memblock) {
4978                 void *src;
4979                 src = pa_memblock_acquire(chunk->memblock);
4980 
4981                 memcpy((uint8_t*) dst + u->memchunk.index + u->memchunk.length,
4982                        (uint8_t*) src + chunk->index, l);
4983 
4984                 pa_memblock_release(chunk->memblock);
4985             } else
4986                 pa_silence_memory((uint8_t*) dst + u->memchunk.index + u->memchunk.length, l, &u->sample_spec);
4987 
4988             pa_memblock_release(u->memchunk.memblock);
4989 
4990             u->memchunk.length += l;
4991             u->length -= l;
4992         }
4993     }
4994 }
4995 
pstream_die_callback(pa_pstream *p, void *userdata)4996 static void pstream_die_callback(pa_pstream *p, void *userdata) {
4997     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4998 
4999     pa_assert(p);
5000     pa_native_connection_assert_ref(c);
5001 
5002     native_connection_unlink(c);
5003     pa_log_info("Connection died.");
5004 }
5005 
pstream_drain_callback(pa_pstream *p, void *userdata)5006 static void pstream_drain_callback(pa_pstream *p, void *userdata) {
5007     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
5008 
5009     pa_assert(p);
5010     pa_native_connection_assert_ref(c);
5011 
5012     native_connection_send_memblock(c);
5013 }
5014 
pstream_revoke_callback(pa_pstream *p, uint32_t block_id, void *userdata)5015 static void pstream_revoke_callback(pa_pstream *p, uint32_t block_id, void *userdata) {
5016     pa_thread_mq *q;
5017 
5018     if (!(q = pa_thread_mq_get()))
5019         pa_pstream_send_revoke(p, block_id);
5020     else
5021         pa_asyncmsgq_post(q->outq, PA_MSGOBJECT(userdata), CONNECTION_MESSAGE_REVOKE, PA_UINT_TO_PTR(block_id), 0, NULL, NULL);
5022 }
5023 
pstream_release_callback(pa_pstream *p, uint32_t block_id, void *userdata)5024 static void pstream_release_callback(pa_pstream *p, uint32_t block_id, void *userdata) {
5025     pa_thread_mq *q;
5026 
5027     if (!(q = pa_thread_mq_get()))
5028         pa_pstream_send_release(p, block_id);
5029     else
5030         pa_asyncmsgq_post(q->outq, PA_MSGOBJECT(userdata), CONNECTION_MESSAGE_RELEASE, PA_UINT_TO_PTR(block_id), 0, NULL, NULL);
5031 }
5032 
5033 /*** client callbacks ***/
5034 
client_kill_cb(pa_client *c)5035 static void client_kill_cb(pa_client *c) {
5036     pa_assert(c);
5037 
5038     native_connection_unlink(PA_NATIVE_CONNECTION(c->userdata));
5039     pa_log_info("Connection killed.");
5040 }
5041 
client_send_event_cb(pa_client *client, const char*event, pa_proplist *pl)5042 static void client_send_event_cb(pa_client *client, const char*event, pa_proplist *pl) {
5043     pa_tagstruct *t;
5044     pa_native_connection *c;
5045 
5046     pa_assert(client);
5047     c = PA_NATIVE_CONNECTION(client->userdata);
5048     pa_native_connection_assert_ref(c);
5049 
5050     if (c->version < 15)
5051       return;
5052 
5053     t = pa_tagstruct_new();
5054     pa_tagstruct_putu32(t, PA_COMMAND_CLIENT_EVENT);
5055     pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
5056     pa_tagstruct_puts(t, event);
5057     pa_tagstruct_put_proplist(t, pl);
5058     pa_pstream_send_tagstruct(c->pstream, t);
5059 }
5060 
5061 /*** module entry points ***/
5062 
auth_timeout(pa_mainloop_api*m, pa_time_event *e, const struct timeval *t, void *userdata)5063 static void auth_timeout(pa_mainloop_api*m, pa_time_event *e, const struct timeval *t, void *userdata) {
5064     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
5065 
5066     pa_assert(m);
5067     pa_native_connection_assert_ref(c);
5068     pa_assert(c->auth_timeout_event == e);
5069 
5070     if (!c->authorized) {
5071         native_connection_unlink(c);
5072         pa_log_info("Connection terminated due to authentication timeout.");
5073     }
5074 }
5075 
pa_native_protocol_connect(pa_native_protocol *p, pa_iochannel *io, pa_native_options *o)5076 void pa_native_protocol_connect(pa_native_protocol *p, pa_iochannel *io, pa_native_options *o) {
5077     pa_native_connection *c;
5078     char pname[128];
5079     pa_client *client;
5080     pa_client_new_data data;
5081 
5082     pa_assert(p);
5083     pa_assert(io);
5084     pa_assert(o);
5085 
5086     if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) {
5087         pa_log_warn("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS);
5088         pa_iochannel_free(io);
5089         return;
5090     }
5091 
5092     pa_client_new_data_init(&data);
5093     data.module = o->module;
5094     data.driver = __FILE__;
5095     pa_iochannel_socket_peer_to_string(io, pname, sizeof(pname));
5096     pa_proplist_setf(data.proplist, PA_PROP_APPLICATION_NAME, "Native client (%s)", pname);
5097     pa_proplist_sets(data.proplist, "native-protocol.peer", pname);
5098     client = pa_client_new(p->core, &data);
5099     pa_client_new_data_done(&data);
5100 
5101     if (!client)
5102         return;
5103 
5104     c = pa_msgobject_new(pa_native_connection);
5105     c->parent.parent.free = native_connection_free;
5106     c->parent.process_msg = native_connection_process_msg;
5107     c->protocol = p;
5108     c->options = pa_native_options_ref(o);
5109     c->authorized = false;
5110     c->srbpending = NULL;
5111 
5112     if (o->auth_anonymous) {
5113         pa_log_info("Client authenticated anonymously.");
5114         c->authorized = true;
5115     }
5116 
5117     if (!c->authorized &&
5118         o->auth_ip_acl &&
5119         pa_ip_acl_check(o->auth_ip_acl, pa_iochannel_get_recv_fd(io)) > 0) {
5120 
5121         pa_log_info("Client authenticated by IP ACL.");
5122         c->authorized = true;
5123     }
5124 
5125     if (!c->authorized)
5126         c->auth_timeout_event = pa_core_rttime_new(p->core, pa_rtclock_now() + AUTH_TIMEOUT, auth_timeout, c);
5127     else
5128         c->auth_timeout_event = NULL;
5129 
5130     c->is_local = pa_iochannel_socket_is_local(io);
5131     c->version = 8;
5132 
5133     c->client = client;
5134     c->client->kill = client_kill_cb;
5135     c->client->send_event = client_send_event_cb;
5136     c->client->userdata = c;
5137 
5138     c->rw_mempool = NULL;
5139 
5140     c->pstream = pa_pstream_new(p->core->mainloop, io, p->core->mempool);
5141     pa_pstream_set_receive_packet_callback(c->pstream, pstream_packet_callback, c);
5142     pa_pstream_set_receive_memblock_callback(c->pstream, pstream_memblock_callback, c);
5143     pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c);
5144     pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c);
5145     pa_pstream_set_revoke_callback(c->pstream, pstream_revoke_callback, c);
5146     pa_pstream_set_release_callback(c->pstream, pstream_release_callback, c);
5147 
5148     c->pdispatch = pa_pdispatch_new(p->core->mainloop, true, command_table, PA_COMMAND_MAX);
5149 
5150     c->record_streams = pa_idxset_new(NULL, NULL);
5151     c->output_streams = pa_idxset_new(NULL, NULL);
5152 
5153     c->rrobin_index = PA_IDXSET_INVALID;
5154     c->subscription = NULL;
5155 
5156     pa_idxset_put(p->connections, c, NULL);
5157 
5158 #ifdef HAVE_CREDS
5159     if (pa_iochannel_creds_supported(io))
5160         pa_iochannel_creds_enable(io);
5161 #endif
5162 
5163     pa_hook_fire(&p->hooks[PA_NATIVE_HOOK_CONNECTION_PUT], c);
5164 }
5165 
pa_native_protocol_disconnect(pa_native_protocol *p, pa_module *m)5166 void pa_native_protocol_disconnect(pa_native_protocol *p, pa_module *m) {
5167     pa_native_connection *c;
5168     void *state = NULL;
5169 
5170     pa_assert(p);
5171     pa_assert(m);
5172 
5173     while ((c = pa_idxset_iterate(p->connections, &state, NULL)))
5174         if (c->options->module == m)
5175             native_connection_unlink(c);
5176 }
5177 
native_protocol_new(pa_core *c)5178 static pa_native_protocol* native_protocol_new(pa_core *c) {
5179     pa_native_protocol *p;
5180     pa_native_hook_t h;
5181 
5182     pa_assert(c);
5183 
5184     p = pa_xnew(pa_native_protocol, 1);
5185     PA_REFCNT_INIT(p);
5186     p->core = c;
5187     p->connections = pa_idxset_new(NULL, NULL);
5188 
5189     p->servers = NULL;
5190 
5191     p->extensions = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
5192 
5193     for (h = 0; h < PA_NATIVE_HOOK_MAX; h++)
5194         pa_hook_init(&p->hooks[h], p);
5195 
5196     pa_assert_se(pa_shared_set(c, "native-protocol", p) >= 0);
5197 
5198     return p;
5199 }
5200 
pa_native_protocol_get(pa_core *c)5201 pa_native_protocol* pa_native_protocol_get(pa_core *c) {
5202     pa_native_protocol *p;
5203 
5204     if ((p = pa_shared_get(c, "native-protocol")))
5205         return pa_native_protocol_ref(p);
5206 
5207     return native_protocol_new(c);
5208 }
5209 
pa_native_protocol_ref(pa_native_protocol *p)5210 pa_native_protocol* pa_native_protocol_ref(pa_native_protocol *p) {
5211     pa_assert(p);
5212     pa_assert(PA_REFCNT_VALUE(p) >= 1);
5213 
5214     PA_REFCNT_INC(p);
5215 
5216     return p;
5217 }
5218 
pa_native_protocol_unref(pa_native_protocol *p)5219 void pa_native_protocol_unref(pa_native_protocol *p) {
5220     pa_native_connection *c;
5221     pa_native_hook_t h;
5222 
5223     pa_assert(p);
5224     pa_assert(PA_REFCNT_VALUE(p) >= 1);
5225 
5226     if (PA_REFCNT_DEC(p) > 0)
5227         return;
5228 
5229     while ((c = pa_idxset_first(p->connections, NULL)))
5230         native_connection_unlink(c);
5231 
5232     pa_idxset_free(p->connections, NULL);
5233 
5234     pa_strlist_free(p->servers);
5235 
5236     for (h = 0; h < PA_NATIVE_HOOK_MAX; h++)
5237         pa_hook_done(&p->hooks[h]);
5238 
5239     pa_hashmap_free(p->extensions);
5240 
5241     pa_assert_se(pa_shared_remove(p->core, "native-protocol") >= 0);
5242 
5243     pa_xfree(p);
5244 }
5245 
pa_native_protocol_add_server_string(pa_native_protocol *p, const char *name)5246 void pa_native_protocol_add_server_string(pa_native_protocol *p, const char *name) {
5247     pa_assert(p);
5248     pa_assert(PA_REFCNT_VALUE(p) >= 1);
5249     pa_assert(name);
5250 
5251     p->servers = pa_strlist_prepend(p->servers, name);
5252 
5253     pa_hook_fire(&p->hooks[PA_NATIVE_HOOK_SERVERS_CHANGED], p->servers);
5254 }
5255 
pa_native_protocol_remove_server_string(pa_native_protocol *p, const char *name)5256 void pa_native_protocol_remove_server_string(pa_native_protocol *p, const char *name) {
5257     pa_assert(p);
5258     pa_assert(PA_REFCNT_VALUE(p) >= 1);
5259     pa_assert(name);
5260 
5261     p->servers = pa_strlist_remove(p->servers, name);
5262 
5263     pa_hook_fire(&p->hooks[PA_NATIVE_HOOK_SERVERS_CHANGED], p->servers);
5264 }
5265 
pa_native_protocol_hooks(pa_native_protocol *p)5266 pa_hook *pa_native_protocol_hooks(pa_native_protocol *p) {
5267     pa_assert(p);
5268     pa_assert(PA_REFCNT_VALUE(p) >= 1);
5269 
5270     return p->hooks;
5271 }
5272 
pa_native_protocol_servers(pa_native_protocol *p)5273 pa_strlist *pa_native_protocol_servers(pa_native_protocol *p) {
5274     pa_assert(p);
5275     pa_assert(PA_REFCNT_VALUE(p) >= 1);
5276 
5277     return p->servers;
5278 }
5279 
pa_native_protocol_install_ext(pa_native_protocol *p, pa_module *m, pa_native_protocol_ext_cb_t cb)5280 int pa_native_protocol_install_ext(pa_native_protocol *p, pa_module *m, pa_native_protocol_ext_cb_t cb) {
5281     pa_assert(p);
5282     pa_assert(PA_REFCNT_VALUE(p) >= 1);
5283     pa_assert(m);
5284     pa_assert(cb);
5285     pa_assert(!pa_hashmap_get(p->extensions, m));
5286 
5287     pa_assert_se(pa_hashmap_put(p->extensions, m, cb) == 0);
5288     return 0;
5289 }
5290 
pa_native_protocol_remove_ext(pa_native_protocol *p, pa_module *m)5291 void pa_native_protocol_remove_ext(pa_native_protocol *p, pa_module *m) {
5292     pa_assert(p);
5293     pa_assert(PA_REFCNT_VALUE(p) >= 1);
5294     pa_assert(m);
5295 
5296     pa_assert_se(pa_hashmap_remove(p->extensions, m));
5297 }
5298 
pa_native_options_new(void)5299 pa_native_options* pa_native_options_new(void) {
5300     pa_native_options *o;
5301 
5302     o = pa_xnew0(pa_native_options, 1);
5303     PA_REFCNT_INIT(o);
5304 
5305     return o;
5306 }
5307 
pa_native_options_ref(pa_native_options *o)5308 pa_native_options* pa_native_options_ref(pa_native_options *o) {
5309     pa_assert(o);
5310     pa_assert(PA_REFCNT_VALUE(o) >= 1);
5311 
5312     PA_REFCNT_INC(o);
5313 
5314     return o;
5315 }
5316 
pa_native_options_unref(pa_native_options *o)5317 void pa_native_options_unref(pa_native_options *o) {
5318     pa_assert(o);
5319     pa_assert(PA_REFCNT_VALUE(o) >= 1);
5320 
5321     if (PA_REFCNT_DEC(o) > 0)
5322         return;
5323 
5324     pa_xfree(o->auth_group);
5325 
5326     if (o->auth_ip_acl)
5327         pa_ip_acl_free(o->auth_ip_acl);
5328 
5329     if (o->auth_cookie)
5330         pa_auth_cookie_unref(o->auth_cookie);
5331 
5332     pa_xfree(o);
5333 }
5334 
pa_native_options_parse(pa_native_options *o, pa_core *c, pa_modargs *ma)5335 int pa_native_options_parse(pa_native_options *o, pa_core *c, pa_modargs *ma) {
5336     bool enabled;
5337     const char *acl;
5338 
5339     pa_assert(o);
5340     pa_assert(PA_REFCNT_VALUE(o) >= 1);
5341     pa_assert(ma);
5342 
5343     o->srbchannel = true;
5344     if (pa_modargs_get_value_boolean(ma, "srbchannel", &o->srbchannel) < 0) {
5345         pa_log_error("srbchannel= expects a boolean argument.");
5346         return -1;
5347     }
5348 
5349     if (pa_modargs_get_value_boolean(ma, "auth-anonymous", &o->auth_anonymous) < 0) {
5350         pa_log_error("auth-anonymous= expects a boolean argument.");
5351         return -1;
5352     }
5353 
5354     enabled = true;
5355     if (pa_modargs_get_value_boolean(ma, "auth-group-enable", &enabled) < 0) {
5356         pa_log_error("auth-group-enable= expects a boolean argument.");
5357         return -1;
5358     }
5359 
5360     pa_xfree(o->auth_group);
5361     o->auth_group = enabled ? pa_xstrdup(pa_modargs_get_value(ma, "auth-group", pa_in_system_mode() ? PA_ACCESS_GROUP : NULL)) : NULL;
5362 
5363 #ifndef HAVE_CREDS
5364     if (o->auth_group)
5365         pa_log_error("Authentication group configured, but not available on local system. Ignoring.");
5366 #endif
5367 
5368     if ((acl = pa_modargs_get_value(ma, "auth-ip-acl", NULL))) {
5369         pa_ip_acl *ipa;
5370 
5371         if (!(ipa = pa_ip_acl_new(acl))) {
5372             pa_log_error("Failed to parse IP ACL '%s'", acl);
5373             return -1;
5374         }
5375 
5376         if (o->auth_ip_acl)
5377             pa_ip_acl_free(o->auth_ip_acl);
5378 
5379         o->auth_ip_acl = ipa;
5380     }
5381 
5382     enabled = true;
5383     if (pa_modargs_get_value_boolean(ma, "auth-cookie-enabled", &enabled) < 0) {
5384         pa_log_error("auth-cookie-enabled= expects a boolean argument.");
5385         return -1;
5386     }
5387 
5388     if (o->auth_cookie)
5389         pa_auth_cookie_unref(o->auth_cookie);
5390 
5391     if (enabled) {
5392         const char *cn;
5393 
5394         /* The new name for this is 'auth-cookie', for compat reasons
5395          * we check the old name too */
5396         cn = pa_modargs_get_value(ma, "auth-cookie", NULL);
5397         if (!cn)
5398             cn = pa_modargs_get_value(ma, "cookie", NULL);
5399 
5400         if (cn)
5401             o->auth_cookie = pa_auth_cookie_get(c, cn, true, PA_NATIVE_COOKIE_LENGTH);
5402         else {
5403             o->auth_cookie = pa_auth_cookie_get(c, PA_NATIVE_COOKIE_FILE, false, PA_NATIVE_COOKIE_LENGTH);
5404             if (!o->auth_cookie) {
5405                 char *fallback_path;
5406 
5407                 if (pa_append_to_home_dir(PA_NATIVE_COOKIE_FILE_FALLBACK, &fallback_path) >= 0) {
5408                     o->auth_cookie = pa_auth_cookie_get(c, fallback_path, false, PA_NATIVE_COOKIE_LENGTH);
5409                     pa_xfree(fallback_path);
5410                 }
5411 
5412                 if (!o->auth_cookie)
5413                     o->auth_cookie = pa_auth_cookie_get(c, PA_NATIVE_COOKIE_FILE, true, PA_NATIVE_COOKIE_LENGTH);
5414             }
5415         }
5416 
5417         if (!o->auth_cookie)
5418             return -1;
5419 
5420     } else
5421           o->auth_cookie = NULL;
5422 
5423     return 0;
5424 }
5425 
pa_native_connection_get_pstream(pa_native_connection *c)5426 pa_pstream* pa_native_connection_get_pstream(pa_native_connection *c) {
5427     pa_native_connection_assert_ref(c);
5428 
5429     return c->pstream;
5430 }
5431 
pa_native_connection_get_client(pa_native_connection *c)5432 pa_client* pa_native_connection_get_client(pa_native_connection *c) {
5433     pa_native_connection_assert_ref(c);
5434 
5435     return c->client;
5436 }
5437