build-sys: Use ax_check_flag macros from autoconf archive
[pulseaudio-mirror.git] / src / pulsecore / socket-util.c
blob00fcbc4f52fd22a457cf3a5cdfde80ac19f36aa3
1 /***
2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2004 Joe Marcus Clarke
6 Copyright 2006-2007 Pierre Ossman <ossman@cendio.se> for Cendio AB
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.
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.
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 ***/
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
28 #include <stdlib.h>
29 #include <signal.h>
30 #include <errno.h>
31 #include <string.h>
32 #include <stdio.h>
33 #include <sys/types.h>
34 #include <unistd.h>
35 #include <sys/stat.h>
37 #ifdef HAVE_SYS_UN_H
38 #include <sys/un.h>
39 #endif
40 #ifdef HAVE_NETINET_IN_H
41 #include <netinet/in.h>
42 #endif
43 #ifdef HAVE_NETINET_IN_SYSTM_H
44 #include <netinet/in_systm.h>
45 #endif
46 #ifdef HAVE_NETINET_IP_H
47 #include <netinet/ip.h>
48 #endif
49 #ifdef HAVE_NETINET_TCP_H
50 #include <netinet/tcp.h>
51 #endif
52 #ifdef HAVE_NETDB_H
53 #include <netdb.h>
54 #endif
56 #include <pulsecore/core-error.h>
57 #include <pulsecore/core-util.h>
58 #include <pulsecore/log.h>
59 #include <pulsecore/macro.h>
60 #include <pulsecore/socket.h>
61 #include <pulsecore/arpa-inet.h>
63 #include "socket-util.h"
65 void pa_socket_peer_to_string(int fd, char *c, size_t l) {
66 struct stat st;
68 pa_assert(fd >= 0);
69 pa_assert(c);
70 pa_assert(l > 0);
72 #ifndef OS_IS_WIN32
73 pa_assert_se(fstat(fd, &st) == 0);
75 if (S_ISSOCK(st.st_mode))
76 #endif
78 union {
79 struct sockaddr_storage storage;
80 struct sockaddr sa;
81 struct sockaddr_in in;
82 #ifdef HAVE_IPV6
83 struct sockaddr_in6 in6;
84 #endif
85 #ifdef HAVE_SYS_UN_H
86 struct sockaddr_un un;
87 #endif
88 } sa;
89 socklen_t sa_len = sizeof(sa);
91 if (getpeername(fd, &sa.sa, &sa_len) >= 0) {
93 if (sa.sa.sa_family == AF_INET) {
94 uint32_t ip = ntohl(sa.in.sin_addr.s_addr);
96 pa_snprintf(c, l, "TCP/IP client from %i.%i.%i.%i:%u",
97 ip >> 24,
98 (ip >> 16) & 0xFF,
99 (ip >> 8) & 0xFF,
100 ip & 0xFF,
101 ntohs(sa.in.sin_port));
102 return;
103 #ifdef HAVE_IPV6
104 } else if (sa.sa.sa_family == AF_INET6) {
105 char buf[INET6_ADDRSTRLEN];
106 const char *res;
108 res = inet_ntop(AF_INET6, &sa.in6.sin6_addr, buf, sizeof(buf));
109 if (res) {
110 pa_snprintf(c, l, "TCP/IP client from [%s]:%u", buf, ntohs(sa.in6.sin6_port));
111 return;
113 #endif
114 #ifdef HAVE_SYS_UN_H
115 } else if (sa.sa.sa_family == AF_UNIX) {
116 pa_snprintf(c, l, "UNIX socket client");
117 return;
118 #endif
122 pa_snprintf(c, l, "Unknown network client");
123 return;
125 #ifndef OS_IS_WIN32
126 else if (S_ISCHR(st.st_mode) && (fd == 0 || fd == 1)) {
127 pa_snprintf(c, l, "STDIN/STDOUT client");
128 return;
130 #endif /* OS_IS_WIN32 */
132 pa_snprintf(c, l, "Unknown client");
135 void pa_make_socket_low_delay(int fd) {
137 #ifdef SO_PRIORITY
138 int priority;
139 pa_assert(fd >= 0);
141 priority = 6;
142 if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, &priority, sizeof(priority)) < 0)
143 pa_log_warn("SO_PRIORITY failed: %s", pa_cstrerror(errno));
144 #endif
147 void pa_make_tcp_socket_low_delay(int fd) {
148 pa_assert(fd >= 0);
150 pa_make_socket_low_delay(fd);
152 #if defined(SOL_TCP) || defined(IPPROTO_TCP)
154 int on = 1;
155 #if defined(SOL_TCP)
156 if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &on, sizeof(on)) < 0)
157 #else
158 if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) < 0)
159 #endif
160 pa_log_warn("TCP_NODELAY failed: %s", pa_cstrerror(errno));
162 #endif
164 #if defined(IPTOS_LOWDELAY) && defined(IP_TOS) && (defined(SOL_IP) || defined(IPPROTO_IP))
166 int tos = IPTOS_LOWDELAY;
167 #ifdef SOL_IP
168 if (setsockopt(fd, SOL_IP, IP_TOS, &tos, sizeof(tos)) < 0)
169 #else
170 if (setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0)
171 #endif
172 pa_log_warn("IP_TOS failed: %s", pa_cstrerror(errno));
174 #endif
177 void pa_make_udp_socket_low_delay(int fd) {
178 pa_assert(fd >= 0);
180 pa_make_socket_low_delay(fd);
182 #if defined(IPTOS_LOWDELAY) && defined(IP_TOS) && (defined(SOL_IP) || defined(IPPROTO_IP))
184 int tos = IPTOS_LOWDELAY;
185 #ifdef SOL_IP
186 if (setsockopt(fd, SOL_IP, IP_TOS, &tos, sizeof(tos)) < 0)
187 #else
188 if (setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0)
189 #endif
190 pa_log_warn("IP_TOS failed: %s", pa_cstrerror(errno));
192 #endif
195 int pa_socket_set_rcvbuf(int fd, size_t l) {
196 int bufsz = (int) l;
198 pa_assert(fd >= 0);
200 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &bufsz, sizeof(bufsz)) < 0) {
201 pa_log_warn("SO_RCVBUF: %s", pa_cstrerror(errno));
202 return -1;
205 return 0;
208 int pa_socket_set_sndbuf(int fd, size_t l) {
209 int bufsz = (int) l;
211 pa_assert(fd >= 0);
213 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &bufsz, sizeof(bufsz)) < 0) {
214 pa_log_warn("SO_SNDBUF: %s", pa_cstrerror(errno));
215 return -1;
218 return 0;
221 #ifdef HAVE_SYS_UN_H
223 int pa_unix_socket_is_stale(const char *fn) {
224 struct sockaddr_un sa;
225 int fd = -1, ret = -1;
227 pa_assert(fn);
229 if ((fd = pa_socket_cloexec(PF_UNIX, SOCK_STREAM, 0)) < 0) {
230 pa_log("socket(): %s", pa_cstrerror(errno));
231 goto finish;
234 sa.sun_family = AF_UNIX;
235 strncpy(sa.sun_path, fn, sizeof(sa.sun_path)-1);
236 sa.sun_path[sizeof(sa.sun_path) - 1] = 0;
238 if (connect(fd, (struct sockaddr*) &sa, sizeof(sa)) < 0) {
239 if (errno == ECONNREFUSED)
240 ret = 1;
241 } else
242 ret = 0;
244 finish:
245 if (fd >= 0)
246 pa_close(fd);
248 return ret;
251 int pa_unix_socket_remove_stale(const char *fn) {
252 int r;
254 pa_assert(fn);
256 if ((r = pa_unix_socket_is_stale(fn)) < 0)
257 return errno != ENOENT ? -1 : 0;
259 if (!r)
260 return 0;
262 /* Yes, here is a race condition. But who cares? */
263 if (unlink(fn) < 0)
264 return -1;
266 return 0;
269 #else /* HAVE_SYS_UN_H */
271 int pa_unix_socket_is_stale(const char *fn) {
272 return -1;
275 int pa_unix_socket_remove_stale(const char *fn) {
276 return -1;
279 #endif /* HAVE_SYS_UN_H */
282 pa_bool_t pa_socket_address_is_local(const struct sockaddr *sa) {
283 pa_assert(sa);
285 switch (sa->sa_family) {
286 case AF_UNIX:
287 return TRUE;
289 case AF_INET:
290 return ((const struct sockaddr_in*) sa)->sin_addr.s_addr == INADDR_LOOPBACK;
292 #ifdef HAVE_IPV6
293 case AF_INET6:
294 return memcmp(&((const struct sockaddr_in6*) sa)->sin6_addr, &in6addr_loopback, sizeof(struct in6_addr)) == 0;
295 #endif
297 default:
298 return FALSE;
302 pa_bool_t pa_socket_is_local(int fd) {
304 union {
305 struct sockaddr_storage storage;
306 struct sockaddr sa;
307 struct sockaddr_in in;
308 #ifdef HAVE_IPV6
309 struct sockaddr_in6 in6;
310 #endif
311 #ifdef HAVE_SYS_UN_H
312 struct sockaddr_un un;
313 #endif
314 } sa;
315 socklen_t sa_len = sizeof(sa);
317 if (getpeername(fd, &sa.sa, &sa_len) < 0)
318 return FALSE;
320 return pa_socket_address_is_local(&sa.sa);