]> code.delx.au - pulseaudio/blob - src/polypcore/protocol-native.c
* modify pa_context_exit_daemon() to return a pa_operation object
[pulseaudio] / src / polypcore / protocol-native.c
1 /* $Id$ */
2
3 /***
4 This file is part of polypaudio.
5
6 polypaudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation; either version 2 of the License,
9 or (at your option) any later version.
10
11 polypaudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with polypaudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <string.h>
27 #include <stdio.h>
28 #include <assert.h>
29 #include <stdlib.h>
30
31 #include <polypcore/native-common.h>
32 #include <polypcore/packet.h>
33 #include <polypcore/client.h>
34 #include <polypcore/source-output.h>
35 #include <polypcore/sink-input.h>
36 #include <polypcore/pstream.h>
37 #include <polypcore/tagstruct.h>
38 #include <polypcore/pdispatch.h>
39 #include <polypcore/pstream-util.h>
40 #include <polypcore/authkey.h>
41 #include <polypcore/namereg.h>
42 #include <polypcore/core-scache.h>
43 #include <polypcore/xmalloc.h>
44 #include <polypcore/util.h>
45 #include <polypcore/core-subscribe.h>
46 #include <polypcore/log.h>
47 #include <polypcore/autoload.h>
48 #include <polypcore/authkey-prop.h>
49 #include <polypcore/strlist.h>
50 #include <polypcore/props.h>
51 #include <polypcore/sample-util.h>
52 #include <polypcore/llist.h>
53
54 #include "protocol-native.h"
55
56 /* Kick a client if it doesn't authenticate within this time */
57 #define AUTH_TIMEOUT 5
58
59 /* Don't accept more connection than this */
60 #define MAX_CONNECTIONS 10
61
62 struct connection;
63 struct pa_protocol_native;
64
65 struct record_stream {
66 struct connection *connection;
67 uint32_t index;
68 pa_source_output *source_output;
69 pa_memblockq *memblockq;
70 size_t fragment_size;
71 };
72
73 struct playback_stream {
74 int type;
75 struct connection *connection;
76 uint32_t index;
77 pa_sink_input *sink_input;
78 pa_memblockq *memblockq;
79 size_t requested_bytes;
80 int drain_request;
81 uint32_t drain_tag;
82 uint32_t syncid;
83 int underrun;
84
85 /* Sync group members */
86 PA_LLIST_FIELDS(struct playback_stream);
87 };
88
89 struct upload_stream {
90 int type;
91 struct connection *connection;
92 uint32_t index;
93 pa_memchunk memchunk;
94 size_t length;
95 char *name;
96 pa_sample_spec sample_spec;
97 pa_channel_map channel_map;
98 };
99
100 struct output_stream {
101 int type;
102 };
103
104 enum {
105 UPLOAD_STREAM,
106 PLAYBACK_STREAM
107 };
108
109 struct connection {
110 int authorized;
111 pa_protocol_native *protocol;
112 pa_client *client;
113 pa_pstream *pstream;
114 pa_pdispatch *pdispatch;
115 pa_idxset *record_streams, *output_streams;
116 uint32_t rrobin_index;
117 pa_subscription *subscription;
118 pa_time_event *auth_timeout_event;
119 };
120
121 struct pa_protocol_native {
122 pa_module *module;
123 int public;
124 pa_core *core;
125 pa_socket_server *server;
126 pa_idxset *connections;
127 uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH];
128 int auth_cookie_in_property;
129 };
130
131 static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk);
132 static void sink_input_drop_cb(pa_sink_input *i, const pa_memchunk *chunk, size_t length);
133 static void sink_input_kill_cb(pa_sink_input *i);
134 static pa_usec_t sink_input_get_latency_cb(pa_sink_input *i);
135
136 static void request_bytes(struct playback_stream*s);
137
138 static void source_output_kill_cb(pa_source_output *o);
139 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk);
140 static pa_usec_t source_output_get_latency_cb(pa_source_output *o);
141
142 static void command_exit(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
143 static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
144 static void command_drain_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
145 static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
146 static void command_delete_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
147 static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
148 static void command_set_client_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
149 static void command_lookup(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
150 static void command_stat(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
151 static void command_get_playback_latency(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
152 static void command_get_record_latency(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
153 static void command_create_upload_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
154 static void command_finish_upload_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
155 static void command_play_sample(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
156 static void command_remove_sample(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
157 static void command_get_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
158 static void command_get_info_list(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
159 static void command_get_server_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
160 static void command_subscribe(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
161 static void command_set_volume(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
162 static void command_cork_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
163 static void command_flush_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
164 static void command_trigger_or_prebuf_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
165 static void command_set_default_sink_or_source(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
166 static void command_set_stream_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
167 static void command_kill(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
168 static void command_load_module(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
169 static void command_unload_module(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
170 static void command_add_autoload(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
171 static void command_remove_autoload(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
172 static void command_get_autoload_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
173 static void command_get_autoload_info_list(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
174 static void command_cork_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
175 static void command_flush_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
176
177 static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
178 [PA_COMMAND_ERROR] = NULL,
179 [PA_COMMAND_TIMEOUT] = NULL,
180 [PA_COMMAND_REPLY] = NULL,
181 [PA_COMMAND_CREATE_PLAYBACK_STREAM] = command_create_playback_stream,
182 [PA_COMMAND_DELETE_PLAYBACK_STREAM] = command_delete_stream,
183 [PA_COMMAND_DRAIN_PLAYBACK_STREAM] = command_drain_playback_stream,
184 [PA_COMMAND_CREATE_RECORD_STREAM] = command_create_record_stream,
185 [PA_COMMAND_DELETE_RECORD_STREAM] = command_delete_stream,
186 [PA_COMMAND_AUTH] = command_auth,
187 [PA_COMMAND_REQUEST] = NULL,
188 [PA_COMMAND_EXIT] = command_exit,
189 [PA_COMMAND_SET_CLIENT_NAME] = command_set_client_name,
190 [PA_COMMAND_LOOKUP_SINK] = command_lookup,
191 [PA_COMMAND_LOOKUP_SOURCE] = command_lookup,
192 [PA_COMMAND_STAT] = command_stat,
193 [PA_COMMAND_GET_PLAYBACK_LATENCY] = command_get_playback_latency,
194 [PA_COMMAND_GET_RECORD_LATENCY] = command_get_record_latency,
195 [PA_COMMAND_CREATE_UPLOAD_STREAM] = command_create_upload_stream,
196 [PA_COMMAND_DELETE_UPLOAD_STREAM] = command_delete_stream,
197 [PA_COMMAND_FINISH_UPLOAD_STREAM] = command_finish_upload_stream,
198 [PA_COMMAND_PLAY_SAMPLE] = command_play_sample,
199 [PA_COMMAND_REMOVE_SAMPLE] = command_remove_sample,
200 [PA_COMMAND_GET_SINK_INFO] = command_get_info,
201 [PA_COMMAND_GET_SOURCE_INFO] = command_get_info,
202 [PA_COMMAND_GET_CLIENT_INFO] = command_get_info,
203 [PA_COMMAND_GET_MODULE_INFO] = command_get_info,
204 [PA_COMMAND_GET_SINK_INPUT_INFO] = command_get_info,
205 [PA_COMMAND_GET_SOURCE_OUTPUT_INFO] = command_get_info,
206 [PA_COMMAND_GET_SAMPLE_INFO] = command_get_info,
207 [PA_COMMAND_GET_SINK_INFO_LIST] = command_get_info_list,
208 [PA_COMMAND_GET_SOURCE_INFO_LIST] = command_get_info_list,
209 [PA_COMMAND_GET_MODULE_INFO_LIST] = command_get_info_list,
210 [PA_COMMAND_GET_CLIENT_INFO_LIST] = command_get_info_list,
211 [PA_COMMAND_GET_SINK_INPUT_INFO_LIST] = command_get_info_list,
212 [PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST] = command_get_info_list,
213 [PA_COMMAND_GET_SAMPLE_INFO_LIST] = command_get_info_list,
214 [PA_COMMAND_GET_SERVER_INFO] = command_get_server_info,
215 [PA_COMMAND_SUBSCRIBE] = command_subscribe,
216
217 [PA_COMMAND_SET_SINK_VOLUME] = command_set_volume,
218 [PA_COMMAND_SET_SINK_INPUT_VOLUME] = command_set_volume,
219
220 [PA_COMMAND_CORK_PLAYBACK_STREAM] = command_cork_playback_stream,
221 [PA_COMMAND_FLUSH_PLAYBACK_STREAM] = command_flush_playback_stream,
222 [PA_COMMAND_TRIGGER_PLAYBACK_STREAM] = command_trigger_or_prebuf_playback_stream,
223 [PA_COMMAND_PREBUF_PLAYBACK_STREAM] = command_trigger_or_prebuf_playback_stream,
224
225 [PA_COMMAND_CORK_RECORD_STREAM] = command_cork_record_stream,
226 [PA_COMMAND_FLUSH_RECORD_STREAM] = command_flush_record_stream,
227
228 [PA_COMMAND_SET_DEFAULT_SINK] = command_set_default_sink_or_source,
229 [PA_COMMAND_SET_DEFAULT_SOURCE] = command_set_default_sink_or_source,
230 [PA_COMMAND_SET_PLAYBACK_STREAM_NAME] = command_set_stream_name,
231 [PA_COMMAND_SET_RECORD_STREAM_NAME] = command_set_stream_name,
232 [PA_COMMAND_KILL_CLIENT] = command_kill,
233 [PA_COMMAND_KILL_SINK_INPUT] = command_kill,
234 [PA_COMMAND_KILL_SOURCE_OUTPUT] = command_kill,
235 [PA_COMMAND_LOAD_MODULE] = command_load_module,
236 [PA_COMMAND_UNLOAD_MODULE] = command_unload_module,
237 [PA_COMMAND_GET_AUTOLOAD_INFO] = command_get_autoload_info,
238 [PA_COMMAND_GET_AUTOLOAD_INFO_LIST] = command_get_autoload_info_list,
239 [PA_COMMAND_ADD_AUTOLOAD] = command_add_autoload,
240 [PA_COMMAND_REMOVE_AUTOLOAD] = command_remove_autoload,
241
242 };
243
244 /* structure management */
245
246 static struct upload_stream* upload_stream_new(
247 struct connection *c,
248 const pa_sample_spec *ss,
249 const pa_channel_map *map,
250 const char *name, size_t length) {
251
252 struct upload_stream *s;
253 assert(c && ss && name && length);
254
255 s = pa_xnew(struct upload_stream, 1);
256 s->type = UPLOAD_STREAM;
257 s->connection = c;
258 s->sample_spec = *ss;
259 s->channel_map = *map;
260 s->name = pa_xstrdup(name);
261
262 s->memchunk.memblock = NULL;
263 s->memchunk.index = 0;
264 s->memchunk.length = 0;
265
266 s->length = length;
267
268 pa_idxset_put(c->output_streams, s, &s->index);
269 return s;
270 }
271
272 static void upload_stream_free(struct upload_stream *o) {
273 assert(o && o->connection);
274
275 pa_idxset_remove_by_data(o->connection->output_streams, o, NULL);
276
277 pa_xfree(o->name);
278
279 if (o->memchunk.memblock)
280 pa_memblock_unref(o->memchunk.memblock);
281
282 pa_xfree(o);
283 }
284
285 static struct record_stream* record_stream_new(
286 struct connection *c,
287 pa_source *source,
288 const pa_sample_spec *ss,
289 const pa_channel_map *map,
290 const char *name,
291 size_t maxlength,
292 size_t fragment_size) {
293
294 struct record_stream *s;
295 pa_source_output *source_output;
296 size_t base;
297 assert(c && source && ss && name && maxlength);
298
299 if (!(source_output = pa_source_output_new(source, __FILE__, name, ss, map, -1)))
300 return NULL;
301
302 s = pa_xnew(struct record_stream, 1);
303 s->connection = c;
304 s->source_output = source_output;
305 s->source_output->push = source_output_push_cb;
306 s->source_output->kill = source_output_kill_cb;
307 s->source_output->get_latency = source_output_get_latency_cb;
308 s->source_output->userdata = s;
309 s->source_output->owner = c->protocol->module;
310 s->source_output->client = c->client;
311
312 s->memblockq = pa_memblockq_new(
313 0,
314 maxlength,
315 0,
316 base = pa_frame_size(ss),
317 1,
318 0,
319 NULL,
320 c->protocol->core->memblock_stat);
321 assert(s->memblockq);
322
323 s->fragment_size = (fragment_size/base)*base;
324 if (!s->fragment_size)
325 s->fragment_size = base;
326
327 pa_idxset_put(c->record_streams, s, &s->index);
328 return s;
329 }
330
331 static void record_stream_free(struct record_stream* r) {
332 assert(r && r->connection);
333
334 pa_idxset_remove_by_data(r->connection->record_streams, r, NULL);
335 pa_source_output_disconnect(r->source_output);
336 pa_source_output_unref(r->source_output);
337 pa_memblockq_free(r->memblockq);
338 pa_xfree(r);
339 }
340
341 static struct playback_stream* playback_stream_new(
342 struct connection *c,
343 pa_sink *sink,
344 const pa_sample_spec *ss,
345 const pa_channel_map *map,
346 const char *name,
347 size_t maxlength,
348 size_t tlength,
349 size_t prebuf,
350 size_t minreq,
351 pa_cvolume *volume,
352 uint32_t syncid) {
353
354 struct playback_stream *s, *sync;
355 pa_sink_input *sink_input;
356 pa_memblock *silence;
357 uint32_t idx;
358 int64_t start_index;
359
360 assert(c && sink && ss && name && maxlength);
361
362 /* Find syncid group */
363 for (sync = pa_idxset_first(c->output_streams, &idx); sync; sync = pa_idxset_next(c->output_streams, &idx)) {
364
365 if (sync->type != PLAYBACK_STREAM)
366 continue;
367
368 if (sync->syncid == syncid)
369 break;
370 }
371
372 /* Synced streams must connect to the same sink */
373 if (sync && sync->sink_input->sink != sink)
374 return NULL;
375
376 if (!(sink_input = pa_sink_input_new(sink, __FILE__, name, ss, map, 0, -1)))
377 return NULL;
378
379 s = pa_xnew(struct playback_stream, 1);
380 s->type = PLAYBACK_STREAM;
381 s->connection = c;
382 s->syncid = syncid;
383 s->sink_input = sink_input;
384 s->underrun = 1;
385
386 s->sink_input->peek = sink_input_peek_cb;
387 s->sink_input->drop = sink_input_drop_cb;
388 s->sink_input->kill = sink_input_kill_cb;
389 s->sink_input->get_latency = sink_input_get_latency_cb;
390 s->sink_input->userdata = s;
391 s->sink_input->owner = c->protocol->module;
392 s->sink_input->client = c->client;
393
394 if (sync) {
395 /* Sync id found, now find head of list */
396 PA_LLIST_FIND_HEAD(struct playback_stream, sync, &sync);
397
398 /* Prepend ourselves */
399 PA_LLIST_PREPEND(struct playback_stream, sync, s);
400
401 /* Set our start index to the current read index of the other grozp member(s) */
402 assert(sync->next);
403 start_index = pa_memblockq_get_read_index(sync->next->memblockq);
404 } else {
405 /* This ia a new sync group */
406 PA_LLIST_INIT(struct playback_stream, s);
407 start_index = 0;
408 }
409
410 silence = pa_silence_memblock_new(ss, 0, c->protocol->core->memblock_stat);
411
412 s->memblockq = pa_memblockq_new(
413 start_index,
414 maxlength,
415 tlength,
416 pa_frame_size(ss),
417 prebuf,
418 minreq,
419 silence,
420 c->protocol->core->memblock_stat);
421
422 pa_memblock_unref(silence);
423
424 s->requested_bytes = 0;
425 s->drain_request = 0;
426
427 s->sink_input->volume = *volume;
428
429 pa_idxset_put(c->output_streams, s, &s->index);
430
431 return s;
432 }
433
434 static void playback_stream_free(struct playback_stream* p) {
435 struct playback_stream *head;
436 assert(p && p->connection);
437
438 if (p->drain_request)
439 pa_pstream_send_error(p->connection->pstream, p->drain_tag, PA_ERR_NOENTITY);
440
441 PA_LLIST_FIND_HEAD(struct playback_stream, p, &head);
442 PA_LLIST_REMOVE(struct playback_stream, head, p);
443
444 pa_idxset_remove_by_data(p->connection->output_streams, p, NULL);
445 pa_sink_input_disconnect(p->sink_input);
446 pa_sink_input_unref(p->sink_input);
447 pa_memblockq_free(p->memblockq);
448 pa_xfree(p);
449 }
450
451 static void connection_free(struct connection *c) {
452 struct record_stream *r;
453 struct output_stream *o;
454 assert(c && c->protocol);
455
456 pa_idxset_remove_by_data(c->protocol->connections, c, NULL);
457 while ((r = pa_idxset_first(c->record_streams, NULL)))
458 record_stream_free(r);
459 pa_idxset_free(c->record_streams, NULL, NULL);
460
461 while ((o = pa_idxset_first(c->output_streams, NULL)))
462 if (o->type == PLAYBACK_STREAM)
463 playback_stream_free((struct playback_stream*) o);
464 else
465 upload_stream_free((struct upload_stream*) o);
466 pa_idxset_free(c->output_streams, NULL, NULL);
467
468 pa_pdispatch_unref(c->pdispatch);
469 pa_pstream_close(c->pstream);
470 pa_pstream_unref(c->pstream);
471 pa_client_free(c->client);
472
473 if (c->subscription)
474 pa_subscription_free(c->subscription);
475
476 if (c->auth_timeout_event)
477 c->protocol->core->mainloop->time_free(c->auth_timeout_event);
478
479 pa_xfree(c);
480 }
481
482 static void request_bytes(struct playback_stream *s) {
483 pa_tagstruct *t;
484 size_t l;
485 assert(s);
486
487 if (!(l = pa_memblockq_missing(s->memblockq)))
488 return;
489
490 if (l <= s->requested_bytes)
491 return;
492
493 l -= s->requested_bytes;
494
495 if (l < pa_memblockq_get_minreq(s->memblockq))
496 return;
497
498 s->requested_bytes += l;
499
500 t = pa_tagstruct_new(NULL, 0);
501 assert(t);
502 pa_tagstruct_putu32(t, PA_COMMAND_REQUEST);
503 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
504 pa_tagstruct_putu32(t, s->index);
505 pa_tagstruct_putu32(t, l);
506 pa_pstream_send_tagstruct(s->connection->pstream, t);
507
508 /* pa_log(__FILE__": Requesting %u bytes\n", l); */
509 }
510
511 static void send_memblock(struct connection *c) {
512 uint32_t start;
513 struct record_stream *r;
514
515 start = PA_IDXSET_INVALID;
516 for (;;) {
517 pa_memchunk chunk;
518
519 if (!(r = pa_idxset_rrobin(c->record_streams, &c->rrobin_index)))
520 return;
521
522 if (start == PA_IDXSET_INVALID)
523 start = c->rrobin_index;
524 else if (start == c->rrobin_index)
525 return;
526
527 if (pa_memblockq_peek(r->memblockq, &chunk) >= 0) {
528 pa_memchunk schunk = chunk;
529
530 if (schunk.length > r->fragment_size)
531 schunk.length = r->fragment_size;
532
533 pa_pstream_send_memblock(c->pstream, r->index, 0, PA_SEEK_RELATIVE, &schunk);
534 pa_memblockq_drop(r->memblockq, &chunk, schunk.length);
535 pa_memblock_unref(schunk.memblock);
536
537 return;
538 }
539 }
540 }
541
542 static void send_playback_stream_killed(struct playback_stream *p) {
543 pa_tagstruct *t;
544 assert(p);
545
546 t = pa_tagstruct_new(NULL, 0);
547 assert(t);
548 pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_KILLED);
549 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
550 pa_tagstruct_putu32(t, p->index);
551 pa_pstream_send_tagstruct(p->connection->pstream, t);
552 }
553
554 static void send_record_stream_killed(struct record_stream *r) {
555 pa_tagstruct *t;
556 assert(r);
557
558 t = pa_tagstruct_new(NULL, 0);
559 assert(t);
560 pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_KILLED);
561 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
562 pa_tagstruct_putu32(t, r->index);
563 pa_pstream_send_tagstruct(r->connection->pstream, t);
564 }
565
566 /*** sinkinput callbacks ***/
567
568 static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
569 struct playback_stream *s;
570 assert(i && i->userdata && chunk);
571 s = i->userdata;
572
573 if (pa_memblockq_get_length(s->memblockq) <= 0 && !s->underrun) {
574 pa_tagstruct *t;
575
576 /* Report that we're empty */
577
578 t = pa_tagstruct_new(NULL, 0);
579 pa_tagstruct_putu32(t, PA_COMMAND_UNDERFLOW);
580 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
581 pa_tagstruct_putu32(t, s->index);
582 pa_pstream_send_tagstruct(s->connection->pstream, t);
583
584 s->underrun = 1;
585 }
586
587 if (pa_memblockq_peek(s->memblockq, chunk) < 0) {
588 pa_log(__FILE__": peek: failure\n");
589 return -1;
590 }
591
592 /* pa_log(__FILE__": peek: %u\n", chunk->length); */
593
594 return 0;
595 }
596
597 static void sink_input_drop_cb(pa_sink_input *i, const pa_memchunk *chunk, size_t length) {
598 struct playback_stream *s;
599 assert(i && i->userdata && length);
600 s = i->userdata;
601
602 pa_memblockq_drop(s->memblockq, chunk, length);
603
604 request_bytes(s);
605
606 if (s->drain_request && !pa_memblockq_is_readable(s->memblockq)) {
607 pa_pstream_send_simple_ack(s->connection->pstream, s->drain_tag);
608 s->drain_request = 0;
609 }
610
611 /* pa_log(__FILE__": after_drop: %u %u\n", pa_memblockq_get_length(s->memblockq), pa_memblockq_is_readable(s->memblockq)); */
612 }
613
614 static void sink_input_kill_cb(pa_sink_input *i) {
615 assert(i && i->userdata);
616 send_playback_stream_killed((struct playback_stream *) i->userdata);
617 playback_stream_free((struct playback_stream *) i->userdata);
618 }
619
620 static pa_usec_t sink_input_get_latency_cb(pa_sink_input *i) {
621 struct playback_stream *s;
622 assert(i && i->userdata);
623 s = i->userdata;
624
625 /*pa_log(__FILE__": get_latency: %u\n", pa_memblockq_get_length(s->memblockq));*/
626
627 return pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &s->sink_input->sample_spec);
628 }
629
630 /*** source_output callbacks ***/
631
632 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) {
633 struct record_stream *s;
634 assert(o && o->userdata && chunk);
635 s = o->userdata;
636
637 if (pa_memblockq_push_align(s->memblockq, chunk) < 0) {
638 pa_log_warn(__FILE__": Failed to push data into output queue.\n");
639 return;
640 }
641
642 if (!pa_pstream_is_pending(s->connection->pstream))
643 send_memblock(s->connection);
644 }
645
646 static void source_output_kill_cb(pa_source_output *o) {
647 assert(o && o->userdata);
648 send_record_stream_killed((struct record_stream *) o->userdata);
649 record_stream_free((struct record_stream *) o->userdata);
650 }
651
652 static pa_usec_t source_output_get_latency_cb(pa_source_output *o) {
653 struct record_stream *s;
654 assert(o && o->userdata);
655 s = o->userdata;
656
657 /*pa_log(__FILE__": get_latency: %u\n", pa_memblockq_get_length(s->memblockq));*/
658
659 return pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &o->sample_spec);
660 }
661
662 /*** pdispatch callbacks ***/
663
664 static void protocol_error(struct connection *c) {
665 pa_log(__FILE__": protocol error, kicking client\n");
666 connection_free(c);
667 }
668
669 static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
670 struct connection *c = userdata;
671 struct playback_stream *s;
672 size_t maxlength, tlength, prebuf, minreq;
673 uint32_t sink_index, syncid;
674 const char *name, *sink_name;
675 pa_sample_spec ss;
676 pa_channel_map map;
677 pa_tagstruct *reply;
678 pa_sink *sink;
679 pa_cvolume volume;
680 int corked;
681
682 assert(c && t && c->protocol && c->protocol->core);
683
684 if (pa_tagstruct_get(
685 t,
686 PA_TAG_STRING, &name,
687 PA_TAG_SAMPLE_SPEC, &ss,
688 PA_TAG_CHANNEL_MAP, &map,
689 PA_TAG_U32, &sink_index,
690 PA_TAG_STRING, &sink_name,
691 PA_TAG_U32, &maxlength,
692 PA_TAG_BOOLEAN, &corked,
693 PA_TAG_U32, &tlength,
694 PA_TAG_U32, &prebuf,
695 PA_TAG_U32, &minreq,
696 PA_TAG_U32, &syncid,
697 PA_TAG_CVOLUME, &volume,
698 PA_TAG_INVALID) < 0 ||
699 !pa_tagstruct_eof(t) ||
700 !name) {
701 protocol_error(c);
702 return;
703 }
704
705 if (!c->authorized) {
706 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
707 return;
708 }
709
710 if (sink_index != PA_INVALID_INDEX)
711 sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index);
712 else
713 sink = pa_namereg_get(c->protocol->core, sink_name, PA_NAMEREG_SINK, 1);
714
715 if (!sink) {
716 pa_log_warn(__FILE__": Can't find a suitable sink.\n");
717 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
718 return;
719 }
720
721 if (!(s = playback_stream_new(c, sink, &ss, &map, name, maxlength, tlength, prebuf, minreq, &volume, syncid))) {
722 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
723 return;
724 }
725
726 pa_sink_input_cork(s->sink_input, corked);
727
728 reply = pa_tagstruct_new(NULL, 0);
729 assert(reply);
730 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
731 pa_tagstruct_putu32(reply, tag);
732 pa_tagstruct_putu32(reply, s->index);
733 assert(s->sink_input);
734 pa_tagstruct_putu32(reply, s->sink_input->index);
735 pa_tagstruct_putu32(reply, s->requested_bytes = pa_memblockq_missing(s->memblockq));
736 pa_pstream_send_tagstruct(c->pstream, reply);
737 request_bytes(s);
738 }
739
740 static void command_delete_stream(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
741 struct connection *c = userdata;
742 uint32_t channel;
743 assert(c && t);
744
745 if (pa_tagstruct_getu32(t, &channel) < 0 ||
746 !pa_tagstruct_eof(t)) {
747 protocol_error(c);
748 return;
749 }
750
751 if (!c->authorized) {
752 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
753 return;
754 }
755
756 if (command == PA_COMMAND_DELETE_PLAYBACK_STREAM) {
757 struct playback_stream *s;
758 if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || (s->type != PLAYBACK_STREAM)) {
759 pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST);
760 return;
761 }
762
763 playback_stream_free(s);
764 } else if (command == PA_COMMAND_DELETE_RECORD_STREAM) {
765 struct record_stream *s;
766 if (!(s = pa_idxset_get_by_index(c->record_streams, channel))) {
767 pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST);
768 return;
769 }
770
771 record_stream_free(s);
772 } else {
773 struct upload_stream *s;
774 assert(command == PA_COMMAND_DELETE_UPLOAD_STREAM);
775 if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || (s->type != UPLOAD_STREAM)) {
776 pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST);
777 return;
778 }
779
780 upload_stream_free(s);
781 }
782
783 pa_pstream_send_simple_ack(c->pstream, tag);
784 }
785
786 static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
787 struct connection *c = userdata;
788 struct record_stream *s;
789 size_t maxlength, fragment_size;
790 uint32_t source_index;
791 const char *name, *source_name;
792 pa_sample_spec ss;
793 pa_channel_map map;
794 pa_tagstruct *reply;
795 pa_source *source;
796 int corked;
797 assert(c && t && c->protocol && c->protocol->core);
798
799 if (pa_tagstruct_gets(t, &name) < 0 || !name ||
800 pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
801 pa_tagstruct_get_channel_map(t, &map) < 0 ||
802 pa_tagstruct_getu32(t, &source_index) < 0 ||
803 pa_tagstruct_gets(t, &source_name) < 0 ||
804 pa_tagstruct_getu32(t, &maxlength) < 0 ||
805 pa_tagstruct_get_boolean(t, &corked) < 0 ||
806 pa_tagstruct_getu32(t, &fragment_size) < 0 ||
807 !pa_tagstruct_eof(t)) {
808 protocol_error(c);
809 return;
810 }
811
812 if (!c->authorized) {
813 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
814 return;
815 }
816
817 if (source_index != (uint32_t) -1)
818 source = pa_idxset_get_by_index(c->protocol->core->sources, source_index);
819 else
820 source = pa_namereg_get(c->protocol->core, source_name, PA_NAMEREG_SOURCE, 1);
821
822 if (!source) {
823 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
824 return;
825 }
826
827 if (!(s = record_stream_new(c, source, &ss, &map, name, maxlength, fragment_size))) {
828 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
829 return;
830 }
831
832 pa_source_output_cork(s->source_output, corked);
833
834 reply = pa_tagstruct_new(NULL, 0);
835 assert(reply);
836 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
837 pa_tagstruct_putu32(reply, tag);
838 pa_tagstruct_putu32(reply, s->index);
839 assert(s->source_output);
840 pa_tagstruct_putu32(reply, s->source_output->index);
841 pa_pstream_send_tagstruct(c->pstream, reply);
842 }
843
844 static void command_exit(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
845 struct connection *c = userdata;
846 assert(c && t);
847
848 if (!pa_tagstruct_eof(t)) {
849 protocol_error(c);
850 return;
851 }
852
853 if (!c->authorized) {
854 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
855 return;
856 }
857
858 assert(c->protocol && c->protocol->core && c->protocol->core->mainloop);
859 c->protocol->core->mainloop->quit(c->protocol->core->mainloop, 0);
860 pa_pstream_send_simple_ack(c->pstream, tag); /* nonsense */
861 return;
862 }
863
864 static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
865 struct connection *c = userdata;
866 const void*cookie;
867 assert(c && t);
868
869 if (pa_tagstruct_get_arbitrary(t, &cookie, PA_NATIVE_COOKIE_LENGTH) < 0 ||
870 !pa_tagstruct_eof(t)) {
871 protocol_error(c);
872 return;
873 }
874
875 if (!c->authorized) {
876 if (memcmp(c->protocol->auth_cookie, cookie, PA_NATIVE_COOKIE_LENGTH) != 0) {
877 pa_log(__FILE__": Denied access to client with invalid authorization key.\n");
878 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
879 return;
880 }
881
882 c->authorized = 1;
883 if (c->auth_timeout_event) {
884 c->protocol->core->mainloop->time_free(c->auth_timeout_event);
885 c->auth_timeout_event = NULL;
886 }
887 }
888
889 pa_pstream_send_simple_ack(c->pstream, tag);
890 return;
891 }
892
893 static void command_set_client_name(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
894 struct connection *c = userdata;
895 const char *name;
896 assert(c && t);
897
898 if (pa_tagstruct_gets(t, &name) < 0 || !name ||
899 !pa_tagstruct_eof(t)) {
900 protocol_error(c);
901 return;
902 }
903
904 pa_client_set_name(c->client, name);
905 pa_pstream_send_simple_ack(c->pstream, tag);
906 return;
907 }
908
909 static void command_lookup(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
910 struct connection *c = userdata;
911 const char *name;
912 uint32_t idx = PA_IDXSET_INVALID;
913 assert(c && t);
914
915 if (pa_tagstruct_gets(t, &name) < 0 || !name ||
916 !pa_tagstruct_eof(t)) {
917 protocol_error(c);
918 return;
919 }
920
921 if (!c->authorized) {
922 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
923 return;
924 }
925
926 if (command == PA_COMMAND_LOOKUP_SINK) {
927 pa_sink *sink;
928 if ((sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1)))
929 idx = sink->index;
930 } else {
931 pa_source *source;
932 assert(command == PA_COMMAND_LOOKUP_SOURCE);
933 if ((source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1)))
934 idx = source->index;
935 }
936
937 if (idx == PA_IDXSET_INVALID)
938 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
939 else {
940 pa_tagstruct *reply;
941 reply = pa_tagstruct_new(NULL, 0);
942 assert(reply);
943 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
944 pa_tagstruct_putu32(reply, tag);
945 pa_tagstruct_putu32(reply, idx);
946 pa_pstream_send_tagstruct(c->pstream, reply);
947 }
948 }
949
950 static void command_drain_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
951 struct connection *c = userdata;
952 uint32_t idx;
953 struct playback_stream *s;
954 assert(c && t);
955
956 if (pa_tagstruct_getu32(t, &idx) < 0 ||
957 !pa_tagstruct_eof(t)) {
958 protocol_error(c);
959 return;
960 }
961
962 if (!c->authorized) {
963 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
964 return;
965 }
966
967 if (!(s = pa_idxset_get_by_index(c->output_streams, idx)) || s->type != PLAYBACK_STREAM) {
968 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
969 return;
970 }
971
972 s->drain_request = 0;
973
974 pa_memblockq_prebuf_disable(s->memblockq);
975
976 if (!pa_memblockq_is_readable(s->memblockq)) {
977 /* pa_log("immediate drain: %u\n", pa_memblockq_get_length(s->memblockq)); */
978 pa_pstream_send_simple_ack(c->pstream, tag);
979 } else {
980 /* pa_log("slow drain triggered\n"); */
981 s->drain_request = 1;
982 s->drain_tag = tag;
983
984 pa_sink_notify(s->sink_input->sink);
985 }
986 }
987
988 static void command_stat(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
989 struct connection *c = userdata;
990 pa_tagstruct *reply;
991 assert(c && t);
992
993 if (!pa_tagstruct_eof(t)) {
994 protocol_error(c);
995 return;
996 }
997
998 if (!c->authorized) {
999 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
1000 return;
1001 }
1002
1003 reply = pa_tagstruct_new(NULL, 0);
1004 assert(reply);
1005 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
1006 pa_tagstruct_putu32(reply, tag);
1007 pa_tagstruct_putu32(reply, c->protocol->core->memblock_stat->total);
1008 pa_tagstruct_putu32(reply, c->protocol->core->memblock_stat->total_size);
1009 pa_tagstruct_putu32(reply, c->protocol->core->memblock_stat->allocated);
1010 pa_tagstruct_putu32(reply, c->protocol->core->memblock_stat->allocated_size);
1011 pa_tagstruct_putu32(reply, pa_scache_total_size(c->protocol->core));
1012 pa_pstream_send_tagstruct(c->pstream, reply);
1013 }
1014
1015 static void command_get_playback_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1016 struct connection *c = userdata;
1017 pa_tagstruct *reply;
1018 struct playback_stream *s;
1019 struct timeval tv, now;
1020 uint64_t counter;
1021 uint32_t idx;
1022 assert(c && t);
1023
1024 if (pa_tagstruct_getu32(t, &idx) < 0 ||
1025 pa_tagstruct_get_timeval(t, &tv) < 0 ||
1026 pa_tagstruct_getu64(t, &counter) < 0 ||
1027 !pa_tagstruct_eof(t)) {
1028 protocol_error(c);
1029 return;
1030 }
1031
1032 if (!c->authorized) {
1033 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
1034 return;
1035 }
1036
1037 if (!(s = pa_idxset_get_by_index(c->output_streams, idx)) || s->type != PLAYBACK_STREAM) {
1038 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1039 return;
1040 }
1041
1042 reply = pa_tagstruct_new(NULL, 0);
1043 assert(reply);
1044 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
1045 pa_tagstruct_putu32(reply, tag);
1046 pa_tagstruct_put_usec(reply, pa_sink_input_get_latency(s->sink_input));
1047 pa_tagstruct_put_usec(reply, pa_sink_get_latency(s->sink_input->sink));
1048 pa_tagstruct_put_usec(reply, 0);
1049 pa_tagstruct_put_boolean(reply, pa_memblockq_is_readable(s->memblockq));
1050 pa_tagstruct_putu32(reply, pa_memblockq_get_length(s->memblockq));
1051 pa_tagstruct_put_timeval(reply, &tv);
1052 pa_gettimeofday(&now);
1053 pa_tagstruct_put_timeval(reply, &now);
1054 pa_tagstruct_putu64(reply, counter);
1055 pa_pstream_send_tagstruct(c->pstream, reply);
1056 }
1057
1058 static void command_get_record_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1059 struct connection *c = userdata;
1060 pa_tagstruct *reply;
1061 struct record_stream *s;
1062 struct timeval tv, now;
1063 uint64_t counter;
1064 uint32_t idx;
1065 assert(c && t);
1066
1067 if (pa_tagstruct_getu32(t, &idx) < 0 ||
1068 pa_tagstruct_get_timeval(t, &tv) < 0 ||
1069 pa_tagstruct_getu64(t, &counter) < 0 ||
1070 !pa_tagstruct_eof(t)) {
1071 protocol_error(c);
1072 return;
1073 }
1074
1075 if (!c->authorized) {
1076 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
1077 return;
1078 }
1079
1080 if (!(s = pa_idxset_get_by_index(c->record_streams, idx))) {
1081 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1082 return;
1083 }
1084
1085 reply = pa_tagstruct_new(NULL, 0);
1086 assert(reply);
1087 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
1088 pa_tagstruct_putu32(reply, tag);
1089 pa_tagstruct_put_usec(reply, pa_source_output_get_latency(s->source_output));
1090 pa_tagstruct_put_usec(reply, s->source_output->source->monitor_of ? pa_sink_get_latency(s->source_output->source->monitor_of) : 0);
1091 pa_tagstruct_put_usec(reply, pa_source_get_latency(s->source_output->source));
1092 pa_tagstruct_put_boolean(reply, 0);
1093 pa_tagstruct_putu32(reply, pa_memblockq_get_length(s->memblockq));
1094 pa_tagstruct_put_timeval(reply, &tv);
1095 pa_gettimeofday(&now);
1096 pa_tagstruct_put_timeval(reply, &now);
1097 pa_tagstruct_putu64(reply, counter);
1098 pa_pstream_send_tagstruct(c->pstream, reply);
1099 }
1100
1101
1102 static void command_create_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1103 struct connection *c = userdata;
1104 struct upload_stream *s;
1105 size_t length;
1106 const char *name;
1107 pa_sample_spec ss;
1108 pa_channel_map map;
1109 pa_tagstruct *reply;
1110 assert(c && t && c->protocol && c->protocol->core);
1111
1112 if (pa_tagstruct_gets(t, &name) < 0 || !name ||
1113 pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
1114 pa_tagstruct_get_channel_map(t, &map) < 0 ||
1115 pa_tagstruct_getu32(t, &length) < 0 ||
1116 !pa_tagstruct_eof(t)) {
1117 protocol_error(c);
1118 return;
1119 }
1120
1121 if (!c->authorized) {
1122 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
1123 return;
1124 }
1125
1126 if ((length % pa_frame_size(&ss)) != 0 || length <= 0 || !*name) {
1127 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
1128 return;
1129 }
1130
1131 if (!(s = upload_stream_new(c, &ss, &map, name, length))) {
1132 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
1133 return;
1134 }
1135
1136 reply = pa_tagstruct_new(NULL, 0);
1137 assert(reply);
1138 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
1139 pa_tagstruct_putu32(reply, tag);
1140 pa_tagstruct_putu32(reply, s->index);
1141 pa_tagstruct_putu32(reply, length);
1142 pa_pstream_send_tagstruct(c->pstream, reply);
1143 }
1144
1145 static void command_finish_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1146 struct connection *c = userdata;
1147 uint32_t channel;
1148 struct upload_stream *s;
1149 uint32_t idx;
1150 assert(c && t);
1151
1152 if (pa_tagstruct_getu32(t, &channel) < 0 ||
1153 !pa_tagstruct_eof(t)) {
1154 protocol_error(c);
1155 return;
1156 }
1157
1158 if (!c->authorized) {
1159 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
1160 return;
1161 }
1162
1163 if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || (s->type != UPLOAD_STREAM)) {
1164 pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST);
1165 return;
1166 }
1167
1168 pa_scache_add_item(c->protocol->core, s->name, &s->sample_spec, &s->channel_map, &s->memchunk, &idx);
1169 pa_pstream_send_simple_ack(c->pstream, tag);
1170 upload_stream_free(s);
1171 }
1172
1173 static void command_play_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1174 struct connection *c = userdata;
1175 uint32_t sink_index;
1176 pa_cvolume volume;
1177 pa_sink *sink;
1178 const char *name, *sink_name;
1179 assert(c && t);
1180
1181 if (pa_tagstruct_getu32(t, &sink_index) < 0 ||
1182 pa_tagstruct_gets(t, &sink_name) < 0 ||
1183 pa_tagstruct_get_cvolume(t, &volume) < 0 ||
1184 pa_tagstruct_gets(t, &name) < 0 || !name ||
1185 !pa_tagstruct_eof(t)) {
1186 protocol_error(c);
1187 return;
1188 }
1189
1190 if (!c->authorized) {
1191 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
1192 return;
1193 }
1194
1195 if (sink_index != (uint32_t) -1)
1196 sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index);
1197 else
1198 sink = pa_namereg_get(c->protocol->core, sink_name, PA_NAMEREG_SINK, 1);
1199
1200 if (!sink) {
1201 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1202 return;
1203 }
1204
1205 if (pa_scache_play_item(c->protocol->core, name, sink, &volume) < 0) {
1206 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1207 return;
1208 }
1209
1210 pa_pstream_send_simple_ack(c->pstream, tag);
1211 }
1212
1213 static void command_remove_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1214 struct connection *c = userdata;
1215 const char *name;
1216 assert(c && t);
1217
1218 if (pa_tagstruct_gets(t, &name) < 0 || !name ||
1219 !pa_tagstruct_eof(t)) {
1220 protocol_error(c);
1221 return;
1222 }
1223
1224 if (!c->authorized) {
1225 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
1226 return;
1227 }
1228
1229 if (pa_scache_remove_item(c->protocol->core, name) < 0) {
1230 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1231 return;
1232 }
1233
1234 pa_pstream_send_simple_ack(c->pstream, tag);
1235 }
1236
1237 static void sink_fill_tagstruct(pa_tagstruct *t, pa_sink *sink) {
1238 assert(t && sink);
1239 pa_tagstruct_put(
1240 t,
1241 PA_TAG_U32, sink->index,
1242 PA_TAG_STRING, sink->name,
1243 PA_TAG_STRING, sink->description,
1244 PA_TAG_SAMPLE_SPEC, &sink->sample_spec,
1245 PA_TAG_CHANNEL_MAP, &sink->channel_map,
1246 PA_TAG_U32, sink->owner ? sink->owner->index : PA_INVALID_INDEX,
1247 PA_TAG_CVOLUME, pa_sink_get_volume(sink, PA_MIXER_HARDWARE),
1248 PA_TAG_U32, sink->monitor_source->index,
1249 PA_TAG_STRING, sink->monitor_source->name,
1250 PA_TAG_USEC, pa_sink_get_latency(sink),
1251 PA_TAG_STRING, sink->driver,
1252 PA_TAG_INVALID);
1253 }
1254
1255 static void source_fill_tagstruct(pa_tagstruct *t, pa_source *source) {
1256 assert(t && source);
1257 pa_tagstruct_putu32(t, source->index);
1258 pa_tagstruct_puts(t, source->name);
1259 pa_tagstruct_puts(t, source->description);
1260 pa_tagstruct_put_sample_spec(t, &source->sample_spec);
1261 pa_tagstruct_put_channel_map(t, &source->channel_map);
1262 pa_tagstruct_putu32(t, source->owner ? source->owner->index : (uint32_t) -1);
1263 pa_tagstruct_putu32(t, source->monitor_of ? source->monitor_of->index : (uint32_t) -1);
1264 pa_tagstruct_puts(t, source->monitor_of ? source->monitor_of->name : NULL);
1265 pa_tagstruct_put_usec(t, pa_source_get_latency(source));
1266 pa_tagstruct_puts(t, source->driver);
1267 }
1268
1269 static void client_fill_tagstruct(pa_tagstruct *t, pa_client *client) {
1270 assert(t && client);
1271 pa_tagstruct_putu32(t, client->index);
1272 pa_tagstruct_puts(t, client->name);
1273 pa_tagstruct_putu32(t, client->owner ? client->owner->index : (uint32_t) -1);
1274 pa_tagstruct_puts(t, client->driver);
1275 }
1276
1277 static void module_fill_tagstruct(pa_tagstruct *t, pa_module *module) {
1278 assert(t && module);
1279 pa_tagstruct_putu32(t, module->index);
1280 pa_tagstruct_puts(t, module->name);
1281 pa_tagstruct_puts(t, module->argument);
1282 pa_tagstruct_putu32(t, module->n_used);
1283 pa_tagstruct_put_boolean(t, module->auto_unload);
1284 }
1285
1286 static void sink_input_fill_tagstruct(pa_tagstruct *t, pa_sink_input *s) {
1287 assert(t && s);
1288 pa_tagstruct_putu32(t, s->index);
1289 pa_tagstruct_puts(t, s->name);
1290 pa_tagstruct_putu32(t, s->owner ? s->owner->index : (uint32_t) -1);
1291 pa_tagstruct_putu32(t, s->client ? s->client->index : (uint32_t) -1);
1292 pa_tagstruct_putu32(t, s->sink->index);
1293 pa_tagstruct_put_sample_spec(t, &s->sample_spec);
1294 pa_tagstruct_put_channel_map(t, &s->channel_map);
1295 pa_tagstruct_put_cvolume(t, &s->volume);
1296 pa_tagstruct_put_usec(t, pa_sink_input_get_latency(s));
1297 pa_tagstruct_put_usec(t, pa_sink_get_latency(s->sink));
1298 pa_tagstruct_puts(t, pa_resample_method_to_string(pa_sink_input_get_resample_method(s)));
1299 pa_tagstruct_puts(t, s->driver);
1300 }
1301
1302 static void source_output_fill_tagstruct(pa_tagstruct *t, pa_source_output *s) {
1303 assert(t && s);
1304 pa_tagstruct_putu32(t, s->index);
1305 pa_tagstruct_puts(t, s->name);
1306 pa_tagstruct_putu32(t, s->owner ? s->owner->index : (uint32_t) -1);
1307 pa_tagstruct_putu32(t, s->client ? s->client->index : (uint32_t) -1);
1308 pa_tagstruct_putu32(t, s->source->index);
1309 pa_tagstruct_put_sample_spec(t, &s->sample_spec);
1310 pa_tagstruct_put_channel_map(t, &s->channel_map);
1311 pa_tagstruct_put_usec(t, pa_source_output_get_latency(s));
1312 pa_tagstruct_put_usec(t, pa_source_get_latency(s->source));
1313 pa_tagstruct_puts(t, pa_resample_method_to_string(pa_source_output_get_resample_method(s)));
1314 pa_tagstruct_puts(t, s->driver);
1315 }
1316
1317 static void scache_fill_tagstruct(pa_tagstruct *t, pa_scache_entry *e) {
1318 assert(t && e);
1319 pa_tagstruct_putu32(t, e->index);
1320 pa_tagstruct_puts(t, e->name);
1321 pa_tagstruct_put_cvolume(t, &e->volume);
1322 pa_tagstruct_put_usec(t, pa_bytes_to_usec(e->memchunk.length, &e->sample_spec));
1323 pa_tagstruct_put_sample_spec(t, &e->sample_spec);
1324 pa_tagstruct_put_channel_map(t, &e->channel_map);
1325 pa_tagstruct_putu32(t, e->memchunk.length);
1326 pa_tagstruct_put_boolean(t, e->lazy);
1327 pa_tagstruct_puts(t, e->filename);
1328 }
1329
1330 static void command_get_info(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1331 struct connection *c = userdata;
1332 uint32_t idx;
1333 pa_sink *sink = NULL;
1334 pa_source *source = NULL;
1335 pa_client *client = NULL;
1336 pa_module *module = NULL;
1337 pa_sink_input *si = NULL;
1338 pa_source_output *so = NULL;
1339 pa_scache_entry *sce = NULL;
1340 const char *name;
1341 pa_tagstruct *reply;
1342 assert(c && t);
1343
1344
1345 if (pa_tagstruct_getu32(t, &idx) < 0 ||
1346 (command != PA_COMMAND_GET_CLIENT_INFO &&
1347 command != PA_COMMAND_GET_MODULE_INFO &&
1348 command != PA_COMMAND_GET_SINK_INPUT_INFO &&
1349 command != PA_COMMAND_GET_SOURCE_OUTPUT_INFO &&
1350 pa_tagstruct_gets(t, &name) < 0) ||
1351 !pa_tagstruct_eof(t)) {
1352 protocol_error(c);
1353 return;
1354 }
1355
1356 if (!c->authorized) {
1357 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
1358 return;
1359 }
1360
1361 if (command == PA_COMMAND_GET_SINK_INFO) {
1362 if (idx != (uint32_t) -1)
1363 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
1364 else
1365 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1);
1366 } else if (command == PA_COMMAND_GET_SOURCE_INFO) {
1367 if (idx != (uint32_t) -1)
1368 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
1369 else
1370 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1);
1371 } else if (command == PA_COMMAND_GET_CLIENT_INFO)
1372 client = pa_idxset_get_by_index(c->protocol->core->clients, idx);
1373 else if (command == PA_COMMAND_GET_MODULE_INFO)
1374 module = pa_idxset_get_by_index(c->protocol->core->modules, idx);
1375 else if (command == PA_COMMAND_GET_SINK_INPUT_INFO)
1376 si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
1377 else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO)
1378 so = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
1379 else {
1380 assert(command == PA_COMMAND_GET_SAMPLE_INFO);
1381 if (idx != (uint32_t) -1)
1382 sce = pa_idxset_get_by_index(c->protocol->core->scache, idx);
1383 else
1384 sce = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SAMPLE, 0);
1385 }
1386
1387 if (!sink && !source && !client && !module && !si && !so && !sce) {
1388 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1389 return;
1390 }
1391
1392 reply = pa_tagstruct_new(NULL, 0);
1393 assert(reply);
1394 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
1395 pa_tagstruct_putu32(reply, tag);
1396 if (sink)
1397 sink_fill_tagstruct(reply, sink);
1398 else if (source)
1399 source_fill_tagstruct(reply, source);
1400 else if (client)
1401 client_fill_tagstruct(reply, client);
1402 else if (module)
1403 module_fill_tagstruct(reply, module);
1404 else if (si)
1405 sink_input_fill_tagstruct(reply, si);
1406 else if (so)
1407 source_output_fill_tagstruct(reply, so);
1408 else
1409 scache_fill_tagstruct(reply, sce);
1410 pa_pstream_send_tagstruct(c->pstream, reply);
1411 }
1412
1413 static void command_get_info_list(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1414 struct connection *c = userdata;
1415 pa_idxset *i;
1416 uint32_t idx;
1417 void *p;
1418 pa_tagstruct *reply;
1419 assert(c && t);
1420
1421 if (!pa_tagstruct_eof(t)) {
1422 protocol_error(c);
1423 return;
1424 }
1425
1426 if (!c->authorized) {
1427 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
1428 return;
1429 }
1430
1431 reply = pa_tagstruct_new(NULL, 0);
1432 assert(reply);
1433 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
1434 pa_tagstruct_putu32(reply, tag);
1435
1436 if (command == PA_COMMAND_GET_SINK_INFO_LIST)
1437 i = c->protocol->core->sinks;
1438 else if (command == PA_COMMAND_GET_SOURCE_INFO_LIST)
1439 i = c->protocol->core->sources;
1440 else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST)
1441 i = c->protocol->core->clients;
1442 else if (command == PA_COMMAND_GET_MODULE_INFO_LIST)
1443 i = c->protocol->core->modules;
1444 else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST)
1445 i = c->protocol->core->sink_inputs;
1446 else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST)
1447 i = c->protocol->core->source_outputs;
1448 else {
1449 assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST);
1450 i = c->protocol->core->scache;
1451 }
1452
1453 if (i) {
1454 for (p = pa_idxset_first(i, &idx); p; p = pa_idxset_next(i, &idx)) {
1455 if (command == PA_COMMAND_GET_SINK_INFO_LIST)
1456 sink_fill_tagstruct(reply, p);
1457 else if (command == PA_COMMAND_GET_SOURCE_INFO_LIST)
1458 source_fill_tagstruct(reply, p);
1459 else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST)
1460 client_fill_tagstruct(reply, p);
1461 else if (command == PA_COMMAND_GET_MODULE_INFO_LIST)
1462 module_fill_tagstruct(reply, p);
1463 else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST)
1464 sink_input_fill_tagstruct(reply, p);
1465 else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST)
1466 source_output_fill_tagstruct(reply, p);
1467 else {
1468 assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST);
1469 scache_fill_tagstruct(reply, p);
1470 }
1471 }
1472 }
1473
1474 pa_pstream_send_tagstruct(c->pstream, reply);
1475 }
1476
1477 static void command_get_server_info(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1478 struct connection *c = userdata;
1479 pa_tagstruct *reply;
1480 char txt[256];
1481 const char *n;
1482 assert(c && t);
1483
1484 if (!pa_tagstruct_eof(t)) {
1485 protocol_error(c);
1486 return;
1487 }
1488
1489 if (!c->authorized) {
1490 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
1491 return;
1492 }
1493
1494 reply = pa_tagstruct_new(NULL, 0);
1495 assert(reply);
1496 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
1497 pa_tagstruct_putu32(reply, tag);
1498 pa_tagstruct_puts(reply, PACKAGE_NAME);
1499 pa_tagstruct_puts(reply, PACKAGE_VERSION);
1500 pa_tagstruct_puts(reply, pa_get_user_name(txt, sizeof(txt)));
1501 pa_tagstruct_puts(reply, pa_get_fqdn(txt, sizeof(txt)));
1502 pa_tagstruct_put_sample_spec(reply, &c->protocol->core->default_sample_spec);
1503
1504 n = pa_namereg_get_default_sink_name(c->protocol->core);
1505 pa_tagstruct_puts(reply, n);
1506 n = pa_namereg_get_default_source_name(c->protocol->core);
1507 pa_tagstruct_puts(reply, n);
1508
1509 pa_tagstruct_putu32(reply, c->protocol->core->cookie);
1510
1511 pa_pstream_send_tagstruct(c->pstream, reply);
1512 }
1513
1514 static void subscription_cb(pa_core *core, pa_subscription_event_type_t e, uint32_t idx, void *userdata) {
1515 pa_tagstruct *t;
1516 struct connection *c = userdata;
1517 assert(c && core);
1518
1519 t = pa_tagstruct_new(NULL, 0);
1520 assert(t);
1521 pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE_EVENT);
1522 pa_tagstruct_putu32(t, (uint32_t) -1);
1523 pa_tagstruct_putu32(t, e);
1524 pa_tagstruct_putu32(t, idx);
1525 pa_pstream_send_tagstruct(c->pstream, t);
1526 }
1527
1528 static void command_subscribe(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1529 struct connection *c = userdata;
1530 pa_subscription_mask_t m;
1531 assert(c && t);
1532
1533 if (pa_tagstruct_getu32(t, &m) < 0 ||
1534 !pa_tagstruct_eof(t)) {
1535 protocol_error(c);
1536 return;
1537 }
1538
1539 if (!c->authorized) {
1540 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
1541 return;
1542 }
1543
1544 if (c->subscription)
1545 pa_subscription_free(c->subscription);
1546
1547 if (m != 0) {
1548 c->subscription = pa_subscription_new(c->protocol->core, m, subscription_cb, c);
1549 assert(c->subscription);
1550 } else
1551 c->subscription = NULL;
1552
1553 pa_pstream_send_simple_ack(c->pstream, tag);
1554 }
1555
1556 static void command_set_volume(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1557 struct connection *c = userdata;
1558 uint32_t idx;
1559 pa_cvolume volume;
1560 pa_sink *sink = NULL;
1561 pa_sink_input *si = NULL;
1562 const char *name = NULL;
1563 assert(c && t);
1564
1565 if (pa_tagstruct_getu32(t, &idx) < 0 ||
1566 (command == PA_COMMAND_SET_SINK_VOLUME && pa_tagstruct_gets(t, &name) < 0) ||
1567 pa_tagstruct_get_cvolume(t, &volume) ||
1568 !pa_tagstruct_eof(t)) {
1569 protocol_error(c);
1570 return;
1571 }
1572
1573 if (!c->authorized) {
1574 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
1575 return;
1576 }
1577
1578 if (command == PA_COMMAND_SET_SINK_VOLUME) {
1579 if (idx != (uint32_t) -1)
1580 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
1581 else
1582 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1);
1583 } else {
1584 assert(command == PA_COMMAND_SET_SINK_INPUT_VOLUME);
1585 si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
1586 }
1587
1588 if (!si && !sink) {
1589 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1590 return;
1591 }
1592
1593 if (sink)
1594 pa_sink_set_volume(sink, PA_MIXER_HARDWARE, &volume);
1595 else if (si)
1596 pa_sink_input_set_volume(si, &volume);
1597
1598 pa_pstream_send_simple_ack(c->pstream, tag);
1599 }
1600
1601 static void command_cork_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1602 struct connection *c = userdata;
1603 uint32_t idx;
1604 int b;
1605 struct playback_stream *s, *sync;
1606 assert(c && t);
1607
1608 if (pa_tagstruct_getu32(t, &idx) < 0 ||
1609 pa_tagstruct_get_boolean(t, &b) < 0 ||
1610 !pa_tagstruct_eof(t)) {
1611 protocol_error(c);
1612 return;
1613 }
1614
1615 if (!c->authorized) {
1616 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
1617 return;
1618 }
1619
1620 if (!(s = pa_idxset_get_by_index(c->output_streams, idx)) || s->type != PLAYBACK_STREAM) {
1621 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1622 return;
1623 }
1624
1625 fprintf(stderr, "Corking %i\n", b);
1626
1627 pa_sink_input_cork(s->sink_input, b);
1628 pa_memblockq_prebuf_force(s->memblockq);
1629
1630 /* Do the same for all other members in the sync group */
1631 for (sync = s->prev; sync; sync = sync->prev) {
1632 pa_sink_input_cork(sync->sink_input, b);
1633 pa_memblockq_prebuf_force(sync->memblockq);
1634 }
1635
1636 for (sync = s->next; sync; sync = sync->next) {
1637 pa_sink_input_cork(sync->sink_input, b);
1638 pa_memblockq_prebuf_force(sync->memblockq);
1639 }
1640
1641 pa_pstream_send_simple_ack(c->pstream, tag);
1642 }
1643
1644 static void command_flush_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1645 struct connection *c = userdata;
1646 uint32_t idx;
1647 struct playback_stream *s, *sync;
1648 assert(c && t);
1649
1650 if (pa_tagstruct_getu32(t, &idx) < 0 ||
1651 !pa_tagstruct_eof(t)) {
1652 protocol_error(c);
1653 return;
1654 }
1655
1656 if (!c->authorized) {
1657 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
1658 return;
1659 }
1660
1661 if (!(s = pa_idxset_get_by_index(c->output_streams, idx)) || s->type != PLAYBACK_STREAM) {
1662 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1663 return;
1664 }
1665
1666 pa_memblockq_flush(s->memblockq);
1667 s->underrun = 0;
1668
1669 /* Do the same for all other members in the sync group */
1670 for (sync = s->prev; sync; sync = sync->prev) {
1671 pa_memblockq_flush(sync->memblockq);
1672 sync->underrun = 0;
1673 }
1674
1675 for (sync = s->next; sync; sync = sync->next) {
1676 pa_memblockq_flush(sync->memblockq);
1677 sync->underrun = 0;
1678 }
1679
1680 pa_pstream_send_simple_ack(c->pstream, tag);
1681 pa_sink_notify(s->sink_input->sink);
1682 request_bytes(s);
1683
1684 for (sync = s->prev; sync; sync = sync->prev)
1685 request_bytes(sync);
1686
1687 for (sync = s->next; sync; sync = sync->next)
1688 request_bytes(sync);
1689 }
1690
1691 static void command_trigger_or_prebuf_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1692 struct connection *c = userdata;
1693 uint32_t idx;
1694 struct playback_stream *s;
1695 assert(c && t);
1696
1697 if (pa_tagstruct_getu32(t, &idx) < 0 ||
1698 !pa_tagstruct_eof(t)) {
1699 protocol_error(c);
1700 return;
1701 }
1702
1703 if (!c->authorized) {
1704 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
1705 return;
1706 }
1707
1708 if (!(s = pa_idxset_get_by_index(c->output_streams, idx)) || s->type != PLAYBACK_STREAM) {
1709 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1710 return;
1711 }
1712
1713 switch (command) {
1714 case PA_COMMAND_PREBUF_PLAYBACK_STREAM:
1715 pa_memblockq_prebuf_force(s->memblockq);
1716 break;
1717
1718 case PA_COMMAND_TRIGGER_PLAYBACK_STREAM:
1719 pa_memblockq_prebuf_disable(s->memblockq);
1720 break;
1721
1722 default:
1723 abort();
1724 }
1725
1726 pa_sink_notify(s->sink_input->sink);
1727 pa_pstream_send_simple_ack(c->pstream, tag);
1728 request_bytes(s);
1729 }
1730
1731 static void command_cork_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1732 struct connection *c = userdata;
1733 uint32_t idx;
1734 struct record_stream *s;
1735 int b;
1736 assert(c && t);
1737
1738 if (pa_tagstruct_getu32(t, &idx) < 0 ||
1739 pa_tagstruct_get_boolean(t, &b) < 0 ||
1740 !pa_tagstruct_eof(t)) {
1741 protocol_error(c);
1742 return;
1743 }
1744
1745 if (!c->authorized) {
1746 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
1747 return;
1748 }
1749
1750 if (!(s = pa_idxset_get_by_index(c->record_streams, idx))) {
1751 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1752 return;
1753 }
1754
1755 pa_source_output_cork(s->source_output, b);
1756 pa_memblockq_prebuf_force(s->memblockq);
1757 pa_pstream_send_simple_ack(c->pstream, tag);
1758 }
1759
1760 static void command_flush_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1761 struct connection *c = userdata;
1762 uint32_t idx;
1763 struct record_stream *s;
1764 assert(c && t);
1765
1766 if (pa_tagstruct_getu32(t, &idx) < 0 ||
1767 !pa_tagstruct_eof(t)) {
1768 protocol_error(c);
1769 return;
1770 }
1771
1772 if (!c->authorized) {
1773 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
1774 return;
1775 }
1776
1777 if (!(s = pa_idxset_get_by_index(c->record_streams, idx))) {
1778 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1779 return;
1780 }
1781
1782 pa_memblockq_flush(s->memblockq);
1783 pa_pstream_send_simple_ack(c->pstream, tag);
1784 }
1785
1786 static void command_set_default_sink_or_source(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1787 struct connection *c = userdata;
1788 uint32_t idx;
1789 const char *s;
1790 assert(c && t);
1791
1792 if (pa_tagstruct_getu32(t, &idx) < 0 ||
1793 pa_tagstruct_gets(t, &s) < 0 || !s ||
1794 !pa_tagstruct_eof(t)) {
1795 protocol_error(c);
1796 return;
1797 }
1798
1799 if (!c->authorized) {
1800 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
1801 return;
1802 }
1803
1804 pa_namereg_set_default(c->protocol->core, s, command == PA_COMMAND_SET_DEFAULT_SOURCE ? PA_NAMEREG_SOURCE : PA_NAMEREG_SINK);
1805 pa_pstream_send_simple_ack(c->pstream, tag);
1806 }
1807
1808 static void command_set_stream_name(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1809 struct connection *c = userdata;
1810 uint32_t idx;
1811 const char *name;
1812 assert(c && t);
1813
1814 if (pa_tagstruct_getu32(t, &idx) < 0 ||
1815 pa_tagstruct_gets(t, &name) < 0 || !name ||
1816 !pa_tagstruct_eof(t)) {
1817 protocol_error(c);
1818 return;
1819 }
1820
1821 if (!c->authorized) {
1822 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
1823 return;
1824 }
1825
1826 if (command == PA_COMMAND_SET_PLAYBACK_STREAM_NAME) {
1827 struct playback_stream *s;
1828
1829 if (!(s = pa_idxset_get_by_index(c->output_streams, idx)) || s->type != PLAYBACK_STREAM) {
1830 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1831 return;
1832 }
1833
1834 pa_sink_input_set_name(s->sink_input, name);
1835
1836 } else {
1837 struct record_stream *s;
1838
1839 if (!(s = pa_idxset_get_by_index(c->record_streams, idx))) {
1840 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1841 return;
1842 }
1843
1844 pa_source_output_set_name(s->source_output, name);
1845 }
1846
1847 pa_pstream_send_simple_ack(c->pstream, tag);
1848 }
1849
1850 static void command_kill(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1851 struct connection *c = userdata;
1852 uint32_t idx;
1853 assert(c && t);
1854
1855 if (pa_tagstruct_getu32(t, &idx) < 0 ||
1856 !pa_tagstruct_eof(t)) {
1857 protocol_error(c);
1858 return;
1859 }
1860
1861 if (!c->authorized) {
1862 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
1863 return;
1864 }
1865
1866 if (command == PA_COMMAND_KILL_CLIENT) {
1867 pa_client *client;
1868
1869 if (!(client = pa_idxset_get_by_index(c->protocol->core->clients, idx))) {
1870 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1871 return;
1872 }
1873
1874 pa_client_kill(client);
1875 } else if (command == PA_COMMAND_KILL_SINK_INPUT) {
1876 pa_sink_input *s;
1877
1878 if (!(s = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx))) {
1879 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1880 return;
1881 }
1882
1883 pa_sink_input_kill(s);
1884 } else {
1885 pa_source_output *s;
1886
1887 assert(command == PA_COMMAND_KILL_SOURCE_OUTPUT);
1888
1889 if (!(s = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx))) {
1890 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1891 return;
1892 }
1893
1894 pa_source_output_kill(s);
1895 }
1896
1897 pa_pstream_send_simple_ack(c->pstream, tag);
1898 }
1899
1900 static void command_load_module(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1901 struct connection *c = userdata;
1902 pa_module *m;
1903 const char *name, *argument;
1904 pa_tagstruct *reply;
1905 assert(c && t);
1906
1907 if (pa_tagstruct_gets(t, &name) < 0 || !name ||
1908 pa_tagstruct_gets(t, &argument) < 0 ||
1909 !pa_tagstruct_eof(t)) {
1910 protocol_error(c);
1911 return;
1912 }
1913
1914 if (!c->authorized) {
1915 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
1916 return;
1917 }
1918
1919 if (!(m = pa_module_load(c->protocol->core, name, argument))) {
1920 pa_pstream_send_error(c->pstream, tag, PA_ERR_MODINITFAILED);
1921 return;
1922 }
1923
1924 reply = pa_tagstruct_new(NULL, 0);
1925 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
1926 pa_tagstruct_putu32(reply, tag);
1927 pa_tagstruct_putu32(reply, m->index);
1928 pa_pstream_send_tagstruct(c->pstream, reply);
1929 }
1930
1931 static void command_unload_module(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1932 struct connection *c = userdata;
1933 uint32_t idx;
1934 pa_module *m;
1935 assert(c && t);
1936
1937 if (pa_tagstruct_getu32(t, &idx) < 0 ||
1938 !pa_tagstruct_eof(t)) {
1939 protocol_error(c);
1940 return;
1941 }
1942
1943 if (!c->authorized) {
1944 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
1945 return;
1946 }
1947
1948 if (!(m = pa_idxset_get_by_index(c->protocol->core->modules, idx))) {
1949 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1950 return;
1951 }
1952
1953 pa_module_unload_request(m);
1954 pa_pstream_send_simple_ack(c->pstream, tag);
1955 }
1956
1957 static void command_add_autoload(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1958 struct connection *c = userdata;
1959 const char *name, *module, *argument;
1960 uint32_t type;
1961 uint32_t idx;
1962 pa_tagstruct *reply;
1963 assert(c && t);
1964
1965 if (pa_tagstruct_gets(t, &name) < 0 || !name ||
1966 pa_tagstruct_getu32(t, &type) < 0 || type > 1 ||
1967 pa_tagstruct_gets(t, &module) < 0 || !module ||
1968 pa_tagstruct_gets(t, &argument) < 0 ||
1969 !pa_tagstruct_eof(t)) {
1970 protocol_error(c);
1971 return;
1972 }
1973
1974 if (!c->authorized) {
1975 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
1976 return;
1977 }
1978
1979 if (pa_autoload_add(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE, module, argument, &idx) < 0) {
1980 pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST);
1981 return;
1982 }
1983
1984 reply = pa_tagstruct_new(NULL, 0);
1985 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
1986 pa_tagstruct_putu32(reply, tag);
1987 pa_tagstruct_putu32(reply, idx);
1988 pa_pstream_send_tagstruct(c->pstream, reply);
1989 }
1990
1991 static void command_remove_autoload(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1992 struct connection *c = userdata;
1993 const char *name = NULL;
1994 uint32_t type, idx = PA_IDXSET_INVALID;
1995 int r;
1996 assert(c && t);
1997
1998 if ((pa_tagstruct_getu32(t, &idx) < 0 &&
1999 (pa_tagstruct_gets(t, &name) < 0 ||
2000 pa_tagstruct_getu32(t, &type) < 0)) ||
2001 (!name && idx == PA_IDXSET_INVALID) ||
2002 (name && type > 1) ||
2003 !pa_tagstruct_eof(t)) {
2004 protocol_error(c);
2005 return;
2006 }
2007
2008 if (!c->authorized) {
2009 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
2010 return;
2011 }
2012
2013 if (name)
2014 r = pa_autoload_remove_by_name(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE);
2015 else
2016 r = pa_autoload_remove_by_index(c->protocol->core, idx);
2017
2018 if (r < 0) {
2019 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2020 return;
2021 }
2022
2023 pa_pstream_send_simple_ack(c->pstream, tag);
2024 }
2025
2026 static void autoload_fill_tagstruct(pa_tagstruct *t, const pa_autoload_entry *e) {
2027 assert(t && e);
2028
2029 pa_tagstruct_putu32(t, e->index);
2030 pa_tagstruct_puts(t, e->name);
2031 pa_tagstruct_putu32(t, e->type == PA_NAMEREG_SINK ? 0 : 1);
2032 pa_tagstruct_puts(t, e->module);
2033 pa_tagstruct_puts(t, e->argument);
2034 }
2035
2036 static void command_get_autoload_info(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2037 struct connection *c = userdata;
2038 const pa_autoload_entry *a = NULL;
2039 uint32_t type, idx;
2040 const char *name;
2041 pa_tagstruct *reply;
2042 assert(c && t);
2043
2044 if ((pa_tagstruct_getu32(t, &idx) < 0 &&
2045 (pa_tagstruct_gets(t, &name) < 0 ||
2046 pa_tagstruct_getu32(t, &type) < 0)) ||
2047 (!name && idx == PA_IDXSET_INVALID) ||
2048 (name && type > 1) ||
2049 !pa_tagstruct_eof(t)) {
2050 protocol_error(c);
2051 return;
2052 }
2053
2054 if (!c->authorized) {
2055 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
2056 return;
2057 }
2058
2059
2060 if (name)
2061 a = pa_autoload_get_by_name(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE);
2062 else
2063 a = pa_autoload_get_by_index(c->protocol->core, idx);
2064
2065 if (!a) {
2066 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2067 return;
2068 }
2069
2070 reply = pa_tagstruct_new(NULL, 0);
2071 assert(reply);
2072 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
2073 pa_tagstruct_putu32(reply, tag);
2074 autoload_fill_tagstruct(reply, a);
2075 pa_pstream_send_tagstruct(c->pstream, reply);
2076 }
2077
2078 static void command_get_autoload_info_list(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2079 struct connection *c = userdata;
2080 pa_tagstruct *reply;
2081 assert(c && t);
2082
2083 if (!pa_tagstruct_eof(t)) {
2084 protocol_error(c);
2085 return;
2086 }
2087
2088 if (!c->authorized) {
2089 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
2090 return;
2091 }
2092
2093 reply = pa_tagstruct_new(NULL, 0);
2094 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
2095 pa_tagstruct_putu32(reply, tag);
2096
2097 if (c->protocol->core->autoload_hashmap) {
2098 pa_autoload_entry *a;
2099 void *state = NULL;
2100
2101 while ((a = pa_hashmap_iterate(c->protocol->core->autoload_hashmap, &state, NULL)))
2102 autoload_fill_tagstruct(reply, a);
2103 }
2104
2105 pa_pstream_send_tagstruct(c->pstream, reply);
2106 }
2107
2108 /*** pstream callbacks ***/
2109
2110 static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, void *userdata) {
2111 struct connection *c = userdata;
2112 assert(p && packet && packet->data && c);
2113
2114 if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) {
2115 pa_log(__FILE__": invalid packet.\n");
2116 connection_free(c);
2117 }
2118 }
2119
2120 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) {
2121 struct connection *c = userdata;
2122 struct output_stream *stream;
2123 assert(p && chunk && userdata);
2124
2125 if (!(stream = pa_idxset_get_by_index(c->output_streams, channel))) {
2126 pa_log(__FILE__": client sent block for invalid stream.\n");
2127 connection_free(c);
2128 return;
2129 }
2130
2131 if (stream->type == PLAYBACK_STREAM) {
2132 struct playback_stream *ps = (struct playback_stream*) stream;
2133 if (chunk->length >= ps->requested_bytes)
2134 ps->requested_bytes = 0;
2135 else
2136 ps->requested_bytes -= chunk->length;
2137
2138 pa_memblockq_seek(ps->memblockq, offset, seek);
2139
2140 if (pa_memblockq_push_align(ps->memblockq, chunk) < 0) {
2141 pa_tagstruct *t;
2142
2143 pa_log_warn(__FILE__": failed to push data into queue\n");
2144
2145 /* Pushing this block into the queue failed, so we simulate
2146 * it by skipping ahead */
2147
2148 pa_memblockq_seek(ps->memblockq, chunk->length, PA_SEEK_RELATIVE);
2149
2150 /* Notify the user */
2151 t = pa_tagstruct_new(NULL, 0);
2152 pa_tagstruct_putu32(t, PA_COMMAND_OVERFLOW);
2153 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
2154 pa_tagstruct_putu32(t, ps->index);
2155 pa_pstream_send_tagstruct(p, t);
2156 }
2157
2158 ps->underrun = 0;
2159
2160 pa_sink_notify(ps->sink_input->sink);
2161
2162 } else {
2163 struct upload_stream *u = (struct upload_stream*) stream;
2164 size_t l;
2165 assert(u->type == UPLOAD_STREAM);
2166
2167 if (!u->memchunk.memblock) {
2168 if (u->length == chunk->length) {
2169 u->memchunk = *chunk;
2170 pa_memblock_ref(u->memchunk.memblock);
2171 u->length = 0;
2172 } else {
2173 u->memchunk.memblock = pa_memblock_new(u->length, c->protocol->core->memblock_stat);
2174 u->memchunk.index = u->memchunk.length = 0;
2175 }
2176 }
2177
2178 assert(u->memchunk.memblock);
2179
2180 l = u->length;
2181 if (l > chunk->length)
2182 l = chunk->length;
2183
2184 if (l > 0) {
2185 memcpy((uint8_t*) u->memchunk.memblock->data + u->memchunk.index + u->memchunk.length,
2186 (uint8_t*) chunk->memblock->data+chunk->index, l);
2187 u->memchunk.length += l;
2188 u->length -= l;
2189 }
2190 }
2191 }
2192
2193 static void pstream_die_callback(pa_pstream *p, void *userdata) {
2194 struct connection *c = userdata;
2195 assert(p && c);
2196 connection_free(c);
2197
2198 /* pa_log(__FILE__": connection died.\n");*/
2199 }
2200
2201
2202 static void pstream_drain_callback(pa_pstream *p, void *userdata) {
2203 struct connection *c = userdata;
2204 assert(p && c);
2205
2206 send_memblock(c);
2207 }
2208
2209 /*** client callbacks ***/
2210
2211 static void client_kill_cb(pa_client *c) {
2212 assert(c && c->userdata);
2213 connection_free(c->userdata);
2214 }
2215
2216 /*** socket server callbacks ***/
2217
2218 static void auth_timeout(pa_mainloop_api*m, pa_time_event *e, const struct timeval *tv, void *userdata) {
2219 struct connection *c = userdata;
2220 assert(m && tv && c && c->auth_timeout_event == e);
2221
2222 if (!c->authorized)
2223 connection_free(c);
2224 }
2225
2226 static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, void *userdata) {
2227 pa_protocol_native *p = userdata;
2228 struct connection *c;
2229 assert(io && p);
2230
2231 if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) {
2232 pa_log_warn(__FILE__": Warning! Too many connections (%u), dropping incoming connection.\n", MAX_CONNECTIONS);
2233 pa_iochannel_free(io);
2234 return;
2235 }
2236
2237 c = pa_xmalloc(sizeof(struct connection));
2238
2239 c->authorized =!! p->public;
2240
2241 if (!c->authorized) {
2242 struct timeval tv;
2243 pa_gettimeofday(&tv);
2244 tv.tv_sec += AUTH_TIMEOUT;
2245 c->auth_timeout_event = p->core->mainloop->time_new(p->core->mainloop, &tv, auth_timeout, c);
2246 } else
2247 c->auth_timeout_event = NULL;
2248
2249 c->protocol = p;
2250 assert(p->core);
2251 c->client = pa_client_new(p->core, __FILE__, "Client");
2252 assert(c->client);
2253 c->client->kill = client_kill_cb;
2254 c->client->userdata = c;
2255 c->client->owner = p->module;
2256
2257 c->pstream = pa_pstream_new(p->core->mainloop, io, p->core->memblock_stat);
2258 assert(c->pstream);
2259
2260 pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c);
2261 pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c);
2262 pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c);
2263 pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c);
2264
2265 c->pdispatch = pa_pdispatch_new(p->core->mainloop, command_table, PA_COMMAND_MAX);
2266 assert(c->pdispatch);
2267
2268 c->record_streams = pa_idxset_new(NULL, NULL);
2269 c->output_streams = pa_idxset_new(NULL, NULL);
2270 assert(c->record_streams && c->output_streams);
2271
2272 c->rrobin_index = PA_IDXSET_INVALID;
2273 c->subscription = NULL;
2274
2275 pa_idxset_put(p->connections, c, NULL);
2276 }
2277
2278 /*** module entry points ***/
2279
2280 static int load_key(pa_protocol_native*p, const char*fn) {
2281 assert(p);
2282
2283 p->auth_cookie_in_property = 0;
2284
2285 if (!fn && pa_authkey_prop_get(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME, p->auth_cookie, sizeof(p->auth_cookie)) >= 0) {
2286 pa_log_info(__FILE__": using already loaded auth cookie.\n");
2287 pa_authkey_prop_ref(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME);
2288 p->auth_cookie_in_property = 1;
2289 return 0;
2290 }
2291
2292 if (!fn)
2293 fn = PA_NATIVE_COOKIE_FILE;
2294
2295 if (pa_authkey_load_auto(fn, p->auth_cookie, sizeof(p->auth_cookie)) < 0)
2296 return -1;
2297
2298 pa_log_info(__FILE__": loading cookie from disk.\n");
2299
2300 if (pa_authkey_prop_put(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME, p->auth_cookie, sizeof(p->auth_cookie)) >= 0)
2301 p->auth_cookie_in_property = 1;
2302
2303 return 0;
2304 }
2305
2306 static pa_protocol_native* protocol_new_internal(pa_core *c, pa_module *m, pa_modargs *ma) {
2307 pa_protocol_native *p;
2308 int public = 0;
2309 assert(c && ma);
2310
2311 if (pa_modargs_get_value_boolean(ma, "public", &public) < 0) {
2312 pa_log(__FILE__": public= expects a boolean argument.\n");
2313 return NULL;
2314 }
2315
2316 p = pa_xmalloc(sizeof(pa_protocol_native));
2317 p->core = c;
2318 p->module = m;
2319 p->public = public;
2320 p->server = NULL;
2321
2322 if (load_key(p, pa_modargs_get_value(ma, "cookie", NULL)) < 0) {
2323 pa_xfree(p);
2324 return NULL;
2325 }
2326
2327 p->connections = pa_idxset_new(NULL, NULL);
2328 assert(p->connections);
2329
2330 return p;
2331 }
2332
2333 pa_protocol_native* pa_protocol_native_new(pa_core *core, pa_socket_server *server, pa_module *m, pa_modargs *ma) {
2334 char t[256];
2335 pa_protocol_native *p;
2336
2337 if (!(p = protocol_new_internal(core, m, ma)))
2338 return NULL;
2339
2340 p->server = server;
2341 pa_socket_server_set_callback(p->server, on_connection, p);
2342
2343 if (pa_socket_server_get_address(p->server, t, sizeof(t))) {
2344 pa_strlist *l;
2345 l = pa_property_get(core, PA_NATIVE_SERVER_PROPERTY_NAME);
2346 l = pa_strlist_prepend(l, t);
2347 pa_property_replace(core, PA_NATIVE_SERVER_PROPERTY_NAME, l);
2348 }
2349
2350 return p;
2351 }
2352
2353 void pa_protocol_native_free(pa_protocol_native *p) {
2354 struct connection *c;
2355 assert(p);
2356
2357 while ((c = pa_idxset_first(p->connections, NULL)))
2358 connection_free(c);
2359 pa_idxset_free(p->connections, NULL, NULL);
2360
2361 if (p->server) {
2362 char t[256];
2363
2364 if (pa_socket_server_get_address(p->server, t, sizeof(t))) {
2365 pa_strlist *l;
2366 l = pa_property_get(p->core, PA_NATIVE_SERVER_PROPERTY_NAME);
2367 l = pa_strlist_remove(l, t);
2368
2369 if (l)
2370 pa_property_replace(p->core, PA_NATIVE_SERVER_PROPERTY_NAME, l);
2371 else
2372 pa_property_remove(p->core, PA_NATIVE_SERVER_PROPERTY_NAME);
2373 }
2374
2375 pa_socket_server_unref(p->server);
2376 }
2377
2378 if (p->auth_cookie_in_property)
2379 pa_authkey_prop_unref(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME);
2380
2381 pa_xfree(p);
2382 }
2383
2384 pa_protocol_native* pa_protocol_native_new_iochannel(pa_core*core, pa_iochannel *io, pa_module *m, pa_modargs *ma) {
2385 pa_protocol_native *p;
2386
2387 if (!(p = protocol_new_internal(core, m, ma)))
2388 return NULL;
2389
2390 on_connection(NULL, io, p);
2391
2392 return p;
2393 }