Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc
Commits
cf95d0f8
Commit
cf95d0f8
authored
Oct 27, 2006
by
Rémi Denis-Courmont
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
*Ahem*
parent
d31e1c2e
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
0 additions
and
846 deletions
+0
-846
modules/misc/network/network/Modules.am
modules/misc/network/network/Modules.am
+0
-2
modules/misc/network/network/ipv4.c
modules/misc/network/network/ipv4.c
+0
-459
modules/misc/network/network/ipv6.c
modules/misc/network/network/ipv6.c
+0
-385
No files found.
modules/misc/network/network/Modules.am
deleted
100644 → 0
View file @
d31e1c2e
SOURCES_ipv4 = ipv4.c
SOURCES_ipv6 = ipv6.c
modules/misc/network/network/ipv4.c
deleted
100644 → 0
View file @
d31e1c2e
/*****************************************************************************
* ipv4.c: IPv4 network abstraction layer
*****************************************************************************
* Copyright (C) 2001-2006 the VideoLAN team
* $Id$
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Mathias Kretschmer <mathias@research.att.com>
* Alexis de Lattre <alexis@via.ecp.fr>
* Rémi Denis-Courmont <rem # videolan.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <stdlib.h>
#include <string.h>
#include <vlc/vlc.h>
#include <errno.h>
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#if defined(WIN32) || defined(UNDER_CE)
# if defined(UNDER_CE) && defined(sockaddr_storage)
# undef sockaddr_storage
# endif
# include <winsock2.h>
# include <ws2tcpip.h>
# include <iphlpapi.h>
# define close closesocket
# if defined(UNDER_CE)
# undef IP_MULTICAST_TTL
# define IP_MULTICAST_TTL 3
# undef IP_ADD_MEMBERSHIP
# define IP_ADD_MEMBERSHIP 5
# endif
#else
# include <netdb.h>
/* hostent ... */
# include <sys/socket.h>
# include <netinet/in.h>
# ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
/* inet_ntoa(), inet_aton() */
# endif
#endif
#include "network.h"
#ifndef INADDR_ANY
# define INADDR_ANY 0x00000000
#endif
#ifndef INADDR_NONE
# define INADDR_NONE 0xFFFFFFFF
#endif
#ifndef IN_MULTICAST
# define IN_MULTICAST(a) IN_CLASSD(a)
#endif
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static
int
OpenUDP
(
vlc_object_t
*
);
/*****************************************************************************
* Module descriptor
*****************************************************************************/
vlc_module_begin
();
set_shortname
(
"IPv4"
);
set_description
(
_
(
"UDP/IPv4 network abstraction layer"
)
);
set_capability
(
"network"
,
50
);
set_category
(
CAT_INPUT
);
set_subcategory
(
SUBCAT_INPUT_GENERAL
);
set_callbacks
(
OpenUDP
,
NULL
);
vlc_module_end
();
/*****************************************************************************
* BuildAddr: utility function to build a struct sockaddr_in
*****************************************************************************/
static
int
BuildAddr
(
vlc_object_t
*
p_obj
,
struct
sockaddr_in
*
p_socket
,
const
char
*
psz_address
,
int
i_port
)
{
struct
addrinfo
hints
,
*
res
;
int
i_val
;
memset
(
&
hints
,
0
,
sizeof
(
hints
)
);
hints
.
ai_family
=
AF_INET
;
hints
.
ai_socktype
=
SOCK_DGRAM
;
hints
.
ai_flags
=
AI_PASSIVE
;
msg_Dbg
(
p_obj
,
"resolving %s:%d..."
,
psz_address
,
i_port
);
i_val
=
vlc_getaddrinfo
(
p_obj
,
psz_address
,
i_port
,
&
hints
,
&
res
);
if
(
i_val
)
{
msg_Warn
(
p_obj
,
"%s: %s"
,
psz_address
,
vlc_gai_strerror
(
i_val
)
);
return
-
1
;
}
/* Copy the first address of the host in the socket address */
memcpy
(
p_socket
,
res
->
ai_addr
,
sizeof
(
*
p_socket
)
);
vlc_freeaddrinfo
(
res
);
return
(
0
);
}
#if defined(WIN32) || defined(UNDER_CE)
# define WINSOCK_STRERROR_SIZE 20
static
const
char
*
winsock_strerror
(
char
*
buf
)
{
snprintf
(
buf
,
WINSOCK_STRERROR_SIZE
,
"Winsock error %d"
,
WSAGetLastError
(
)
);
buf
[
WINSOCK_STRERROR_SIZE
-
1
]
=
'\0'
;
return
buf
;
}
#endif
/*****************************************************************************
* OpenUDP: open a UDP socket
*****************************************************************************
* psz_bind_addr, i_bind_port : address and port used for the bind()
* system call. If psz_bind_addr == "", the socket is bound to
* INADDR_ANY and broadcast reception is enabled. If psz_bind_addr is a
* multicast (class D) address, join the multicast group.
* psz_server_addr, i_server_port : address and port used for the connect()
* system call. It can avoid receiving packets from unauthorized IPs.
* Its use leads to great confusion and is currently discouraged.
* This function returns -1 in case of error.
*****************************************************************************/
static
int
OpenUDP
(
vlc_object_t
*
p_this
)
{
network_socket_t
*
p_socket
=
p_this
->
p_private
;
const
char
*
psz_bind_addr
=
p_socket
->
psz_bind_addr
;
int
i_bind_port
=
p_socket
->
i_bind_port
;
const
char
*
psz_server_addr
=
p_socket
->
psz_server_addr
;
int
i_server_port
=
p_socket
->
i_server_port
;
int
i_handle
,
i_opt
;
struct
sockaddr_in
sock
;
vlc_value_t
val
;
#if defined(WIN32) || defined(UNDER_CE)
char
strerror_buf
[
WINSOCK_STRERROR_SIZE
];
# define strerror( x ) winsock_strerror( strerror_buf )
#endif
/* Build the local socket */
if
(
BuildAddr
(
p_this
,
&
sock
,
psz_bind_addr
,
i_bind_port
)
==
-
1
)
{
msg_Dbg
(
p_this
,
"could not build local address"
);
return
0
;
}
p_socket
->
i_handle
=
-
1
;
/* Open a SOCK_DGRAM (UDP) socket, in the AF_INET domain, automatic (0)
* protocol */
if
(
(
i_handle
=
socket
(
AF_INET
,
SOCK_DGRAM
,
0
))
==
-
1
)
{
msg_Err
(
p_this
,
"cannot create socket (%s)"
,
strerror
(
errno
)
);
return
0
;
}
/* We may want to reuse an already used socket */
setsockopt
(
i_handle
,
SOL_SOCKET
,
SO_REUSEADDR
,
&
(
int
){
1
},
sizeof
(
int
)
);
#ifdef SO_REUSEPORT
setsockopt
(
i_handle
,
SOL_SOCKET
,
SO_REUSEPORT
,
&
(
int
){
1
},
sizeof
(
int
)
);
#endif
/* Increase the receive buffer size to 1/2MB (8Mb/s during 1/2s) to avoid
* packet loss caused by scheduling problems */
#ifdef SO_RCVBUF
i_opt
=
0x80000
;
if
(
setsockopt
(
i_handle
,
SOL_SOCKET
,
SO_RCVBUF
,
(
void
*
)
&
i_opt
,
sizeof
(
i_opt
)
)
==
-
1
)
msg_Dbg
(
p_this
,
"cannot configure socket (SO_RCVBUF: %s)"
,
strerror
(
errno
));
i_opt
=
0x80000
;
if
(
setsockopt
(
i_handle
,
SOL_SOCKET
,
SO_SNDBUF
,
(
void
*
)
&
i_opt
,
sizeof
(
i_opt
)
)
==
-
1
)
msg_Dbg
(
p_this
,
"cannot configure socket (SO_SNDBUF: %s)"
,
strerror
(
errno
));
#endif
#if defined( WIN32 ) || defined( UNDER_CE )
/*
* Under Win32 and for multicasting, we bind to INADDR_ANY.
* This is of course a severe bug, since the socket would logically
* receive unicast traffic, and multicast traffic of groups subscribed
* to via other sockets. How this actually works in Winsock, I don't
* know.
*/
if
(
IN_MULTICAST
(
ntohl
(
sock
.
sin_addr
.
s_addr
)
)
)
{
struct
sockaddr_in
stupid
=
sock
;
stupid
.
sin_addr
.
s_addr
=
INADDR_ANY
;
if
(
bind
(
i_handle
,
(
struct
sockaddr
*
)
&
stupid
,
sizeof
(
stupid
)
)
<
0
)
{
msg_Warn
(
p_this
,
"cannot bind socket (%d)"
,
WSAGetLastError
()
);
close
(
i_handle
);
return
0
;
}
}
else
#endif
/* Bind it */
if
(
bind
(
i_handle
,
(
struct
sockaddr
*
)
&
sock
,
sizeof
(
sock
)
)
<
0
)
{
msg_Warn
(
p_this
,
"cannot bind socket (%s)"
,
strerror
(
errno
)
);
close
(
i_handle
);
return
0
;
}
#if !defined( SYS_BEOS )
/* Allow broadcast reception if we bound on INADDR_ANY */
if
(
!*
psz_bind_addr
)
{
i_opt
=
1
;
if
(
setsockopt
(
i_handle
,
SOL_SOCKET
,
SO_BROADCAST
,
(
void
*
)
&
i_opt
,
sizeof
(
i_opt
)
)
==
-
1
)
msg_Warn
(
p_this
,
"cannot configure socket (SO_BROADCAST: %s)"
,
strerror
(
errno
)
);
}
#endif
#if !defined( SYS_BEOS )
/* Join the multicast group if the socket is a multicast address */
if
(
IN_MULTICAST
(
ntohl
(
sock
.
sin_addr
.
s_addr
)
)
)
{
/* Determine interface to be used for multicast */
char
*
psz_if_addr
=
config_GetPsz
(
p_this
,
"miface-addr"
);
#ifdef IP_ADD_SOURCE_MEMBERSHIP
/* If we have a source address, we use IP_ADD_SOURCE_MEMBERSHIP
so that IGMPv3 aware OSes running on IGMPv3 aware networks
will do an IGMPv3 query on the network */
if
(
*
psz_server_addr
)
{
struct
ip_mreq_source
imr
;
imr
.
imr_multiaddr
.
s_addr
=
sock
.
sin_addr
.
s_addr
;
imr
.
imr_sourceaddr
.
s_addr
=
inet_addr
(
psz_server_addr
);
if
(
psz_if_addr
!=
NULL
&&
*
psz_if_addr
&&
inet_addr
(
psz_if_addr
)
!=
INADDR_NONE
)
imr
.
imr_interface
.
s_addr
=
inet_addr
(
psz_if_addr
);
else
imr
.
imr_interface
.
s_addr
=
INADDR_ANY
;
if
(
psz_if_addr
!=
NULL
)
free
(
psz_if_addr
);
/* Join Multicast group with source filter */
if
(
setsockopt
(
i_handle
,
IPPROTO_IP
,
IP_ADD_SOURCE_MEMBERSHIP
,
(
char
*
)
&
imr
,
sizeof
(
struct
ip_mreq_source
)
)
==
-
1
)
{
msg_Warn
(
p_this
,
"Source specific multicast failed (%s) -"
"falling back to non-specific mode"
,
strerror
(
errno
)
);
goto
igmpv2
;
}
}
/* If there is no source address, we use IP_ADD_MEMBERSHIP */
else
#endif
{
struct
ip_mreq
imr
;
igmpv2:
imr
.
imr_interface
.
s_addr
=
INADDR_ANY
;
imr
.
imr_multiaddr
.
s_addr
=
sock
.
sin_addr
.
s_addr
;
if
(
psz_if_addr
!=
NULL
&&
*
psz_if_addr
&&
inet_addr
(
psz_if_addr
)
!=
INADDR_NONE
)
{
imr
.
imr_interface
.
s_addr
=
inet_addr
(
psz_if_addr
);
}
#if defined (WIN32) || defined (UNDER_CE)
else
{
typedef
DWORD
(
CALLBACK
*
GETBESTINTERFACE
)
(
IPAddr
,
PDWORD
);
typedef
DWORD
(
CALLBACK
*
GETIPADDRTABLE
)
(
PMIB_IPADDRTABLE
,
PULONG
,
BOOL
);
GETBESTINTERFACE
OurGetBestInterface
;
GETIPADDRTABLE
OurGetIpAddrTable
;
HINSTANCE
hiphlpapi
=
LoadLibrary
(
_T
(
"Iphlpapi.dll"
));
DWORD
i_index
;
if
(
hiphlpapi
)
{
OurGetBestInterface
=
(
void
*
)
GetProcAddress
(
hiphlpapi
,
_T
(
"GetBestInterface"
)
);
OurGetIpAddrTable
=
(
void
*
)
GetProcAddress
(
hiphlpapi
,
_T
(
"GetIpAddrTable"
)
);
}
if
(
hiphlpapi
&&
OurGetBestInterface
&&
OurGetIpAddrTable
&&
OurGetBestInterface
(
sock
.
sin_addr
.
s_addr
,
&
i_index
)
==
NO_ERROR
)
{
PMIB_IPADDRTABLE
p_table
;
DWORD
i
=
0
;
msg_Dbg
(
p_this
,
"Winsock best interface is %lu"
,
(
unsigned
long
)
i_index
);
OurGetIpAddrTable
(
NULL
,
&
i
,
0
);
p_table
=
(
PMIB_IPADDRTABLE
)
malloc
(
i
);
if
(
p_table
!=
NULL
)
{
if
(
OurGetIpAddrTable
(
p_table
,
&
i
,
0
)
==
NO_ERROR
)
{
for
(
i
=
0
;
i
<
p_table
->
dwNumEntries
;
i
--
)
{
if
(
p_table
->
table
[
i
].
dwIndex
==
i_index
)
{
imr
.
imr_interface
.
s_addr
=
p_table
->
table
[
i
].
dwAddr
;
msg_Dbg
(
p_this
,
"using interface 0x%08x"
,
p_table
->
table
[
i
].
dwAddr
);
}
}
}
else
msg_Warn
(
p_this
,
"GetIpAddrTable failed"
);
free
(
p_table
);
}
}
else
msg_Dbg
(
p_this
,
"GetBestInterface failed"
);
if
(
hiphlpapi
)
FreeLibrary
(
hiphlpapi
);
}
#endif
if
(
psz_if_addr
!=
NULL
)
free
(
psz_if_addr
);
msg_Dbg
(
p_this
,
"IP_ADD_MEMBERSHIP multicast request"
);
/* Join Multicast group without source filter */
if
(
setsockopt
(
i_handle
,
IPPROTO_IP
,
IP_ADD_MEMBERSHIP
,
(
char
*
)
&
imr
,
sizeof
(
struct
ip_mreq
)
)
==
-
1
)
{
msg_Err
(
p_this
,
"failed to join IP multicast group (%s)"
,
strerror
(
errno
)
);
close
(
i_handle
);
return
0
;
}
}
}
else
#endif
if
(
*
psz_server_addr
)
{
/* Build socket for remote connection */
if
(
BuildAddr
(
p_this
,
&
sock
,
psz_server_addr
,
i_server_port
)
==
-
1
)
{
msg_Warn
(
p_this
,
"cannot build remote address"
);
close
(
i_handle
);
return
0
;
}
/* Connect the socket */
if
(
connect
(
i_handle
,
(
struct
sockaddr
*
)
&
sock
,
sizeof
(
sock
)
)
==
(
-
1
)
)
{
msg_Warn
(
p_this
,
"cannot connect socket (%s)"
,
strerror
(
errno
)
);
close
(
i_handle
);
return
0
;
}
#if !defined( SYS_BEOS )
if
(
IN_MULTICAST
(
ntohl
(
inet_addr
(
psz_server_addr
)
)
)
)
{
/* set the time-to-live */
int
i_ttl
=
p_socket
->
i_ttl
;
/* set the multicast interface */
char
*
psz_mif_addr
=
config_GetPsz
(
p_this
,
"miface-addr"
);
if
(
psz_mif_addr
)
{
struct
in_addr
intf
;
intf
.
s_addr
=
inet_addr
(
psz_mif_addr
);
free
(
psz_mif_addr
);
if
(
setsockopt
(
i_handle
,
IPPROTO_IP
,
IP_MULTICAST_IF
,
&
intf
,
sizeof
(
intf
)
)
<
0
)
{
msg_Dbg
(
p_this
,
"failed to set multicast interface (%s)."
,
strerror
(
errno
)
);
close
(
i_handle
);
return
0
;
}
}
if
(
i_ttl
<=
0
)
i_ttl
=
config_GetInt
(
p_this
,
"ttl"
);
if
(
i_ttl
>
0
)
{
unsigned
char
ttl
=
(
unsigned
char
)
i_ttl
;
/* There is some confusion in the world whether IP_MULTICAST_TTL
* takes a byte or an int as an argument.
* BSD seems to indicate byte so we are going with that and use
* int as a fallback to be safe */
if
(
setsockopt
(
i_handle
,
IPPROTO_IP
,
IP_MULTICAST_TTL
,
&
ttl
,
sizeof
(
ttl
)
)
<
0
)
{
msg_Dbg
(
p_this
,
"failed to set ttl (%s). Let's try it "
"the integer way."
,
strerror
(
errno
)
);
if
(
setsockopt
(
i_handle
,
IPPROTO_IP
,
IP_MULTICAST_TTL
,
&
i_ttl
,
sizeof
(
i_ttl
)
)
<
0
)
{
msg_Err
(
p_this
,
"failed to set ttl (%s)"
,
strerror
(
errno
)
);
close
(
i_handle
);
return
0
;
}
}
}
}
#endif
}
p_socket
->
i_handle
=
i_handle
;
if
(
var_Get
(
p_this
,
"mtu"
,
&
val
)
!=
VLC_SUCCESS
)
{
var_Create
(
p_this
,
"mtu"
,
VLC_VAR_INTEGER
|
VLC_VAR_DOINHERIT
);
var_Get
(
p_this
,
"mtu"
,
&
val
);
}
p_socket
->
i_mtu
=
val
.
i_int
;
return
0
;
}
modules/misc/network/network/ipv6.c
deleted
100644 → 0
View file @
d31e1c2e
/*****************************************************************************
* ipv6.c: IPv6 network abstraction layer
*****************************************************************************
* Copyright (C) 2002-2006 the VideoLAN team
* $Id$
*
* Authors: Alexis Guillard <alexis.guillard@bt.com>
* Christophe Massiot <massiot@via.ecp.fr>
* Remco Poortinga <poortinga@telin.nl>
* Rémi Denis-Courmont <rem # videolan.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <stdlib.h>
#include <string.h>
#include <vlc/vlc.h>
#include <errno.h>
#ifdef WIN32
# include <winsock2.h>
# include <ws2tcpip.h>
# define if_nametoindex( str ) atoi( str )
#else
# include <sys/types.h>
# include <unistd.h>
# include <netdb.h>
/* hostent ... */
# include <sys/socket.h>
# include <netinet/in.h>
# include <net/if.h>
#endif
#include "network.h"
#if defined(WIN32)
static
const
struct
in6_addr
in6addr_any
=
{{
IN6ADDR_ANY_INIT
}};
# define close closesocket
#endif
#ifndef MCAST_JOIN_SOURCE_GROUP
# ifdef WIN32
/* Most (all?) Mingw32 versions in use are yet to pick up Vista stuff */
# define MCAST_JOIN_SOURCE_GROUP 45
/* from <ws2ipdef.h> */
# else
# define MCAST_JOIN_SOURCE_GROUP 46
# endif
struct
group_source_req
{
uint32_t
gsr_interface
;
/* interface index */
struct
sockaddr_storage
gsr_group
;
/* group address */
struct
sockaddr_storage
gsr_source
;
/* source address */
};
#endif
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static
int
OpenUDP
(
vlc_object_t
*
);
/*****************************************************************************
* Module descriptor
*****************************************************************************/
vlc_module_begin
();
set_description
(
_
(
"UDP/IPv6 network abstraction layer"
)
);
set_capability
(
"network"
,
40
);
set_callbacks
(
OpenUDP
,
NULL
);
vlc_module_end
();
/*****************************************************************************
* BuildAddr: utility function to build a struct sockaddr_in6
*****************************************************************************/
static
int
BuildAddr
(
vlc_object_t
*
p_this
,
struct
sockaddr_in6
*
p_socket
,
const
char
*
psz_address
,
int
i_port
)
{
struct
addrinfo
hints
,
*
res
;
int
i
;
memset
(
&
hints
,
0
,
sizeof
(
hints
)
);
hints
.
ai_family
=
AF_INET6
;
hints
.
ai_socktype
=
SOCK_DGRAM
;
hints
.
ai_flags
=
AI_PASSIVE
;
i
=
vlc_getaddrinfo
(
p_this
,
psz_address
,
0
,
&
hints
,
&
res
);
if
(
i
)
{
msg_Dbg
(
p_this
,
"%s: %s"
,
psz_address
,
vlc_gai_strerror
(
i
)
);
return
-
1
;
}
if
(
res
->
ai_addrlen
>
sizeof
(
struct
sockaddr_in6
)
)
{
vlc_freeaddrinfo
(
res
);
return
-
1
;
}
memcpy
(
p_socket
,
res
->
ai_addr
,
res
->
ai_addrlen
);
vlc_freeaddrinfo
(
res
);
p_socket
->
sin6_port
=
htons
(
i_port
);
return
0
;
}
#if defined(WIN32) || defined(UNDER_CE)
# define WINSOCK_STRERROR_SIZE 20
static
const
char
*
winsock_strerror
(
char
*
buf
)
{
snprintf
(
buf
,
WINSOCK_STRERROR_SIZE
,
"Winsock error %d"
,
WSAGetLastError
(
)
);
buf
[
WINSOCK_STRERROR_SIZE
-
1
]
=
'\0'
;
return
buf
;
}
#endif
/*****************************************************************************
* OpenUDP: open a UDP socket
*****************************************************************************
* psz_bind_addr, i_bind_port : address and port used for the bind()
* system call. If psz_bind_addr == NULL, the socket is bound to
* in6addr_any and broadcast reception is enabled. If psz_bind_addr is a
* multicast (FF00::/8) address, join the multicast group.
* psz_server_addr, i_server_port : address and port used for the connect()
* system call. It can avoid receiving packets from unauthorized IPs.
* Its use leads to great confusion and is currently discouraged.
* This function returns -1 in case of error.
*****************************************************************************/
static
int
OpenUDP
(
vlc_object_t
*
p_this
)
{
network_socket_t
*
p_socket
=
p_this
->
p_private
;
const
char
*
psz_bind_addr
=
p_socket
->
psz_bind_addr
;
int
i_bind_port
=
p_socket
->
i_bind_port
;
const
char
*
psz_server_addr
=
p_socket
->
psz_server_addr
;
int
i_server_port
=
p_socket
->
i_server_port
;
int
i_handle
,
i_opt
;
struct
sockaddr_in6
sock
;
vlc_value_t
val
;
#if defined(WIN32) || defined(UNDER_CE)
char
strerror_buf
[
WINSOCK_STRERROR_SIZE
];
# define strerror( x ) winsock_strerror( strerror_buf )
#endif
p_socket
->
i_handle
=
-
1
;
/* Build the local socket */
if
(
BuildAddr
(
p_this
,
&
sock
,
psz_bind_addr
,
i_bind_port
)
==
-
1
)
return
0
;
/* Open a SOCK_DGRAM (UDP) socket, in the AF_INET6 domain, automatic (0)
* protocol */
if
(
(
i_handle
=
socket
(
AF_INET6
,
SOCK_DGRAM
,
0
))
==
-
1
)
{
msg_Warn
(
p_this
,
"cannot create socket (%s)"
,
strerror
(
errno
)
);
return
0
;
}
#ifdef IPV6_V6ONLY
val
.
i_int
=
p_socket
->
v6only
;
if
(
setsockopt
(
i_handle
,
IPPROTO_IPV6
,
IPV6_V6ONLY
,
(
void
*
)
&
val
.
i_int
,
sizeof
(
val
.
i_int
)
)
)
{
msg_Warn
(
p_this
,
"IPV6_V6ONLY: %s"
,
strerror
(
errno
)
);
p_socket
->
v6only
=
1
;
}
#else
p_socket
->
v6only
=
1
;
#endif
#ifdef WIN32
# ifndef IPV6_PROTECTION_LEVEL
# define IPV6_PROTECTION_LEVEL 23
# endif
{
int
i_val
=
30
/*PROTECTION_LEVEL_UNRESTRICTED*/
;
setsockopt
(
i_handle
,
IPPROTO_IPV6
,
IPV6_PROTECTION_LEVEL
,
&
i_val
,
sizeof
(
i_val
)
);
}
#endif
/* We may want to reuse an already used socket */
i_opt
=
1
;
if
(
setsockopt
(
i_handle
,
SOL_SOCKET
,
SO_REUSEADDR
,
(
void
*
)
&
i_opt
,
sizeof
(
i_opt
)
)
==
-
1
)
{
msg_Warn
(
p_this
,
"cannot configure socket (SO_REUSEADDR: %s)"
,
strerror
(
errno
)
);
close
(
i_handle
);
return
0
;
}
/* Increase the receive buffer size to 1/2MB (8Mb/s during 1/2s) to avoid
* packet loss caused by scheduling problems */
i_opt
=
0x80000
;
if
(
setsockopt
(
i_handle
,
SOL_SOCKET
,
SO_RCVBUF
,
(
void
*
)
&
i_opt
,
sizeof
(
i_opt
)
)
==
-
1
)
{
msg_Warn
(
p_this
,
"cannot configure socket (SO_RCVBUF: %s)"
,
strerror
(
errno
)
);
}
#if defined(WIN32)
/* Under Win32 and for multicasting, we bind to IN6ADDR_ANY */
if
(
IN6_IS_ADDR_MULTICAST
(
&
sock
.
sin6_addr
)
)
{
struct
sockaddr_in6
sockany
=
sock
;
sockany
.
sin6_addr
=
in6addr_any
;
sockany
.
sin6_scope_id
=
0
;
/* Bind it */
if
(
bind
(
i_handle
,
(
struct
sockaddr
*
)
&
sockany
,
sizeof
(
sock
)
)
<
0
)
{
msg_Warn
(
p_this
,
"cannot bind socket (%s)"
,
strerror
(
errno
)
);
close
(
i_handle
);
return
0
;
}
}
else
#endif
/* Bind it */
if
(
bind
(
i_handle
,
(
struct
sockaddr
*
)
&
sock
,
sizeof
(
sock
)
)
<
0
)
{
msg_Warn
(
p_this
,
"cannot bind socket (%s)"
,
strerror
(
errno
)
);
close
(
i_handle
);
return
0
;
}
/* Join the multicast group if the socket is a multicast address */
if
(
IN6_IS_ADDR_MULTICAST
(
&
sock
.
sin6_addr
)
)
{
if
(
*
psz_server_addr
)
{
struct
group_source_req
imr
;
struct
sockaddr_in6
*
p_sin6
;
imr
.
gsr_interface
=
0
;
imr
.
gsr_group
.
ss_family
=
AF_INET6
;
imr
.
gsr_source
.
ss_family
=
AF_INET6
;
p_sin6
=
(
struct
sockaddr_in6
*
)
&
imr
.
gsr_group
;
p_sin6
->
sin6_addr
=
sock
.
sin6_addr
;
/* Build socket for remote connection */
msg_Dbg
(
p_this
,
"psz_server_addr : %s"
,
psz_server_addr
);
if
(
BuildAddr
(
p_this
,
&
sock
,
psz_server_addr
,
i_server_port
)
)
{
msg_Warn
(
p_this
,
"cannot build remote address"
);
close
(
i_handle
);
return
0
;
}
p_sin6
=
(
struct
sockaddr_in6
*
)
&
imr
.
gsr_source
;
p_sin6
->
sin6_addr
=
sock
.
sin6_addr
;
msg_Dbg
(
p_this
,
"IPV6_ADD_SOURCE_MEMBERSHIP multicast request"
);
if
(
setsockopt
(
i_handle
,
IPPROTO_IPV6
,
MCAST_JOIN_SOURCE_GROUP
,
(
char
*
)
&
imr
,
sizeof
(
struct
group_source_req
)
)
==
-
1
)
{
msg_Err
(
p_this
,
"failed to join IP multicast group (%s)"
,
strerror
(
errno
)
);
}
}
else
{
struct
ipv6_mreq
imr
;
int
res
;
imr
.
ipv6mr_interface
=
sock
.
sin6_scope_id
;
imr
.
ipv6mr_multiaddr
=
sock
.
sin6_addr
;
res
=
setsockopt
(
i_handle
,
IPPROTO_IPV6
,
IPV6_JOIN_GROUP
,
(
void
*
)
&
imr
,
#if defined(WIN32)
sizeof
(
imr
)
+
4
);
/* Doesn't work without this */
#else
sizeof
(
imr
));
#endif
if
(
res
==
-
1
)
{
msg_Err
(
p_this
,
"cannot join multicast group"
);
}
}
}
else
if
(
*
psz_server_addr
)
{
int
ttl
;
/* Build socket for remote connection */
if
(
BuildAddr
(
p_this
,
&
sock
,
psz_server_addr
,
i_server_port
)
==
-
1
)
{
msg_Warn
(
p_this
,
"cannot build remote address"
);
close
(
i_handle
);
return
0
;
}
/* Connect the socket */
if
(
connect
(
i_handle
,
(
struct
sockaddr
*
)
&
sock
,
sizeof
(
sock
)
)
==
(
-
1
)
)
{
msg_Warn
(
p_this
,
"cannot connect socket (%s)"
,
strerror
(
errno
)
);
close
(
i_handle
);
return
0
;
}
/* Set the time-to-live */
ttl
=
p_socket
->
i_ttl
;
if
(
ttl
<=
0
)
ttl
=
config_GetInt
(
p_this
,
"ttl"
);
if
(
ttl
>
0
)
{
if
(
IN6_IS_ADDR_MULTICAST
(
&
sock
.
sin6_addr
)
)
{
if
(
setsockopt
(
i_handle
,
IPPROTO_IPV6
,
IPV6_MULTICAST_HOPS
,
(
void
*
)
&
ttl
,
sizeof
(
ttl
)
)
<
0
)
{
msg_Err
(
p_this
,
"failed to set multicast ttl (%s)"
,
strerror
(
errno
)
);
}
}
else
{
if
(
setsockopt
(
i_handle
,
IPPROTO_IPV6
,
IPV6_UNICAST_HOPS
,
(
void
*
)
&
ttl
,
sizeof
(
ttl
)
)
<
0
)
{
msg_Err
(
p_this
,
"failed to set unicast ttl (%s)"
,
strerror
(
errno
)
);
}
}
}
/* Set multicast output interface */
if
(
IN6_IS_ADDR_MULTICAST
(
&
sock
.
sin6_addr
)
)
{
char
*
psz_mif
=
config_GetPsz
(
p_this
,
"miface"
);
if
(
psz_mif
!=
NULL
)
{
int
intf
=
if_nametoindex
(
psz_mif
);
free
(
psz_mif
);
if
(
intf
!=
0
)
{
if
(
setsockopt
(
i_handle
,
IPPROTO_IPV6
,
IPV6_MULTICAST_IF
,
&
intf
,
sizeof
(
intf
)
)
<
0
)
{
msg_Err
(
p_this
,
"%s as multicast interface: %s"
,
psz_mif
,
strerror
(
errno
)
);
close
(
i_handle
);
return
0
;
}
}
else
{
msg_Err
(
p_this
,
"%s: bad IPv6 interface specification"
,
psz_mif
);
close
(
i_handle
);
return
0
;
}
}
}
}
p_socket
->
i_handle
=
i_handle
;
var_Create
(
p_this
,
"mtu"
,
VLC_VAR_INTEGER
|
VLC_VAR_DOINHERIT
);
var_Get
(
p_this
,
"mtu"
,
&
val
);
p_socket
->
i_mtu
=
val
.
i_int
;
return
0
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment