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