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