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