core: call pa_sink_get_latency_within_thread() instead of going directly via process_...
[pulseaudio-mirror.git] / src / pulsecore / socket-client.c
blob2453515785f86caac832182110b451d28b779e6e
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_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
51 #ifdef HAVE_LIBASYNCNS
52 #include <asyncns.h>
53 #endif
55 #include <pulse/rtclock.h>
56 #include <pulse/timeval.h>
57 #include <pulse/xmalloc.h>
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>
70 #include "socket-client.h"
72 #define CONNECT_TIMEOUT 5
74 struct pa_socket_client {
75 PA_REFCNT_DECLARE;
76 pa_mainloop_api *mainloop;
77 int fd;
78 pa_io_event *io_event;
79 pa_time_event *timeout_event;
80 pa_defer_event *defer_event;
81 pa_socket_client_cb_t callback;
82 void *userdata;
83 pa_bool_t local;
84 #ifdef HAVE_LIBASYNCNS
85 asyncns_t *asyncns;
86 asyncns_query_t * asyncns_query;
87 pa_io_event *asyncns_io_event;
88 #endif
91 static pa_socket_client* socket_client_new(pa_mainloop_api *m) {
92 pa_socket_client *c;
93 pa_assert(m);
95 c = pa_xnew(pa_socket_client, 1);
96 PA_REFCNT_INIT(c);
97 c->mainloop = m;
98 c->fd = -1;
99 c->io_event = NULL;
100 c->timeout_event = NULL;
101 c->defer_event = NULL;
102 c->callback = NULL;
103 c->userdata = NULL;
104 c->local = FALSE;
106 #ifdef HAVE_LIBASYNCNS
107 c->asyncns = NULL;
108 c->asyncns_io_event = NULL;
109 c->asyncns_query = NULL;
110 #endif
112 return c;
115 static void free_events(pa_socket_client *c) {
116 pa_assert(c);
118 if (c->io_event) {
119 c->mainloop->io_free(c->io_event);
120 c->io_event = NULL;
123 if (c->timeout_event) {
124 c->mainloop->time_free(c->timeout_event);
125 c->timeout_event = NULL;
128 if (c->defer_event) {
129 c->mainloop->defer_free(c->defer_event);
130 c->defer_event = NULL;
134 static void do_call(pa_socket_client *c) {
135 pa_iochannel *io = NULL;
136 int error;
137 socklen_t lerror;
139 pa_assert(c);
140 pa_assert(PA_REFCNT_VALUE(c) >= 1);
141 pa_assert(c->callback);
143 pa_socket_client_ref(c);
145 if (c->fd < 0)
146 goto finish;
148 lerror = sizeof(error);
149 if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void*)&error, &lerror) < 0) {
150 pa_log("getsockopt(): %s", pa_cstrerror(errno));
151 goto finish;
154 if (lerror != sizeof(error)) {
155 pa_log("getsockopt() returned invalid size.");
156 goto finish;
159 if (error != 0) {
160 pa_log_debug("connect(): %s", pa_cstrerror(error));
161 errno = error;
162 goto finish;
165 io = pa_iochannel_new(c->mainloop, c->fd, c->fd);
166 pa_assert(io);
168 finish:
169 if (!io && c->fd >= 0)
170 pa_close(c->fd);
171 c->fd = -1;
173 free_events(c);
175 pa_assert(c->callback);
176 c->callback(c, io, c->userdata);
178 pa_socket_client_unref(c);
181 static void connect_defer_cb(pa_mainloop_api *m, pa_defer_event *e, void *userdata) {
182 pa_socket_client *c = userdata;
184 pa_assert(m);
185 pa_assert(c);
186 pa_assert(PA_REFCNT_VALUE(c) >= 1);
187 pa_assert(c->defer_event == e);
189 do_call(c);
192 static void connect_io_cb(pa_mainloop_api*m, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) {
193 pa_socket_client *c = userdata;
195 pa_assert(m);
196 pa_assert(c);
197 pa_assert(PA_REFCNT_VALUE(c) >= 1);
198 pa_assert(c->io_event == e);
199 pa_assert(fd >= 0);
201 do_call(c);
204 static int do_connect(pa_socket_client *c, const struct sockaddr *sa, socklen_t len) {
205 int r;
207 pa_assert(c);
208 pa_assert(PA_REFCNT_VALUE(c) >= 1);
209 pa_assert(sa);
210 pa_assert(len > 0);
212 pa_make_fd_nonblock(c->fd);
214 if ((r = connect(c->fd, sa, len)) < 0) {
215 #ifdef OS_IS_WIN32
216 if (WSAGetLastError() != EWOULDBLOCK) {
217 pa_log_debug("connect(): %d", WSAGetLastError());
218 #else
219 if (errno != EINPROGRESS) {
220 pa_log_debug("connect(): %s (%d)", pa_cstrerror(errno), errno);
221 #endif
222 return -1;
225 pa_assert_se(c->io_event = c->mainloop->io_new(c->mainloop, c->fd, PA_IO_EVENT_OUTPUT, connect_io_cb, c));
226 } else
227 pa_assert_se(c->defer_event = c->mainloop->defer_new(c->mainloop, connect_defer_cb, c));
229 return 0;
232 pa_socket_client* pa_socket_client_new_ipv4(pa_mainloop_api *m, uint32_t address, uint16_t port) {
233 struct sockaddr_in sa;
235 pa_assert(m);
236 pa_assert(port > 0);
238 memset(&sa, 0, sizeof(sa));
239 sa.sin_family = AF_INET;
240 sa.sin_port = htons(port);
241 sa.sin_addr.s_addr = htonl(address);
243 return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa));
246 #ifdef HAVE_SYS_UN_H
248 pa_socket_client* pa_socket_client_new_unix(pa_mainloop_api *m, const char *filename) {
249 struct sockaddr_un sa;
251 pa_assert(m);
252 pa_assert(filename);
254 memset(&sa, 0, sizeof(sa));
255 sa.sun_family = AF_UNIX;
256 pa_strlcpy(sa.sun_path, filename, sizeof(sa.sun_path));
258 return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa));
261 #else /* HAVE_SYS_UN_H */
263 pa_socket_client* pa_socket_client_new_unix(pa_mainloop_api *m, const char *filename) {
264 return NULL;
267 #endif /* HAVE_SYS_UN_H */
269 static int sockaddr_prepare(pa_socket_client *c, const struct sockaddr *sa, size_t salen) {
270 pa_assert(c);
271 pa_assert(sa);
272 pa_assert(salen);
274 c->local = pa_socket_address_is_local(sa);
276 if ((c->fd = socket(sa->sa_family, SOCK_STREAM, 0)) < 0) {
277 pa_log("socket(): %s", pa_cstrerror(errno));
278 return -1;
281 pa_make_fd_cloexec(c->fd);
283 #ifdef HAVE_IPV6
284 if (sa->sa_family == AF_INET || sa->sa_family == AF_INET6)
285 #else
286 if (sa->sa_family == AF_INET)
287 #endif
288 pa_make_tcp_socket_low_delay(c->fd);
289 else
290 pa_make_socket_low_delay(c->fd);
292 if (do_connect(c, sa, (socklen_t) salen) < 0)
293 return -1;
295 return 0;
298 pa_socket_client* pa_socket_client_new_sockaddr(pa_mainloop_api *m, const struct sockaddr *sa, size_t salen) {
299 pa_socket_client *c;
301 pa_assert(m);
302 pa_assert(sa);
303 pa_assert(salen > 0);
305 pa_assert_se(c = socket_client_new(m));
307 if (sockaddr_prepare(c, sa, salen) < 0)
308 goto fail;
310 return c;
312 fail:
313 pa_socket_client_unref(c);
314 return NULL;
317 static void socket_client_free(pa_socket_client *c) {
318 pa_assert(c);
319 pa_assert(c->mainloop);
321 free_events(c);
323 if (c->fd >= 0)
324 pa_close(c->fd);
326 #ifdef HAVE_LIBASYNCNS
327 if (c->asyncns_query)
328 asyncns_cancel(c->asyncns, c->asyncns_query);
329 if (c->asyncns)
330 asyncns_free(c->asyncns);
331 if (c->asyncns_io_event)
332 c->mainloop->io_free(c->asyncns_io_event);
333 #endif
335 pa_xfree(c);
338 void pa_socket_client_unref(pa_socket_client *c) {
339 pa_assert(c);
340 pa_assert(PA_REFCNT_VALUE(c) >= 1);
342 if (PA_REFCNT_DEC(c) <= 0)
343 socket_client_free(c);
346 pa_socket_client* pa_socket_client_ref(pa_socket_client *c) {
347 pa_assert(c);
348 pa_assert(PA_REFCNT_VALUE(c) >= 1);
350 PA_REFCNT_INC(c);
351 return c;
354 void pa_socket_client_set_callback(pa_socket_client *c, pa_socket_client_cb_t on_connection, void *userdata) {
355 pa_assert(c);
356 pa_assert(PA_REFCNT_VALUE(c) >= 1);
358 c->callback = on_connection;
359 c->userdata = userdata;
362 #ifdef HAVE_IPV6
363 pa_socket_client* pa_socket_client_new_ipv6(pa_mainloop_api *m, uint8_t address[16], uint16_t port) {
364 struct sockaddr_in6 sa;
366 pa_assert(m);
367 pa_assert(address);
368 pa_assert(port > 0);
370 memset(&sa, 0, sizeof(sa));
371 sa.sin6_family = AF_INET6;
372 sa.sin6_port = htons(port);
373 memcpy(&sa.sin6_addr, address, sizeof(sa.sin6_addr));
375 return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa));
377 #endif
379 #ifdef HAVE_LIBASYNCNS
381 static void asyncns_cb(pa_mainloop_api*m, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) {
382 pa_socket_client *c = userdata;
383 struct addrinfo *res = NULL;
384 int ret;
386 pa_assert(m);
387 pa_assert(c);
388 pa_assert(PA_REFCNT_VALUE(c) >= 1);
389 pa_assert(c->asyncns_io_event == e);
390 pa_assert(fd >= 0);
392 if (asyncns_wait(c->asyncns, 0) < 0)
393 goto fail;
395 if (!asyncns_isdone(c->asyncns, c->asyncns_query))
396 return;
398 ret = asyncns_getaddrinfo_done(c->asyncns, c->asyncns_query, &res);
399 c->asyncns_query = NULL;
401 if (ret != 0 || !res)
402 goto fail;
404 if (res->ai_addr)
405 sockaddr_prepare(c, res->ai_addr, res->ai_addrlen);
407 asyncns_freeaddrinfo(res);
409 m->io_free(c->asyncns_io_event);
410 c->asyncns_io_event = NULL;
411 return;
413 fail:
414 m->io_free(c->asyncns_io_event);
415 c->asyncns_io_event = NULL;
417 errno = EHOSTUNREACH;
418 do_call(c);
419 return;
423 #endif
425 static void timeout_cb(pa_mainloop_api *m, pa_time_event *e, const struct timeval *t, void *userdata) {
426 pa_socket_client *c = userdata;
428 pa_assert(m);
429 pa_assert(e);
430 pa_assert(c);
432 if (c->fd >= 0) {
433 pa_close(c->fd);
434 c->fd = -1;
437 errno = ETIMEDOUT;
438 do_call(c);
441 static void start_timeout(pa_socket_client *c, pa_bool_t use_rtclock) {
442 struct timeval tv;
444 pa_assert(c);
445 pa_assert(!c->timeout_event);
447 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);
450 pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, pa_bool_t use_rtclock, const char*name, uint16_t default_port) {
451 pa_socket_client *c = NULL;
452 pa_parsed_address a;
454 pa_assert(m);
455 pa_assert(name);
457 if (pa_parse_address(name, &a) < 0)
458 return NULL;
460 if (!a.port)
461 a.port = default_port;
463 switch (a.type) {
464 case PA_PARSED_ADDRESS_UNIX:
465 if ((c = pa_socket_client_new_unix(m, a.path_or_host)))
466 start_timeout(c, use_rtclock);
467 break;
469 case PA_PARSED_ADDRESS_TCP4: /* Fallthrough */
470 case PA_PARSED_ADDRESS_TCP6: /* Fallthrough */
471 case PA_PARSED_ADDRESS_TCP_AUTO:{
473 struct addrinfo hints;
474 char port[12];
476 pa_snprintf(port, sizeof(port), "%u", (unsigned) a.port);
478 memset(&hints, 0, sizeof(hints));
479 if (a.type == PA_PARSED_ADDRESS_TCP4)
480 hints.ai_family = PF_INET;
481 #ifdef HAVE_IPV6
482 else if (a.type == PA_PARSED_ADDRESS_TCP6)
483 hints.ai_family = PF_INET6;
484 #endif
485 else
486 hints.ai_family = PF_UNSPEC;
488 hints.ai_socktype = SOCK_STREAM;
490 #if defined(HAVE_LIBASYNCNS)
492 asyncns_t *asyncns;
494 if (!(asyncns = asyncns_new(1)))
495 goto finish;
497 pa_assert_se(c = socket_client_new(m));
498 c->asyncns = asyncns;
499 c->asyncns_io_event = m->io_new(m, asyncns_fd(c->asyncns), PA_IO_EVENT_INPUT, asyncns_cb, c);
500 c->asyncns_query = asyncns_getaddrinfo(c->asyncns, a.path_or_host, port, &hints);
501 pa_assert(c->asyncns_query);
502 start_timeout(c, use_rtclock);
504 #elif defined(HAVE_GETADDRINFO)
506 int ret;
507 struct addrinfo *res = NULL;
509 ret = getaddrinfo(a.path_or_host, port, &hints, &res);
511 if (ret < 0 || !res)
512 goto finish;
514 if (res->ai_addr) {
515 if ((c = pa_socket_client_new_sockaddr(m, res->ai_addr, res->ai_addrlen)))
516 start_timeout(c, use_rtclock);
519 freeaddrinfo(res);
521 #else
523 struct hostent *host = NULL;
524 struct sockaddr_in s;
526 #ifdef HAVE_IPV6
527 /* FIXME: PF_INET6 support */
528 if (hints.ai_family == PF_INET6) {
529 pa_log_error("IPv6 is not supported on Windows");
530 goto finish;
532 #endif
534 host = gethostbyname(a.path_or_host);
535 if (!host) {
536 unsigned int addr = inet_addr(a.path_or_host);
537 if (addr != INADDR_NONE)
538 host = gethostbyaddr((char*)&addr, 4, AF_INET);
541 if (!host)
542 goto finish;
544 s.sin_family = AF_INET;
545 memcpy(&s.sin_addr, host->h_addr, sizeof(struct in_addr));
546 s.sin_port = htons(a.port);
548 if ((c = pa_socket_client_new_sockaddr(m, (struct sockaddr*)&s, sizeof(s))))
549 start_timeout(c, use_rtclock);
551 #endif /* HAVE_LIBASYNCNS */
555 finish:
556 pa_xfree(a.path_or_host);
557 return c;
561 /* Return non-zero when the target sockaddr is considered
562 local. "local" means UNIX socket or TCP socket on localhost. Other
563 local IP addresses are not considered local. */
564 pa_bool_t pa_socket_client_is_local(pa_socket_client *c) {
565 pa_assert(c);
566 pa_assert(PA_REFCNT_VALUE(c) >= 1);
568 return c->local;