default: esd is obsolete, hence don't load it anymore by default
[pulseaudio-mirror.git] / src / pulsecore / socket-client.c
blob23d5d880cf9f2b60387a280abcb8f036110ca05f
1 /***
2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2006-2007 Pierre Ossman <ossman@cendio.se> for Cendio AB
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.
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.
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 ***/
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
27 /* #undef HAVE_LIBASYNCNS */
29 #include <unistd.h>
30 #include <stdio.h>
31 #include <errno.h>
32 #include <string.h>
33 #include <stdlib.h>
35 #ifdef HAVE_SYS_UN_H
36 #include <sys/un.h>
37 #endif
38 #ifdef HAVE_NETINET_IN_H
39 #include <netinet/in.h>
40 #endif
41 #ifdef HAVE_NETDB_H
42 #include <netdb.h>
43 #endif
45 #ifdef HAVE_LIBASYNCNS
46 #include <asyncns.h>
47 #endif
49 #include <pulse/rtclock.h>
50 #include <pulse/timeval.h>
51 #include <pulse/xmalloc.h>
53 #include <pulsecore/socket.h>
54 #include <pulsecore/socket-util.h>
55 #include <pulsecore/core-error.h>
56 #include <pulsecore/core-rtclock.h>
57 #include <pulsecore/core-util.h>
58 #include <pulsecore/socket-util.h>
59 #include <pulsecore/log.h>
60 #include <pulsecore/parseaddr.h>
61 #include <pulsecore/macro.h>
62 #include <pulsecore/refcnt.h>
63 #include <pulsecore/arpa-inet.h>
65 #include "socket-client.h"
67 #define CONNECT_TIMEOUT 5
69 struct pa_socket_client {
70 PA_REFCNT_DECLARE;
71 int fd;
73 pa_mainloop_api *mainloop;
74 pa_io_event *io_event;
75 pa_time_event *timeout_event;
76 pa_defer_event *defer_event;
78 pa_socket_client_cb_t callback;
79 void *userdata;
81 pa_bool_t local;
83 #ifdef HAVE_LIBASYNCNS
84 asyncns_t *asyncns;
85 asyncns_query_t * asyncns_query;
86 pa_io_event *asyncns_io_event;
87 #endif
90 static pa_socket_client* socket_client_new(pa_mainloop_api *m) {
91 pa_socket_client *c;
92 pa_assert(m);
94 c = pa_xnew0(pa_socket_client, 1);
95 PA_REFCNT_INIT(c);
96 c->mainloop = m;
97 c->fd = -1;
99 return c;
102 static void free_events(pa_socket_client *c) {
103 pa_assert(c);
105 if (c->io_event) {
106 c->mainloop->io_free(c->io_event);
107 c->io_event = NULL;
110 if (c->timeout_event) {
111 c->mainloop->time_free(c->timeout_event);
112 c->timeout_event = NULL;
115 if (c->defer_event) {
116 c->mainloop->defer_free(c->defer_event);
117 c->defer_event = NULL;
121 static void do_call(pa_socket_client *c) {
122 pa_iochannel *io = NULL;
123 int error;
124 socklen_t lerror;
126 pa_assert(c);
127 pa_assert(PA_REFCNT_VALUE(c) >= 1);
128 pa_assert(c->callback);
130 pa_socket_client_ref(c);
132 if (c->fd < 0)
133 goto finish;
135 lerror = sizeof(error);
136 if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void*)&error, &lerror) < 0) {
137 pa_log("getsockopt(): %s", pa_cstrerror(errno));
138 goto finish;
141 if (lerror != sizeof(error)) {
142 pa_log("getsockopt() returned invalid size.");
143 goto finish;
146 if (error != 0) {
147 pa_log_debug("connect(): %s", pa_cstrerror(error));
148 errno = error;
149 goto finish;
152 io = pa_iochannel_new(c->mainloop, c->fd, c->fd);
154 finish:
155 if (!io && c->fd >= 0)
156 pa_close(c->fd);
157 c->fd = -1;
159 free_events(c);
161 c->callback(c, io, c->userdata);
163 pa_socket_client_unref(c);
166 static void connect_defer_cb(pa_mainloop_api *m, pa_defer_event *e, void *userdata) {
167 pa_socket_client *c = userdata;
169 pa_assert(m);
170 pa_assert(c);
171 pa_assert(PA_REFCNT_VALUE(c) >= 1);
172 pa_assert(c->defer_event == e);
174 do_call(c);
177 static void connect_io_cb(pa_mainloop_api*m, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) {
178 pa_socket_client *c = userdata;
180 pa_assert(m);
181 pa_assert(c);
182 pa_assert(PA_REFCNT_VALUE(c) >= 1);
183 pa_assert(c->io_event == e);
184 pa_assert(fd >= 0);
186 do_call(c);
189 static int do_connect(pa_socket_client *c, const struct sockaddr *sa, socklen_t len) {
190 pa_assert(c);
191 pa_assert(PA_REFCNT_VALUE(c) >= 1);
192 pa_assert(sa);
193 pa_assert(len > 0);
195 pa_make_fd_nonblock(c->fd);
197 if (connect(c->fd, sa, len) < 0) {
198 #ifdef OS_IS_WIN32
199 if (WSAGetLastError() != EWOULDBLOCK) {
200 pa_log_debug("connect(): %d", WSAGetLastError());
201 #else
202 if (errno != EINPROGRESS) {
203 pa_log_debug("connect(): %s (%d)", pa_cstrerror(errno), errno);
204 #endif
205 return -1;
208 c->io_event = c->mainloop->io_new(c->mainloop, c->fd, PA_IO_EVENT_OUTPUT, connect_io_cb, c);
209 } else
210 c->defer_event = c->mainloop->defer_new(c->mainloop, connect_defer_cb, c);
212 return 0;
215 pa_socket_client* pa_socket_client_new_ipv4(pa_mainloop_api *m, uint32_t address, uint16_t port) {
216 struct sockaddr_in sa;
218 pa_assert(m);
219 pa_assert(port > 0);
221 pa_zero(sa);
222 sa.sin_family = AF_INET;
223 sa.sin_port = htons(port);
224 sa.sin_addr.s_addr = htonl(address);
226 return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa));
230 pa_socket_client* pa_socket_client_new_unix(pa_mainloop_api *m, const char *filename) {
231 #ifdef HAVE_SYS_UN_H
232 struct sockaddr_un sa;
234 pa_assert(m);
235 pa_assert(filename);
237 pa_zero(sa);
238 sa.sun_family = AF_UNIX;
239 pa_strlcpy(sa.sun_path, filename, sizeof(sa.sun_path));
241 return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa));
242 #else /* HAVE_SYS_UN_H */
244 return NULL;
245 #endif /* HAVE_SYS_UN_H */
248 static int sockaddr_prepare(pa_socket_client *c, const struct sockaddr *sa, size_t salen) {
249 pa_assert(c);
250 pa_assert(sa);
251 pa_assert(salen);
253 c->local = pa_socket_address_is_local(sa);
255 if ((c->fd = pa_socket_cloexec(sa->sa_family, SOCK_STREAM, 0)) < 0) {
256 pa_log("socket(): %s", pa_cstrerror(errno));
257 return -1;
260 #ifdef HAVE_IPV6
261 if (sa->sa_family == AF_INET || sa->sa_family == AF_INET6)
262 #else
263 if (sa->sa_family == AF_INET)
264 #endif
265 pa_make_tcp_socket_low_delay(c->fd);
266 else
267 pa_make_socket_low_delay(c->fd);
269 if (do_connect(c, sa, (socklen_t) salen) < 0)
270 return -1;
272 return 0;
275 pa_socket_client* pa_socket_client_new_sockaddr(pa_mainloop_api *m, const struct sockaddr *sa, size_t salen) {
276 pa_socket_client *c;
278 pa_assert(m);
279 pa_assert(sa);
280 pa_assert(salen > 0);
282 c = socket_client_new(m);
284 if (sockaddr_prepare(c, sa, salen) < 0)
285 goto fail;
287 return c;
289 fail:
290 pa_socket_client_unref(c);
291 return NULL;
294 static void socket_client_free(pa_socket_client *c) {
295 pa_assert(c);
296 pa_assert(c->mainloop);
298 free_events(c);
300 if (c->fd >= 0)
301 pa_close(c->fd);
303 #ifdef HAVE_LIBASYNCNS
304 if (c->asyncns_query)
305 asyncns_cancel(c->asyncns, c->asyncns_query);
306 if (c->asyncns)
307 asyncns_free(c->asyncns);
308 if (c->asyncns_io_event)
309 c->mainloop->io_free(c->asyncns_io_event);
310 #endif
312 pa_xfree(c);
315 void pa_socket_client_unref(pa_socket_client *c) {
316 pa_assert(c);
317 pa_assert(PA_REFCNT_VALUE(c) >= 1);
319 if (PA_REFCNT_DEC(c) <= 0)
320 socket_client_free(c);
323 pa_socket_client* pa_socket_client_ref(pa_socket_client *c) {
324 pa_assert(c);
325 pa_assert(PA_REFCNT_VALUE(c) >= 1);
327 PA_REFCNT_INC(c);
328 return c;
331 void pa_socket_client_set_callback(pa_socket_client *c, pa_socket_client_cb_t on_connection, void *userdata) {
332 pa_assert(c);
333 pa_assert(PA_REFCNT_VALUE(c) >= 1);
335 c->callback = on_connection;
336 c->userdata = userdata;
339 pa_socket_client* pa_socket_client_new_ipv6(pa_mainloop_api *m, uint8_t address[16], uint16_t port) {
340 #ifdef HAVE_IPV6
341 struct sockaddr_in6 sa;
343 pa_assert(m);
344 pa_assert(address);
345 pa_assert(port > 0);
347 pa_zero(sa);
348 sa.sin6_family = AF_INET6;
349 sa.sin6_port = htons(port);
350 memcpy(&sa.sin6_addr, address, sizeof(sa.sin6_addr));
352 return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa));
354 #else
355 return NULL;
356 #endif
359 #ifdef HAVE_LIBASYNCNS
361 static void asyncns_cb(pa_mainloop_api*m, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) {
362 pa_socket_client *c = userdata;
363 struct addrinfo *res = NULL;
364 int ret;
366 pa_assert(m);
367 pa_assert(c);
368 pa_assert(PA_REFCNT_VALUE(c) >= 1);
369 pa_assert(c->asyncns_io_event == e);
370 pa_assert(fd >= 0);
372 if (asyncns_wait(c->asyncns, 0) < 0)
373 goto fail;
375 if (!asyncns_isdone(c->asyncns, c->asyncns_query))
376 return;
378 ret = asyncns_getaddrinfo_done(c->asyncns, c->asyncns_query, &res);
379 c->asyncns_query = NULL;
381 if (ret != 0 || !res)
382 goto fail;
384 if (res->ai_addr)
385 if (sockaddr_prepare(c, res->ai_addr, res->ai_addrlen) < 0)
386 goto fail;
388 asyncns_freeaddrinfo(res);
390 m->io_free(c->asyncns_io_event);
391 c->asyncns_io_event = NULL;
392 return;
394 fail:
395 m->io_free(c->asyncns_io_event);
396 c->asyncns_io_event = NULL;
398 errno = EHOSTUNREACH;
399 do_call(c);
400 return;
404 #endif
406 static void timeout_cb(pa_mainloop_api *m, pa_time_event *e, const struct timeval *t, void *userdata) {
407 pa_socket_client *c = userdata;
409 pa_assert(m);
410 pa_assert(e);
411 pa_assert(c);
413 if (c->fd >= 0) {
414 pa_close(c->fd);
415 c->fd = -1;
418 errno = ETIMEDOUT;
419 do_call(c);
422 static void start_timeout(pa_socket_client *c, pa_bool_t use_rtclock) {
423 struct timeval tv;
425 pa_assert(c);
426 pa_assert(!c->timeout_event);
428 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);
431 pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, pa_bool_t use_rtclock, const char*name, uint16_t default_port) {
432 pa_socket_client *c = NULL;
433 pa_parsed_address a;
435 pa_assert(m);
436 pa_assert(name);
438 if (pa_parse_address(name, &a) < 0)
439 return NULL;
441 if (!a.port)
442 a.port = default_port;
444 switch (a.type) {
445 case PA_PARSED_ADDRESS_UNIX:
446 if ((c = pa_socket_client_new_unix(m, a.path_or_host)))
447 start_timeout(c, use_rtclock);
448 break;
450 case PA_PARSED_ADDRESS_TCP4: /* Fallthrough */
451 case PA_PARSED_ADDRESS_TCP6: /* Fallthrough */
452 case PA_PARSED_ADDRESS_TCP_AUTO: {
453 struct addrinfo hints;
454 char port[12];
456 pa_snprintf(port, sizeof(port), "%u", (unsigned) a.port);
458 pa_zero(hints);
459 if (a.type == PA_PARSED_ADDRESS_TCP4)
460 hints.ai_family = PF_INET;
461 #ifdef HAVE_IPV6
462 else if (a.type == PA_PARSED_ADDRESS_TCP6)
463 hints.ai_family = PF_INET6;
464 #endif
465 else
466 hints.ai_family = PF_UNSPEC;
468 hints.ai_socktype = SOCK_STREAM;
470 #if defined(HAVE_LIBASYNCNS)
472 asyncns_t *asyncns;
474 if (!(asyncns = asyncns_new(1)))
475 goto finish;
477 c = socket_client_new(m);
478 c->asyncns = asyncns;
479 c->asyncns_io_event = m->io_new(m, asyncns_fd(c->asyncns), PA_IO_EVENT_INPUT, asyncns_cb, c);
480 pa_assert_se(c->asyncns_query = asyncns_getaddrinfo(c->asyncns, a.path_or_host, port, &hints));
481 start_timeout(c, use_rtclock);
483 #elif defined(HAVE_GETADDRINFO)
485 int ret;
486 struct addrinfo *res = NULL;
488 ret = getaddrinfo(a.path_or_host, port, &hints, &res);
490 if (ret < 0 || !res)
491 goto finish;
493 if (res->ai_addr) {
494 if ((c = pa_socket_client_new_sockaddr(m, res->ai_addr, res->ai_addrlen)))
495 start_timeout(c, use_rtclock);
498 freeaddrinfo(res);
500 #else
502 struct hostent *host = NULL;
503 struct sockaddr_in s;
505 #ifdef HAVE_IPV6
506 /* FIXME: PF_INET6 support */
507 if (hints.ai_family == PF_INET6) {
508 pa_log_error("IPv6 is not supported on Windows");
509 goto finish;
511 #endif
513 host = gethostbyname(a.path_or_host);
514 if (!host) {
515 unsigned int addr = inet_addr(a.path_or_host);
516 if (addr != INADDR_NONE)
517 host = gethostbyaddr((char*)&addr, 4, AF_INET);
520 if (!host)
521 goto finish;
523 pa_zero(s);
524 s.sin_family = AF_INET;
525 memcpy(&s.sin_addr, host->h_addr, sizeof(struct in_addr));
526 s.sin_port = htons(a.port);
528 if ((c = pa_socket_client_new_sockaddr(m, (struct sockaddr*)&s, sizeof(s))))
529 start_timeout(c, use_rtclock);
531 #endif /* HAVE_LIBASYNCNS */
535 finish:
536 pa_xfree(a.path_or_host);
537 return c;
541 /* Return non-zero when the target sockaddr is considered
542 local. "local" means UNIX socket or TCP socket on localhost. Other
543 local IP addresses are not considered local. */
544 pa_bool_t pa_socket_client_is_local(pa_socket_client *c) {
545 pa_assert(c);
546 pa_assert(PA_REFCNT_VALUE(c) >= 1);
548 return c->local;