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