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