]>
code.delx.au - pulseaudio/blob - src/pulsecore/socket-util.c
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
33 #include <sys/types.h>
40 #ifdef HAVE_NETINET_IN_H
41 #include <netinet/in.h>
43 #ifdef HAVE_NETINET_IN_SYSTM_H
44 #include <netinet/in_systm.h>
46 #ifdef HAVE_NETINET_IP_H
47 #include <netinet/ip.h>
49 #ifdef HAVE_NETINET_TCP_H
50 #include <netinet/tcp.h>
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
) {
75 pa_assert_se(fstat(fd
, &st
) == 0);
77 if (S_ISSOCK(st
.st_mode
))
81 struct sockaddr_storage storage
;
83 struct sockaddr_in in
;
85 struct sockaddr_in6 in6
;
88 struct sockaddr_un un
;
91 socklen_t sa_len
= sizeof(sa
);
93 if (getpeername(fd
, &sa
.sa
, &sa_len
) >= 0) {
95 if (sa
.sa
.sa_family
== AF_INET
) {
96 uint32_t ip
= ntohl(sa
.in
.sin_addr
.s_addr
);
98 pa_snprintf(c
, l
, "TCP/IP client from %i.%i.%i.%i:%u",
103 ntohs(sa
.in
.sin_port
));
106 } else if (sa
.sa
.sa_family
== AF_INET6
) {
107 char buf
[INET6_ADDRSTRLEN
];
110 res
= inet_ntop(AF_INET6
, &sa
.in6
.sin6_addr
, buf
, sizeof(buf
));
112 pa_snprintf(c
, l
, "TCP/IP client from [%s]:%u", buf
, ntohs(sa
.in6
.sin6_port
));
117 } else if (sa
.sa
.sa_family
== AF_UNIX
) {
118 pa_snprintf(c
, l
, "UNIX socket client");
124 pa_snprintf(c
, l
, "Unknown network client");
128 else if (S_ISCHR(st
.st_mode
) && (fd
== 0 || fd
== 1)) {
129 pa_snprintf(c
, l
, "STDIN/STDOUT client");
132 #endif /* OS_IS_WIN32 */
134 pa_snprintf(c
, l
, "Unknown client");
137 void pa_make_socket_low_delay(int fd
) {
144 if (setsockopt(fd
, SOL_SOCKET
, SO_PRIORITY
, (const void *) &priority
, sizeof(priority
)) < 0)
145 pa_log_warn("SO_PRIORITY failed: %s", pa_cstrerror(errno
));
149 void pa_make_tcp_socket_low_delay(int fd
) {
152 pa_make_socket_low_delay(fd
);
154 #if defined(SOL_TCP) || defined(IPPROTO_TCP)
158 if (setsockopt(fd
, SOL_TCP
, TCP_NODELAY
, (const void *) &on
, sizeof(on
)) < 0)
160 if (setsockopt(fd
, IPPROTO_TCP
, TCP_NODELAY
, (const void *) &on
, sizeof(on
)) < 0)
162 pa_log_warn("TCP_NODELAY failed: %s", pa_cstrerror(errno
));
166 #if defined(IPTOS_LOWDELAY) && defined(IP_TOS) && (defined(SOL_IP) || defined(IPPROTO_IP))
168 int tos
= IPTOS_LOWDELAY
;
170 if (setsockopt(fd
, SOL_IP
, IP_TOS
, (const void *) &tos
, sizeof(tos
)) < 0)
172 if (setsockopt(fd
, IPPROTO_IP
, IP_TOS
, (const void *) &tos
, sizeof(tos
)) < 0)
174 pa_log_warn("IP_TOS failed: %s", pa_cstrerror(errno
));
179 void pa_make_udp_socket_low_delay(int fd
) {
182 pa_make_socket_low_delay(fd
);
184 #if defined(IPTOS_LOWDELAY) && defined(IP_TOS) && (defined(SOL_IP) || defined(IPPROTO_IP))
186 int tos
= IPTOS_LOWDELAY
;
188 if (setsockopt(fd
, SOL_IP
, IP_TOS
, (const void *) &tos
, sizeof(tos
)) < 0)
190 if (setsockopt(fd
, IPPROTO_IP
, IP_TOS
, (const void *) &tos
, sizeof(tos
)) < 0)
192 pa_log_warn("IP_TOS failed: %s", pa_cstrerror(errno
));
197 int pa_socket_set_rcvbuf(int fd
, size_t l
) {
202 if (setsockopt(fd
, SOL_SOCKET
, SO_RCVBUF
, (const void *) &bufsz
, sizeof(bufsz
)) < 0) {
203 pa_log_warn("SO_RCVBUF: %s", pa_cstrerror(errno
));
210 int pa_socket_set_sndbuf(int fd
, size_t l
) {
215 if (setsockopt(fd
, SOL_SOCKET
, SO_SNDBUF
, (const void *) &bufsz
, sizeof(bufsz
)) < 0) {
216 pa_log_warn("SO_SNDBUF: %s", pa_cstrerror(errno
));
225 int pa_unix_socket_is_stale(const char *fn
) {
226 struct sockaddr_un sa
;
227 int fd
= -1, ret
= -1;
231 if ((fd
= pa_socket_cloexec(PF_UNIX
, SOCK_STREAM
, 0)) < 0) {
232 pa_log("socket(): %s", pa_cstrerror(errno
));
236 sa
.sun_family
= AF_UNIX
;
237 strncpy(sa
.sun_path
, fn
, sizeof(sa
.sun_path
)-1);
238 sa
.sun_path
[sizeof(sa
.sun_path
) - 1] = 0;
240 if (connect(fd
, (struct sockaddr
*) &sa
, sizeof(sa
)) < 0) {
241 if (errno
== ECONNREFUSED
)
253 int pa_unix_socket_remove_stale(const char *fn
) {
258 if ((r
= pa_unix_socket_is_stale(fn
)) < 0)
259 return errno
!= ENOENT
? -1 : 0;
264 /* Yes, here is a race condition. But who cares? */
271 #else /* HAVE_SYS_UN_H */
273 int pa_unix_socket_is_stale(const char *fn
) {
277 int pa_unix_socket_remove_stale(const char *fn
) {
281 #endif /* HAVE_SYS_UN_H */
283 bool pa_socket_address_is_local(const struct sockaddr
*sa
) {
286 switch (sa
->sa_family
) {
291 return ((const struct sockaddr_in
*) sa
)->sin_addr
.s_addr
== INADDR_LOOPBACK
;
295 return memcmp(&((const struct sockaddr_in6
*) sa
)->sin6_addr
, &in6addr_loopback
, sizeof(struct in6_addr
)) == 0;
303 bool pa_socket_is_local(int fd
) {
306 struct sockaddr_storage storage
;
308 struct sockaddr_in in
;
310 struct sockaddr_in6 in6
;
313 struct sockaddr_un un
;
316 socklen_t sa_len
= sizeof(sa
);
318 if (getpeername(fd
, &sa
.sa
, &sa_len
) < 0)
321 return pa_socket_address_is_local(&sa
.sa
);