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