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