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
27 /* #undef HAVE_LIBASYNCNS */
35 #ifdef HAVE_SYS_SOCKET_H
36 #include <sys/socket.h>
41 #ifdef HAVE_ARPA_INET_H
42 #include <arpa/inet.h>
44 #ifdef HAVE_NETINET_IN_H
45 #include <netinet/in.h>
51 #ifdef HAVE_LIBASYNCNS
55 #include <pulse/timeval.h>
56 #include <pulse/xmalloc.h>
58 #include <pulsecore/winsock.h>
59 #include <pulsecore/core-error.h>
60 #include <pulsecore/socket-util.h>
61 #include <pulsecore/core-util.h>
62 #include <pulsecore/socket-util.h>
63 #include <pulsecore/log.h>
64 #include <pulsecore/parseaddr.h>
65 #include <pulsecore/macro.h>
66 #include <pulsecore/refcnt.h>
68 #include "socket-client.h"
70 #define CONNECT_TIMEOUT 5
72 struct pa_socket_client
{
74 pa_mainloop_api
*mainloop
;
76 pa_io_event
*io_event
;
77 pa_time_event
*timeout_event
;
78 pa_defer_event
*defer_event
;
79 pa_socket_client_cb_t callback
;
82 #ifdef HAVE_LIBASYNCNS
84 asyncns_query_t
* asyncns_query
;
85 pa_io_event
*asyncns_io_event
;
89 static pa_socket_client
* socket_client_new(pa_mainloop_api
*m
) {
93 c
= pa_xnew(pa_socket_client
, 1);
98 c
->timeout_event
= NULL
;
99 c
->defer_event
= NULL
;
104 #ifdef HAVE_LIBASYNCNS
106 c
->asyncns_io_event
= NULL
;
107 c
->asyncns_query
= NULL
;
113 static void free_events(pa_socket_client
*c
) {
117 c
->mainloop
->io_free(c
->io_event
);
121 if (c
->timeout_event
) {
122 c
->mainloop
->time_free(c
->timeout_event
);
123 c
->timeout_event
= NULL
;
126 if (c
->defer_event
) {
127 c
->mainloop
->defer_free(c
->defer_event
);
128 c
->defer_event
= NULL
;
132 static void do_call(pa_socket_client
*c
) {
133 pa_iochannel
*io
= NULL
;
138 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
139 pa_assert(c
->callback
);
141 pa_socket_client_ref(c
);
146 lerror
= sizeof(error
);
147 if (getsockopt(c
->fd
, SOL_SOCKET
, SO_ERROR
, (void*)&error
, &lerror
) < 0) {
148 pa_log("getsockopt(): %s", pa_cstrerror(errno
));
152 if (lerror
!= sizeof(error
)) {
153 pa_log("getsockopt() returned invalid size.");
158 pa_log_debug("connect(): %s", pa_cstrerror(error
));
163 io
= pa_iochannel_new(c
->mainloop
, c
->fd
, c
->fd
);
167 if (!io
&& c
->fd
>= 0)
173 pa_assert(c
->callback
);
174 c
->callback(c
, io
, c
->userdata
);
176 pa_socket_client_unref(c
);
179 static void connect_defer_cb(pa_mainloop_api
*m
, pa_defer_event
*e
, void *userdata
) {
180 pa_socket_client
*c
= userdata
;
184 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
185 pa_assert(c
->defer_event
== e
);
190 static void connect_io_cb(pa_mainloop_api
*m
, pa_io_event
*e
, int fd
, PA_GCC_UNUSED pa_io_event_flags_t f
, void *userdata
) {
191 pa_socket_client
*c
= userdata
;
195 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
196 pa_assert(c
->io_event
== e
);
202 static int do_connect(pa_socket_client
*c
, const struct sockaddr
*sa
, socklen_t len
) {
206 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
210 pa_make_fd_nonblock(c
->fd
);
212 if ((r
= connect(c
->fd
, sa
, len
)) < 0) {
214 if (WSAGetLastError() != EWOULDBLOCK
) {
215 pa_log_debug("connect(): %d", WSAGetLastError());
217 if (errno
!= EINPROGRESS
) {
218 pa_log_debug("connect(): %s (%d)", pa_cstrerror(errno
), errno
);
223 pa_assert_se(c
->io_event
= c
->mainloop
->io_new(c
->mainloop
, c
->fd
, PA_IO_EVENT_OUTPUT
, connect_io_cb
, c
));
225 pa_assert_se(c
->defer_event
= c
->mainloop
->defer_new(c
->mainloop
, connect_defer_cb
, c
));
230 pa_socket_client
* pa_socket_client_new_ipv4(pa_mainloop_api
*m
, uint32_t address
, uint16_t port
) {
231 struct sockaddr_in sa
;
236 memset(&sa
, 0, sizeof(sa
));
237 sa
.sin_family
= AF_INET
;
238 sa
.sin_port
= htons(port
);
239 sa
.sin_addr
.s_addr
= htonl(address
);
241 return pa_socket_client_new_sockaddr(m
, (struct sockaddr
*) &sa
, sizeof(sa
));
246 pa_socket_client
* pa_socket_client_new_unix(pa_mainloop_api
*m
, const char *filename
) {
247 struct sockaddr_un sa
;
252 memset(&sa
, 0, sizeof(sa
));
253 sa
.sun_family
= AF_UNIX
;
254 pa_strlcpy(sa
.sun_path
, filename
, sizeof(sa
.sun_path
));
256 return pa_socket_client_new_sockaddr(m
, (struct sockaddr
*) &sa
, sizeof(sa
));
259 #else /* HAVE_SYS_UN_H */
261 pa_socket_client
* pa_socket_client_new_unix(pa_mainloop_api
*m
, const char *filename
) {
265 #endif /* HAVE_SYS_UN_H */
267 static int sockaddr_prepare(pa_socket_client
*c
, const struct sockaddr
*sa
, size_t salen
) {
272 c
->local
= pa_socket_address_is_local(sa
);
274 if ((c
->fd
= socket(sa
->sa_family
, SOCK_STREAM
, 0)) < 0) {
275 pa_log("socket(): %s", pa_cstrerror(errno
));
279 pa_make_fd_cloexec(c
->fd
);
281 if (sa
->sa_family
== AF_INET
|| sa
->sa_family
== AF_INET6
)
282 pa_make_tcp_socket_low_delay(c
->fd
);
284 pa_make_socket_low_delay(c
->fd
);
286 if (do_connect(c
, sa
, salen
) < 0)
292 pa_socket_client
* pa_socket_client_new_sockaddr(pa_mainloop_api
*m
, const struct sockaddr
*sa
, size_t salen
) {
297 pa_assert(salen
> 0);
299 pa_assert_se(c
= socket_client_new(m
));
301 if (sockaddr_prepare(c
, sa
, salen
) < 0)
307 pa_socket_client_unref(c
);
311 static void socket_client_free(pa_socket_client
*c
) {
313 pa_assert(c
->mainloop
);
320 #ifdef HAVE_LIBASYNCNS
321 if (c
->asyncns_query
)
322 asyncns_cancel(c
->asyncns
, c
->asyncns_query
);
324 asyncns_free(c
->asyncns
);
325 if (c
->asyncns_io_event
)
326 c
->mainloop
->io_free(c
->asyncns_io_event
);
332 void pa_socket_client_unref(pa_socket_client
*c
) {
334 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
336 if (PA_REFCNT_DEC(c
) <= 0)
337 socket_client_free(c
);
340 pa_socket_client
* pa_socket_client_ref(pa_socket_client
*c
) {
342 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
348 void pa_socket_client_set_callback(pa_socket_client
*c
, pa_socket_client_cb_t on_connection
, void *userdata
) {
350 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
352 c
->callback
= on_connection
;
353 c
->userdata
= userdata
;
356 pa_socket_client
* pa_socket_client_new_ipv6(pa_mainloop_api
*m
, uint8_t address
[16], uint16_t port
) {
357 struct sockaddr_in6 sa
;
363 memset(&sa
, 0, sizeof(sa
));
364 sa
.sin6_family
= AF_INET6
;
365 sa
.sin6_port
= htons(port
);
366 memcpy(&sa
.sin6_addr
, address
, sizeof(sa
.sin6_addr
));
368 return pa_socket_client_new_sockaddr(m
, (struct sockaddr
*) &sa
, sizeof(sa
));
371 #ifdef HAVE_LIBASYNCNS
373 static void asyncns_cb(pa_mainloop_api
*m
, pa_io_event
*e
, int fd
, PA_GCC_UNUSED pa_io_event_flags_t f
, void *userdata
) {
374 pa_socket_client
*c
= userdata
;
375 struct addrinfo
*res
= NULL
;
380 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
381 pa_assert(c
->asyncns_io_event
== e
);
384 if (asyncns_wait(c
->asyncns
, 0) < 0)
387 if (!asyncns_isdone(c
->asyncns
, c
->asyncns_query
))
390 ret
= asyncns_getaddrinfo_done(c
->asyncns
, c
->asyncns_query
, &res
);
391 c
->asyncns_query
= NULL
;
393 if (ret
!= 0 || !res
)
397 sockaddr_prepare(c
, res
->ai_addr
, res
->ai_addrlen
);
399 asyncns_freeaddrinfo(res
);
401 m
->io_free(c
->asyncns_io_event
);
402 c
->asyncns_io_event
= NULL
;
406 m
->io_free(c
->asyncns_io_event
);
407 c
->asyncns_io_event
= NULL
;
409 errno
= EHOSTUNREACH
;
417 static void timeout_cb(pa_mainloop_api
*m
, pa_time_event
*e
, const struct timeval
*tv
, void *userdata
) {
418 pa_socket_client
*c
= userdata
;
434 static void start_timeout(pa_socket_client
*c
) {
437 pa_assert(!c
->timeout_event
);
439 pa_gettimeofday(&tv
);
440 pa_timeval_add(&tv
, CONNECT_TIMEOUT
* 1000000);
441 c
->timeout_event
= c
->mainloop
->time_new(c
->mainloop
, &tv
, timeout_cb
, c
);
444 pa_socket_client
* pa_socket_client_new_string(pa_mainloop_api
*m
, const char*name
, uint16_t default_port
) {
445 pa_socket_client
*c
= NULL
;
451 if (pa_parse_address(name
, &a
) < 0)
455 a
.port
= default_port
;
458 case PA_PARSED_ADDRESS_UNIX
:
459 if ((c
= pa_socket_client_new_unix(m
, a
.path_or_host
)))
463 case PA_PARSED_ADDRESS_TCP4
: /* Fallthrough */
464 case PA_PARSED_ADDRESS_TCP6
: /* Fallthrough */
465 case PA_PARSED_ADDRESS_TCP_AUTO
:{
467 struct addrinfo hints
;
470 pa_snprintf(port
, sizeof(port
), "%u", (unsigned) a
.port
);
472 memset(&hints
, 0, sizeof(hints
));
473 hints
.ai_family
= a
.type
== PA_PARSED_ADDRESS_TCP4
? PF_INET
: (a
.type
== PA_PARSED_ADDRESS_TCP6
? PF_INET6
: PF_UNSPEC
);
474 hints
.ai_socktype
= SOCK_STREAM
;
476 #if defined(HAVE_LIBASYNCNS)
480 if (!(asyncns
= asyncns_new(1)))
483 pa_assert_se(c
= socket_client_new(m
));
484 c
->asyncns
= asyncns
;
485 c
->asyncns_io_event
= m
->io_new(m
, asyncns_fd(c
->asyncns
), PA_IO_EVENT_INPUT
, asyncns_cb
, c
);
486 c
->asyncns_query
= asyncns_getaddrinfo(c
->asyncns
, a
.path_or_host
, port
, &hints
);
487 pa_assert(c
->asyncns_query
);
490 #elif defined(HAVE_GETADDRINFO)
493 struct addrinfo
*res
= NULL
;
495 ret
= getaddrinfo(a
.path_or_host
, port
, &hints
, &res
);
501 if ((c
= pa_socket_client_new_sockaddr(m
, res
->ai_addr
, res
->ai_addrlen
)))
509 struct hostent
*host
= NULL
;
510 struct sockaddr_in s
;
512 /* FIXME: PF_INET6 support */
513 if (hints
.ai_family
== PF_INET6
) {
514 pa_log_error("IPv6 is not supported on Windows");
518 host
= gethostbyname(a
.path_or_host
);
520 unsigned int addr
= inet_addr(a
.path_or_host
);
521 if (addr
!= INADDR_NONE
)
522 host
= gethostbyaddr((char*)&addr
, 4, AF_INET
);
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
);
532 if ((c
= pa_socket_client_new_sockaddr(m
, (struct sockaddr
*)&s
, sizeof(s
))))
535 #endif /* HAVE_LIBASYNCNS */
540 pa_xfree(a
.path_or_host
);
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
) {
550 pa_assert(PA_REFCNT_VALUE(c
) >= 1);