]> code.delx.au - pulseaudio/blob - src/pulse/context.c
fix bad memory access when initializing client proplist
[pulseaudio] / src / pulse / context.c
1 /* $Id$ */
2
3 /***
4 This file is part of PulseAudio.
5
6 Copyright 2004-2006 Lennart Poettering
7 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
8
9 PulseAudio is free software; you can redistribute it and/or modify
10 it under the terms of the GNU Lesser General Public License as published
11 by the Free Software Foundation; either version 2 of the License,
12 or (at your option) any later version.
13
14 PulseAudio is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public License
20 along with PulseAudio; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22 USA.
23 ***/
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
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 #include <limits.h>
38 #include <locale.h>
39
40 #ifdef HAVE_SYS_WAIT_H
41 #include <sys/wait.h>
42 #endif
43
44 #ifdef HAVE_SYS_SOCKET_H
45 #include <sys/socket.h>
46 #endif
47 #ifdef HAVE_SYS_UN_H
48 #include <sys/un.h>
49 #endif
50 #ifdef HAVE_NETDB_H
51 #include <netdb.h>
52 #endif
53
54 #include <pulse/version.h>
55 #include <pulse/xmalloc.h>
56 #include <pulse/utf8.h>
57 #include <pulse/util.h>
58
59 #include <pulsecore/winsock.h>
60 #include <pulsecore/core-error.h>
61
62 #include <pulsecore/native-common.h>
63 #include <pulsecore/pdispatch.h>
64 #include <pulsecore/pstream.h>
65 #include <pulsecore/dynarray.h>
66 #include <pulsecore/socket-client.h>
67 #include <pulsecore/pstream-util.h>
68 #include <pulsecore/core-util.h>
69 #include <pulsecore/log.h>
70 #include <pulsecore/socket-util.h>
71 #include <pulsecore/creds.h>
72 #include <pulsecore/macro.h>
73
74 #include "internal.h"
75
76 #include "client-conf.h"
77
78 #ifdef HAVE_X11
79 #include "client-conf-x11.h"
80 #endif
81
82 #include "context.h"
83
84 #define AUTOSPAWN_LOCK "autospawn.lock"
85
86 static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
87 [PA_COMMAND_REQUEST] = pa_command_request,
88 [PA_COMMAND_OVERFLOW] = pa_command_overflow_or_underflow,
89 [PA_COMMAND_UNDERFLOW] = pa_command_overflow_or_underflow,
90 [PA_COMMAND_PLAYBACK_STREAM_KILLED] = pa_command_stream_killed,
91 [PA_COMMAND_RECORD_STREAM_KILLED] = pa_command_stream_killed,
92 [PA_COMMAND_PLAYBACK_STREAM_MOVED] = pa_command_stream_moved,
93 [PA_COMMAND_RECORD_STREAM_MOVED] = pa_command_stream_moved,
94 [PA_COMMAND_PLAYBACK_STREAM_SUSPENDED] = pa_command_stream_suspended,
95 [PA_COMMAND_RECORD_STREAM_SUSPENDED] = pa_command_stream_suspended,
96 [PA_COMMAND_SUBSCRIBE_EVENT] = pa_command_subscribe_event
97 };
98
99 static void unlock_autospawn_lock_file(pa_context *c) {
100 pa_assert(c);
101
102 if (c->autospawn_lock_fd >= 0) {
103 char lf[PATH_MAX];
104 pa_runtime_path(AUTOSPAWN_LOCK, lf, sizeof(lf));
105
106 pa_unlock_lockfile(lf, c->autospawn_lock_fd);
107 c->autospawn_lock_fd = -1;
108 }
109 }
110
111 static void context_free(pa_context *c);
112
113 pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) {
114 return pa_context_new_with_proplist(mainloop, name, NULL);
115 }
116
117 pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char *name, pa_proplist *p) {
118 pa_context *c;
119
120 pa_assert(mainloop);
121
122 if (!name && !pa_proplist_contains(p, PA_PROP_APPLICATION_NAME))
123 return NULL;
124
125 c = pa_xnew(pa_context, 1);
126 PA_REFCNT_INIT(c);
127
128 c->proplist = p ? pa_proplist_copy(p) : pa_proplist_new();
129
130 if (name)
131 pa_proplist_sets(c->proplist, PA_PROP_APPLICATION_NAME, name);
132
133 c->mainloop = mainloop;
134 c->client = NULL;
135 c->pstream = NULL;
136 c->pdispatch = NULL;
137 c->playback_streams = pa_dynarray_new();
138 c->record_streams = pa_dynarray_new();
139 c->client_index = PA_INVALID_INDEX;
140
141 PA_LLIST_HEAD_INIT(pa_stream, c->streams);
142 PA_LLIST_HEAD_INIT(pa_operation, c->operations);
143
144 c->error = PA_OK;
145 c->state = PA_CONTEXT_UNCONNECTED;
146 c->ctag = 0;
147 c->csyncid = 0;
148
149 c->state_callback = NULL;
150 c->state_userdata = NULL;
151
152 c->subscribe_callback = NULL;
153 c->subscribe_userdata = NULL;
154
155 c->is_local = -1;
156 c->server_list = NULL;
157 c->server = NULL;
158 c->autospawn_lock_fd = -1;
159 memset(&c->spawn_api, 0, sizeof(c->spawn_api));
160 c->do_autospawn = 0;
161
162 #ifndef MSG_NOSIGNAL
163 #ifdef SIGPIPE
164 pa_check_signal_is_blocked(SIGPIPE);
165 #endif
166 #endif
167
168 c->conf = pa_client_conf_new();
169 pa_client_conf_load(c->conf, NULL);
170 #ifdef HAVE_X11
171 pa_client_conf_from_x11(c->conf, NULL);
172 #endif
173 pa_client_conf_env(c->conf);
174
175 if (!(c->mempool = pa_mempool_new(!c->conf->disable_shm))) {
176
177 if (!c->conf->disable_shm)
178 c->mempool = pa_mempool_new(0);
179
180 if (!c->mempool) {
181 context_free(c);
182 return NULL;
183 }
184 }
185
186 return c;
187 }
188
189 static void context_free(pa_context *c) {
190 pa_assert(c);
191
192 unlock_autospawn_lock_file(c);
193
194 while (c->operations)
195 pa_operation_cancel(c->operations);
196
197 while (c->streams)
198 pa_stream_set_state(c->streams, PA_STREAM_TERMINATED);
199
200 if (c->client)
201 pa_socket_client_unref(c->client);
202 if (c->pdispatch)
203 pa_pdispatch_unref(c->pdispatch);
204 if (c->pstream) {
205 pa_pstream_unlink(c->pstream);
206 pa_pstream_unref(c->pstream);
207 }
208
209 if (c->record_streams)
210 pa_dynarray_free(c->record_streams, NULL, NULL);
211 if (c->playback_streams)
212 pa_dynarray_free(c->playback_streams, NULL, NULL);
213
214 if (c->mempool)
215 pa_mempool_free(c->mempool);
216
217 if (c->conf)
218 pa_client_conf_free(c->conf);
219
220 pa_strlist_free(c->server_list);
221
222 if (c->proplist)
223 pa_proplist_free(c->proplist);
224
225 pa_xfree(c->server);
226 pa_xfree(c);
227 }
228
229 pa_context* pa_context_ref(pa_context *c) {
230 pa_assert(c);
231 pa_assert(PA_REFCNT_VALUE(c) >= 1);
232
233 PA_REFCNT_INC(c);
234 return c;
235 }
236
237 void pa_context_unref(pa_context *c) {
238 pa_assert(c);
239 pa_assert(PA_REFCNT_VALUE(c) >= 1);
240
241 if (PA_REFCNT_DEC(c) <= 0)
242 context_free(c);
243 }
244
245 void pa_context_set_state(pa_context *c, pa_context_state_t st) {
246 pa_assert(c);
247 pa_assert(PA_REFCNT_VALUE(c) >= 1);
248
249 if (c->state == st)
250 return;
251
252 pa_context_ref(c);
253
254 c->state = st;
255 if (c->state_callback)
256 c->state_callback(c, c->state_userdata);
257
258 if (st == PA_CONTEXT_FAILED || st == PA_CONTEXT_TERMINATED) {
259 pa_stream *s;
260
261 s = c->streams ? pa_stream_ref(c->streams) : NULL;
262 while (s) {
263 pa_stream *n = s->next ? pa_stream_ref(s->next) : NULL;
264 pa_stream_set_state(s, st == PA_CONTEXT_FAILED ? PA_STREAM_FAILED : PA_STREAM_TERMINATED);
265 pa_stream_unref(s);
266 s = n;
267 }
268
269 if (c->pdispatch)
270 pa_pdispatch_unref(c->pdispatch);
271 c->pdispatch = NULL;
272
273 if (c->pstream) {
274 pa_pstream_unlink(c->pstream);
275 pa_pstream_unref(c->pstream);
276 }
277 c->pstream = NULL;
278
279 if (c->client)
280 pa_socket_client_unref(c->client);
281 c->client = NULL;
282 }
283
284 pa_context_unref(c);
285 }
286
287 void pa_context_fail(pa_context *c, int error) {
288 pa_assert(c);
289 pa_assert(PA_REFCNT_VALUE(c) >= 1);
290
291 pa_context_set_error(c, error);
292 pa_context_set_state(c, PA_CONTEXT_FAILED);
293 }
294
295 int pa_context_set_error(pa_context *c, int error) {
296 pa_assert(error >= 0);
297 pa_assert(error < PA_ERR_MAX);
298
299 if (c)
300 c->error = error;
301
302 return error;
303 }
304
305 static void pstream_die_callback(pa_pstream *p, void *userdata) {
306 pa_context *c = userdata;
307
308 pa_assert(p);
309 pa_assert(c);
310
311 pa_context_fail(c, PA_ERR_CONNECTIONTERMINATED);
312 }
313
314 static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata) {
315 pa_context *c = userdata;
316
317 pa_assert(p);
318 pa_assert(packet);
319 pa_assert(c);
320
321 pa_context_ref(c);
322
323 if (pa_pdispatch_run(c->pdispatch, packet, creds, c) < 0)
324 pa_context_fail(c, PA_ERR_PROTOCOL);
325
326 pa_context_unref(c);
327 }
328
329 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) {
330 pa_context *c = userdata;
331 pa_stream *s;
332
333 pa_assert(p);
334 pa_assert(chunk);
335 pa_assert(chunk->memblock);
336 pa_assert(chunk->length);
337 pa_assert(c);
338 pa_assert(PA_REFCNT_VALUE(c) >= 1);
339
340 pa_context_ref(c);
341
342 if ((s = pa_dynarray_get(c->record_streams, channel))) {
343
344 pa_assert(seek == PA_SEEK_RELATIVE);
345 pa_assert(offset == 0);
346
347 pa_memblockq_seek(s->record_memblockq, offset, seek);
348 pa_memblockq_push_align(s->record_memblockq, chunk);
349
350 if (s->read_callback) {
351 size_t l;
352
353 if ((l = pa_memblockq_get_length(s->record_memblockq)) > 0)
354 s->read_callback(s, l, s->read_userdata);
355 }
356 }
357
358 pa_context_unref(c);
359 }
360
361 int pa_context_handle_error(pa_context *c, uint32_t command, pa_tagstruct *t) {
362 pa_assert(c);
363 pa_assert(PA_REFCNT_VALUE(c) >= 1);
364
365 if (command == PA_COMMAND_ERROR) {
366 pa_assert(t);
367
368 if (pa_tagstruct_getu32(t, &c->error) < 0) {
369 pa_context_fail(c, PA_ERR_PROTOCOL);
370 return -1;
371
372 }
373 } else if (command == PA_COMMAND_TIMEOUT)
374 c->error = PA_ERR_TIMEOUT;
375 else {
376 pa_context_fail(c, PA_ERR_PROTOCOL);
377 return -1;
378 }
379
380 return 0;
381 }
382
383 static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
384 pa_context *c = userdata;
385
386 pa_assert(pd);
387 pa_assert(c);
388 pa_assert(c->state == PA_CONTEXT_AUTHORIZING || c->state == PA_CONTEXT_SETTING_NAME);
389
390 pa_context_ref(c);
391
392 if (command != PA_COMMAND_REPLY) {
393
394 if (pa_context_handle_error(c, command, t) < 0)
395 pa_context_fail(c, PA_ERR_PROTOCOL);
396
397 pa_context_fail(c, c->error);
398 goto finish;
399 }
400
401 switch(c->state) {
402 case PA_CONTEXT_AUTHORIZING: {
403 pa_tagstruct *reply;
404
405 if (pa_tagstruct_getu32(t, &c->version) < 0 ||
406 !pa_tagstruct_eof(t)) {
407 pa_context_fail(c, PA_ERR_PROTOCOL);
408 goto finish;
409 }
410
411 /* Minimum supported version */
412 if (c->version < 8) {
413 pa_context_fail(c, PA_ERR_VERSION);
414 goto finish;
415 }
416
417 /* Enable shared memory support if possible */
418 if (c->version >= 10 &&
419 pa_mempool_is_shared(c->mempool) &&
420 c->is_local > 0) {
421
422 /* Only enable SHM if both sides are owned by the same
423 * user. This is a security measure because otherwise
424 * data private to the user might leak. */
425
426 #ifdef HAVE_CREDS
427 const pa_creds *creds;
428 if ((creds = pa_pdispatch_creds(pd)))
429 if (getuid() == creds->uid)
430 pa_pstream_use_shm(c->pstream, 1);
431 #endif
432 }
433
434 reply = pa_tagstruct_command(c, PA_COMMAND_SET_CLIENT_NAME, &tag);
435
436 if (c->version >= 13) {
437 pa_init_proplist(c->proplist);
438 pa_tagstruct_put_proplist(reply, c->proplist);
439 } else
440 pa_tagstruct_puts(reply, pa_proplist_gets(c->proplist, PA_PROP_APPLICATION_NAME));
441
442 pa_pstream_send_tagstruct(c->pstream, reply);
443 pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c, NULL);
444
445 pa_context_set_state(c, PA_CONTEXT_SETTING_NAME);
446 break;
447 }
448
449 case PA_CONTEXT_SETTING_NAME :
450
451 if ((c->version >= 13 && (pa_tagstruct_getu32(t, &c->client_index) < 0 ||
452 c->client_index == PA_INVALID_INDEX)) ||
453 !pa_tagstruct_eof(t)) {
454 pa_context_fail(c, PA_ERR_PROTOCOL);
455 goto finish;
456 }
457
458 pa_context_set_state(c, PA_CONTEXT_READY);
459 break;
460
461 default:
462 pa_assert_not_reached();
463 }
464
465 finish:
466 pa_context_unref(c);
467 }
468
469 static void setup_context(pa_context *c, pa_iochannel *io) {
470 pa_tagstruct *t;
471 uint32_t tag;
472
473 pa_assert(c);
474 pa_assert(io);
475
476 pa_context_ref(c);
477
478 pa_assert(!c->pstream);
479 c->pstream = pa_pstream_new(c->mainloop, io, c->mempool);
480
481 pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c);
482 pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c);
483 pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c);
484
485 pa_assert(!c->pdispatch);
486 c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX);
487
488 if (!c->conf->cookie_valid)
489 pa_log_warn("No cookie loaded. Attempting to connect without.");
490
491 t = pa_tagstruct_command(c, PA_COMMAND_AUTH, &tag);
492 pa_tagstruct_putu32(t, PA_PROTOCOL_VERSION);
493 pa_tagstruct_put_arbitrary(t, c->conf->cookie, sizeof(c->conf->cookie));
494
495 #ifdef HAVE_CREDS
496 {
497 pa_creds ucred;
498
499 if (pa_iochannel_creds_supported(io))
500 pa_iochannel_creds_enable(io);
501
502 ucred.uid = getuid();
503 ucred.gid = getgid();
504
505 pa_pstream_send_tagstruct_with_creds(c->pstream, t, &ucred);
506 }
507 #else
508 pa_pstream_send_tagstruct(c->pstream, t);
509 #endif
510
511 pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c, NULL);
512
513 pa_context_set_state(c, PA_CONTEXT_AUTHORIZING);
514
515 pa_context_unref(c);
516 }
517
518 static void on_connection(pa_socket_client *client, pa_iochannel*io, void *userdata);
519
520 #ifndef OS_IS_WIN32
521
522 static int context_connect_spawn(pa_context *c) {
523 pid_t pid;
524 int status, r;
525 int fds[2] = { -1, -1} ;
526 pa_iochannel *io;
527
528 pa_context_ref(c);
529
530 if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) {
531 pa_log("socketpair(): %s", pa_cstrerror(errno));
532 pa_context_fail(c, PA_ERR_INTERNAL);
533 goto fail;
534 }
535
536 pa_make_fd_cloexec(fds[0]);
537
538 pa_make_socket_low_delay(fds[0]);
539 pa_make_socket_low_delay(fds[1]);
540
541 if (c->spawn_api.prefork)
542 c->spawn_api.prefork();
543
544 if ((pid = fork()) < 0) {
545 pa_log("fork(): %s", pa_cstrerror(errno));
546 pa_context_fail(c, PA_ERR_INTERNAL);
547
548 if (c->spawn_api.postfork)
549 c->spawn_api.postfork();
550
551 goto fail;
552 } else if (!pid) {
553 /* Child */
554
555 char t[128];
556 const char *state = NULL;
557 #define MAX_ARGS 64
558 const char * argv[MAX_ARGS+1];
559 int n;
560
561 /* Not required, since fds[0] has CLOEXEC enabled anyway */
562 pa_assert_se(pa_close(fds[0]) == 0);
563
564 if (c->spawn_api.atfork)
565 c->spawn_api.atfork();
566
567 /* Setup argv */
568
569 n = 0;
570
571 argv[n++] = c->conf->daemon_binary;
572 argv[n++] = "--daemonize=yes";
573
574 pa_snprintf(t, sizeof(t), "-Lmodule-native-protocol-fd fd=%i", fds[1]);
575 argv[n++] = strdup(t);
576
577 while (n < MAX_ARGS) {
578 char *a;
579
580 if (!(a = pa_split_spaces(c->conf->extra_arguments, &state)))
581 break;
582
583 argv[n++] = a;
584 }
585
586 argv[n++] = NULL;
587
588 execv(argv[0], (char * const *) argv);
589 _exit(1);
590 #undef MAX_ARGS
591 }
592
593 /* Parent */
594
595 r = waitpid(pid, &status, 0);
596
597 if (c->spawn_api.postfork)
598 c->spawn_api.postfork();
599
600 if (r < 0) {
601 pa_log("waitpid(): %s", pa_cstrerror(errno));
602 pa_context_fail(c, PA_ERR_INTERNAL);
603 goto fail;
604 } else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
605 pa_context_fail(c, PA_ERR_CONNECTIONREFUSED);
606 goto fail;
607 }
608
609 pa_assert_se(pa_close(fds[1]) == 0);
610
611 c->is_local = 1;
612
613 io = pa_iochannel_new(c->mainloop, fds[0], fds[0]);
614
615 setup_context(c, io);
616 unlock_autospawn_lock_file(c);
617
618 pa_context_unref(c);
619
620 return 0;
621
622 fail:
623 pa_close_pipe(fds);
624
625 unlock_autospawn_lock_file(c);
626
627 pa_context_unref(c);
628
629 return -1;
630 }
631
632 #endif /* OS_IS_WIN32 */
633
634 static int try_next_connection(pa_context *c) {
635 char *u = NULL;
636 int r = -1;
637
638 pa_assert(c);
639 pa_assert(!c->client);
640
641 for (;;) {
642 pa_xfree(u);
643 u = NULL;
644
645 c->server_list = pa_strlist_pop(c->server_list, &u);
646
647 if (!u) {
648
649 #ifndef OS_IS_WIN32
650 if (c->do_autospawn) {
651 r = context_connect_spawn(c);
652 goto finish;
653 }
654 #endif
655
656 pa_context_fail(c, PA_ERR_CONNECTIONREFUSED);
657 goto finish;
658 }
659
660 pa_log_debug("Trying to connect to %s...", u);
661
662 pa_xfree(c->server);
663 c->server = pa_xstrdup(u);
664
665 if (!(c->client = pa_socket_client_new_string(c->mainloop, u, PA_NATIVE_DEFAULT_PORT)))
666 continue;
667
668 c->is_local = pa_socket_client_is_local(c->client);
669 pa_socket_client_set_callback(c->client, on_connection, c);
670 break;
671 }
672
673 r = 0;
674
675 finish:
676 pa_xfree(u);
677
678 return r;
679 }
680
681 static void on_connection(pa_socket_client *client, pa_iochannel*io, void *userdata) {
682 pa_context *c = userdata;
683
684 pa_assert(client);
685 pa_assert(c);
686 pa_assert(c->state == PA_CONTEXT_CONNECTING);
687
688 pa_context_ref(c);
689
690 pa_socket_client_unref(client);
691 c->client = NULL;
692
693 if (!io) {
694 /* Try the item in the list */
695 if (errno == ECONNREFUSED || errno == ETIMEDOUT || errno == EHOSTUNREACH) {
696 try_next_connection(c);
697 goto finish;
698 }
699
700 pa_context_fail(c, PA_ERR_CONNECTIONREFUSED);
701 goto finish;
702 }
703
704 unlock_autospawn_lock_file(c);
705 setup_context(c, io);
706
707 finish:
708 pa_context_unref(c);
709 }
710
711 int pa_context_connect(
712 pa_context *c,
713 const char *server,
714 pa_context_flags_t flags,
715 const pa_spawn_api *api) {
716
717 int r = -1;
718
719 pa_assert(c);
720 pa_assert(PA_REFCNT_VALUE(c) >= 1);
721
722 PA_CHECK_VALIDITY(c, c->state == PA_CONTEXT_UNCONNECTED, PA_ERR_BADSTATE);
723 PA_CHECK_VALIDITY(c, !(flags & ~PA_CONTEXT_NOAUTOSPAWN), PA_ERR_INVALID);
724 PA_CHECK_VALIDITY(c, !server || *server, PA_ERR_INVALID);
725
726 if (!server)
727 server = c->conf->default_server;
728
729 pa_context_ref(c);
730
731 pa_assert(!c->server_list);
732
733 if (server) {
734 if (!(c->server_list = pa_strlist_parse(server))) {
735 pa_context_fail(c, PA_ERR_INVALIDSERVER);
736 goto finish;
737 }
738 } else {
739 char *d;
740 char ufn[PATH_MAX];
741
742 /* Prepend in reverse order */
743
744 if ((d = getenv("DISPLAY"))) {
745 char *e;
746 d = pa_xstrdup(d);
747 if ((e = strchr(d, ':')))
748 *e = 0;
749
750 if (*d)
751 c->server_list = pa_strlist_prepend(c->server_list, d);
752
753 pa_xfree(d);
754 }
755
756 c->server_list = pa_strlist_prepend(c->server_list, "tcp6:localhost");
757 c->server_list = pa_strlist_prepend(c->server_list, "tcp4:localhost");
758
759 /* The system wide instance */
760 c->server_list = pa_strlist_prepend(c->server_list, PA_SYSTEM_RUNTIME_PATH "/" PA_NATIVE_DEFAULT_UNIX_SOCKET);
761
762 /* The per-user instance */
763 c->server_list = pa_strlist_prepend(c->server_list, pa_runtime_path(PA_NATIVE_DEFAULT_UNIX_SOCKET, ufn, sizeof(ufn)));
764
765 /* Wrap the connection attempts in a single transaction for sane autospawn locking */
766 if (!(flags & PA_CONTEXT_NOAUTOSPAWN) && c->conf->autospawn) {
767 char lf[PATH_MAX];
768
769 pa_runtime_path(AUTOSPAWN_LOCK, lf, sizeof(lf));
770 pa_make_secure_parent_dir(lf, 0700, (uid_t)-1, (gid_t)-1);
771 pa_assert(c->autospawn_lock_fd <= 0);
772 c->autospawn_lock_fd = pa_lock_lockfile(lf);
773
774 if (api)
775 c->spawn_api = *api;
776 c->do_autospawn = 1;
777 }
778
779 }
780
781 pa_context_set_state(c, PA_CONTEXT_CONNECTING);
782 r = try_next_connection(c);
783
784 finish:
785 pa_context_unref(c);
786
787 return r;
788 }
789
790 void pa_context_disconnect(pa_context *c) {
791 pa_assert(c);
792 pa_assert(PA_REFCNT_VALUE(c) >= 1);
793
794 pa_context_set_state(c, PA_CONTEXT_TERMINATED);
795 }
796
797 pa_context_state_t pa_context_get_state(pa_context *c) {
798 pa_assert(c);
799 pa_assert(PA_REFCNT_VALUE(c) >= 1);
800
801 return c->state;
802 }
803
804 int pa_context_errno(pa_context *c) {
805 pa_assert(c);
806 pa_assert(PA_REFCNT_VALUE(c) >= 1);
807
808 return c->error;
809 }
810
811 void pa_context_set_state_callback(pa_context *c, pa_context_notify_cb_t cb, void *userdata) {
812 pa_assert(c);
813 pa_assert(PA_REFCNT_VALUE(c) >= 1);
814
815 c->state_callback = cb;
816 c->state_userdata = userdata;
817 }
818
819 int pa_context_is_pending(pa_context *c) {
820 pa_assert(c);
821 pa_assert(PA_REFCNT_VALUE(c) >= 1);
822
823 PA_CHECK_VALIDITY(c,
824 c->state == PA_CONTEXT_CONNECTING ||
825 c->state == PA_CONTEXT_AUTHORIZING ||
826 c->state == PA_CONTEXT_SETTING_NAME ||
827 c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
828
829 return (c->pstream && pa_pstream_is_pending(c->pstream)) ||
830 (c->pdispatch && pa_pdispatch_is_pending(c->pdispatch)) ||
831 c->client;
832 }
833
834 static void set_dispatch_callbacks(pa_operation *o);
835
836 static void pdispatch_drain_callback(PA_GCC_UNUSED pa_pdispatch*pd, void *userdata) {
837 set_dispatch_callbacks(userdata);
838 }
839
840 static void pstream_drain_callback(PA_GCC_UNUSED pa_pstream *s, void *userdata) {
841 set_dispatch_callbacks(userdata);
842 }
843
844 static void set_dispatch_callbacks(pa_operation *o) {
845 int done = 1;
846
847 pa_assert(o);
848 pa_assert(PA_REFCNT_VALUE(o) >= 1);
849 pa_assert(o->context);
850 pa_assert(PA_REFCNT_VALUE(o->context) >= 1);
851 pa_assert(o->context->state == PA_CONTEXT_READY);
852
853 pa_pstream_set_drain_callback(o->context->pstream, NULL, NULL);
854 pa_pdispatch_set_drain_callback(o->context->pdispatch, NULL, NULL);
855
856 if (pa_pdispatch_is_pending(o->context->pdispatch)) {
857 pa_pdispatch_set_drain_callback(o->context->pdispatch, pdispatch_drain_callback, o);
858 done = 0;
859 }
860
861 if (pa_pstream_is_pending(o->context->pstream)) {
862 pa_pstream_set_drain_callback(o->context->pstream, pstream_drain_callback, o);
863 done = 0;
864 }
865
866 if (done) {
867 if (o->callback) {
868 pa_context_notify_cb_t cb = (pa_context_notify_cb_t) o->callback;
869 cb(o->context, o->userdata);
870 }
871
872 pa_operation_done(o);
873 pa_operation_unref(o);
874 }
875 }
876
877 pa_operation* pa_context_drain(pa_context *c, pa_context_notify_cb_t cb, void *userdata) {
878 pa_operation *o;
879
880 pa_assert(c);
881 pa_assert(PA_REFCNT_VALUE(c) >= 1);
882
883 PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
884 PA_CHECK_VALIDITY_RETURN_NULL(c, pa_context_is_pending(c), PA_ERR_BADSTATE);
885
886 o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
887 set_dispatch_callbacks(pa_operation_ref(o));
888
889 return o;
890 }
891
892 void pa_context_simple_ack_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
893 pa_operation *o = userdata;
894 int success = 1;
895
896 pa_assert(pd);
897 pa_assert(o);
898 pa_assert(PA_REFCNT_VALUE(o) >= 1);
899
900 if (!o->context)
901 goto finish;
902
903 if (command != PA_COMMAND_REPLY) {
904 if (pa_context_handle_error(o->context, command, t) < 0)
905 goto finish;
906
907 success = 0;
908 } else if (!pa_tagstruct_eof(t)) {
909 pa_context_fail(o->context, PA_ERR_PROTOCOL);
910 goto finish;
911 }
912
913 if (o->callback) {
914 pa_context_success_cb_t cb = (pa_context_success_cb_t) o->callback;
915 cb(o->context, success, o->userdata);
916 }
917
918 finish:
919 pa_operation_done(o);
920 pa_operation_unref(o);
921 }
922
923 pa_operation* pa_context_exit_daemon(pa_context *c, pa_context_success_cb_t cb, void *userdata) {
924 pa_tagstruct *t;
925 pa_operation *o;
926 uint32_t tag;
927
928 pa_assert(c);
929 pa_assert(PA_REFCNT_VALUE(c) >= 1);
930
931 PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
932
933 o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
934
935 t = pa_tagstruct_command(c, PA_COMMAND_EXIT, &tag);
936 pa_pstream_send_tagstruct(c->pstream, t);
937 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);
938
939 return o;
940 }
941
942 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) {
943 pa_tagstruct *t;
944 pa_operation *o;
945 uint32_t tag;
946
947 pa_assert(c);
948 pa_assert(PA_REFCNT_VALUE(c) >= 1);
949
950 PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
951
952 o = pa_operation_new(c, NULL, cb, userdata);
953
954 t = pa_tagstruct_command(c, command, &tag);
955 pa_pstream_send_tagstruct(c->pstream, t);
956 pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, internal_cb, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
957
958 return o;
959 }
960
961 pa_operation* pa_context_set_default_sink(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata) {
962 pa_tagstruct *t;
963 pa_operation *o;
964 uint32_t tag;
965
966 pa_assert(c);
967 pa_assert(PA_REFCNT_VALUE(c) >= 1);
968
969 PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
970
971 o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
972
973 t = pa_tagstruct_command(c, PA_COMMAND_SET_DEFAULT_SINK, &tag);
974 pa_tagstruct_puts(t, name);
975 pa_pstream_send_tagstruct(c->pstream, t);
976 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);
977
978 return o;
979 }
980
981 pa_operation* pa_context_set_default_source(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata) {
982 pa_tagstruct *t;
983 pa_operation *o;
984 uint32_t tag;
985
986 pa_assert(c);
987 pa_assert(PA_REFCNT_VALUE(c) >= 1);
988
989 PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
990
991 o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
992
993 t = pa_tagstruct_command(c, PA_COMMAND_SET_DEFAULT_SOURCE, &tag);
994 pa_tagstruct_puts(t, name);
995 pa_pstream_send_tagstruct(c->pstream, t);
996 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);
997
998 return o;
999 }
1000
1001 int pa_context_is_local(pa_context *c) {
1002 pa_assert(c);
1003 pa_assert(PA_REFCNT_VALUE(c) >= 1);
1004
1005 PA_CHECK_VALIDITY(c, c->is_local >= 0, PA_ERR_BADSTATE);
1006
1007 return c->is_local;
1008 }
1009
1010 pa_operation* pa_context_set_name(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata) {
1011 pa_tagstruct *t;
1012 pa_operation *o;
1013 uint32_t tag;
1014
1015 pa_assert(c);
1016 pa_assert(PA_REFCNT_VALUE(c) >= 1);
1017 pa_assert(name);
1018
1019 PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1020
1021 if (c->version >= 13) {
1022 pa_proplist *p = pa_proplist_new();
1023 pa_proplist_sets(p, PA_PROP_APPLICATION_NAME, name);
1024 o = pa_context_proplist_update(c, PA_UPDATE_REPLACE, p, cb, userdata);
1025 pa_proplist_free(p);
1026
1027 } else {
1028 o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1029 t = pa_tagstruct_command(c, PA_COMMAND_SET_CLIENT_NAME, &tag);
1030 pa_tagstruct_puts(t, name);
1031 pa_pstream_send_tagstruct(c->pstream, t);
1032 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);
1033 }
1034
1035 return o;
1036 }
1037
1038 const char* pa_get_library_version(void) {
1039 return PACKAGE_VERSION;
1040 }
1041
1042 const char* pa_context_get_server(pa_context *c) {
1043 pa_assert(c);
1044 pa_assert(PA_REFCNT_VALUE(c) >= 1);
1045
1046 if (!c->server)
1047 return NULL;
1048
1049 if (*c->server == '{') {
1050 char *e = strchr(c->server+1, '}');
1051 return e ? e+1 : c->server;
1052 }
1053
1054 return c->server;
1055 }
1056
1057 uint32_t pa_context_get_protocol_version(PA_GCC_UNUSED pa_context *c) {
1058 return PA_PROTOCOL_VERSION;
1059 }
1060
1061 uint32_t pa_context_get_server_protocol_version(pa_context *c) {
1062 pa_assert(c);
1063 pa_assert(PA_REFCNT_VALUE(c) >= 1);
1064
1065 PA_CHECK_VALIDITY_RETURN_ANY(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE, PA_INVALID_INDEX);
1066
1067 return c->version;
1068 }
1069
1070 pa_tagstruct *pa_tagstruct_command(pa_context *c, uint32_t command, uint32_t *tag) {
1071 pa_tagstruct *t;
1072
1073 pa_assert(c);
1074 pa_assert(tag);
1075
1076 t = pa_tagstruct_new(NULL, 0);
1077 pa_tagstruct_putu32(t, command);
1078 pa_tagstruct_putu32(t, *tag = c->ctag++);
1079
1080 return t;
1081 }
1082
1083 uint32_t pa_context_get_index(pa_context *c) {
1084 pa_assert(c);
1085 pa_assert(PA_REFCNT_VALUE(c) >= 1);
1086
1087 PA_CHECK_VALIDITY_RETURN_ANY(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE, PA_INVALID_INDEX);
1088 PA_CHECK_VALIDITY_RETURN_ANY(c, c->version >= 13, PA_ERR_NOTSUPPORTED, PA_INVALID_INDEX);
1089
1090 return c->client_index;
1091 }
1092
1093 pa_operation *pa_context_proplist_update(pa_context *c, pa_update_mode_t mode, pa_proplist *p, pa_context_success_cb_t cb, void *userdata) {
1094 pa_operation *o;
1095 pa_tagstruct *t;
1096 uint32_t tag;
1097
1098 pa_assert(c);
1099 pa_assert(PA_REFCNT_VALUE(c) >= 1);
1100
1101 PA_CHECK_VALIDITY_RETURN_NULL(c, mode == PA_UPDATE_SET || mode == PA_UPDATE_MERGE || mode == PA_UPDATE_REPLACE, PA_ERR_INVALID);
1102 PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1103 PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 13, PA_ERR_NOTSUPPORTED);
1104
1105 o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1106
1107 t = pa_tagstruct_command(c, PA_COMMAND_UPDATE_CLIENT_PROPLIST, &tag);
1108 pa_tagstruct_putu32(t, (uint32_t) mode);
1109 pa_tagstruct_put_proplist(t, p);
1110
1111 pa_pstream_send_tagstruct(c->pstream, t);
1112 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);
1113
1114 /* Please note that we don't update c->proplist here, because we
1115 * don't export that field */
1116
1117 return o;
1118 }
1119
1120 pa_operation *pa_context_proplist_remove(pa_context *c, const char *const keys[], pa_context_success_cb_t cb, void *userdata) {
1121 pa_operation *o;
1122 pa_tagstruct *t;
1123 uint32_t tag;
1124 const char * const *k;
1125
1126 pa_assert(c);
1127 pa_assert(PA_REFCNT_VALUE(c) >= 1);
1128
1129 PA_CHECK_VALIDITY_RETURN_NULL(c, keys && keys[0], PA_ERR_INVALID);
1130 PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1131 PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 13, PA_ERR_NOTSUPPORTED);
1132
1133 o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1134
1135 t = pa_tagstruct_command(c, PA_COMMAND_REMOVE_CLIENT_PROPLIST, &tag);
1136
1137 for (k = keys; *k; k++)
1138 pa_tagstruct_puts(t, *k);
1139
1140 pa_tagstruct_puts(t, NULL);
1141
1142 pa_pstream_send_tagstruct(c->pstream, t);
1143 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);
1144
1145 /* Please note that we don't update c->proplist here, because we
1146 * don't export that field */
1147
1148 return o;
1149 }
1150
1151 void pa_init_proplist(pa_proplist *p) {
1152 int a, b;
1153 #ifndef HAVE_DECL_ENVIRON
1154 extern char **environ;
1155 #endif
1156 char **e;
1157
1158 pa_assert(p);
1159
1160 for (e = environ; *e; e++) {
1161
1162 if (pa_startswith(*e, "PULSE_PROP_")) {
1163 size_t kl = strcspn(*e+11, "=");
1164 char *k;
1165
1166 if ((*e)[11+kl] != '=')
1167 continue;
1168
1169 if (!pa_utf8_valid(*e+11+kl+1))
1170 continue;
1171
1172 k = pa_xstrndup(*e+11, kl);
1173
1174 if (pa_proplist_contains(p, k)) {
1175 pa_xfree(k);
1176 continue;
1177 }
1178
1179 pa_proplist_sets(p, k, *e+11+kl+1);
1180 pa_xfree(k);
1181 }
1182 }
1183
1184 if (!pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_ID)) {
1185 char t[32];
1186 pa_snprintf(t, sizeof(t), "%lu", (unsigned long) getpid());
1187 pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_ID, t);
1188 }
1189
1190 if (!pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_USER)) {
1191 char t[64];
1192 if (pa_get_user_name(t, sizeof(t))) {
1193 char *c = pa_utf8_filter(t);
1194 pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_USER, c);
1195 pa_xfree(c);
1196 }
1197 }
1198
1199 if (!pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_HOST)) {
1200 char t[64];
1201 if (pa_get_host_name(t, sizeof(t))) {
1202 char *c = pa_utf8_filter(t);
1203 pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_HOST, c);
1204 pa_xfree(c);
1205 }
1206 }
1207
1208 a = pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_BINARY);
1209 b = pa_proplist_contains(p, PA_PROP_APPLICATION_NAME);
1210
1211 if (!a || !b) {
1212 char t[PATH_MAX];
1213 if (pa_get_binary_name(t, sizeof(t))) {
1214 char *c = pa_utf8_filter(t);
1215
1216 if (!a)
1217 pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_BINARY, c);
1218 if (!b)
1219 pa_proplist_sets(p, PA_PROP_APPLICATION_NAME, c);
1220
1221 pa_xfree(c);
1222 }
1223 }
1224
1225 if (!pa_proplist_contains(p, PA_PROP_APPLICATION_LANGUAGE)) {
1226 const char *l;
1227
1228 if ((l = setlocale(LC_MESSAGES, NULL)))
1229 pa_proplist_sets(p, PA_PROP_APPLICATION_LANGUAGE, l);
1230 }
1231 }