]> code.delx.au - pulseaudio/blob - src/pulsecore/socket-client.c
llvm-clang-analyzer: drop a few unnecessary assignments and other trivial fixes
[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 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 (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 *t, void *userdata) {
424 pa_socket_client *c = userdata;
425
426 pa_assert(m);
427 pa_assert(e);
428 pa_assert(c);
429
430 if (c->fd >= 0) {
431 pa_close(c->fd);
432 c->fd = -1;
433 }
434
435 errno = ETIMEDOUT;
436 do_call(c);
437 }
438
439 static void start_timeout(pa_socket_client *c, pa_bool_t use_rtclock) {
440 struct timeval tv;
441
442 pa_assert(c);
443 pa_assert(!c->timeout_event);
444
445 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);
446 }
447
448 pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, pa_bool_t use_rtclock, const char*name, uint16_t default_port) {
449 pa_socket_client *c = NULL;
450 pa_parsed_address a;
451
452 pa_assert(m);
453 pa_assert(name);
454
455 if (pa_parse_address(name, &a) < 0)
456 return NULL;
457
458 if (!a.port)
459 a.port = default_port;
460
461 switch (a.type) {
462 case PA_PARSED_ADDRESS_UNIX:
463 if ((c = pa_socket_client_new_unix(m, a.path_or_host)))
464 start_timeout(c, use_rtclock);
465 break;
466
467 case PA_PARSED_ADDRESS_TCP4: /* Fallthrough */
468 case PA_PARSED_ADDRESS_TCP6: /* Fallthrough */
469 case PA_PARSED_ADDRESS_TCP_AUTO:{
470
471 struct addrinfo hints;
472 char port[12];
473
474 pa_snprintf(port, sizeof(port), "%u", (unsigned) a.port);
475
476 memset(&hints, 0, sizeof(hints));
477 if (a.type == PA_PARSED_ADDRESS_TCP4)
478 hints.ai_family = PF_INET;
479 #ifdef HAVE_IPV6
480 else if (a.type == PA_PARSED_ADDRESS_TCP6)
481 hints.ai_family = PF_INET6;
482 #endif
483 else
484 hints.ai_family = PF_UNSPEC;
485
486 hints.ai_socktype = SOCK_STREAM;
487
488 #if defined(HAVE_LIBASYNCNS)
489 {
490 asyncns_t *asyncns;
491
492 if (!(asyncns = asyncns_new(1)))
493 goto finish;
494
495 pa_assert_se(c = socket_client_new(m));
496 c->asyncns = asyncns;
497 c->asyncns_io_event = m->io_new(m, asyncns_fd(c->asyncns), PA_IO_EVENT_INPUT, asyncns_cb, c);
498 c->asyncns_query = asyncns_getaddrinfo(c->asyncns, a.path_or_host, port, &hints);
499 pa_assert(c->asyncns_query);
500 start_timeout(c, use_rtclock);
501 }
502 #elif defined(HAVE_GETADDRINFO)
503 {
504 int ret;
505 struct addrinfo *res = NULL;
506
507 ret = getaddrinfo(a.path_or_host, port, &hints, &res);
508
509 if (ret < 0 || !res)
510 goto finish;
511
512 if (res->ai_addr) {
513 if ((c = pa_socket_client_new_sockaddr(m, res->ai_addr, res->ai_addrlen)))
514 start_timeout(c, use_rtclock);
515 }
516
517 freeaddrinfo(res);
518 }
519 #else
520 {
521 struct hostent *host = NULL;
522 struct sockaddr_in s;
523
524 #ifdef HAVE_IPV6
525 /* FIXME: PF_INET6 support */
526 if (hints.ai_family == PF_INET6) {
527 pa_log_error("IPv6 is not supported on Windows");
528 goto finish;
529 }
530 #endif
531
532 host = gethostbyname(a.path_or_host);
533 if (!host) {
534 unsigned int addr = inet_addr(a.path_or_host);
535 if (addr != INADDR_NONE)
536 host = gethostbyaddr((char*)&addr, 4, AF_INET);
537 }
538
539 if (!host)
540 goto finish;
541
542 s.sin_family = AF_INET;
543 memcpy(&s.sin_addr, host->h_addr, sizeof(struct in_addr));
544 s.sin_port = htons(a.port);
545
546 if ((c = pa_socket_client_new_sockaddr(m, (struct sockaddr*)&s, sizeof(s))))
547 start_timeout(c, use_rtclock);
548 }
549 #endif /* HAVE_LIBASYNCNS */
550 }
551 }
552
553 finish:
554 pa_xfree(a.path_or_host);
555 return c;
556
557 }
558
559 /* Return non-zero when the target sockaddr is considered
560 local. "local" means UNIX socket or TCP socket on localhost. Other
561 local IP addresses are not considered local. */
562 pa_bool_t pa_socket_client_is_local(pa_socket_client *c) {
563 pa_assert(c);
564 pa_assert(PA_REFCNT_VALUE(c) >= 1);
565
566 return c->local;
567 }