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/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 {
78 pa_mainloop_api *mainloop;
79 pa_io_event *io_event;
80 pa_time_event *timeout_event;
81 pa_defer_event *defer_event;
83 pa_socket_client_cb_t callback;
88 #ifdef HAVE_LIBASYNCNS
90 asyncns_query_t * asyncns_query;
91 pa_io_event *asyncns_io_event;
95 static pa_socket_client* socket_client_new(pa_mainloop_api *m) {
99 c = pa_xnew0(pa_socket_client, 1);
107 static void free_events(pa_socket_client *c) {
111 c->mainloop->io_free(c->io_event);
115 if (c->timeout_event) {
116 c->mainloop->time_free(c->timeout_event);
117 c->timeout_event = NULL;
120 if (c->defer_event) {
121 c->mainloop->defer_free(c->defer_event);
122 c->defer_event = NULL;
126 static void do_call(pa_socket_client *c) {
127 pa_iochannel *io = NULL;
132 pa_assert(PA_REFCNT_VALUE(c) >= 1);
133 pa_assert(c->callback);
135 pa_socket_client_ref(c);
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));
146 if (lerror != sizeof(error)) {
147 pa_log("getsockopt() returned invalid size.");
152 pa_log_debug("connect(): %s", pa_cstrerror(error));
157 io = pa_iochannel_new(c->mainloop, c->fd, c->fd);
160 if (!io && c->fd >= 0)
166 c->callback(c, io, c->userdata);
168 pa_socket_client_unref(c);
171 static void connect_defer_cb(pa_mainloop_api *m, pa_defer_event *e, void *userdata) {
172 pa_socket_client *c = userdata;
176 pa_assert(PA_REFCNT_VALUE(c) >= 1);
177 pa_assert(c->defer_event == e);
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;
187 pa_assert(PA_REFCNT_VALUE(c) >= 1);
188 pa_assert(c->io_event == e);
194 static int do_connect(pa_socket_client *c, const struct sockaddr *sa, socklen_t len) {
196 pa_assert(PA_REFCNT_VALUE(c) >= 1);
200 pa_make_fd_nonblock(c->fd);
202 if (connect(c->fd, sa, len) < 0) {
204 if (WSAGetLastError() != EWOULDBLOCK) {
205 pa_log_debug("connect(): %d", WSAGetLastError());
207 if (errno != EINPROGRESS) {
208 pa_log_debug("connect(): %s (%d)", pa_cstrerror(errno), errno);
213 c->io_event = c->mainloop->io_new(c->mainloop, c->fd, PA_IO_EVENT_OUTPUT, connect_io_cb, c);
215 c->defer_event = c->mainloop->defer_new(c->mainloop, connect_defer_cb, c);
220 pa_socket_client* pa_socket_client_new_ipv4(pa_mainloop_api *m, uint32_t address, uint16_t port) {
221 struct sockaddr_in sa;
227 sa.sin_family = AF_INET;
228 sa.sin_port = htons(port);
229 sa.sin_addr.s_addr = htonl(address);
231 return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa));
235 pa_socket_client* pa_socket_client_new_unix(pa_mainloop_api *m, const char *filename) {
237 struct sockaddr_un sa;
243 sa.sun_family = AF_UNIX;
244 pa_strlcpy(sa.sun_path, filename, sizeof(sa.sun_path));
246 return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa));
247 #else /* HAVE_SYS_UN_H */
250 #endif /* HAVE_SYS_UN_H */
253 static int sockaddr_prepare(pa_socket_client *c, const struct sockaddr *sa, size_t salen) {
258 c->local = pa_socket_address_is_local(sa);
260 if ((c->fd = pa_socket_cloexec(sa->sa_family, SOCK_STREAM, 0)) < 0) {
261 pa_log("socket(): %s", pa_cstrerror(errno));
266 if (sa->sa_family == AF_INET || sa->sa_family == AF_INET6)
268 if (sa->sa_family == AF_INET)
270 pa_make_tcp_socket_low_delay(c->fd);
272 pa_make_socket_low_delay(c->fd);
274 if (do_connect(c, sa, (socklen_t) salen) < 0)
280 pa_socket_client* pa_socket_client_new_sockaddr(pa_mainloop_api *m, const struct sockaddr *sa, size_t salen) {
285 pa_assert(salen > 0);
287 c = socket_client_new(m);
289 if (sockaddr_prepare(c, sa, salen) < 0)
295 pa_socket_client_unref(c);
299 static void socket_client_free(pa_socket_client *c) {
301 pa_assert(c->mainloop);
308 #ifdef HAVE_LIBASYNCNS
309 if (c->asyncns_query)
310 asyncns_cancel(c->asyncns, c->asyncns_query);
312 asyncns_free(c->asyncns);
313 if (c->asyncns_io_event)
314 c->mainloop->io_free(c->asyncns_io_event);
320 void pa_socket_client_unref(pa_socket_client *c) {
322 pa_assert(PA_REFCNT_VALUE(c) >= 1);
324 if (PA_REFCNT_DEC(c) <= 0)
325 socket_client_free(c);
328 pa_socket_client* pa_socket_client_ref(pa_socket_client *c) {
330 pa_assert(PA_REFCNT_VALUE(c) >= 1);
336 void pa_socket_client_set_callback(pa_socket_client *c, pa_socket_client_cb_t on_connection, void *userdata) {
338 pa_assert(PA_REFCNT_VALUE(c) >= 1);
340 c->callback = on_connection;
341 c->userdata = userdata;
344 pa_socket_client* pa_socket_client_new_ipv6(pa_mainloop_api *m, uint8_t address[16], uint16_t port) {
346 struct sockaddr_in6 sa;
353 sa.sin6_family = AF_INET6;
354 sa.sin6_port = htons(port);
355 memcpy(&sa.sin6_addr, address, sizeof(sa.sin6_addr));
357 return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa));
364 #ifdef HAVE_LIBASYNCNS
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;
373 pa_assert(PA_REFCNT_VALUE(c) >= 1);
374 pa_assert(c->asyncns_io_event == e);
377 if (asyncns_wait(c->asyncns, 0) < 0)
380 if (!asyncns_isdone(c->asyncns, c->asyncns_query))
383 ret = asyncns_getaddrinfo_done(c->asyncns, c->asyncns_query, &res);
384 c->asyncns_query = NULL;
386 if (ret != 0 || !res)
390 sockaddr_prepare(c, res->ai_addr, res->ai_addrlen);
392 asyncns_freeaddrinfo(res);
394 m->io_free(c->asyncns_io_event);
395 c->asyncns_io_event = NULL;
399 m->io_free(c->asyncns_io_event);
400 c->asyncns_io_event = NULL;
402 errno = EHOSTUNREACH;
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;
426 static void start_timeout(pa_socket_client *c, pa_bool_t use_rtclock) {
430 pa_assert(!c->timeout_event);
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);
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;
442 if (pa_parse_address(name, &a) < 0)
446 a.port = default_port;
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);
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;
460 pa_snprintf(port, sizeof(port), "%u", (unsigned) a.port);
463 if (a.type == PA_PARSED_ADDRESS_TCP4)
464 hints.ai_family = PF_INET;
466 else if (a.type == PA_PARSED_ADDRESS_TCP6)
467 hints.ai_family = PF_INET6;
470 hints.ai_family = PF_UNSPEC;
472 hints.ai_socktype = SOCK_STREAM;
474 #if defined(HAVE_LIBASYNCNS)
478 if (!(asyncns = asyncns_new(1)))
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);
487 #elif defined(HAVE_GETADDRINFO)
490 struct addrinfo *res = NULL;
492 ret = getaddrinfo(a.path_or_host, port, &hints, &res);
498 if ((c = pa_socket_client_new_sockaddr(m, res->ai_addr, res->ai_addrlen)))
499 start_timeout(c, use_rtclock);
506 struct hostent *host = NULL;
507 struct sockaddr_in s;
510 /* FIXME: PF_INET6 support */
511 if (hints.ai_family == PF_INET6) {
512 pa_log_error("IPv6 is not supported on Windows");
517 host = gethostbyname(a.path_or_host);
519 unsigned int addr = inet_addr(a.path_or_host);
520 if (addr != INADDR_NONE)
521 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))))
533 start_timeout(c, use_rtclock);
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);