• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***
2   This file is part of PulseAudio.
3 
4   Copyright 2004-2008 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 #undef LOG_TAG
26 #define LOG_TAG "Context"
27 
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <sys/types.h>
32 #include <unistd.h>
33 #include <sys/stat.h>
34 #include <errno.h>
35 #include <signal.h>
36 
37 #ifdef HAVE_SYS_WAIT_H
38 #include <sys/wait.h>
39 #endif
40 
41 #ifdef HAVE_NETDB_H
42 #include <netdb.h>
43 #endif
44 
45 #include <pulse/version.h>
46 #include <pulse/xmalloc.h>
47 #include <pulse/util.h>
48 #include <pulse/mainloop.h>
49 #include <pulse/timeval.h>
50 #include <pulse/fork-detect.h>
51 #include <pulse/client-conf.h>
52 
53 #include <pulsecore/core-error.h>
54 #include <pulsecore/i18n.h>
55 #include <pulsecore/native-common.h>
56 #include <pulsecore/pdispatch.h>
57 #include <pulsecore/pstream.h>
58 #include <pulsecore/hashmap.h>
59 #include <pulsecore/socket-client.h>
60 #include <pulsecore/pstream-util.h>
61 #include <pulsecore/core-rtclock.h>
62 #include <pulsecore/core-util.h>
63 #include <pulsecore/log.h>
64 #include <pulsecore/socket.h>
65 #include <pulsecore/creds.h>
66 #include <pulsecore/macro.h>
67 #include <pulsecore/proplist-util.h>
68 
69 #include "log/audio_log.h"
70 
71 #include "internal.h"
72 #include "context.h"
73 
74 void pa_command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
75 static void pa_command_enable_srbchannel(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
76 static void pa_command_disable_srbchannel(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
77 static void pa_command_register_memfd_shmid(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
78 
79 static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
80     [PA_COMMAND_REQUEST] = pa_command_request,
81     [PA_COMMAND_OVERFLOW] = pa_command_overflow_or_underflow,
82     [PA_COMMAND_UNDERFLOW] = pa_command_overflow_or_underflow,
83     [PA_COMMAND_PLAYBACK_STREAM_KILLED] = pa_command_stream_killed,
84     [PA_COMMAND_RECORD_STREAM_KILLED] = pa_command_stream_killed,
85     [PA_COMMAND_PLAYBACK_STREAM_MOVED] = pa_command_stream_moved,
86     [PA_COMMAND_RECORD_STREAM_MOVED] = pa_command_stream_moved,
87     [PA_COMMAND_PLAYBACK_STREAM_SUSPENDED] = pa_command_stream_suspended,
88     [PA_COMMAND_RECORD_STREAM_SUSPENDED] = pa_command_stream_suspended,
89     [PA_COMMAND_STARTED] = pa_command_stream_started,
90     [PA_COMMAND_SUBSCRIBE_EVENT] = pa_command_subscribe_event,
91     [PA_COMMAND_EXTENSION] = pa_command_extension,
92     [PA_COMMAND_PLAYBACK_STREAM_EVENT] = pa_command_stream_event,
93     [PA_COMMAND_RECORD_STREAM_EVENT] = pa_command_stream_event,
94     [PA_COMMAND_CLIENT_EVENT] = pa_command_client_event,
95     [PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED] = pa_command_stream_buffer_attr,
96     [PA_COMMAND_RECORD_BUFFER_ATTR_CHANGED] = pa_command_stream_buffer_attr,
97     [PA_COMMAND_ENABLE_SRBCHANNEL] = pa_command_enable_srbchannel,
98     [PA_COMMAND_DISABLE_SRBCHANNEL] = pa_command_disable_srbchannel,
99     [PA_COMMAND_REGISTER_MEMFD_SHMID] = pa_command_register_memfd_shmid,
100     [PA_COMMAND_UNDERFLOW_OHOS] = pa_command_overflow_or_underflow,
101 };
102 static void context_free(pa_context *c);
103 
104 #ifdef HAVE_DBUS
105 static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *message, void *userdata);
106 #endif
107 
pa_context_new(pa_mainloop_api * mainloop,const char * name)108 pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) {
109     return pa_context_new_with_proplist(mainloop, name, NULL);
110 }
111 
reset_callbacks(pa_context * c)112 static void reset_callbacks(pa_context *c) {
113     pa_assert(c);
114 
115     c->state_callback = NULL;
116     c->state_userdata = NULL;
117 
118     c->subscribe_callback = NULL;
119     c->subscribe_userdata = NULL;
120 
121     c->event_callback = NULL;
122     c->event_userdata = NULL;
123 
124     c->ext_device_manager.callback = NULL;
125     c->ext_device_manager.userdata = NULL;
126 
127     c->ext_device_restore.callback = NULL;
128     c->ext_device_restore.userdata = NULL;
129 
130     c->ext_stream_restore.callback = NULL;
131     c->ext_stream_restore.userdata = NULL;
132 }
133 
pa_context_new_with_proplist(pa_mainloop_api * mainloop,const char * name,const pa_proplist * p)134 pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char *name, const pa_proplist *p) {
135     pa_context *c;
136     pa_mem_type_t type;
137     const char *force_disable_shm_str;
138 
139     pa_assert(mainloop);
140 
141     if (pa_detect_fork())
142         return NULL;
143 
144     pa_init_i18n();
145 
146     c = pa_xnew0(pa_context, 1);
147     PA_REFCNT_INIT(c);
148 
149     c->error = pa_xnew0(pa_context_error, 1);
150     assert(c->error);
151 
152     c->proplist = p ? pa_proplist_copy(p) : pa_proplist_new();
153 
154     if (name)
155         pa_proplist_sets(c->proplist, PA_PROP_APPLICATION_NAME, name);
156 
157 #ifdef HAVE_DBUS
158     c->system_bus = c->session_bus = NULL;
159 #endif
160     c->mainloop = mainloop;
161     c->playback_streams = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
162     c->record_streams = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
163     c->client_index = PA_INVALID_INDEX;
164     c->use_rtclock = pa_mainloop_is_our_api(mainloop);
165 
166     PA_LLIST_HEAD_INIT(pa_stream, c->streams);
167     PA_LLIST_HEAD_INIT(pa_operation, c->operations);
168 
169     c->error->error = PA_OK;
170     c->state = PA_CONTEXT_UNCONNECTED;
171 
172     reset_callbacks(c);
173 
174 #ifndef MSG_NOSIGNAL
175 #ifdef SIGPIPE
176     pa_check_signal_is_blocked(SIGPIPE);
177 #endif
178 #endif
179 
180     c->conf = pa_client_conf_new();
181     pa_client_conf_load(c->conf, true, true);
182 
183     force_disable_shm_str = pa_proplist_gets(c->proplist, PA_PROP_CONTEXT_FORCE_DISABLE_SHM);
184     if (force_disable_shm_str) {
185         int b = pa_parse_boolean(force_disable_shm_str);
186         if (b < 0) {
187             pa_log_warn("Ignored invalid value for '%s' property: %s", PA_PROP_CONTEXT_FORCE_DISABLE_SHM, force_disable_shm_str);
188         } else if (b) {
189             c->conf->disable_shm = true;
190         }
191     }
192 
193     c->srb_template.readfd = -1;
194     c->srb_template.writefd = -1;
195 
196     c->memfd_on_local = (!c->conf->disable_memfd && pa_memfd_is_locally_supported());
197 
198     type = (c->conf->disable_shm) ? PA_MEM_TYPE_PRIVATE :
199            ((!c->memfd_on_local) ?
200                PA_MEM_TYPE_SHARED_POSIX : PA_MEM_TYPE_SHARED_MEMFD);
201 
202     if (!(c->mempool = pa_mempool_new(type, c->conf->shm_size, true))) {
203 
204         if (!c->conf->disable_shm) {
205             pa_log_warn("Failed to allocate shared memory pool. Falling back to a normal private one.");
206             c->mempool = pa_mempool_new(PA_MEM_TYPE_PRIVATE, c->conf->shm_size, true);
207         }
208 
209         if (!c->mempool) {
210             context_free(c);
211             return NULL;
212         }
213     }
214 
215     return c;
216 }
217 
context_unlink(pa_context * c)218 static void context_unlink(pa_context *c) {
219     pa_stream *s;
220 
221     pa_assert(c);
222 
223     s = c->streams ? pa_stream_ref(c->streams) : NULL;
224     while (s) {
225         pa_stream *n = s->next ? pa_stream_ref(s->next) : NULL;
226         pa_stream_set_state(s, c->state == PA_CONTEXT_FAILED ? PA_STREAM_FAILED : PA_STREAM_TERMINATED);
227         pa_stream_unref(s);
228         s = n;
229     }
230 
231     while (c->operations)
232         pa_operation_cancel(c->operations);
233 
234     if (c->pdispatch) {
235         pa_pdispatch_unref(c->pdispatch);
236         c->pdispatch = NULL;
237     }
238 
239     if (c->pstream) {
240         pa_pstream_unlink(c->pstream);
241         pa_pstream_unref(c->pstream);
242         c->pstream = NULL;
243     }
244 
245     if (c->srb_template.memblock) {
246         pa_memblock_unref(c->srb_template.memblock);
247         c->srb_template.memblock = NULL;
248     }
249 
250     if (c->client) {
251         pa_socket_client_unref(c->client);
252         c->client = NULL;
253     }
254 
255     reset_callbacks(c);
256 }
257 
context_free(pa_context * c)258 static void context_free(pa_context *c) {
259     pa_assert(c);
260 
261     context_unlink(c);
262 
263 #ifdef HAVE_DBUS
264     if (c->system_bus) {
265         if (c->filter_added)
266             dbus_connection_remove_filter(pa_dbus_wrap_connection_get(c->system_bus), filter_cb, c);
267         pa_dbus_wrap_connection_free(c->system_bus);
268     }
269 
270     if (c->session_bus) {
271         if (c->filter_added)
272             dbus_connection_remove_filter(pa_dbus_wrap_connection_get(c->session_bus), filter_cb, c);
273         pa_dbus_wrap_connection_free(c->session_bus);
274     }
275 #endif
276 
277     if (c->record_streams)
278         pa_hashmap_free(c->record_streams);
279     if (c->playback_streams)
280         pa_hashmap_free(c->playback_streams);
281 
282     if (c->mempool)
283         pa_mempool_unref(c->mempool);
284 
285     if (c->conf)
286         pa_client_conf_free(c->conf);
287 
288     pa_strlist_free(c->server_list);
289 
290     if (c->proplist)
291         pa_proplist_free(c->proplist);
292 
293     pa_xfree(c->server);
294     pa_xfree(c->error);
295     pa_xfree(c);
296 }
297 
pa_context_ref(pa_context * c)298 pa_context* pa_context_ref(pa_context *c) {
299     pa_assert(c);
300     pa_assert(PA_REFCNT_VALUE(c) >= 1);
301 
302     PA_REFCNT_INC(c);
303     return c;
304 }
305 
pa_context_unref(pa_context * c)306 void pa_context_unref(pa_context *c) {
307     pa_assert(c);
308     pa_assert(PA_REFCNT_VALUE(c) >= 1);
309 
310     if (PA_REFCNT_DEC(c) <= 0)
311         context_free(c);
312 }
313 
pa_context_set_state(pa_context * c,pa_context_state_t st)314 void pa_context_set_state(pa_context *c, pa_context_state_t st) {
315     pa_assert(c);
316     pa_assert(PA_REFCNT_VALUE(c) >= 1);
317 
318     if (c->state == st)
319         return;
320 
321     pa_context_ref(c);
322 
323     c->state = st;
324 
325     if (c->state_callback)
326         c->state_callback(c, c->state_userdata);
327 
328     if (st == PA_CONTEXT_FAILED || st == PA_CONTEXT_TERMINATED)
329         context_unlink(c);
330 
331     pa_context_unref(c);
332 }
333 
pa_context_set_error(const pa_context * c,int error)334 int pa_context_set_error(const pa_context *c, int error) {
335     pa_assert(error >= 0);
336     pa_assert(error < PA_ERR_MAX);
337 
338     if (c)
339         c->error->error = error;
340 
341     return error;
342 }
343 
pa_context_fail(pa_context * c,int error)344 void pa_context_fail(pa_context *c, int error) {
345     pa_assert(c);
346     pa_assert(PA_REFCNT_VALUE(c) >= 1);
347 
348     pa_context_set_error(c, error);
349     pa_context_set_state(c, PA_CONTEXT_FAILED);
350 }
351 
pstream_die_callback(pa_pstream * p,void * userdata)352 static void pstream_die_callback(pa_pstream *p, void *userdata) {
353     pa_context *c = userdata;
354 
355     pa_assert(p);
356     pa_assert(c);
357 
358     pa_context_fail(c, PA_ERR_CONNECTIONTERMINATED);
359 }
360 
pstream_packet_callback(pa_pstream * p,pa_packet * packet,pa_cmsg_ancil_data * ancil_data,void * userdata)361 static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, pa_cmsg_ancil_data *ancil_data, void *userdata) {
362     pa_context *c = userdata;
363 
364     pa_assert(p);
365     pa_assert(packet);
366     pa_assert(c);
367 
368     pa_context_ref(c);
369 
370     if (pa_pdispatch_run(c->pdispatch, packet, ancil_data, c) < 0)
371         pa_context_fail(c, PA_ERR_PROTOCOL);
372 
373     pa_context_unref(c);
374 }
375 
handle_srbchannel_memblock(pa_context * c,pa_memblock * memblock)376 static void handle_srbchannel_memblock(pa_context *c, pa_memblock *memblock) {
377     pa_srbchannel *sr;
378     pa_tagstruct *t;
379 
380     pa_assert(c);
381 
382     /* Memblock sanity check */
383     if (!memblock) {
384         pa_context_fail(c, PA_ERR_PROTOCOL);
385         return;
386     } else if (pa_memblock_is_read_only(memblock)) {
387         pa_context_fail(c, PA_ERR_PROTOCOL);
388         return;
389     } else if (pa_memblock_is_ours(memblock)) {
390         pa_context_fail(c, PA_ERR_PROTOCOL);
391         return;
392     }
393 
394     /* Create the srbchannel */
395     c->srb_template.memblock = memblock;
396     pa_memblock_ref(memblock);
397     sr = pa_srbchannel_new_from_template(c->mainloop, &c->srb_template);
398     if (!sr) {
399         pa_log_warn("Failed to create srbchannel from template");
400         c->srb_template.readfd = -1;
401         c->srb_template.writefd = -1;
402         pa_memblock_unref(c->srb_template.memblock);
403         c->srb_template.memblock = NULL;
404         return;
405     }
406 
407     /* Ack the enable command */
408     t = pa_tagstruct_new();
409     pa_tagstruct_putu32(t, PA_COMMAND_ENABLE_SRBCHANNEL);
410     pa_tagstruct_putu32(t, c->srb_setup_tag);
411     pa_pstream_send_tagstruct(c->pstream, t);
412 
413     /* ...and switch over */
414     pa_pstream_set_srbchannel(c->pstream, sr);
415 }
416 
pstream_memblock_callback(pa_pstream * p,uint32_t channel,int64_t offset,pa_seek_mode_t seek,const pa_memchunk * chunk,void * userdata)417 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) {
418     pa_context *c = userdata;
419     pa_stream *s;
420 
421     pa_assert(p);
422     pa_assert(chunk);
423     pa_assert(chunk->length > 0);
424     pa_assert(c);
425     pa_assert(PA_REFCNT_VALUE(c) >= 1);
426 
427     pa_context_ref(c);
428 
429     if (c->srb_template.readfd != -1 && c->srb_template.memblock == NULL) {
430         handle_srbchannel_memblock(c, chunk->memblock);
431         pa_context_unref(c);
432         return;
433     }
434 
435     if ((s = pa_hashmap_get(c->record_streams, PA_UINT32_TO_PTR(channel)))) {
436 
437         if (chunk->memblock) {
438             pa_memblockq_seek(s->record_memblockq, offset, seek, true);
439             pa_memblockq_push_align(s->record_memblockq, chunk);
440         } else
441             pa_memblockq_seek(s->record_memblockq, offset+chunk->length, seek, true);
442 
443         if (s->read_callback) {
444             size_t l;
445 
446             if ((l = pa_memblockq_get_length(s->record_memblockq)) > 0)
447                 s->read_callback(s, l, s->read_userdata);
448         }
449     }
450 
451     pa_context_unref(c);
452 }
453 
pa_context_handle_error(pa_context * c,uint32_t command,pa_tagstruct * t,bool fail)454 int pa_context_handle_error(pa_context *c, uint32_t command, pa_tagstruct *t, bool fail) {
455     uint32_t err;
456     pa_assert(c);
457     pa_assert(PA_REFCNT_VALUE(c) >= 1);
458 
459     if (command == PA_COMMAND_ERROR) {
460         pa_assert(t);
461 
462         if (pa_tagstruct_getu32(t, &err) < 0 ||
463             !pa_tagstruct_eof(t)) {
464             pa_context_fail(c, PA_ERR_PROTOCOL);
465             return -1;
466         }
467 
468     } else if (command == PA_COMMAND_TIMEOUT)
469         err = PA_ERR_TIMEOUT;
470     else {
471         pa_context_fail(c, PA_ERR_PROTOCOL);
472         return -1;
473     }
474 
475     if (err == PA_OK) {
476         pa_context_fail(c, PA_ERR_PROTOCOL);
477         return -1;
478     }
479 
480     if (err >= PA_ERR_MAX)
481         err = PA_ERR_UNKNOWN;
482 
483     if (fail) {
484         pa_context_fail(c, (int) err);
485         return -1;
486     }
487 
488     pa_context_set_error(c, (int) err);
489 
490     return 0;
491 }
492 
setup_complete_callback(pa_pdispatch * pd,uint32_t command,uint32_t tag,pa_tagstruct * t,void * userdata)493 static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
494     pa_context *c = userdata;
495 
496     pa_assert(pd);
497     pa_assert(c);
498     pa_assert(c->state == PA_CONTEXT_AUTHORIZING || c->state == PA_CONTEXT_SETTING_NAME);
499 
500     pa_context_ref(c);
501 
502     if (command != PA_COMMAND_REPLY) {
503         pa_context_handle_error(c, command, t, true);
504         goto finish;
505     }
506 
507     switch(c->state) {
508         case PA_CONTEXT_AUTHORIZING: {
509             pa_tagstruct *reply;
510             bool shm_on_remote = false;
511             bool memfd_on_remote = false;
512 
513             if (pa_tagstruct_getu32(t, &c->version) < 0 ||
514                 !pa_tagstruct_eof(t)) {
515                 pa_context_fail(c, PA_ERR_PROTOCOL);
516                 goto finish;
517             }
518 
519             /* Minimum supported version */
520             if (c->version < 8) {
521                 pa_context_fail(c, PA_ERR_VERSION);
522                 goto finish;
523             }
524 
525             /* Starting with protocol version 13 the MSB of the version
526                tag reflects if shm is available for this connection or
527                not. */
528             if ((c->version & PA_PROTOCOL_VERSION_MASK) >= 13) {
529                 shm_on_remote = !!(c->version & PA_PROTOCOL_FLAG_SHM);
530 
531                 /* Starting with protocol version 31, the second MSB of the version
532                  * tag reflects whether memfd is supported on the other PA end. */
533                 if ((c->version & PA_PROTOCOL_VERSION_MASK) >= 31)
534                     memfd_on_remote = !!(c->version & PA_PROTOCOL_FLAG_MEMFD);
535 
536                 /* Reserve the two most-significant _bytes_ of the version tag
537                  * for flags. */
538                 c->version &= PA_PROTOCOL_VERSION_MASK;
539             }
540 
541             pa_log_debug("Protocol version: remote %u, local %u", c->version, PA_PROTOCOL_VERSION);
542 
543             /* Enable shared memory support if possible */
544             if (c->do_shm)
545                 if (c->version < 10 || (c->version >= 13 && !shm_on_remote))
546                     c->do_shm = false;
547 
548             if (c->do_shm) {
549 
550                 /* Only enable SHM if both sides are owned by the same
551                  * user. This is a security measure because otherwise
552                  * data private to the user might leak. */
553 
554 #ifdef HAVE_CREDS
555                 const pa_creds *creds;
556                 if (!(creds = pa_pdispatch_creds(pd)) || getuid() != creds->uid)
557                     c->do_shm = false;
558 #endif
559             }
560 
561             pa_log_debug("Negotiated SHM: %s", pa_yes_no(c->do_shm));
562             pa_pstream_enable_shm(c->pstream, c->do_shm);
563 
564             c->shm_type = PA_MEM_TYPE_PRIVATE;
565             if (c->do_shm) {
566                 if (c->version >= 31 && memfd_on_remote && c->memfd_on_local) {
567                     const char *reason;
568 
569                     pa_pstream_enable_memfd(c->pstream);
570                     if (pa_mempool_is_memfd_backed(c->mempool))
571                         if (pa_pstream_register_memfd_mempool(c->pstream, c->mempool, &reason))
572                             pa_log("Failed to regester memfd mempool. Reason: %s", reason);
573 
574                     /* Even if memfd pool registration fails, the negotiated SHM type
575                      * shall remain memfd as both endpoints claim to support it. */
576                     c->shm_type = PA_MEM_TYPE_SHARED_MEMFD;
577                 } else
578                     c->shm_type = PA_MEM_TYPE_SHARED_POSIX;
579             }
580 
581             AUDIO_DEBUG_LOG("Memfd possible: %{public}s", pa_yes_no(c->memfd_on_local));
582             AUDIO_DEBUG_LOG("Negotiated SHM type: %{public}s", pa_mem_type_to_string(c->shm_type));
583 
584             reply = pa_tagstruct_command(c, PA_COMMAND_SET_CLIENT_NAME, &tag);
585 
586             if (c->version >= 13) {
587                 pa_init_proplist(c->proplist);
588                 pa_tagstruct_put_proplist(reply, c->proplist);
589             } else
590                 pa_tagstruct_puts(reply, pa_proplist_gets(c->proplist, PA_PROP_APPLICATION_NAME));
591 
592             pa_pstream_send_tagstruct(c->pstream, reply);
593             pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c, NULL);
594 
595             pa_context_set_state(c, PA_CONTEXT_SETTING_NAME);
596             break;
597         }
598 
599         case PA_CONTEXT_SETTING_NAME :
600 
601             if ((c->version >= 13 && (pa_tagstruct_getu32(t, &c->client_index) < 0 ||
602                                       c->client_index == PA_INVALID_INDEX)) ||
603                 !pa_tagstruct_eof(t)) {
604                 pa_context_fail(c, PA_ERR_PROTOCOL);
605                 goto finish;
606             }
607 
608             pa_context_set_state(c, PA_CONTEXT_READY);
609             break;
610 
611         default:
612             pa_assert_not_reached();
613     }
614 
615 finish:
616     pa_context_unref(c);
617 }
618 
setup_context(pa_context * c,pa_iochannel * io)619 static void setup_context(pa_context *c, pa_iochannel *io) {
620     uint8_t cookie[PA_NATIVE_COOKIE_LENGTH];
621     pa_tagstruct *t;
622     uint32_t tag;
623 
624     pa_assert(c);
625     pa_assert(io);
626 
627     pa_context_ref(c);
628 
629     pa_assert(!c->pstream);
630     c->pstream = pa_pstream_new(c->mainloop, io, c->mempool);
631 
632     pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c);
633     pa_pstream_set_receive_packet_callback(c->pstream, pstream_packet_callback, c);
634     pa_pstream_set_receive_memblock_callback(c->pstream, pstream_memblock_callback, c);
635 
636     pa_assert(!c->pdispatch);
637     c->pdispatch = pa_pdispatch_new(c->mainloop, c->use_rtclock, command_table, PA_COMMAND_MAX);
638 
639     if (pa_client_conf_load_cookie(c->conf, cookie, sizeof(cookie)) < 0)
640         pa_log_info("No cookie loaded. Attempting to connect without.");
641 
642     t = pa_tagstruct_command(c, PA_COMMAND_AUTH, &tag);
643 
644     c->do_shm =
645         pa_mempool_is_shared(c->mempool) &&
646         c->is_local;
647 
648     pa_log_debug("SHM possible: %s", pa_yes_no(c->do_shm));
649 
650     /* Starting with protocol version 13 we use the MSB of the version
651      * tag for informing the other side if we could do SHM or not.
652      * Starting from version 31, second MSB is used to flag memfd support. */
653     pa_tagstruct_putu32(t, PA_PROTOCOL_VERSION | (c->do_shm ? PA_PROTOCOL_FLAG_SHM : 0) |
654                         (c->memfd_on_local ? PA_PROTOCOL_FLAG_MEMFD: 0));
655     pa_tagstruct_put_arbitrary(t, cookie, sizeof(cookie));
656 
657 #ifdef HAVE_CREDS
658 {
659     pa_creds ucred;
660 
661     if (pa_iochannel_creds_supported(io))
662         pa_iochannel_creds_enable(io);
663 
664     ucred.uid = getuid();
665     ucred.gid = getgid();
666 
667     pa_pstream_send_tagstruct_with_creds(c->pstream, t, &ucred);
668 }
669 #else
670     pa_pstream_send_tagstruct(c->pstream, t);
671 #endif
672 
673     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c, NULL);
674 
675     pa_context_set_state(c, PA_CONTEXT_AUTHORIZING);
676 
677     pa_context_unref(c);
678 }
679 
prepend_per_user(pa_strlist * l)680 static pa_strlist *prepend_per_user(pa_strlist *l) {
681     char *ufn;
682 
683     /* The per-user instance */
684     if ((ufn = pa_runtime_path(PA_NATIVE_DEFAULT_UNIX_SOCKET))) {
685         l = pa_strlist_prepend(l, ufn);
686         pa_xfree(ufn);
687     }
688 
689     return l;
690 }
691 
692 #ifndef OS_IS_WIN32
693 
context_autospawn(pa_context * c)694 static int context_autospawn(pa_context *c) {
695     pid_t pid;
696     int status, r;
697     struct sigaction sa;
698 
699     pa_context_ref(c);
700 
701     if (sigaction(SIGCHLD, NULL, &sa) < 0) {
702         pa_log_debug("sigaction() failed: %s", pa_cstrerror(errno));
703         pa_context_fail(c, PA_ERR_INTERNAL);
704         goto fail;
705     }
706 
707 #ifdef SA_NOCLDWAIT
708     if ((sa.sa_flags & SA_NOCLDWAIT) || sa.sa_handler == SIG_IGN) {
709 #else
710     if (sa.sa_handler == SIG_IGN) {
711 #endif
712         AUDIO_ERR_LOG("Process disabled waitpid(), cannot autospawn.");
713         pa_context_fail(c, PA_ERR_CONNECTIONREFUSED);
714         goto fail;
715     }
716 
717     pa_log_debug("Trying to autospawn...");
718 
719     if (c->spawn_api.prefork)
720         c->spawn_api.prefork();
721 
722     if ((pid = fork()) < 0) {
723         pa_log_error(_("fork(): %s"), pa_cstrerror(errno));
724         pa_context_fail(c, PA_ERR_INTERNAL);
725 
726         if (c->spawn_api.postfork)
727             c->spawn_api.postfork();
728 
729         goto fail;
730     } else if (!pid) {
731         /* Child */
732 
733         const char *state = NULL;
734         const char * argv[32];
735         unsigned n = 0;
736 
737         if (c->spawn_api.atfork)
738             c->spawn_api.atfork();
739 
740         /* We leave most of the cleaning up of the process environment
741          * to the executable. We only clean up the file descriptors to
742          * make sure the executable can actually be loaded
743          * correctly. */
744         pa_close_all(-1);
745 
746         /* Setup argv */
747         argv[n++] = c->conf->daemon_binary;
748         argv[n++] = "--start";
749 
750         while (n < PA_ELEMENTSOF(argv)-1) {
751             char *a;
752 
753             if (!(a = pa_split_spaces(c->conf->extra_arguments, &state)))
754                 break;
755 
756             argv[n++] = a;
757         }
758 
759         argv[n++] = NULL;
760         pa_assert(n <= PA_ELEMENTSOF(argv));
761 
762         execv(argv[0], (char * const *) argv);
763         _exit(1);
764     }
765 
766     /* Parent */
767 
768     if (c->spawn_api.postfork)
769         c->spawn_api.postfork();
770 
771     do {
772         r = waitpid(pid, &status, 0);
773     } while (r < 0 && errno == EINTR);
774 
775     if (r < 0) {
776 
777         if (errno != ECHILD) {
778             pa_log(_("waitpid(): %s"), pa_cstrerror(errno));
779             pa_context_fail(c, PA_ERR_INTERNAL);
780             goto fail;
781         }
782 
783         /* hmm, something already reaped our child, so we assume
784          * startup worked, even if we cannot know */
785 
786     } else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
787         AUDIO_ERR_LOG("Connection refused for status");
788         pa_context_fail(c, PA_ERR_CONNECTIONREFUSED);
789         goto fail;
790     }
791 
792     pa_context_unref(c);
793 
794     return 0;
795 
796 fail:
797 
798     pa_context_unref(c);
799 
800     return -1;
801 }
802 
803 #endif /* OS_IS_WIN32 */
804 
805 static void on_connection(pa_socket_client *client, pa_iochannel*io, void *userdata);
806 
807 #ifdef HAVE_DBUS
808 static void track_pulseaudio_on_dbus(pa_context *c, DBusBusType type, pa_dbus_wrap_connection **conn) {
809     DBusError error;
810 
811     pa_assert(c);
812     pa_assert(conn);
813 
814     dbus_error_init(&error);
815 
816     if (!(*conn = pa_dbus_wrap_connection_new(c->mainloop, c->use_rtclock, type, &error)) || dbus_error_is_set(&error)) {
817         pa_log_warn("Unable to contact DBUS: %s: %s", error.name, error.message);
818         goto fail;
819     }
820 
821     if (!dbus_connection_add_filter(pa_dbus_wrap_connection_get(*conn), filter_cb, c, NULL)) {
822         pa_log_warn("Failed to add filter function");
823         goto fail;
824     }
825     c->filter_added = true;
826 
827     if (pa_dbus_add_matches(
828                 pa_dbus_wrap_connection_get(*conn), &error,
829                 "type='signal',sender='" DBUS_SERVICE_DBUS "',interface='" DBUS_INTERFACE_DBUS "',member='NameOwnerChanged',arg0='org.pulseaudio.Server',arg1=''", NULL) < 0) {
830 
831         pa_log_warn("Unable to track org.pulseaudio.Server: %s: %s", error.name, error.message);
832         goto fail;
833     }
834 
835     return;
836 
837 fail:
838     if (*conn) {
839         pa_dbus_wrap_connection_free(*conn);
840         *conn = NULL;
841     }
842 
843     dbus_error_free(&error);
844 }
845 #endif
846 
847 static int try_next_connection(pa_context *c) {
848     char *u = NULL;
849     int r = -1;
850 
851     pa_assert(c);
852     pa_assert(!c->client);
853 
854     for (;;) {
855         pa_xfree(u);
856         u = NULL;
857 
858         c->server_list = pa_strlist_pop(c->server_list, &u);
859 
860         if (!u) {
861 
862 #ifndef OS_IS_WIN32
863             if (c->do_autospawn) {
864 
865                 if ((r = context_autospawn(c)) < 0)
866                     goto finish;
867 
868                 /* Autospawn only once */
869                 c->do_autospawn = false;
870 
871                 /* Connect only to per-user sockets this time */
872                 c->server_list = prepend_per_user(c->server_list);
873 
874                 /* Retry connection */
875                 continue;
876             }
877 #endif
878 
879 #ifdef HAVE_DBUS
880             if (c->no_fail && !c->server_specified) {
881                 if (!c->session_bus)
882                     track_pulseaudio_on_dbus(c, DBUS_BUS_SESSION, &c->session_bus);
883                 if (!c->system_bus)
884                     track_pulseaudio_on_dbus(c, DBUS_BUS_SYSTEM, &c->system_bus);
885 
886                 if (c->session_bus || c->system_bus) {
887                     pa_log_debug("Waiting for PA on D-Bus...");
888                     break;
889                 }
890             } else
891 #endif
892                 AUDIO_ERR_LOG("Connection refused for try connect");
893                 pa_context_fail(c, PA_ERR_CONNECTIONREFUSED);
894 
895             goto finish;
896         }
897 
898         pa_log_debug("Trying to connect to %s...", u);
899 
900         pa_xfree(c->server);
901         c->server = pa_xstrdup(u);
902 
903         if (!(c->client = pa_socket_client_new_string(c->mainloop, c->use_rtclock, u, PA_NATIVE_DEFAULT_PORT)))
904             continue;
905 
906         c->is_local = pa_socket_client_is_local(c->client);
907         pa_socket_client_set_callback(c->client, on_connection, c);
908         break;
909     }
910 
911     r = 0;
912 
913 finish:
914     pa_xfree(u);
915 
916     return r;
917 }
918 
919 static void on_connection(pa_socket_client *client, pa_iochannel*io, void *userdata) {
920     pa_context *c = userdata;
921     int saved_errno = errno;
922 
923     pa_assert(client);
924     pa_assert(c);
925     pa_assert(c->state == PA_CONTEXT_CONNECTING);
926 
927     pa_context_ref(c);
928 
929     pa_socket_client_unref(client);
930     c->client = NULL;
931 
932     if (!io) {
933         /* Try the next item in the list */
934         if (saved_errno == ECONNREFUSED ||
935             saved_errno == ETIMEDOUT ||
936             saved_errno == EHOSTUNREACH) {
937             try_next_connection(c);
938             goto finish;
939         }
940 
941         AUDIO_ERR_LOG("Connection refused for io");
942         pa_context_fail(c, PA_ERR_CONNECTIONREFUSED);
943         goto finish;
944     }
945 
946     setup_context(c, io);
947 
948 finish:
949     pa_context_unref(c);
950 }
951 
952 #ifdef HAVE_DBUS
953 static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *message, void *userdata) {
954     pa_context *c = userdata;
955     bool is_session;
956 
957     pa_assert(bus);
958     pa_assert(message);
959     pa_assert(c);
960 
961     if (c->state != PA_CONTEXT_CONNECTING)
962         goto finish;
963 
964     if (!c->no_fail)
965         goto finish;
966 
967     /* FIXME: We probably should check if this is actually the NameOwnerChanged we were looking for */
968 
969     is_session = c->session_bus && bus == pa_dbus_wrap_connection_get(c->session_bus);
970     pa_log_debug("Rock!! PulseAudio might be back on %s bus", is_session ? "session" : "system");
971 
972     if (is_session)
973         /* The user instance via PF_LOCAL */
974         c->server_list = prepend_per_user(c->server_list);
975     else
976         /* The system wide instance via PF_LOCAL */
977         c->server_list = pa_strlist_prepend(c->server_list, PA_SYSTEM_RUNTIME_PATH PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET);
978 
979     if (!c->client)
980         try_next_connection(c);
981 
982 finish:
983     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
984 }
985 #endif
986 
987 int pa_context_connect(
988         pa_context *c,
989         const char *server,
990         pa_context_flags_t flags,
991         const pa_spawn_api *api) {
992 
993     int r = -1;
994 
995     pa_assert(c);
996     pa_assert(PA_REFCNT_VALUE(c) >= 1);
997 
998     PA_CHECK_VALIDITY(c, !pa_detect_fork(), PA_ERR_FORKED);
999     PA_CHECK_VALIDITY(c, c->state == PA_CONTEXT_UNCONNECTED, PA_ERR_BADSTATE);
1000     PA_CHECK_VALIDITY(c, !(flags & ~(PA_CONTEXT_NOAUTOSPAWN|PA_CONTEXT_NOFAIL)), PA_ERR_INVALID);
1001     PA_CHECK_VALIDITY(c, !server || *server, PA_ERR_INVALID);
1002 
1003     if (server)
1004         c->conf->autospawn = false;
1005     else
1006         server = c->conf->default_server;
1007 
1008     pa_context_ref(c);
1009 
1010     c->no_fail = !!(flags & PA_CONTEXT_NOFAIL);
1011     c->server_specified = !!server;
1012     pa_assert(!c->server_list);
1013 
1014     if (server) {
1015         if (!(c->server_list = pa_strlist_parse(server))) {
1016             pa_context_fail(c, PA_ERR_INVALIDSERVER);
1017             goto finish;
1018         }
1019 
1020     } else {
1021         char *d;
1022 
1023         /* Prepend in reverse order */
1024 
1025         /* Follow the X display */
1026         if (c->conf->auto_connect_display) {
1027             if ((d = getenv("DISPLAY"))) {
1028                 d = pa_xstrndup(d, strcspn(d, ":"));
1029 
1030                 if (*d)
1031                     c->server_list = pa_strlist_prepend(c->server_list, d);
1032 
1033                 pa_xfree(d);
1034             }
1035         }
1036 
1037         /* Add TCP/IP on the localhost */
1038         if (c->conf->auto_connect_localhost) {
1039 #if defined(HAVE_IPV6) && !defined(OS_IS_WIN32)
1040             /* FIXME: pa_socket_client does not support IPv6 on Windows */
1041             c->server_list = pa_strlist_prepend(c->server_list, "tcp6:[::1]");
1042 #endif
1043             c->server_list = pa_strlist_prepend(c->server_list, "tcp4:127.0.0.1");
1044         }
1045 
1046         /* The system wide instance via PF_LOCAL */
1047 #ifndef OS_IS_WIN32
1048         c->server_list = pa_strlist_prepend(c->server_list, PA_SYSTEM_RUNTIME_PATH PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET);
1049 #else
1050         /* see change_user in src/daemon/main.c */
1051         char *run_path = pa_sprintf_malloc("%s" PA_PATH_SEP "run" PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET, pa_win32_get_system_appdata());
1052         c->server_list = pa_strlist_prepend(c->server_list, run_path);
1053         pa_xfree(run_path);
1054 #endif
1055 
1056         /* The user instance via PF_LOCAL */
1057         c->server_list = prepend_per_user(c->server_list);
1058     }
1059 
1060     /* Set up autospawning */
1061     if (!(flags & PA_CONTEXT_NOAUTOSPAWN) && c->conf->autospawn) {
1062 
1063 #ifdef HAVE_GETUID
1064         if (getuid() == 0)
1065             pa_log_debug("Not doing autospawn since we are root.");
1066         else {
1067             c->do_autospawn = true;
1068 
1069             if (api)
1070                 c->spawn_api = *api;
1071         }
1072 #endif
1073     }
1074 
1075     pa_context_set_state(c, PA_CONTEXT_CONNECTING);
1076     r = try_next_connection(c);
1077 
1078 finish:
1079     pa_context_unref(c);
1080 
1081     return r;
1082 }
1083 
1084 void pa_context_disconnect(pa_context *c) {
1085     pa_assert(c);
1086     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1087 
1088     if (pa_detect_fork())
1089         return;
1090 
1091     if (PA_CONTEXT_IS_GOOD(c->state))
1092         pa_context_set_state(c, PA_CONTEXT_TERMINATED);
1093 }
1094 
1095 pa_context_state_t pa_context_get_state(const pa_context *c) {
1096     pa_assert(c);
1097     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1098 
1099     return c->state;
1100 }
1101 
1102 int pa_context_errno(const pa_context *c) {
1103 
1104     if (!c)
1105         return PA_ERR_INVALID;
1106 
1107     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1108 
1109     return c->error->error;
1110 }
1111 
1112 void pa_context_set_state_callback(pa_context *c, pa_context_notify_cb_t cb, void *userdata) {
1113     pa_assert(c);
1114     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1115 
1116     if (pa_detect_fork())
1117         return;
1118 
1119     if (c->state == PA_CONTEXT_TERMINATED || c->state == PA_CONTEXT_FAILED)
1120         return;
1121 
1122     c->state_callback = cb;
1123     c->state_userdata = userdata;
1124 }
1125 
1126 void pa_context_set_event_callback(pa_context *c, pa_context_event_cb_t cb, void *userdata) {
1127     pa_assert(c);
1128     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1129 
1130     if (pa_detect_fork())
1131         return;
1132 
1133     if (c->state == PA_CONTEXT_TERMINATED || c->state == PA_CONTEXT_FAILED)
1134         return;
1135 
1136     c->event_callback = cb;
1137     c->event_userdata = userdata;
1138 }
1139 
1140 int pa_context_is_pending(const pa_context *c) {
1141     pa_assert(c);
1142     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1143 
1144     PA_CHECK_VALIDITY(c, !pa_detect_fork(), PA_ERR_FORKED);
1145     PA_CHECK_VALIDITY(c, PA_CONTEXT_IS_GOOD(c->state), PA_ERR_BADSTATE);
1146 
1147     return (c->pstream && pa_pstream_is_pending(c->pstream)) ||
1148         (c->pdispatch && pa_pdispatch_is_pending(c->pdispatch)) ||
1149         c->client;
1150 }
1151 
1152 static void set_dispatch_callbacks(pa_operation *o);
1153 
1154 static void pdispatch_drain_callback(pa_pdispatch*pd, void *userdata) {
1155     set_dispatch_callbacks(userdata);
1156 }
1157 
1158 static void pstream_drain_callback(pa_pstream *s, void *userdata) {
1159     set_dispatch_callbacks(userdata);
1160 }
1161 
1162 static void set_dispatch_callbacks(pa_operation *o) {
1163     int done = 1;
1164 
1165     pa_assert(o);
1166     pa_assert(PA_REFCNT_VALUE(o) >= 1);
1167     pa_assert(o->context);
1168     pa_assert(PA_REFCNT_VALUE(o->context) >= 1);
1169     pa_assert(o->context->state == PA_CONTEXT_READY);
1170 
1171     pa_pstream_set_drain_callback(o->context->pstream, NULL, NULL);
1172     pa_pdispatch_set_drain_callback(o->context->pdispatch, NULL, NULL);
1173 
1174     if (pa_pdispatch_is_pending(o->context->pdispatch)) {
1175         pa_pdispatch_set_drain_callback(o->context->pdispatch, pdispatch_drain_callback, o);
1176         done = 0;
1177     }
1178 
1179     if (pa_pstream_is_pending(o->context->pstream)) {
1180         pa_pstream_set_drain_callback(o->context->pstream, pstream_drain_callback, o);
1181         done = 0;
1182     }
1183 
1184     if (done) {
1185         if (o->callback) {
1186             pa_context_notify_cb_t cb = (pa_context_notify_cb_t) o->callback;
1187             cb(o->context, o->userdata);
1188         }
1189 
1190         pa_operation_done(o);
1191         pa_operation_unref(o);
1192     }
1193 }
1194 
1195 pa_operation* pa_context_drain(pa_context *c, pa_context_notify_cb_t cb, void *userdata) {
1196     pa_operation *o;
1197 
1198     pa_assert(c);
1199     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1200 
1201     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1202     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1203     PA_CHECK_VALIDITY_RETURN_NULL(c, pa_context_is_pending(c), PA_ERR_BADSTATE);
1204 
1205     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1206     set_dispatch_callbacks(pa_operation_ref(o));
1207 
1208     return o;
1209 }
1210 
1211 void pa_context_simple_ack_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1212     pa_operation *o = userdata;
1213     int success = 1;
1214 
1215     pa_assert(pd);
1216     pa_assert(o);
1217     pa_assert(PA_REFCNT_VALUE(o) >= 1);
1218 
1219     if (!o->context)
1220         goto finish;
1221 
1222     if (command != PA_COMMAND_REPLY) {
1223         if (pa_context_handle_error(o->context, command, t, false) < 0)
1224             goto finish;
1225 
1226         success = 0;
1227     } else if (!pa_tagstruct_eof(t)) {
1228         pa_context_fail(o->context, PA_ERR_PROTOCOL);
1229         goto finish;
1230     }
1231 
1232     if (o->callback) {
1233         pa_context_success_cb_t cb = (pa_context_success_cb_t) o->callback;
1234         cb(o->context, success, o->userdata);
1235     }
1236 
1237 finish:
1238     pa_operation_done(o);
1239     pa_operation_unref(o);
1240 }
1241 
1242 pa_operation* pa_context_send_simple_command(pa_context *c, uint32_t command, pa_pdispatch_cb_t internal_cb, pa_operation_cb_t cb, void *userdata) {
1243     pa_tagstruct *t;
1244     pa_operation *o;
1245     uint32_t tag;
1246 
1247     pa_assert(c);
1248     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1249 
1250     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1251     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1252 
1253     o = pa_operation_new(c, NULL, cb, userdata);
1254 
1255     t = pa_tagstruct_command(c, command, &tag);
1256     pa_pstream_send_tagstruct(c->pstream, t);
1257     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, internal_cb, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1258 
1259     return o;
1260 }
1261 
1262 pa_operation* pa_context_exit_daemon(pa_context *c, pa_context_success_cb_t cb, void *userdata) {
1263     pa_assert(c);
1264     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1265 
1266     return pa_context_send_simple_command(c, PA_COMMAND_EXIT, pa_context_simple_ack_callback, (pa_operation_cb_t) cb, userdata);
1267 }
1268 
1269 pa_operation* pa_context_set_default_sink(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata) {
1270     pa_tagstruct *t;
1271     pa_operation *o;
1272     uint32_t tag;
1273 
1274     pa_assert(c);
1275     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1276 
1277     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1278     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1279 
1280     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1281     t = pa_tagstruct_command(c, PA_COMMAND_SET_DEFAULT_SINK, &tag);
1282     pa_tagstruct_puts(t, name);
1283     pa_pstream_send_tagstruct(c->pstream, t);
1284     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT,  pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1285 
1286     return o;
1287 }
1288 
1289 pa_operation* pa_context_set_default_source(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata) {
1290     pa_tagstruct *t;
1291     pa_operation *o;
1292     uint32_t tag;
1293 
1294     pa_assert(c);
1295     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1296 
1297     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1298     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1299 
1300     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1301     t = pa_tagstruct_command(c, PA_COMMAND_SET_DEFAULT_SOURCE, &tag);
1302     pa_tagstruct_puts(t, name);
1303     pa_pstream_send_tagstruct(c->pstream, t);
1304     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT,  pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1305 
1306     return o;
1307 }
1308 
1309 int pa_context_is_local(const pa_context *c) {
1310     pa_assert(c);
1311     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1312 
1313     PA_CHECK_VALIDITY_RETURN_ANY(c, !pa_detect_fork(), PA_ERR_FORKED, -1);
1314     PA_CHECK_VALIDITY_RETURN_ANY(c, PA_CONTEXT_IS_GOOD(c->state), PA_ERR_BADSTATE, -1);
1315 
1316     return c->is_local;
1317 }
1318 
1319 pa_operation* pa_context_set_name(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata) {
1320     pa_operation *o;
1321 
1322     pa_assert(c);
1323     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1324     pa_assert(name);
1325 
1326     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1327     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1328 
1329     if (c->version >= 13) {
1330         pa_proplist *p = pa_proplist_new();
1331 
1332         pa_proplist_sets(p, PA_PROP_APPLICATION_NAME, name);
1333         o = pa_context_proplist_update(c, PA_UPDATE_REPLACE, p, cb, userdata);
1334         pa_proplist_free(p);
1335     } else {
1336         pa_tagstruct *t;
1337         uint32_t tag;
1338 
1339         o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1340         t = pa_tagstruct_command(c, PA_COMMAND_SET_CLIENT_NAME, &tag);
1341         pa_tagstruct_puts(t, name);
1342         pa_pstream_send_tagstruct(c->pstream, t);
1343         pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT,  pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1344     }
1345 
1346     return o;
1347 }
1348 
1349 const char* pa_get_library_version(void) {
1350     return pa_get_headers_version();
1351 }
1352 
1353 const char* pa_context_get_server(const pa_context *c) {
1354     pa_assert(c);
1355     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1356 
1357     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1358     PA_CHECK_VALIDITY_RETURN_NULL(c, c->server, PA_ERR_NOENTITY);
1359 
1360     if (*c->server == '{') {
1361         char *e = strchr(c->server+1, '}');
1362         return e ? e+1 : c->server;
1363     }
1364 
1365     return c->server;
1366 }
1367 
1368 uint32_t pa_context_get_protocol_version(const pa_context *c) {
1369     return PA_PROTOCOL_VERSION;
1370 }
1371 
1372 uint32_t pa_context_get_server_protocol_version(const pa_context *c) {
1373     pa_assert(c);
1374     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1375 
1376     PA_CHECK_VALIDITY_RETURN_ANY(c, !pa_detect_fork(), PA_ERR_FORKED, PA_INVALID_INDEX);
1377     PA_CHECK_VALIDITY_RETURN_ANY(c, PA_CONTEXT_IS_GOOD(c->state), PA_ERR_BADSTATE, PA_INVALID_INDEX);
1378 
1379     return c->version;
1380 }
1381 
1382 pa_tagstruct *pa_tagstruct_command(pa_context *c, uint32_t command, uint32_t *tag) {
1383     pa_tagstruct *t;
1384 
1385     pa_assert(c);
1386     pa_assert(tag);
1387 
1388     t = pa_tagstruct_new();
1389     pa_tagstruct_putu32(t, command);
1390     pa_tagstruct_putu32(t, *tag = c->ctag++);
1391 
1392     return t;
1393 }
1394 
1395 uint32_t pa_context_get_index(const pa_context *c) {
1396     pa_assert(c);
1397     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1398 
1399     PA_CHECK_VALIDITY_RETURN_ANY(c, !pa_detect_fork(), PA_ERR_FORKED, PA_INVALID_INDEX);
1400     PA_CHECK_VALIDITY_RETURN_ANY(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE, PA_INVALID_INDEX);
1401     PA_CHECK_VALIDITY_RETURN_ANY(c, c->version >= 13, PA_ERR_NOTSUPPORTED, PA_INVALID_INDEX);
1402 
1403     return c->client_index;
1404 }
1405 
1406 pa_operation *pa_context_proplist_update(pa_context *c, pa_update_mode_t mode, const pa_proplist *p, pa_context_success_cb_t cb, void *userdata) {
1407     pa_operation *o;
1408     pa_tagstruct *t;
1409     uint32_t tag;
1410 
1411     pa_assert(c);
1412     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1413 
1414     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1415     PA_CHECK_VALIDITY_RETURN_NULL(c, mode == PA_UPDATE_SET || mode == PA_UPDATE_MERGE || mode == PA_UPDATE_REPLACE, PA_ERR_INVALID);
1416     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1417     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 13, PA_ERR_NOTSUPPORTED);
1418 
1419     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1420 
1421     t = pa_tagstruct_command(c, PA_COMMAND_UPDATE_CLIENT_PROPLIST, &tag);
1422     pa_tagstruct_putu32(t, (uint32_t) mode);
1423     pa_tagstruct_put_proplist(t, p);
1424 
1425     pa_pstream_send_tagstruct(c->pstream, t);
1426     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1427 
1428     /* Please note that we don't update c->proplist here, because we
1429      * don't export that field */
1430 
1431     return o;
1432 }
1433 
1434 pa_operation *pa_context_proplist_remove(pa_context *c, const char *const keys[], pa_context_success_cb_t cb, void *userdata) {
1435     pa_operation *o;
1436     pa_tagstruct *t;
1437     uint32_t tag;
1438     const char * const *k;
1439 
1440     pa_assert(c);
1441     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1442 
1443     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1444     PA_CHECK_VALIDITY_RETURN_NULL(c, keys && keys[0], PA_ERR_INVALID);
1445     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1446     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 13, PA_ERR_NOTSUPPORTED);
1447 
1448     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1449 
1450     t = pa_tagstruct_command(c, PA_COMMAND_REMOVE_CLIENT_PROPLIST, &tag);
1451 
1452     for (k = keys; *k; k++)
1453         pa_tagstruct_puts(t, *k);
1454 
1455     pa_tagstruct_puts(t, NULL);
1456 
1457     pa_pstream_send_tagstruct(c->pstream, t);
1458     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1459 
1460     /* Please note that we don't update c->proplist here, because we
1461      * don't export that field */
1462 
1463     return o;
1464 }
1465 
1466 void pa_command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1467     pa_context *c = userdata;
1468     uint32_t idx;
1469     const char *name;
1470 
1471     pa_assert(pd);
1472     pa_assert(command == PA_COMMAND_EXTENSION);
1473     pa_assert(t);
1474     pa_assert(c);
1475     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1476 
1477     pa_context_ref(c);
1478 
1479     if (c->version < 15) {
1480         pa_context_fail(c, PA_ERR_PROTOCOL);
1481         goto finish;
1482     }
1483 
1484     if (pa_tagstruct_getu32(t, &idx) < 0 ||
1485         pa_tagstruct_gets(t, &name) < 0) {
1486         pa_context_fail(c, PA_ERR_PROTOCOL);
1487         goto finish;
1488     }
1489 
1490     if (pa_streq(name, "module-device-manager"))
1491         pa_ext_device_manager_command(c, tag, t);
1492     else if (pa_streq(name, "module-device-restore"))
1493         pa_ext_device_restore_command(c, tag, t);
1494     else if (pa_streq(name, "module-stream-restore"))
1495         pa_ext_stream_restore_command(c, tag, t);
1496     else
1497         pa_log(_("Received message for unknown extension '%s'"), name);
1498 
1499 finish:
1500     pa_context_unref(c);
1501 }
1502 
1503 static void pa_command_enable_srbchannel(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1504     pa_context *c = userdata;
1505 
1506 #ifdef HAVE_CREDS
1507     pa_cmsg_ancil_data *ancil = NULL;
1508 
1509     pa_assert(pd);
1510     pa_assert(command == PA_COMMAND_ENABLE_SRBCHANNEL);
1511     pa_assert(t);
1512     pa_assert(c);
1513     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1514 
1515     ancil = pa_pdispatch_take_ancil_data(pd);
1516     if (!ancil)
1517         goto fail;
1518 
1519     /* Currently only one srb channel is supported, might change in future versions */
1520     if (c->srb_template.readfd != -1)
1521         goto fail;
1522 
1523     if (ancil->nfd != 2 || ancil->fds[0] == -1 || ancil->fds[1] == -1)
1524         goto fail;
1525 
1526     pa_context_ref(c);
1527 
1528     c->srb_template.readfd = ancil->fds[0];
1529     c->srb_template.writefd = ancil->fds[1];
1530     c->srb_setup_tag = tag;
1531 
1532     pa_context_unref(c);
1533 
1534     ancil->close_fds_on_cleanup = false;
1535     return;
1536 
1537 fail:
1538     if (ancil)
1539         pa_cmsg_ancil_data_close_fds(ancil);
1540 
1541     pa_context_fail(c, PA_ERR_PROTOCOL);
1542     return;
1543 #else
1544     pa_assert(c);
1545     pa_context_fail(c, PA_ERR_PROTOCOL);
1546 #endif
1547 }
1548 
1549 static void pa_command_disable_srbchannel(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1550     pa_context *c = userdata;
1551     pa_tagstruct *t2;
1552 
1553     pa_assert(pd);
1554     pa_assert(command == PA_COMMAND_DISABLE_SRBCHANNEL);
1555     pa_assert(t);
1556     pa_assert(c);
1557     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1558 
1559     pa_pstream_set_srbchannel(c->pstream, NULL);
1560 
1561     c->srb_template.readfd = -1;
1562     c->srb_template.writefd = -1;
1563     if (c->srb_template.memblock) {
1564         pa_memblock_unref(c->srb_template.memblock);
1565         c->srb_template.memblock = NULL;
1566     }
1567 
1568     /* Send disable command back again */
1569     t2 = pa_tagstruct_new();
1570     pa_tagstruct_putu32(t2, PA_COMMAND_DISABLE_SRBCHANNEL);
1571     pa_tagstruct_putu32(t2, tag);
1572     pa_pstream_send_tagstruct(c->pstream, t2);
1573 }
1574 
1575 static void pa_command_register_memfd_shmid(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1576     pa_context *c = userdata;
1577 
1578     pa_assert(pd);
1579     pa_assert(command == PA_COMMAND_REGISTER_MEMFD_SHMID);
1580     pa_assert(t);
1581     pa_assert(c);
1582     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1583 
1584     if (pa_common_command_register_memfd_shmid(c->pstream, pd, c->version, command, t))
1585         pa_context_fail(c, PA_ERR_PROTOCOL);
1586 }
1587 
1588 void pa_command_client_event(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1589     pa_context *c = userdata;
1590     pa_proplist *pl = NULL;
1591     const char *event;
1592 
1593     pa_assert(pd);
1594     pa_assert(command == PA_COMMAND_CLIENT_EVENT);
1595     pa_assert(t);
1596     pa_assert(c);
1597     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1598 
1599     pa_context_ref(c);
1600 
1601     if (c->version < 15) {
1602         pa_context_fail(c, PA_ERR_PROTOCOL);
1603         goto finish;
1604     }
1605 
1606     pl = pa_proplist_new();
1607 
1608     if (pa_tagstruct_gets(t, &event) < 0 ||
1609         pa_tagstruct_get_proplist(t, pl) < 0 ||
1610         !pa_tagstruct_eof(t) || !event) {
1611         pa_context_fail(c, PA_ERR_PROTOCOL);
1612         goto finish;
1613     }
1614 
1615     if (c->event_callback)
1616         c->event_callback(c, event, pl, c->event_userdata);
1617 
1618 finish:
1619     pa_context_unref(c);
1620 
1621     if (pl)
1622         pa_proplist_free(pl);
1623 }
1624 
1625 pa_time_event* pa_context_rttime_new(const pa_context *c, pa_usec_t usec, pa_time_event_cb_t cb, void *userdata) {
1626     struct timeval tv;
1627 
1628     pa_assert(c);
1629     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1630     pa_assert(c->mainloop);
1631 
1632     if (usec == PA_USEC_INVALID)
1633         return c->mainloop->time_new(c->mainloop, NULL, cb, userdata);
1634 
1635     pa_timeval_rtstore(&tv, usec, c->use_rtclock);
1636 
1637     return c->mainloop->time_new(c->mainloop, &tv, cb, userdata);
1638 }
1639 
1640 void pa_context_rttime_restart(const pa_context *c, pa_time_event *e, pa_usec_t usec) {
1641     struct timeval tv;
1642 
1643     pa_assert(c);
1644     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1645     pa_assert(c->mainloop);
1646 
1647     if (usec == PA_USEC_INVALID)
1648         c->mainloop->time_restart(e, NULL);
1649     else {
1650         pa_timeval_rtstore(&tv, usec, c->use_rtclock);
1651         c->mainloop->time_restart(e, &tv);
1652     }
1653 }
1654 
1655 size_t pa_context_get_tile_size(const pa_context *c, const pa_sample_spec *ss) {
1656     size_t fs, mbs;
1657 
1658     pa_assert(c);
1659     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1660 
1661     PA_CHECK_VALIDITY_RETURN_ANY(c, !pa_detect_fork(), PA_ERR_FORKED, (size_t) -1);
1662     PA_CHECK_VALIDITY_RETURN_ANY(c, !ss || pa_sample_spec_valid(ss), PA_ERR_INVALID, (size_t) -1);
1663 
1664     fs = ss ? pa_frame_size(ss) : 1;
1665     mbs = PA_ROUND_DOWN(pa_mempool_block_size_max(c->mempool), fs);
1666     return PA_MAX(mbs, fs);
1667 }
1668 
1669 int pa_context_load_cookie_from_file(pa_context *c, const char *cookie_file_path) {
1670     pa_assert(c);
1671     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1672 
1673     PA_CHECK_VALIDITY(c, !pa_detect_fork(), PA_ERR_FORKED);
1674     PA_CHECK_VALIDITY(c, c->state == PA_CONTEXT_UNCONNECTED, PA_ERR_BADSTATE);
1675     PA_CHECK_VALIDITY(c, !cookie_file_path || *cookie_file_path, PA_ERR_INVALID);
1676 
1677     pa_client_conf_set_cookie_file_from_application(c->conf, cookie_file_path);
1678 
1679     return 0;
1680 }
1681