• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
67 struct 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 
socket_client_new(pa_mainloop_api * m)88 static 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 
free_events(pa_socket_client * c)100 static 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 
do_call(pa_socket_client * c)119 static 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 
152 finish:
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 
connect_defer_cb(pa_mainloop_api * m,pa_defer_event * e,void * userdata)164 static 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 
connect_io_cb(pa_mainloop_api * m,pa_io_event * e,int fd,pa_io_event_flags_t f,void * userdata)175 static 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 
do_connect(pa_socket_client * c,const struct sockaddr * sa,socklen_t len)187 static 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 
213 pa_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 
227 pa_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 
245 static 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 
272 pa_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 
286 fail:
287     pa_socket_client_unref(c);
288     return NULL;
289 }
290 
291 static 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 
312 void 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 
320 pa_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 
328 void 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 
336 pa_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 
358 static 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 
391 fail:
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 
403 static 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 
419 static 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 
428 pa_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 
548 finish:
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. */
558 bool 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