]> code.delx.au - pulseaudio/blob - polyp/module-tunnel.c
Add module-tunnel
[pulseaudio] / polyp / module-tunnel.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 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 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 <unistd.h>
27 #include <assert.h>
28 #include <string.h>
29 #include <errno.h>
30 #include <sys/types.h>
31 #include <regex.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34
35 #include "module.h"
36 #include "util.h"
37 #include "modargs.h"
38 #include "log.h"
39 #include "subscribe.h"
40 #include "xmalloc.h"
41 #include "sink-input.h"
42 #include "pdispatch.h"
43 #include "pstream.h"
44 #include "pstream-util.h"
45 #include "authkey.h"
46 #include "socket-client.h"
47 #include "socket-util.h"
48
49 PA_MODULE_AUTHOR("Lennart Poettering")
50 PA_MODULE_DESCRIPTION("Tunnel module")
51 PA_MODULE_USAGE("server=<filename> sink=<remote sink name> cookie=<filename> format=<sample format> channels=<number of channels> rate=<sample rate> sink_name=<name for the local sink>")
52 PA_MODULE_VERSION(PACKAGE_VERSION)
53
54 #define DEFAULT_SINK_NAME "tunnel"
55
56 #define DEFAULT_TLENGTH (10240*8)
57 #define DEFAULT_MAXLENGTH ((DEFAULT_TLENGTH*3)/2)
58 #define DEFAULT_PREBUF DEFAULT_TLENGTH
59 #define DEFAULT_MINREQ 512
60 #define DEFAULT_FRAGSIZE 1024
61
62 #define DEFAULT_TIMEOUT 5
63
64 static const char* const valid_modargs[] = {
65 "server",
66 "sink",
67 "cookie",
68 "format",
69 "channels",
70 "rate",
71 "sink_name",
72 NULL,
73 };
74
75 static void command_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
76 static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
77
78 static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = {
79 [PA_COMMAND_REQUEST] = { command_request },
80 [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { command_stream_killed },
81 [PA_COMMAND_RECORD_STREAM_KILLED] = { command_stream_killed },
82 };
83
84 struct userdata {
85 struct pa_socket_client *client;
86 struct pa_pstream *pstream;
87 struct pa_pdispatch *pdispatch;
88
89 char *server_name, *sink_name;
90
91 struct pa_sink *sink;
92 struct pa_module *module;
93 struct pa_core *core;
94
95 uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH];
96
97 uint32_t ctag;
98 uint32_t device_index;
99 uint32_t requested_bytes;
100 uint32_t channel;
101 };
102
103
104 static void close_stuff(struct userdata *u) {
105 if (u->pstream) {
106 pa_pstream_close(u->pstream);
107 pa_pstream_unref(u->pstream);
108 u->pstream = NULL;
109 }
110
111 if (u->pdispatch) {
112 pa_pdispatch_unref(u->pdispatch);
113 u->pdispatch = NULL;
114 }
115
116 if (u->client) {
117 pa_socket_client_unref(u->client);
118 u->client = NULL;
119 }
120
121 if (u->sink) {
122 pa_sink_disconnect(u->sink);
123 pa_sink_unref(u->sink);
124 u->sink = NULL;
125 }
126 }
127
128 static void die(struct userdata *u) {
129 assert(u);
130 close_stuff(u);
131 pa_module_unload_request(u->module);
132 }
133
134 static void request_bytes(struct userdata *u) {
135 assert(u);
136
137 if (!u->pstream)
138 return;
139
140 while (u->requested_bytes > 0) {
141 struct pa_memchunk chunk;
142 if (pa_sink_render(u->sink, u->requested_bytes, &chunk) < 0)
143 return;
144
145 pa_pstream_send_memblock(u->pstream, u->channel, 0, &chunk);
146 pa_memblock_unref(chunk.memblock);
147
148 if (chunk.length > u->requested_bytes)
149 u->requested_bytes = 0;
150 else
151 u->requested_bytes -= chunk.length;
152 }
153 }
154
155 static void command_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
156 struct userdata *u = userdata;
157 assert(pd && t && u && u->pdispatch == pd);
158
159 pa_log(__FILE__": stream killed\n");
160 die(u);
161 }
162
163 static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
164 struct userdata *u = userdata;
165 uint32_t bytes, channel;
166 assert(pd && command == PA_COMMAND_REQUEST && t && u && u->pdispatch == pd);
167
168 if (pa_tagstruct_getu32(t, &channel) < 0 ||
169 pa_tagstruct_getu32(t, &bytes) < 0 ||
170 !pa_tagstruct_eof(t)) {
171 pa_log(__FILE__": invalid protocol reply\n");
172 die(u);
173 return;
174 }
175
176 if (channel != u->channel) {
177 pa_log(__FILE__": recieved data for invalid channel\n");
178 die(u);
179 return;
180 }
181
182 u->requested_bytes += bytes;
183 request_bytes(u);
184 }
185
186
187 static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
188 struct userdata *u = userdata;
189 assert(pd && u && u->pdispatch == pd);
190
191 if (command != PA_COMMAND_REPLY) {
192 if (command == PA_COMMAND_ERROR)
193 pa_log(__FILE__": failed to create stream.\n");
194 else
195 pa_log(__FILE__": protocol error.\n");
196 die(u);
197 return;
198 }
199
200 if (pa_tagstruct_getu32(t, &u->channel) < 0 ||
201 pa_tagstruct_getu32(t, &u->device_index) < 0 ||
202 pa_tagstruct_getu32(t, &u->requested_bytes) < 0 ||
203 !pa_tagstruct_eof(t)) {
204 pa_log(__FILE__": invalid reply.\n");
205 die(u);
206 return;
207 }
208
209 request_bytes(u);
210 }
211
212 static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
213 struct userdata *u = userdata;
214 struct pa_tagstruct *reply;
215 char name[256], un[128], hn[128];
216 assert(pd && u && u->pdispatch == pd);
217
218 if (command != PA_COMMAND_REPLY || !pa_tagstruct_eof(t)) {
219 if (command == PA_COMMAND_ERROR)
220 pa_log(__FILE__": failed to authenticate\n");
221 else
222 pa_log(__FILE__": protocol error.\n");
223 die(u);
224 return;
225 }
226
227 snprintf(name, sizeof(name), "Tunnel from host '%s', user '%s', sink '%s'",
228 pa_get_host_name(hn, sizeof(hn)),
229 pa_get_user_name(un, sizeof(un)),
230 u->sink->name);
231
232 reply = pa_tagstruct_new(NULL, 0);
233 pa_tagstruct_putu32(reply, PA_COMMAND_SET_CLIENT_NAME);
234 pa_tagstruct_putu32(reply, tag = u->ctag++);
235 pa_tagstruct_puts(reply, name);
236 pa_pstream_send_tagstruct(u->pstream, reply);
237 /* We ignore the server's reply here */
238
239 reply = pa_tagstruct_new(NULL, 0);
240 pa_tagstruct_putu32(reply, PA_COMMAND_CREATE_PLAYBACK_STREAM);
241 pa_tagstruct_putu32(reply, tag = u->ctag++);
242 pa_tagstruct_puts(reply, name);
243 pa_tagstruct_put_sample_spec(reply, &u->sink->sample_spec);
244 pa_tagstruct_putu32(reply, PA_INVALID_INDEX);
245 pa_tagstruct_puts(reply, u->sink_name);
246 pa_tagstruct_putu32(reply, DEFAULT_MAXLENGTH);
247 pa_tagstruct_put_boolean(reply, 0);
248 pa_tagstruct_putu32(reply, DEFAULT_TLENGTH);
249 pa_tagstruct_putu32(reply, DEFAULT_PREBUF);
250 pa_tagstruct_putu32(reply, DEFAULT_MINREQ);
251 pa_tagstruct_putu32(reply, PA_VOLUME_NORM);
252
253 pa_pstream_send_tagstruct(u->pstream, reply);
254 pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, u);
255 }
256
257 static void pstream_die_callback(struct pa_pstream *p, void *userdata) {
258 struct userdata *u = userdata;
259 assert(p && u);
260
261 pa_log(__FILE__": stream died.\n");
262 die(u);
263 }
264
265
266 static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) {
267 struct userdata *u = userdata;
268 assert(p && packet && u);
269
270 if (pa_pdispatch_run(u->pdispatch, packet, u) < 0) {
271 pa_log(__FILE__": invalid packet\n");
272 die(u);
273 }
274 }
275
276 static void on_connection(struct pa_socket_client *sc, struct pa_iochannel *io, void *userdata) {
277 struct userdata *u = userdata;
278 struct pa_tagstruct *t;
279 uint32_t tag;
280 assert(sc && io && u && u->client == sc);
281
282 pa_socket_client_unref(u->client);
283 u->client = NULL;
284
285 if (!io) {
286 pa_log(__FILE__": connection failed.\n");
287 pa_module_unload_request(u->module);
288 return;
289 }
290
291 u->pstream = pa_pstream_new(u->core->mainloop, io, u->core->memblock_stat);
292 u->pdispatch = pa_pdispatch_new(u->core->mainloop, command_table, PA_COMMAND_MAX);
293
294 pa_pstream_set_die_callback(u->pstream, pstream_die_callback, u);
295 pa_pstream_set_recieve_packet_callback(u->pstream, pstream_packet_callback, u);
296
297 t = pa_tagstruct_new(NULL, 0);
298 pa_tagstruct_putu32(t, PA_COMMAND_AUTH);
299 pa_tagstruct_putu32(t, tag = u->ctag++);
300 pa_tagstruct_put_arbitrary(t, u->auth_cookie, sizeof(u->auth_cookie));
301 pa_pstream_send_tagstruct(u->pstream, t);
302 pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, u);
303
304 }
305
306 static void sink_notify(struct pa_sink*sink) {
307 struct userdata *u;
308 assert(sink && sink->userdata);
309 u = sink->userdata;
310
311 request_bytes(u);
312 }
313
314 static pa_usec_t sink_get_latency(struct pa_sink *sink) {
315 struct userdata *u;
316 assert(sink && sink->userdata);
317 u = sink->userdata;
318
319 return 0;
320 }
321
322 int pa__init(struct pa_core *c, struct pa_module*m) {
323 struct pa_modargs *ma = NULL;
324 struct userdata *u = NULL;
325 struct pa_sample_spec ss;
326 assert(c && m);
327
328 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
329 pa_log(__FILE__": failed to parse module arguments\n");
330
331 }
332
333 u = pa_xmalloc(sizeof(struct userdata));
334 m->userdata = u;
335 u->module = m;
336 u->core = c;
337 u->client = NULL;
338 u->pdispatch = NULL;
339 u->pstream = NULL;
340 u->server_name = u->sink_name = NULL;
341 u->sink = NULL;
342 u->ctag = 1;
343 u->device_index = u->channel = PA_INVALID_INDEX;
344 u->requested_bytes = 0;
345
346 if (pa_authkey_load_from_home(pa_modargs_get_value(ma, "cookie", PA_NATIVE_COOKIE_FILE), u->auth_cookie, sizeof(u->auth_cookie)) < 0) {
347 pa_log(__FILE__": failed to load cookie.\n");
348 goto fail;
349 }
350
351 if (!(u->server_name = pa_xstrdup(pa_modargs_get_value(ma, "server", NULL)))) {
352 pa_log(__FILE__": no server specified.\n");
353 goto fail;
354 }
355
356 u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL));
357
358 ss = c->default_sample_spec;
359 if (pa_modargs_get_sample_spec(ma, &ss) < 0) {
360 pa_log(__FILE__": invalid sample format specification\n");
361 goto fail;
362 }
363
364 if (u->server_name[0] == '/')
365 u->client = pa_socket_client_new_unix(c->mainloop, u->server_name);
366 else {
367 size_t len;
368 struct sockaddr *sa;
369
370 if (!(sa = pa_resolve_server(u->server_name, &len, PA_NATIVE_DEFAULT_PORT))) {
371 pa_log(__FILE__": failed to resolve server '%s'\n", u->server_name);
372 goto fail;
373 }
374
375 u->client = pa_socket_client_new_sockaddr(c->mainloop, sa, len);
376 pa_xfree(sa);
377 }
378
379 if (!u->client)
380 goto fail;
381
382 pa_socket_client_set_callback(u->client, on_connection, u);
383
384 if (!(u->sink = pa_sink_new(c, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss))) {
385 pa_log(__FILE__": failed to create sink.\n");
386 goto fail;
387 }
388
389 u->sink->notify = sink_notify;
390 u->sink->get_latency = sink_get_latency;
391 u->sink->userdata = u;
392 u->sink->description = pa_sprintf_malloc("Tunnel to '%s%s%s'", u->sink_name ? u->sink_name : "", u->sink_name ? "@" : "", u->server_name);
393
394 pa_sink_set_owner(u->sink, m);
395
396 pa_modargs_free(ma);
397
398 return 0;
399
400 fail:
401 pa__done(c, m);
402
403 if (ma)
404 pa_modargs_free(ma);
405 return -1;
406 }
407
408 void pa__done(struct pa_core *c, struct pa_module*m) {
409 struct userdata* u;
410 assert(c && m);
411
412 if (!(u = m->userdata))
413 return;
414
415 close_stuff(u);
416
417 pa_xfree(u->sink_name);
418 pa_xfree(u->server_name);
419
420 pa_xfree(u);
421 }
422
423