socket-util: drop redundant casts
[profile/ivi/pulseaudio.git] / src / pulsecore / socket-util.c
1 /***
2   This file is part of PulseAudio.
3
4   Copyright 2004-2006 Lennart Poettering
5   Copyright 2004 Joe Marcus Clarke
6   Copyright 2006-2007 Pierre Ossman <ossman@cendio.se> for Cendio AB
7
8   PulseAudio is free software; you can redistribute it and/or modify
9   it under the terms of the GNU Lesser General Public License as published
10   by the Free Software Foundation; either version 2.1 of the License,
11   or (at your option) any later version.
12
13   PulseAudio is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with PulseAudio; if not, write to the Free Software
20   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21   USA.
22 ***/
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <stdarg.h>
29 #include <stdlib.h>
30 #include <signal.h>
31 #include <errno.h>
32 #include <string.h>
33 #include <stdio.h>
34 #include <sys/types.h>
35 #include <fcntl.h>
36 #include <unistd.h>
37 #include <sys/stat.h>
38
39 #ifdef HAVE_SYS_SOCKET_H
40 #include <sys/socket.h>
41 #endif
42 #ifdef HAVE_SYS_UN_H
43 #include <sys/un.h>
44 #endif
45 #ifdef HAVE_NETINET_IN_H
46 #include <netinet/in.h>
47 #endif
48 #ifdef HAVE_NETINET_IN_SYSTM_H
49 #include <netinet/in_systm.h>
50 #endif
51 #ifdef HAVE_NETINET_IP_H
52 #include <netinet/ip.h>
53 #endif
54 #ifdef HAVE_NETINET_TCP_H
55 #include <netinet/tcp.h>
56 #endif
57 #ifdef HAVE_NETDB_H
58 #include <netdb.h>
59 #endif
60 #ifdef HAVE_ARPA_INET_H
61 #include <arpa/inet.h>
62 #endif
63
64 #ifndef HAVE_INET_NTOP
65 #include "inet_ntop.h"
66 #endif
67
68 #include "winsock.h"
69
70 #include <pulse/xmalloc.h>
71
72 #include <pulsecore/core-error.h>
73 #include <pulsecore/core-util.h>
74 #include <pulsecore/log.h>
75 #include <pulsecore/macro.h>
76
77 #include "socket-util.h"
78
79 void pa_socket_peer_to_string(int fd, char *c, size_t l) {
80     struct stat st;
81
82     pa_assert(fd >= 0);
83     pa_assert(c);
84     pa_assert(l > 0);
85
86 #ifndef OS_IS_WIN32
87     pa_assert_se(fstat(fd, &st) == 0);
88
89     if (S_ISSOCK(st.st_mode)) {
90 #endif
91         union {
92             struct sockaddr_storage storage;
93             struct sockaddr sa;
94             struct sockaddr_in in;
95 #ifdef HAVE_IPV6
96             struct sockaddr_in6 in6;
97 #endif
98 #ifdef HAVE_SYS_UN_H
99             struct sockaddr_un un;
100 #endif
101         } sa;
102         socklen_t sa_len = sizeof(sa);
103
104         if (getpeername(fd, &sa.sa, &sa_len) >= 0) {
105
106             if (sa.sa.sa_family == AF_INET) {
107                 uint32_t ip = ntohl(sa.in.sin_addr.s_addr);
108
109                 pa_snprintf(c, l, "TCP/IP client from %i.%i.%i.%i:%u",
110                             ip >> 24,
111                             (ip >> 16) & 0xFF,
112                             (ip >> 8) & 0xFF,
113                             ip & 0xFF,
114                             ntohs(sa.in.sin_port));
115                 return;
116 #ifdef HAVE_IPV6
117             } else if (sa.sa.sa_family == AF_INET6) {
118                 char buf[INET6_ADDRSTRLEN];
119                 const char *res;
120
121                 res = inet_ntop(AF_INET6, &sa.in6.sin6_addr, buf, sizeof(buf));
122                 if (res) {
123                     pa_snprintf(c, l, "TCP/IP client from [%s]:%u", buf, ntohs(sa.in6.sin6_port));
124                     return;
125                 }
126 #endif
127 #ifdef HAVE_SYS_UN_H
128             } else if (sa.sa.sa_family == AF_UNIX) {
129                 pa_snprintf(c, l, "UNIX socket client");
130                 return;
131 #endif
132             }
133         }
134
135 #ifndef OS_IS_WIN32
136         pa_snprintf(c, l, "Unknown network client");
137         return;
138     } else if (S_ISCHR(st.st_mode) && (fd == 0 || fd == 1)) {
139         pa_snprintf(c, l, "STDIN/STDOUT client");
140         return;
141     }
142 #endif /* OS_IS_WIN32 */
143
144     pa_snprintf(c, l, "Unknown client");
145 }
146
147 void pa_make_socket_low_delay(int fd) {
148
149 #ifdef SO_PRIORITY
150     int priority;
151     pa_assert(fd >= 0);
152
153     priority = 6;
154     if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, &priority, sizeof(priority)) < 0)
155         pa_log_warn("SO_PRIORITY failed: %s", pa_cstrerror(errno));
156 #endif
157 }
158
159 void pa_make_tcp_socket_low_delay(int fd) {
160     pa_assert(fd >= 0);
161
162     pa_make_socket_low_delay(fd);
163
164 #if defined(SOL_TCP) || defined(IPPROTO_TCP)
165     {
166         int on = 1;
167 #if defined(SOL_TCP)
168         if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &on, sizeof(on)) < 0)
169 #else
170         if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) < 0)
171 #endif
172             pa_log_warn("TCP_NODELAY failed: %s", pa_cstrerror(errno));
173     }
174 #endif
175
176 #if defined(IPTOS_LOWDELAY) && defined(IP_TOS) && (defined(SOL_IP) || defined(IPPROTO_IP))
177     {
178         int tos = IPTOS_LOWDELAY;
179 #ifdef SOL_IP
180         if (setsockopt(fd, SOL_IP, IP_TOS, &tos, sizeof(tos)) < 0)
181 #else
182         if (setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0)
183 #endif
184             pa_log_warn("IP_TOS failed: %s", pa_cstrerror(errno));
185     }
186 #endif
187 }
188
189 void pa_make_udp_socket_low_delay(int fd) {
190     pa_assert(fd >= 0);
191
192     pa_make_socket_low_delay(fd);
193
194 #if defined(IPTOS_LOWDELAY) && defined(IP_TOS) && (defined(SOL_IP) || defined(IPPROTO_IP))
195     {
196         int tos = IPTOS_LOWDELAY;
197 #ifdef SOL_IP
198         if (setsockopt(fd, SOL_IP, IP_TOS, &tos, sizeof(tos)) < 0)
199 #else
200         if (setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0)
201 #endif
202             pa_log_warn("IP_TOS failed: %s", pa_cstrerror(errno));
203     }
204 #endif
205 }
206
207 int pa_socket_set_rcvbuf(int fd, size_t l) {
208     int bufsz = (int) l;
209
210     pa_assert(fd >= 0);
211
212     if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &bufsz, sizeof(bufsz)) < 0) {
213         pa_log_warn("SO_RCVBUF: %s", pa_cstrerror(errno));
214         return -1;
215     }
216
217     return 0;
218 }
219
220 int pa_socket_set_sndbuf(int fd, size_t l) {
221     int bufsz = (int) l;
222
223     pa_assert(fd >= 0);
224
225     if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &bufsz, sizeof(bufsz)) < 0) {
226         pa_log_warn("SO_SNDBUF: %s", pa_cstrerror(errno));
227         return -1;
228     }
229
230     return 0;
231 }
232
233 #ifdef HAVE_SYS_UN_H
234
235 int pa_unix_socket_is_stale(const char *fn) {
236     struct sockaddr_un sa;
237     int fd = -1, ret = -1;
238
239     pa_assert(fn);
240
241     if ((fd = pa_socket_cloexec(PF_UNIX, SOCK_STREAM, 0)) < 0) {
242         pa_log("socket(): %s", pa_cstrerror(errno));
243         goto finish;
244     }
245
246     sa.sun_family = AF_UNIX;
247     strncpy(sa.sun_path, fn, sizeof(sa.sun_path)-1);
248     sa.sun_path[sizeof(sa.sun_path) - 1] = 0;
249
250     if (connect(fd, (struct sockaddr*) &sa, sizeof(sa)) < 0) {
251         if (errno == ECONNREFUSED)
252             ret = 1;
253     } else
254         ret = 0;
255
256 finish:
257     if (fd >= 0)
258         pa_close(fd);
259
260     return ret;
261 }
262
263 int pa_unix_socket_remove_stale(const char *fn) {
264     int r;
265
266     pa_assert(fn);
267
268     if ((r = pa_unix_socket_is_stale(fn)) < 0)
269         return errno != ENOENT ? -1 : 0;
270
271     if (!r)
272         return 0;
273
274     /* Yes, here is a race condition. But who cares? */
275     if (unlink(fn) < 0)
276         return -1;
277
278     return 0;
279 }
280
281 #else /* HAVE_SYS_UN_H */
282
283 int pa_unix_socket_is_stale(const char *fn) {
284     return -1;
285 }
286
287 int pa_unix_socket_remove_stale(const char *fn) {
288     return -1;
289 }
290
291 #endif /* HAVE_SYS_UN_H */
292
293
294 pa_bool_t pa_socket_address_is_local(const struct sockaddr *sa) {
295     pa_assert(sa);
296
297     switch (sa->sa_family) {
298         case AF_UNIX:
299             return TRUE;
300
301         case AF_INET:
302             return ((const struct sockaddr_in*) sa)->sin_addr.s_addr == INADDR_LOOPBACK;
303
304 #ifdef HAVE_IPV6
305         case AF_INET6:
306             return memcmp(&((const struct sockaddr_in6*) sa)->sin6_addr, &in6addr_loopback, sizeof(struct in6_addr)) == 0;
307 #endif
308
309         default:
310             return FALSE;
311     }
312 }
313
314 pa_bool_t pa_socket_is_local(int fd) {
315
316     union {
317         struct sockaddr_storage storage;
318         struct sockaddr sa;
319         struct sockaddr_in in;
320 #ifdef HAVE_IPV6
321         struct sockaddr_in6 in6;
322 #endif
323 #ifdef HAVE_SYS_UN_H
324         struct sockaddr_un un;
325 #endif
326     } sa;
327     socklen_t sa_len = sizeof(sa);
328
329     if (getpeername(fd, &sa.sa, &sa_len) < 0)
330         return FALSE;
331
332     return pa_socket_address_is_local(&sa.sa);
333 }