]> code.delx.au - pulseaudio/blob - src/pulsecore/socket-client.c
Merge remote branch 'tanuk/master'
[pulseaudio] / src / pulsecore / socket-client.c
1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2006-2007 Pierre Ossman <ossman@cendio.se> for Cendio AB
6
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as
9 published by the Free Software Foundation; either version 2.1 of the
10 License, or (at your option) any later version.
11
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 USA.
21 ***/
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 /* #undef HAVE_LIBASYNCNS */
28
29 #include <unistd.h>
30 #include <stdio.h>
31 #include <errno.h>
32 #include <string.h>
33 #include <stdlib.h>
34
35 #ifdef HAVE_SYS_SOCKET_H
36 #include <sys/socket.h>
37 #endif
38 #ifdef HAVE_SYS_UN_H
39 #include <sys/un.h>
40 #endif
41 #ifdef HAVE_ARPA_INET_H
42 #include <arpa/inet.h>
43 #endif
44 #ifdef HAVE_NETINET_IN_H
45 #include <netinet/in.h>
46 #endif
47 #ifdef HAVE_NETDB_H
48 #include <netdb.h>
49 #endif
50
51 #ifdef HAVE_LIBASYNCNS
52 #include <asyncns.h>
53 #endif
54
55 #include <pulse/rtclock.h>
56 #include <pulse/timeval.h>
57 #include <pulse/xmalloc.h>
58
59 #include <pulsecore/winsock.h>
60 #include <pulsecore/core-error.h>
61 #include <pulsecore/socket-util.h>
62 #include <pulsecore/core-rtclock.h>
63 #include <pulsecore/core-util.h>
64 #include <pulsecore/socket-util.h>
65 #include <pulsecore/log.h>
66 #include <pulsecore/parseaddr.h>
67 #include <pulsecore/macro.h>
68 #include <pulsecore/refcnt.h>
69
70 #include "socket-client.h"
71
72 #define CONNECT_TIMEOUT 5
73
74 struct pa_socket_client {
75 PA_REFCNT_DECLARE;
76 int fd;
77
78 pa_mainloop_api *mainloop;
79 pa_io_event *io_event;
80 pa_time_event *timeout_event;
81 pa_defer_event *defer_event;
82
83 pa_socket_client_cb_t callback;
84 void *userdata;
85
86 pa_bool_t local;
87
88 #ifdef HAVE_LIBASYNCNS
89 asyncns_t *asyncns;
90 asyncns_query_t * asyncns_query;
91 pa_io_event *asyncns_io_event;
92 #endif
93 };
94
95 static pa_socket_client* socket_client_new(pa_mainloop_api *m) {
96 pa_socket_client *c;
97 pa_assert(m);
98
99 c = pa_xnew0(pa_socket_client, 1);
100 PA_REFCNT_INIT(c);
101 c->mainloop = m;
102 c->fd = -1;
103
104 return c;
105 }
106
107 static void free_events(pa_socket_client *c) {
108 pa_assert(c);
109
110 if (c->io_event) {
111 c->mainloop->io_free(c->io_event);
112 c->io_event = NULL;
113 }
114
115 if (c->timeout_event) {
116 c->mainloop->time_free(c->timeout_event);
117 c->timeout_event = NULL;
118 }
119
120 if (c->defer_event) {
121 c->mainloop->defer_free(c->defer_event);
122 c->defer_event = NULL;
123 }
124 }
125
126 static void do_call(pa_socket_client *c) {
127 pa_iochannel *io = NULL;
128 int error;
129 socklen_t lerror;
130
131 pa_assert(c);
132 pa_assert(PA_REFCNT_VALUE(c) >= 1);
133 pa_assert(c->callback);
134
135 pa_socket_client_ref(c);
136
137 if (c->fd < 0)
138 goto finish;
139
140 lerror = sizeof(error);
141 if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void*)&error, &lerror) < 0) {
142 pa_log("getsockopt(): %s", pa_cstrerror(errno));
143 goto finish;
144 }
145
146 if (lerror != sizeof(error)) {
147 pa_log("getsockopt() returned invalid size.");
148 goto finish;
149 }
150
151 if (error != 0) {
152 pa_log_debug("connect(): %s", pa_cstrerror(error));
153 errno = error;
154 goto finish;
155 }
156
157 io = pa_iochannel_new(c->mainloop, c->fd, c->fd);
158
159 finish:
160 if (!io && c->fd >= 0)
161 pa_close(c->fd);
162 c->fd = -1;
163
164 free_events(c);
165
166 c->callback(c, io, c->userdata);
167
168 pa_socket_client_unref(c);
169 }
170
171 static void connect_defer_cb(pa_mainloop_api *m, pa_defer_event *e, void *userdata) {
172 pa_socket_client *c = userdata;
173
174 pa_assert(m);
175 pa_assert(c);
176 pa_assert(PA_REFCNT_VALUE(c) >= 1);
177 pa_assert(c->defer_event == e);
178
179 do_call(c);
180 }
181
182 static void connect_io_cb(pa_mainloop_api*m, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) {
183 pa_socket_client *c = userdata;
184
185 pa_assert(m);
186 pa_assert(c);
187 pa_assert(PA_REFCNT_VALUE(c) >= 1);
188 pa_assert(c->io_event == e);
189 pa_assert(fd >= 0);
190
191 do_call(c);
192 }
193
194 static int do_connect(pa_socket_client *c, const struct sockaddr *sa, socklen_t len) {
195 pa_assert(c);
196 pa_assert(PA_REFCNT_VALUE(c) >= 1);
197 pa_assert(sa);
198 pa_assert(len > 0);
199
200 pa_make_fd_nonblock(c->fd);
201
202 if (connect(c->fd, sa, len) < 0) {
203 #ifdef OS_IS_WIN32
204 if (WSAGetLastError() != EWOULDBLOCK) {
205 pa_log_debug("connect(): %d", WSAGetLastError());
206 #else
207 if (errno != EINPROGRESS) {
208 pa_log_debug("connect(): %s (%d)", pa_cstrerror(errno), errno);
209 #endif
210 return -1;
211 }
212
213 c->io_event = c->mainloop->io_new(c->mainloop, c->fd, PA_IO_EVENT_OUTPUT, connect_io_cb, c);
214 } else
215 c->defer_event = c->mainloop->defer_new(c->mainloop, connect_defer_cb, c);
216
217 return 0;
218 }
219
220 pa_socket_client* pa_socket_client_new_ipv4(pa_mainloop_api *m, uint32_t address, uint16_t port) {
221 struct sockaddr_in sa;
222
223 pa_assert(m);
224 pa_assert(port > 0);
225
226 pa_zero(sa);
227 sa.sin_family = AF_INET;
228 sa.sin_port = htons(port);
229 sa.sin_addr.s_addr = htonl(address);
230
231 return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa));
232 }
233
234
235 pa_socket_client* pa_socket_client_new_unix(pa_mainloop_api *m, const char *filename) {
236 #ifdef HAVE_SYS_UN_H
237 struct sockaddr_un sa;
238
239 pa_assert(m);
240 pa_assert(filename);
241
242 pa_zero(sa);
243 sa.sun_family = AF_UNIX;
244 pa_strlcpy(sa.sun_path, filename, sizeof(sa.sun_path));
245
246 return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa));
247 #else /* HAVE_SYS_UN_H */
248
249 return NULL;
250 #endif /* HAVE_SYS_UN_H */
251 }
252
253 static int sockaddr_prepare(pa_socket_client *c, const struct sockaddr *sa, size_t salen) {
254 pa_assert(c);
255 pa_assert(sa);
256 pa_assert(salen);
257
258 c->local = pa_socket_address_is_local(sa);
259
260 if ((c->fd = pa_socket_cloexec(sa->sa_family, SOCK_STREAM, 0)) < 0) {
261 pa_log("socket(): %s", pa_cstrerror(errno));
262 return -1;
263 }
264
265 #ifdef HAVE_IPV6
266 if (sa->sa_family == AF_INET || sa->sa_family == AF_INET6)
267 #else
268 if (sa->sa_family == AF_INET)
269 #endif
270 pa_make_tcp_socket_low_delay(c->fd);
271 else
272 pa_make_socket_low_delay(c->fd);
273
274 if (do_connect(c, sa, (socklen_t) salen) < 0)
275 return -1;
276
277 return 0;
278 }
279
280 pa_socket_client* pa_socket_client_new_sockaddr(pa_mainloop_api *m, const struct sockaddr *sa, size_t salen) {
281 pa_socket_client *c;
282
283 pa_assert(m);
284 pa_assert(sa);
285 pa_assert(salen > 0);
286
287 c = socket_client_new(m);
288
289 if (sockaddr_prepare(c, sa, salen) < 0)
290 goto fail;
291
292 return c;
293
294 fail:
295 pa_socket_client_unref(c);
296 return NULL;
297 }
298
299 static void socket_client_free(pa_socket_client *c) {
300 pa_assert(c);
301 pa_assert(c->mainloop);
302
303 free_events(c);
304
305 if (c->fd >= 0)
306 pa_close(c->fd);
307
308 #ifdef HAVE_LIBASYNCNS
309 if (c->asyncns_query)
310 asyncns_cancel(c->asyncns, c->asyncns_query);
311 if (c->asyncns)
312 asyncns_free(c->asyncns);
313 if (c->asyncns_io_event)
314 c->mainloop->io_free(c->asyncns_io_event);
315 #endif
316
317 pa_xfree(c);
318 }
319
320 void pa_socket_client_unref(pa_socket_client *c) {
321 pa_assert(c);
322 pa_assert(PA_REFCNT_VALUE(c) >= 1);
323
324 if (PA_REFCNT_DEC(c) <= 0)
325 socket_client_free(c);
326 }
327
328 pa_socket_client* pa_socket_client_ref(pa_socket_client *c) {
329 pa_assert(c);
330 pa_assert(PA_REFCNT_VALUE(c) >= 1);
331
332 PA_REFCNT_INC(c);
333 return c;
334 }
335
336 void pa_socket_client_set_callback(pa_socket_client *c, pa_socket_client_cb_t on_connection, void *userdata) {
337 pa_assert(c);
338 pa_assert(PA_REFCNT_VALUE(c) >= 1);
339
340 c->callback = on_connection;
341 c->userdata = userdata;
342 }
343
344 pa_socket_client* pa_socket_client_new_ipv6(pa_mainloop_api *m, uint8_t address[16], uint16_t port) {
345 #ifdef HAVE_IPV6
346 struct sockaddr_in6 sa;
347
348 pa_assert(m);
349 pa_assert(address);
350 pa_assert(port > 0);
351
352 pa_zero(sa);
353 sa.sin6_family = AF_INET6;
354 sa.sin6_port = htons(port);
355 memcpy(&sa.sin6_addr, address, sizeof(sa.sin6_addr));
356
357 return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa));
358
359 #else
360 return NULL;
361 #endif
362 }
363
364 #ifdef HAVE_LIBASYNCNS
365
366 static void asyncns_cb(pa_mainloop_api*m, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) {
367 pa_socket_client *c = userdata;
368 struct addrinfo *res = NULL;
369 int ret;
370
371 pa_assert(m);
372 pa_assert(c);
373 pa_assert(PA_REFCNT_VALUE(c) >= 1);
374 pa_assert(c->asyncns_io_event == e);
375 pa_assert(fd >= 0);
376
377 if (asyncns_wait(c->asyncns, 0) < 0)
378 goto fail;
379
380 if (!asyncns_isdone(c->asyncns, c->asyncns_query))
381 return;
382
383 ret = asyncns_getaddrinfo_done(c->asyncns, c->asyncns_query, &res);
384 c->asyncns_query = NULL;
385
386 if (ret != 0 || !res)
387 goto fail;
388
389 if (res->ai_addr)
390 sockaddr_prepare(c, res->ai_addr, res->ai_addrlen);
391
392 asyncns_freeaddrinfo(res);
393
394 m->io_free(c->asyncns_io_event);
395 c->asyncns_io_event = NULL;
396 return;
397
398 fail:
399 m->io_free(c->asyncns_io_event);
400 c->asyncns_io_event = NULL;
401
402 errno = EHOSTUNREACH;
403 do_call(c);
404 return;
405
406 }
407
408 #endif
409
410 static void timeout_cb(pa_mainloop_api *m, pa_time_event *e, const struct timeval *t, void *userdata) {
411 pa_socket_client *c = userdata;
412
413 pa_assert(m);
414 pa_assert(e);
415 pa_assert(c);
416
417 if (c->fd >= 0) {
418 pa_close(c->fd);
419 c->fd = -1;
420 }
421
422 errno = ETIMEDOUT;
423 do_call(c);
424 }
425
426 static void start_timeout(pa_socket_client *c, pa_bool_t use_rtclock) {
427 struct timeval tv;
428
429 pa_assert(c);
430 pa_assert(!c->timeout_event);
431
432 c->timeout_event = c->mainloop->time_new(c->mainloop, pa_timeval_rtstore(&tv, pa_rtclock_now() + CONNECT_TIMEOUT * PA_USEC_PER_SEC, use_rtclock), timeout_cb, c);
433 }
434
435 pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, pa_bool_t use_rtclock, const char*name, uint16_t default_port) {
436 pa_socket_client *c = NULL;
437 pa_parsed_address a;
438
439 pa_assert(m);
440 pa_assert(name);
441
442 if (pa_parse_address(name, &a) < 0)
443 return NULL;
444
445 if (!a.port)
446 a.port = default_port;
447
448 switch (a.type) {
449 case PA_PARSED_ADDRESS_UNIX:
450 if ((c = pa_socket_client_new_unix(m, a.path_or_host)))
451 start_timeout(c, use_rtclock);
452 break;
453
454 case PA_PARSED_ADDRESS_TCP4: /* Fallthrough */
455 case PA_PARSED_ADDRESS_TCP6: /* Fallthrough */
456 case PA_PARSED_ADDRESS_TCP_AUTO: {
457 struct addrinfo hints;
458 char port[12];
459
460 pa_snprintf(port, sizeof(port), "%u", (unsigned) a.port);
461
462 pa_zero(hints);
463 if (a.type == PA_PARSED_ADDRESS_TCP4)
464 hints.ai_family = PF_INET;
465 #ifdef HAVE_IPV6
466 else if (a.type == PA_PARSED_ADDRESS_TCP6)
467 hints.ai_family = PF_INET6;
468 #endif
469 else
470 hints.ai_family = PF_UNSPEC;
471
472 hints.ai_socktype = SOCK_STREAM;
473
474 #if defined(HAVE_LIBASYNCNS)
475 {
476 asyncns_t *asyncns;
477
478 if (!(asyncns = asyncns_new(1)))
479 goto finish;
480
481 c = socket_client_new(m);
482 c->asyncns = asyncns;
483 c->asyncns_io_event = m->io_new(m, asyncns_fd(c->asyncns), PA_IO_EVENT_INPUT, asyncns_cb, c);
484 pa_assert_se(c->asyncns_query = asyncns_getaddrinfo(c->asyncns, a.path_or_host, port, &hints));
485 start_timeout(c, use_rtclock);
486 }
487 #elif defined(HAVE_GETADDRINFO)
488 {
489 int ret;
490 struct addrinfo *res = NULL;
491
492 ret = getaddrinfo(a.path_or_host, port, &hints, &res);
493
494 if (ret < 0 || !res)
495 goto finish;
496
497 if (res->ai_addr) {
498 if ((c = pa_socket_client_new_sockaddr(m, res->ai_addr, res->ai_addrlen)))
499 start_timeout(c, use_rtclock);
500 }
501
502 freeaddrinfo(res);
503 }
504 #else
505 {
506 struct hostent *host = NULL;
507 struct sockaddr_in s;
508
509 #ifdef HAVE_IPV6
510 /* FIXME: PF_INET6 support */
511 if (hints.ai_family == PF_INET6) {
512 pa_log_error("IPv6 is not supported on Windows");
513 goto finish;
514 }
515 #endif
516
517 host = gethostbyname(a.path_or_host);
518 if (!host) {
519 unsigned int addr = inet_addr(a.path_or_host);
520 if (addr != INADDR_NONE)
521 host = gethostbyaddr((char*)&addr, 4, AF_INET);
522 }
523
524 if (!host)
525 goto finish;
526
527 pa_zero(sa);
528 s.sin_family = AF_INET;
529 memcpy(&s.sin_addr, host->h_addr, sizeof(struct in_addr));
530 s.sin_port = htons(a.port);
531
532 if ((c = pa_socket_client_new_sockaddr(m, (struct sockaddr*)&s, sizeof(s))))
533 start_timeout(c, use_rtclock);
534 }
535 #endif /* HAVE_LIBASYNCNS */
536 }
537 }
538
539 finish:
540 pa_xfree(a.path_or_host);
541 return c;
542
543 }
544
545 /* Return non-zero when the target sockaddr is considered
546 local. "local" means UNIX socket or TCP socket on localhost. Other
547 local IP addresses are not considered local. */
548 pa_bool_t pa_socket_client_is_local(pa_socket_client *c) {
549 pa_assert(c);
550 pa_assert(PA_REFCNT_VALUE(c) >= 1);
551
552 return c->local;
553 }