]> code.delx.au - pulseaudio/blob - src/pulsecore/socket-client.c
remap: Change remapping function argument type from void to int16_t / float as approp...
[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 bool 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 pa_socket_client* pa_socket_client_new_unix(pa_mainloop_api *m, const char *filename) {
230 #ifdef HAVE_SYS_UN_H
231 struct sockaddr_un sa;
232
233 pa_assert(m);
234 pa_assert(filename);
235
236 pa_zero(sa);
237 sa.sun_family = AF_UNIX;
238 pa_strlcpy(sa.sun_path, filename, sizeof(sa.sun_path));
239
240 return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa));
241 #else /* HAVE_SYS_UN_H */
242
243 return NULL;
244 #endif /* HAVE_SYS_UN_H */
245 }
246
247 static int sockaddr_prepare(pa_socket_client *c, const struct sockaddr *sa, size_t salen) {
248 pa_assert(c);
249 pa_assert(sa);
250 pa_assert(salen);
251
252 c->local = pa_socket_address_is_local(sa);
253
254 if ((c->fd = pa_socket_cloexec(sa->sa_family, SOCK_STREAM, 0)) < 0) {
255 pa_log("socket(): %s", pa_cstrerror(errno));
256 return -1;
257 }
258
259 #ifdef HAVE_IPV6
260 if (sa->sa_family == AF_INET || sa->sa_family == AF_INET6)
261 #else
262 if (sa->sa_family == AF_INET)
263 #endif
264 pa_make_tcp_socket_low_delay(c->fd);
265 else
266 pa_make_socket_low_delay(c->fd);
267
268 if (do_connect(c, sa, (socklen_t) salen) < 0)
269 return -1;
270
271 return 0;
272 }
273
274 pa_socket_client* pa_socket_client_new_sockaddr(pa_mainloop_api *m, const struct sockaddr *sa, size_t salen) {
275 pa_socket_client *c;
276
277 pa_assert(m);
278 pa_assert(sa);
279 pa_assert(salen > 0);
280
281 c = socket_client_new(m);
282
283 if (sockaddr_prepare(c, sa, salen) < 0)
284 goto fail;
285
286 return c;
287
288 fail:
289 pa_socket_client_unref(c);
290 return NULL;
291 }
292
293 static void socket_client_free(pa_socket_client *c) {
294 pa_assert(c);
295 pa_assert(c->mainloop);
296
297 free_events(c);
298
299 if (c->fd >= 0)
300 pa_close(c->fd);
301
302 #ifdef HAVE_LIBASYNCNS
303 if (c->asyncns_query)
304 asyncns_cancel(c->asyncns, c->asyncns_query);
305 if (c->asyncns)
306 asyncns_free(c->asyncns);
307 if (c->asyncns_io_event)
308 c->mainloop->io_free(c->asyncns_io_event);
309 #endif
310
311 pa_xfree(c);
312 }
313
314 void pa_socket_client_unref(pa_socket_client *c) {
315 pa_assert(c);
316 pa_assert(PA_REFCNT_VALUE(c) >= 1);
317
318 if (PA_REFCNT_DEC(c) <= 0)
319 socket_client_free(c);
320 }
321
322 pa_socket_client* pa_socket_client_ref(pa_socket_client *c) {
323 pa_assert(c);
324 pa_assert(PA_REFCNT_VALUE(c) >= 1);
325
326 PA_REFCNT_INC(c);
327 return c;
328 }
329
330 void pa_socket_client_set_callback(pa_socket_client *c, pa_socket_client_cb_t on_connection, void *userdata) {
331 pa_assert(c);
332 pa_assert(PA_REFCNT_VALUE(c) >= 1);
333
334 c->callback = on_connection;
335 c->userdata = userdata;
336 }
337
338 pa_socket_client* pa_socket_client_new_ipv6(pa_mainloop_api *m, uint8_t address[16], uint16_t port) {
339 #ifdef HAVE_IPV6
340 struct sockaddr_in6 sa;
341
342 pa_assert(m);
343 pa_assert(address);
344 pa_assert(port > 0);
345
346 pa_zero(sa);
347 sa.sin6_family = AF_INET6;
348 sa.sin6_port = htons(port);
349 memcpy(&sa.sin6_addr, address, sizeof(sa.sin6_addr));
350
351 return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa));
352
353 #else
354 return NULL;
355 #endif
356 }
357
358 #ifdef HAVE_LIBASYNCNS
359
360 static void asyncns_cb(pa_mainloop_api*m, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) {
361 pa_socket_client *c = userdata;
362 struct addrinfo *res = NULL;
363 int ret;
364
365 pa_assert(m);
366 pa_assert(c);
367 pa_assert(PA_REFCNT_VALUE(c) >= 1);
368 pa_assert(c->asyncns_io_event == e);
369 pa_assert(fd >= 0);
370
371 if (asyncns_wait(c->asyncns, 0) < 0)
372 goto fail;
373
374 if (!asyncns_isdone(c->asyncns, c->asyncns_query))
375 return;
376
377 ret = asyncns_getaddrinfo_done(c->asyncns, c->asyncns_query, &res);
378 c->asyncns_query = NULL;
379
380 if (ret != 0 || !res)
381 goto fail;
382
383 if (res->ai_addr)
384 if (sockaddr_prepare(c, res->ai_addr, res->ai_addrlen) < 0)
385 goto fail;
386
387 asyncns_freeaddrinfo(res);
388
389 m->io_free(c->asyncns_io_event);
390 c->asyncns_io_event = NULL;
391 return;
392
393 fail:
394 m->io_free(c->asyncns_io_event);
395 c->asyncns_io_event = NULL;
396
397 errno = EHOSTUNREACH;
398 do_call(c);
399 return;
400
401 }
402
403 #endif
404
405 static void timeout_cb(pa_mainloop_api *m, pa_time_event *e, const struct timeval *t, void *userdata) {
406 pa_socket_client *c = userdata;
407
408 pa_assert(m);
409 pa_assert(e);
410 pa_assert(c);
411
412 if (c->fd >= 0) {
413 pa_close(c->fd);
414 c->fd = -1;
415 }
416
417 errno = ETIMEDOUT;
418 do_call(c);
419 }
420
421 static void start_timeout(pa_socket_client *c, bool use_rtclock) {
422 struct timeval tv;
423
424 pa_assert(c);
425 pa_assert(!c->timeout_event);
426
427 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);
428 }
429
430 pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, bool use_rtclock, const char*name, uint16_t default_port) {
431 pa_socket_client *c = NULL;
432 pa_parsed_address a;
433
434 pa_assert(m);
435 pa_assert(name);
436
437 if (pa_parse_address(name, &a) < 0)
438 return NULL;
439
440 if (!a.port)
441 a.port = default_port;
442
443 switch (a.type) {
444 case PA_PARSED_ADDRESS_UNIX:
445 if ((c = pa_socket_client_new_unix(m, a.path_or_host)))
446 start_timeout(c, use_rtclock);
447 break;
448
449 case PA_PARSED_ADDRESS_TCP4: /* Fallthrough */
450 case PA_PARSED_ADDRESS_TCP6: /* Fallthrough */
451 case PA_PARSED_ADDRESS_TCP_AUTO: {
452 struct addrinfo hints;
453 char port[12];
454
455 pa_snprintf(port, sizeof(port), "%u", (unsigned) a.port);
456
457 pa_zero(hints);
458 if (a.type == PA_PARSED_ADDRESS_TCP4)
459 hints.ai_family = PF_INET;
460 #ifdef HAVE_IPV6
461 else if (a.type == PA_PARSED_ADDRESS_TCP6)
462 hints.ai_family = PF_INET6;
463 #endif
464 else
465 hints.ai_family = PF_UNSPEC;
466
467 hints.ai_socktype = SOCK_STREAM;
468
469 #if defined(HAVE_LIBASYNCNS)
470 {
471 asyncns_t *asyncns;
472
473 if (!(asyncns = asyncns_new(1)))
474 goto finish;
475
476 c = socket_client_new(m);
477 c->asyncns = asyncns;
478 c->asyncns_io_event = m->io_new(m, asyncns_fd(c->asyncns), PA_IO_EVENT_INPUT, asyncns_cb, c);
479 pa_assert_se(c->asyncns_query = asyncns_getaddrinfo(c->asyncns, a.path_or_host, port, &hints));
480 start_timeout(c, use_rtclock);
481 }
482 #elif defined(HAVE_GETADDRINFO)
483 {
484 int ret;
485 struct addrinfo *res = NULL;
486
487 ret = getaddrinfo(a.path_or_host, port, &hints, &res);
488
489 if (ret < 0 || !res)
490 goto finish;
491
492 if (res->ai_addr) {
493 if ((c = pa_socket_client_new_sockaddr(m, res->ai_addr, res->ai_addrlen)))
494 start_timeout(c, use_rtclock);
495 }
496
497 freeaddrinfo(res);
498 }
499 #else
500 {
501 struct hostent *host = NULL;
502 struct sockaddr_in s;
503
504 #ifdef HAVE_IPV6
505 /* FIXME: PF_INET6 support */
506 if (hints.ai_family == PF_INET6) {
507 pa_log_error("IPv6 is not supported on Windows");
508 goto finish;
509 }
510 #endif
511
512 host = gethostbyname(a.path_or_host);
513 if (!host) {
514 unsigned int addr = inet_addr(a.path_or_host);
515 if (addr != INADDR_NONE)
516 host = gethostbyaddr((char*)&addr, 4, AF_INET);
517 }
518
519 if (!host)
520 goto finish;
521
522 pa_zero(s);
523 s.sin_family = AF_INET;
524 memcpy(&s.sin_addr, host->h_addr, sizeof(struct in_addr));
525 s.sin_port = htons(a.port);
526
527 if ((c = pa_socket_client_new_sockaddr(m, (struct sockaddr*)&s, sizeof(s))))
528 start_timeout(c, use_rtclock);
529 }
530 #endif /* HAVE_LIBASYNCNS */
531 }
532 }
533
534 finish:
535 pa_xfree(a.path_or_host);
536 return c;
537
538 }
539
540 /* Return non-zero when the target sockaddr is considered
541 local. "local" means UNIX socket or TCP socket on localhost. Other
542 local IP addresses are not considered local. */
543 bool pa_socket_client_is_local(pa_socket_client *c) {
544 pa_assert(c);
545 pa_assert(PA_REFCNT_VALUE(c) >= 1);
546
547 return c->local;
548 }