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