1 /*****************************************************************************
2 * io.c: network I/O functions
3 *****************************************************************************
4 * Copyright (C) 2004-2005, 2007 VLC authors and VideoLAN
5 * Copyright © 2005-2006 Rémi Denis-Courmont
8 * Authors: Laurent Aimar <fenrir@videolan.org>
9 * Rémi Denis-Courmont <rem # videolan.org>
10 * Christophe Mutricy <xtophe at videolan dot org>
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU Lesser General Public License as published by
14 * the Free Software Foundation; either version 2.1 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public License
23 * along with this program; if not, write to the Free Software Foundation,
24 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25 *****************************************************************************/
27 /*****************************************************************************
29 *****************************************************************************/
42 #ifdef HAVE_LINUX_DCCP_H
43 /* TODO: use glibc instead of linux-kernel headers */
44 # include <linux/dccp.h>
48 #include <vlc_common.h>
49 #include <vlc_network.h>
50 #include <vlc_interrupt.h>
52 extern int rootwrap_bind (int family
, int socktype
, int protocol
,
53 const struct sockaddr
*addr
, size_t alen
);
55 int net_Socket (vlc_object_t
*p_this
, int family
, int socktype
,
58 int fd
= vlc_socket (family
, socktype
, protocol
, true);
61 if (net_errno
!= EAFNOSUPPORT
)
62 msg_Err (p_this
, "cannot create socket: %s",
63 vlc_strerror_c(net_errno
));
67 setsockopt (fd
, SOL_SOCKET
, SO_REUSEADDR
, &(int){ 1 }, sizeof (int));
71 * Accepts only IPv6 connections on IPv6 sockets.
72 * If possible, we should open two sockets, but it is not always possible.
74 if (family
== AF_INET6
)
75 setsockopt (fd
, IPPROTO_IPV6
, IPV6_V6ONLY
, &(int){ 1 }, sizeof (int));
79 # ifndef IPV6_PROTECTION_LEVEL
80 # warning Please update your C library headers.
81 # define IPV6_PROTECTION_LEVEL 23
82 # define PROTECTION_LEVEL_UNRESTRICTED 10
84 if (family
== AF_INET6
)
85 setsockopt (fd
, IPPROTO_IPV6
, IPV6_PROTECTION_LEVEL
,
86 &(int){ PROTECTION_LEVEL_UNRESTRICTED
}, sizeof (int));
89 #ifdef DCCP_SOCKOPT_SERVICE
90 if (socktype
== SOL_DCCP
)
92 char *dccps
= var_InheritString (p_this
, "dccp-service");
95 setsockopt (fd
, SOL_DCCP
, DCCP_SOCKOPT_SERVICE
, dccps
,
96 (strlen (dccps
) + 3) & ~3);
106 int *net_Listen (vlc_object_t
*p_this
, const char *psz_host
,
107 int i_port
, int type
, int protocol
)
109 struct addrinfo hints
= {
111 .ai_protocol
= protocol
,
112 .ai_flags
= AI_PASSIVE
| AI_NUMERICSERV
| AI_IDN
,
115 msg_Dbg (p_this
, "net: listening to %s port %d",
116 (psz_host
!= NULL
) ? psz_host
: "*", i_port
);
118 int i_val
= vlc_getaddrinfo (psz_host
, i_port
, &hints
, &res
);
121 msg_Err (p_this
, "Cannot resolve %s port %d : %s",
122 (psz_host
!= NULL
) ? psz_host
: "", i_port
,
123 gai_strerror (i_val
));
130 for (struct addrinfo
*ptr
= res
; ptr
!= NULL
; ptr
= ptr
->ai_next
)
132 int fd
= net_Socket (p_this
, ptr
->ai_family
, ptr
->ai_socktype
,
136 msg_Dbg (p_this
, "socket error: %s", vlc_strerror_c(net_errno
));
140 /* Bind the socket */
143 * Under Win32 and for multicasting, we bind to INADDR_ANY.
144 * This is of course a severe bug, since the socket would logically
145 * receive unicast traffic, and multicast traffic of groups subscribed
146 * to via other sockets.
148 if (net_SockAddrIsMulticast (ptr
->ai_addr
, ptr
->ai_addrlen
)
149 && (sizeof (struct sockaddr_storage
) >= ptr
->ai_addrlen
))
151 // This works for IPv4 too - don't worry!
152 struct sockaddr_in6 dumb
=
154 .sin6_family
= ptr
->ai_addr
->sa_family
,
155 .sin6_port
= ((struct sockaddr_in
*)(ptr
->ai_addr
))->sin_port
158 bind (fd
, (struct sockaddr
*)&dumb
, ptr
->ai_addrlen
);
162 if (bind (fd
, ptr
->ai_addr
, ptr
->ai_addrlen
))
167 fd
= rootwrap_bind (ptr
->ai_family
, ptr
->ai_socktype
,
169 ptr
->ai_addr
, ptr
->ai_addrlen
);
172 msg_Dbg (p_this
, "got socket %d from rootwrap", fd
);
177 msg_Err (p_this
, "socket bind error: %s", vlc_strerror_c(err
));
182 if (net_SockAddrIsMulticast (ptr
->ai_addr
, ptr
->ai_addrlen
))
184 if (net_Subscribe (p_this
, fd
, ptr
->ai_addr
, ptr
->ai_addrlen
))
192 switch (ptr
->ai_socktype
)
200 if (listen (fd
, INT_MAX
))
202 msg_Err (p_this
, "socket listen error: %s",
203 vlc_strerror_c(net_errno
));
209 int *nsockv
= (int *)realloc (sockv
, (sockc
+ 2) * sizeof (int));
212 nsockv
[sockc
++] = fd
;
228 * Reads data from a socket, blocking until all requested data is received or
229 * the end of the stream is reached.
230 * This function is a cancellation point.
231 * @return -1 on error, or the number of bytes of read.
233 ssize_t (net_Read
)(vlc_object_t
*restrict obj
, int fd
,
234 void *restrict buf
, size_t len
)
247 ssize_t val
= vlc_recv_i11e(fd
, buf
, len
, 0);
250 if (errno
== EINTR
|| errno
== EAGAIN
)
253 else if (WSAGetLastError() == WSAEMSGSIZE
) /* datagram too big */
255 msg_Warn(obj
, "read truncated to %zu bytes", len
);
261 msg_Err(obj
, "read error: %s", vlc_strerror_c(errno
));
262 return rd
? (ssize_t
)rd
: -1;
271 assert(len
>= (size_t)val
);
273 buf
= ((char *)buf
) + val
;
281 * Writes data to a socket.
282 * This blocks until all data is written or an error occurs.
284 * This function is a cancellation point.
286 * @return the total number of bytes written, or -1 if an error occurs
287 * before any data is written.
289 ssize_t (net_Write
)(vlc_object_t
*obj
, int fd
, const void *buf
, size_t len
)
302 ssize_t val
= vlc_send_i11e (fd
, buf
, len
, MSG_NOSIGNAL
);
305 if (errno
== EINTR
|| errno
== EAGAIN
)
308 msg_Err(obj
, "write error: %s", vlc_strerror_c(errno
));
309 return written
? (ssize_t
)written
: -1;
316 assert(len
>= (size_t)val
);
318 buf
= ((const char *)buf
) + val
;
327 * Reads a line from a file descriptor.
328 * This function is not thread-safe; the same file descriptor I/O cannot be
329 * read by another thread at the same time (although it can be written to).
331 * @note This only works with stream-oriented file descriptors, not with
332 * datagram or packet-oriented ones.
334 * @return nul-terminated heap-allocated string, or NULL on I/O error.
336 char *net_Gets(vlc_object_t
*obj
, int fd
)
339 size_t size
= 0, len
= 0;
345 if (unlikely(size
>= (1 << 16)))
348 goto error
; /* put sane buffer size limit */
351 char *newbuf
= realloc(buf
, size
+ 1024);
352 if (unlikely(newbuf
== NULL
))
359 ssize_t val
= vlc_recv_i11e(fd
, buf
+ len
, size
- len
, MSG_PEEK
);
363 char *end
= memchr(buf
+ len
, '\n', val
);
365 val
= (end
+ 1) - (buf
+ len
);
366 if (recv(fd
, buf
+ len
, val
, 0) != val
)
375 if (len
> 0 && buf
[--len
] == '\r')
379 msg_Err(obj
, "read error: %s", vlc_strerror_c(errno
));
385 ssize_t
net_Printf( vlc_object_t
*p_this
, int fd
, const char *psz_fmt
, ... )
389 va_start( args
, psz_fmt
);
390 i_ret
= net_vaPrintf( p_this
, fd
, psz_fmt
, args
);
397 ssize_t
net_vaPrintf( vlc_object_t
*p_this
, int fd
,
398 const char *psz_fmt
, va_list args
)
403 int i_size
= vasprintf( &psz
, psz_fmt
, args
);
406 i_ret
= net_Write( p_this
, fd
, psz
, i_size
) < i_size