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