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