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