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