]> code.delx.au - pulseaudio/blob - src/pulsecore/socket-client.c
Merge commit 'origin/master-tx'
[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/timeval.h>
56 #include <pulse/xmalloc.h>
57
58 #include <pulsecore/winsock.h>
59 #include <pulsecore/core-error.h>
60 #include <pulsecore/socket-util.h>
61 #include <pulsecore/core-util.h>
62 #include <pulsecore/socket-util.h>
63 #include <pulsecore/log.h>
64 #include <pulsecore/parseaddr.h>
65 #include <pulsecore/macro.h>
66 #include <pulsecore/refcnt.h>
67
68 #include "socket-client.h"
69
70 #define CONNECT_TIMEOUT 5
71
72 struct pa_socket_client {
73 PA_REFCNT_DECLARE;
74 pa_mainloop_api *mainloop;
75 int fd;
76 pa_io_event *io_event;
77 pa_time_event *timeout_event;
78 pa_defer_event *defer_event;
79 pa_socket_client_cb_t callback;
80 void *userdata;
81 pa_bool_t local;
82 #ifdef HAVE_LIBASYNCNS
83 asyncns_t *asyncns;
84 asyncns_query_t * asyncns_query;
85 pa_io_event *asyncns_io_event;
86 #endif
87 };
88
89 static pa_socket_client* socket_client_new(pa_mainloop_api *m) {
90 pa_socket_client *c;
91 pa_assert(m);
92
93 c = pa_xnew(pa_socket_client, 1);
94 PA_REFCNT_INIT(c);
95 c->mainloop = m;
96 c->fd = -1;
97 c->io_event = NULL;
98 c->timeout_event = NULL;
99 c->defer_event = NULL;
100 c->callback = NULL;
101 c->userdata = NULL;
102 c->local = FALSE;
103
104 #ifdef HAVE_LIBASYNCNS
105 c->asyncns = NULL;
106 c->asyncns_io_event = NULL;
107 c->asyncns_query = NULL;
108 #endif
109
110 return c;
111 }
112
113 static void free_events(pa_socket_client *c) {
114 pa_assert(c);
115
116 if (c->io_event) {
117 c->mainloop->io_free(c->io_event);
118 c->io_event = NULL;
119 }
120
121 if (c->timeout_event) {
122 c->mainloop->time_free(c->timeout_event);
123 c->timeout_event = NULL;
124 }
125
126 if (c->defer_event) {
127 c->mainloop->defer_free(c->defer_event);
128 c->defer_event = NULL;
129 }
130 }
131
132 static void do_call(pa_socket_client *c) {
133 pa_iochannel *io = NULL;
134 int error;
135 socklen_t lerror;
136
137 pa_assert(c);
138 pa_assert(PA_REFCNT_VALUE(c) >= 1);
139 pa_assert(c->callback);
140
141 pa_socket_client_ref(c);
142
143 if (c->fd < 0)
144 goto finish;
145
146 lerror = sizeof(error);
147 if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void*)&error, &lerror) < 0) {
148 pa_log("getsockopt(): %s", pa_cstrerror(errno));
149 goto finish;
150 }
151
152 if (lerror != sizeof(error)) {
153 pa_log("getsockopt() returned invalid size.");
154 goto finish;
155 }
156
157 if (error != 0) {
158 pa_log_debug("connect(): %s", pa_cstrerror(error));
159 errno = error;
160 goto finish;
161 }
162
163 io = pa_iochannel_new(c->mainloop, c->fd, c->fd);
164 pa_assert(io);
165
166 finish:
167 if (!io && c->fd >= 0)
168 pa_close(c->fd);
169 c->fd = -1;
170
171 free_events(c);
172
173 pa_assert(c->callback);
174 c->callback(c, io, c->userdata);
175
176 pa_socket_client_unref(c);
177 }
178
179 static void connect_defer_cb(pa_mainloop_api *m, pa_defer_event *e, void *userdata) {
180 pa_socket_client *c = userdata;
181
182 pa_assert(m);
183 pa_assert(c);
184 pa_assert(PA_REFCNT_VALUE(c) >= 1);
185 pa_assert(c->defer_event == e);
186
187 do_call(c);
188 }
189
190 static void connect_io_cb(pa_mainloop_api*m, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) {
191 pa_socket_client *c = userdata;
192
193 pa_assert(m);
194 pa_assert(c);
195 pa_assert(PA_REFCNT_VALUE(c) >= 1);
196 pa_assert(c->io_event == e);
197 pa_assert(fd >= 0);
198
199 do_call(c);
200 }
201
202 static int do_connect(pa_socket_client *c, const struct sockaddr *sa, socklen_t len) {
203 int r;
204
205 pa_assert(c);
206 pa_assert(PA_REFCNT_VALUE(c) >= 1);
207 pa_assert(sa);
208 pa_assert(len > 0);
209
210 pa_make_fd_nonblock(c->fd);
211
212 if ((r = connect(c->fd, sa, len)) < 0) {
213 #ifdef OS_IS_WIN32
214 if (WSAGetLastError() != EWOULDBLOCK) {
215 pa_log_debug("connect(): %d", WSAGetLastError());
216 #else
217 if (errno != EINPROGRESS) {
218 pa_log_debug("connect(): %s (%d)", pa_cstrerror(errno), errno);
219 #endif
220 return -1;
221 }
222
223 pa_assert_se(c->io_event = c->mainloop->io_new(c->mainloop, c->fd, PA_IO_EVENT_OUTPUT, connect_io_cb, c));
224 } else
225 pa_assert_se(c->defer_event = c->mainloop->defer_new(c->mainloop, connect_defer_cb, c));
226
227 return 0;
228 }
229
230 pa_socket_client* pa_socket_client_new_ipv4(pa_mainloop_api *m, uint32_t address, uint16_t port) {
231 struct sockaddr_in sa;
232
233 pa_assert(m);
234 pa_assert(port > 0);
235
236 memset(&sa, 0, sizeof(sa));
237 sa.sin_family = AF_INET;
238 sa.sin_port = htons(port);
239 sa.sin_addr.s_addr = htonl(address);
240
241 return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa));
242 }
243
244 #ifdef HAVE_SYS_UN_H
245
246 pa_socket_client* pa_socket_client_new_unix(pa_mainloop_api *m, const char *filename) {
247 struct sockaddr_un sa;
248
249 pa_assert(m);
250 pa_assert(filename);
251
252 memset(&sa, 0, sizeof(sa));
253 sa.sun_family = AF_UNIX;
254 pa_strlcpy(sa.sun_path, filename, sizeof(sa.sun_path));
255
256 return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa));
257 }
258
259 #else /* HAVE_SYS_UN_H */
260
261 pa_socket_client* pa_socket_client_new_unix(pa_mainloop_api *m, const char *filename) {
262 return NULL;
263 }
264
265 #endif /* HAVE_SYS_UN_H */
266
267 static int sockaddr_prepare(pa_socket_client *c, const struct sockaddr *sa, size_t salen) {
268 pa_assert(c);
269 pa_assert(sa);
270 pa_assert(salen);
271
272 c->local = pa_socket_address_is_local(sa);
273
274 if ((c->fd = socket(sa->sa_family, SOCK_STREAM, 0)) < 0) {
275 pa_log("socket(): %s", pa_cstrerror(errno));
276 return -1;
277 }
278
279 pa_make_fd_cloexec(c->fd);
280
281 #ifdef HAVE_IPV6
282 if (sa->sa_family == AF_INET || sa->sa_family == AF_INET6)
283 #else
284 if (sa->sa_family == AF_INET)
285 #endif
286 pa_make_tcp_socket_low_delay(c->fd);
287 else
288 pa_make_socket_low_delay(c->fd);
289
290 if (do_connect(c, sa, (socklen_t) salen) < 0)
291 return -1;
292
293 return 0;
294 }
295
296 pa_socket_client* pa_socket_client_new_sockaddr(pa_mainloop_api *m, const struct sockaddr *sa, size_t salen) {
297 pa_socket_client *c;
298
299 pa_assert(m);
300 pa_assert(sa);
301 pa_assert(salen > 0);
302
303 pa_assert_se(c = socket_client_new(m));
304
305 if (sockaddr_prepare(c, sa, salen) < 0)
306 goto fail;
307
308 return c;
309
310 fail:
311 pa_socket_client_unref(c);
312 return NULL;
313 }
314
315 static void socket_client_free(pa_socket_client *c) {
316 pa_assert(c);
317 pa_assert(c->mainloop);
318
319 free_events(c);
320
321 if (c->fd >= 0)
322 pa_close(c->fd);
323
324 #ifdef HAVE_LIBASYNCNS
325 if (c->asyncns_query)
326 asyncns_cancel(c->asyncns, c->asyncns_query);
327 if (c->asyncns)
328 asyncns_free(c->asyncns);
329 if (c->asyncns_io_event)
330 c->mainloop->io_free(c->asyncns_io_event);
331 #endif
332
333 pa_xfree(c);
334 }
335
336 void pa_socket_client_unref(pa_socket_client *c) {
337 pa_assert(c);
338 pa_assert(PA_REFCNT_VALUE(c) >= 1);
339
340 if (PA_REFCNT_DEC(c) <= 0)
341 socket_client_free(c);
342 }
343
344 pa_socket_client* pa_socket_client_ref(pa_socket_client *c) {
345 pa_assert(c);
346 pa_assert(PA_REFCNT_VALUE(c) >= 1);
347
348 PA_REFCNT_INC(c);
349 return c;
350 }
351
352 void pa_socket_client_set_callback(pa_socket_client *c, pa_socket_client_cb_t on_connection, void *userdata) {
353 pa_assert(c);
354 pa_assert(PA_REFCNT_VALUE(c) >= 1);
355
356 c->callback = on_connection;
357 c->userdata = userdata;
358 }
359
360 #ifdef HAVE_IPV6
361 pa_socket_client* pa_socket_client_new_ipv6(pa_mainloop_api *m, uint8_t address[16], uint16_t port) {
362 struct sockaddr_in6 sa;
363
364 pa_assert(m);
365 pa_assert(address);
366 pa_assert(port > 0);
367
368 memset(&sa, 0, sizeof(sa));
369 sa.sin6_family = AF_INET6;
370 sa.sin6_port = htons(port);
371 memcpy(&sa.sin6_addr, address, sizeof(sa.sin6_addr));
372
373 return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa));
374 }
375 #endif
376
377 #ifdef HAVE_LIBASYNCNS
378
379 static void asyncns_cb(pa_mainloop_api*m, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) {
380 pa_socket_client *c = userdata;
381 struct addrinfo *res = NULL;
382 int ret;
383
384 pa_assert(m);
385 pa_assert(c);
386 pa_assert(PA_REFCNT_VALUE(c) >= 1);
387 pa_assert(c->asyncns_io_event == e);
388 pa_assert(fd >= 0);
389
390 if (asyncns_wait(c->asyncns, 0) < 0)
391 goto fail;
392
393 if (!asyncns_isdone(c->asyncns, c->asyncns_query))
394 return;
395
396 ret = asyncns_getaddrinfo_done(c->asyncns, c->asyncns_query, &res);
397 c->asyncns_query = NULL;
398
399 if (ret != 0 || !res)
400 goto fail;
401
402 if (res->ai_addr)
403 sockaddr_prepare(c, res->ai_addr, res->ai_addrlen);
404
405 asyncns_freeaddrinfo(res);
406
407 m->io_free(c->asyncns_io_event);
408 c->asyncns_io_event = NULL;
409 return;
410
411 fail:
412 m->io_free(c->asyncns_io_event);
413 c->asyncns_io_event = NULL;
414
415 errno = EHOSTUNREACH;
416 do_call(c);
417 return;
418
419 }
420
421 #endif
422
423 static void timeout_cb(pa_mainloop_api *m, pa_time_event *e, const struct timeval *tv, void *userdata) {
424 pa_socket_client *c = userdata;
425
426 pa_assert(m);
427 pa_assert(e);
428 pa_assert(tv);
429 pa_assert(c);
430
431 if (c->fd >= 0) {
432 pa_close(c->fd);
433 c->fd = -1;
434 }
435
436 errno = ETIMEDOUT;
437 do_call(c);
438 }
439
440 static void start_timeout(pa_socket_client *c) {
441 struct timeval tv;
442 pa_assert(c);
443 pa_assert(!c->timeout_event);
444
445 pa_gettimeofday(&tv);
446 pa_timeval_add(&tv, CONNECT_TIMEOUT * PA_USEC_PER_SEC);
447 c->timeout_event = c->mainloop->time_new(c->mainloop, &tv, timeout_cb, c);
448 }
449
450 pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, 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);
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);
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);
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);
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 }