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