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