Add copyright notices to all relevant files. (based on svn log)
[profile/ivi/pulseaudio.git] / src / pulsecore / socket-client.c
1 /* $Id$ */
2
3 /***
4   This file is part of PulseAudio.
5
6   Copyright 2004-2006 Lennart Poettering
7   Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
8
9   PulseAudio is free software; you can redistribute it and/or modify
10   it under the terms of the GNU Lesser General Public License as
11   published by the Free Software Foundation; either version 2.1 of the
12   License, or (at your option) any later version.
13
14   PulseAudio is distributed in the hope that it will be useful, but
15   WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17   Lesser General Public License for more details.
18
19   You should have received a copy of the GNU Lesser General Public
20   License along with PulseAudio; if not, write to the Free Software
21   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22   USA.
23 ***/
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 /* #undef HAVE_LIBASYNCNS */
30
31 #include <unistd.h>
32 #include <stdio.h>
33 #include <errno.h>
34 #include <string.h>
35 #include <assert.h>
36 #include <stdlib.h>
37
38 #ifdef HAVE_SYS_SOCKET_H
39 #include <sys/socket.h>
40 #endif
41 #ifdef HAVE_SYS_UN_H
42 #include <sys/un.h>
43 #endif
44 #ifdef HAVE_ARPA_INET_H
45 #include <arpa/inet.h>
46 #endif
47 #ifdef HAVE_NETINET_IN_H
48 #include <netinet/in.h>
49 #endif
50 #ifdef HAVE_NETDB_H
51 #include <netdb.h>
52 #endif
53
54 #ifdef HAVE_LIBASYNCNS
55 #include <asyncns.h>
56 #endif
57
58 #include "winsock.h"
59
60 #include <pulse/timeval.h>
61 #include <pulse/xmalloc.h>
62
63 #include <pulsecore/core-error.h>
64 #include <pulsecore/socket-util.h>
65 #include <pulsecore/core-util.h>
66 #include <pulsecore/log.h>
67 #include <pulsecore/parseaddr.h>
68
69 #include "socket-client.h"
70
71 #define CONNECT_TIMEOUT 5
72
73 struct pa_socket_client {
74     int ref;
75     pa_mainloop_api *mainloop;
76     int fd;
77     pa_io_event *io_event;
78     pa_time_event *timeout_event;
79     pa_defer_event *defer_event;
80     void (*callback)(pa_socket_client*c, pa_iochannel *io, void *userdata);
81     void *userdata;
82     int local;
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*pa_socket_client_new(pa_mainloop_api *m) {
91     pa_socket_client *c;
92     assert(m);
93
94     c = pa_xmalloc(sizeof(pa_socket_client));
95     c->ref = 1;
96     c->mainloop = m;
97     c->fd = -1;
98     c->io_event = NULL;
99     c->defer_event = NULL;
100     c->timeout_event = NULL;
101     c->callback = NULL;
102     c->userdata = NULL;
103     c->local = 0;
104
105 #ifdef HAVE_LIBASYNCNS
106     c->asyncns = NULL;
107     c->asyncns_io_event = NULL;
108     c->asyncns_query = NULL;
109 #endif
110
111     return c;
112 }
113
114 static void free_events(pa_socket_client *c) {
115     assert(c);
116
117     if (c->io_event) {
118         c->mainloop->io_free(c->io_event);
119         c->io_event = NULL;
120     }
121
122     if (c->defer_event) {
123         c->mainloop->defer_free(c->defer_event);
124         c->defer_event = NULL;
125     }
126
127     if (c->timeout_event) {
128         c->mainloop->time_free(c->timeout_event);
129         c->timeout_event = NULL;
130     }
131 }
132
133 static void do_call(pa_socket_client *c) {
134     pa_iochannel *io = NULL;
135     int error;
136     socklen_t lerror;
137     assert(c && c->callback);
138
139     pa_socket_client_ref(c);
140
141     if (c->fd < 0)
142         goto finish;
143
144     lerror = sizeof(error);
145     if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void*)&error, &lerror) < 0) {
146         pa_log("getsockopt(): %s", pa_cstrerror(errno));
147         goto finish;
148     }
149
150     if (lerror != sizeof(error)) {
151         pa_log("getsockopt() returned invalid size.");
152         goto finish;
153     }
154
155     if (error != 0) {
156         pa_log_debug("connect(): %s", pa_cstrerror(errno));
157         errno = error;
158         goto finish;
159     }
160
161     io = pa_iochannel_new(c->mainloop, c->fd, c->fd);
162     assert(io);
163
164 finish:
165     if (!io && c->fd >= 0)
166         close(c->fd);
167     c->fd = -1;
168
169     free_events(c);
170
171     assert(c->callback);
172     c->callback(c, io, c->userdata);
173
174     pa_socket_client_unref(c);
175 }
176
177 static void connect_fixed_cb(pa_mainloop_api *m, pa_defer_event *e, void *userdata) {
178     pa_socket_client *c = userdata;
179     assert(m && c && c->defer_event == e);
180     do_call(c);
181 }
182
183 static void connect_io_cb(pa_mainloop_api*m, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags_t f, void *userdata) {
184     pa_socket_client *c = userdata;
185     assert(m && c && c->io_event == e && fd >= 0);
186     do_call(c);
187 }
188
189 static int do_connect(pa_socket_client *c, const struct sockaddr *sa, socklen_t len) {
190     int r;
191     assert(c && sa && len);
192
193     pa_make_nonblock_fd(c->fd);
194
195     if ((r = 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         assert(c->io_event);
208     } else {
209         c->defer_event = c->mainloop->defer_new(c->mainloop, connect_fixed_cb, c);
210         assert(c->defer_event);
211     }
212
213     return 0;
214 }
215
216 pa_socket_client* pa_socket_client_new_ipv4(pa_mainloop_api *m, uint32_t address, uint16_t port) {
217     struct sockaddr_in sa;
218     assert(m && port > 0);
219
220     memset(&sa, 0, sizeof(sa));
221     sa.sin_family = AF_INET;
222     sa.sin_port = htons(port);
223     sa.sin_addr.s_addr = htonl(address);
224
225     return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa));
226 }
227
228 #ifdef HAVE_SYS_UN_H
229
230 pa_socket_client* pa_socket_client_new_unix(pa_mainloop_api *m, const char *filename) {
231     struct sockaddr_un sa;
232     assert(m && filename);
233
234     memset(&sa, 0, sizeof(sa));
235     sa.sun_family = AF_UNIX;
236     strncpy(sa.sun_path, filename, sizeof(sa.sun_path)-1);
237     sa.sun_path[sizeof(sa.sun_path) - 1] = 0;
238
239     return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa));
240 }
241
242 #else /* HAVE_SYS_UN_H */
243
244 pa_socket_client* pa_socket_client_new_unix(pa_mainloop_api *m, const char *filename) {
245     return NULL;
246 }
247
248 #endif /* HAVE_SYS_UN_H */
249
250 static int sockaddr_prepare(pa_socket_client *c, const struct sockaddr *sa, size_t salen) {
251     assert(c);
252     assert(sa);
253     assert(salen);
254
255     switch (sa->sa_family) {
256         case AF_UNIX:
257             c->local = 1;
258             break;
259
260         case AF_INET:
261             c->local = ((const struct sockaddr_in*) sa)->sin_addr.s_addr == INADDR_LOOPBACK;
262             break;
263
264         case AF_INET6:
265             c->local = memcmp(&((const struct sockaddr_in6*) sa)->sin6_addr, &in6addr_loopback, sizeof(struct in6_addr)) == 0;
266             break;
267
268         default:
269             c->local = 0;
270     }
271
272     if ((c->fd = socket(sa->sa_family, SOCK_STREAM, 0)) < 0) {
273         pa_log("socket(): %s", pa_cstrerror(errno));
274         return -1;
275     }
276
277     pa_fd_set_cloexec(c->fd, 1);
278     if (sa->sa_family == AF_INET || sa->sa_family == AF_INET6)
279         pa_socket_tcp_low_delay(c->fd);
280     else
281         pa_socket_low_delay(c->fd);
282
283     if (do_connect(c, sa, salen) < 0)
284         return -1;
285
286     return 0;
287 }
288
289 pa_socket_client* pa_socket_client_new_sockaddr(pa_mainloop_api *m, const struct sockaddr *sa, size_t salen) {
290     pa_socket_client *c;
291     assert(m && sa);
292     c = pa_socket_client_new(m);
293     assert(c);
294
295     if (sockaddr_prepare(c, sa, salen) < 0)
296         goto fail;
297
298     return c;
299
300 fail:
301     pa_socket_client_unref(c);
302     return NULL;
303
304 }
305
306 static void socket_client_free(pa_socket_client *c) {
307     assert(c && c->mainloop);
308
309
310     free_events(c);
311
312     if (c->fd >= 0)
313         close(c->fd);
314
315 #ifdef HAVE_LIBASYNCNS
316     if (c->asyncns_query)
317         asyncns_cancel(c->asyncns, c->asyncns_query);
318     if (c->asyncns)
319         asyncns_free(c->asyncns);
320     if (c->asyncns_io_event)
321         c->mainloop->io_free(c->asyncns_io_event);
322 #endif
323
324     pa_xfree(c);
325 }
326
327 void pa_socket_client_unref(pa_socket_client *c) {
328     assert(c && c->ref >= 1);
329
330     if (!(--(c->ref)))
331         socket_client_free(c);
332 }
333
334 pa_socket_client* pa_socket_client_ref(pa_socket_client *c) {
335     assert(c && c->ref >= 1);
336     c->ref++;
337     return c;
338 }
339
340 void pa_socket_client_set_callback(pa_socket_client *c, void (*on_connection)(pa_socket_client *c, pa_iochannel*io, void *userdata), void *userdata) {
341     assert(c);
342     c->callback = on_connection;
343     c->userdata = userdata;
344 }
345
346 pa_socket_client* pa_socket_client_new_ipv6(pa_mainloop_api *m, uint8_t address[16], uint16_t port) {
347     struct sockaddr_in6 sa;
348
349     memset(&sa, 0, sizeof(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
357 #ifdef HAVE_LIBASYNCNS
358
359 static void asyncns_cb(pa_mainloop_api*m, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags_t f, void *userdata) {
360     pa_socket_client *c = userdata;
361     struct addrinfo *res = NULL;
362     int ret;
363     assert(m && c && c->asyncns_io_event == e && fd >= 0);
364
365     if (asyncns_wait(c->asyncns, 0) < 0)
366         goto fail;
367
368     if (!asyncns_isdone(c->asyncns, c->asyncns_query))
369         return;
370
371     ret = asyncns_getaddrinfo_done(c->asyncns, c->asyncns_query, &res);
372     c->asyncns_query = NULL;
373
374     if (ret != 0 || !res)
375         goto fail;
376
377     if (res->ai_addr)
378         sockaddr_prepare(c, res->ai_addr, res->ai_addrlen);
379
380     asyncns_freeaddrinfo(res);
381
382     m->io_free(c->asyncns_io_event);
383     c->asyncns_io_event = NULL;
384     return;
385
386 fail:
387     m->io_free(c->asyncns_io_event);
388     c->asyncns_io_event = NULL;
389
390     errno = EHOSTUNREACH;
391     do_call(c);
392     return;
393
394 }
395
396 #endif
397
398 static void timeout_cb(pa_mainloop_api *m, pa_time_event *e, const struct timeval *tv, void *userdata) {
399     pa_socket_client *c = userdata;
400     assert(m);
401     assert(e);
402     assert(tv);
403     assert(c);
404
405     if (c->fd >= 0) {
406         close(c->fd);
407         c->fd = -1;
408     }
409
410     errno = ETIMEDOUT;
411     do_call(c);
412 }
413
414 static void start_timeout(pa_socket_client *c) {
415     struct timeval tv;
416     assert(c);
417     assert(!c->timeout_event);
418
419     pa_gettimeofday(&tv);
420     pa_timeval_add(&tv, CONNECT_TIMEOUT * 1000000);
421     c->timeout_event = c->mainloop->time_new(c->mainloop, &tv, timeout_cb, c);
422 }
423
424 pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char*name, uint16_t default_port) {
425     pa_socket_client *c = NULL;
426     pa_parsed_address a;
427     assert(m && name);
428
429     if (pa_parse_address(name, &a) < 0)
430         return NULL;
431
432     if (!a.port)
433         a.port = default_port;
434
435     switch (a.type) {
436         case PA_PARSED_ADDRESS_UNIX:
437             if ((c = pa_socket_client_new_unix(m, a.path_or_host)))
438                 start_timeout(c);
439             break;
440
441         case PA_PARSED_ADDRESS_TCP4:  /* Fallthrough */
442         case PA_PARSED_ADDRESS_TCP6:  /* Fallthrough */
443         case PA_PARSED_ADDRESS_TCP_AUTO:{
444
445             struct addrinfo hints;
446             char port[12];
447
448             snprintf(port, sizeof(port), "%u", (unsigned) a.port);
449
450             memset(&hints, 0, sizeof(hints));
451             hints.ai_family = a.type == PA_PARSED_ADDRESS_TCP4 ? PF_INET : (a.type == PA_PARSED_ADDRESS_TCP6 ? PF_INET6 : PF_UNSPEC);
452             hints.ai_socktype = SOCK_STREAM;
453
454 #ifdef HAVE_LIBASYNCNS
455             {
456                 asyncns_t *asyncns;
457
458                 if (!(asyncns = asyncns_new(1)))
459                     goto finish;
460
461                 c = pa_socket_client_new(m);
462                 c->asyncns = asyncns;
463                 c->asyncns_io_event = m->io_new(m, asyncns_fd(c->asyncns), PA_IO_EVENT_INPUT, asyncns_cb, c);
464                 c->asyncns_query = asyncns_getaddrinfo(c->asyncns, a.path_or_host, port, &hints);
465                 assert(c->asyncns_query);
466                 start_timeout(c);
467             }
468 #else /* HAVE_LIBASYNCNS */
469             {
470 #ifdef HAVE_GETADDRINFO
471                 int ret;
472                 struct addrinfo *res = NULL;
473
474                 ret = getaddrinfo(a.path_or_host, port, &hints, &res);
475
476                 if (ret < 0 || !res)
477                     goto finish;
478
479                 if (res->ai_addr) {
480                     if ((c = pa_socket_client_new_sockaddr(m, res->ai_addr, res->ai_addrlen)))
481                         start_timeout(c);
482                                 }
483
484                 freeaddrinfo(res);
485 #else /* HAVE_GETADDRINFO */
486                 struct hostent *host = NULL;
487                 struct sockaddr_in s;
488
489                 /* FIXME: PF_INET6 support */
490                 if (hints.ai_family == PF_INET6) {
491                     pa_log_error("IPv6 is not supported on Windows");
492                     goto finish;
493                 }
494
495                 host = gethostbyname(a.path_or_host);
496                 if (!host) {
497                     unsigned int addr = inet_addr(a.path_or_host);
498                     if (addr != INADDR_NONE)
499                         host = gethostbyaddr((char*)&addr, 4, AF_INET);
500                 }
501
502                 if (!host)
503                     goto finish;
504
505                 s.sin_family = AF_INET;
506                 memcpy(&s.sin_addr, host->h_addr, sizeof(struct in_addr));
507                 s.sin_port = htons(a.port);
508
509                 if ((c = pa_socket_client_new_sockaddr(m, (struct sockaddr*)&s, sizeof(s))))
510                         start_timeout(c);
511 #endif /* HAVE_GETADDRINFO */
512             }
513 #endif /* HAVE_LIBASYNCNS */
514         }
515     }
516
517 finish:
518     pa_xfree(a.path_or_host);
519     return c;
520
521 }
522
523 /* Return non-zero when the target sockaddr is considered
524    local. "local" means UNIX socket or TCP socket on localhost. Other
525    local IP addresses are not considered local. */
526 int pa_socket_client_is_local(pa_socket_client *c) {
527     assert(c);
528     return c->local;
529 }