2005-12-05 10:36:39 +01:00
|
|
|
/*****************************************************************************
|
|
|
|
* udp.c:
|
|
|
|
*****************************************************************************
|
LGPL
Re-license almost all of libVLC and libVLCcore to LGPLv2.1+
This move was authorized by the developers, either:
- by e-mail,
- by vote at the VideoLAN Dev Days 2011,
- on the license website,
- in a contract, oral or written.
No objection was raised, so far.
The developers agreeing are:
Justus Piater
Alexis Ballier
Alexander Bethke
Mohammed Adnène Trojette
Alex Converse
Alexey Sokolov
Alexis de Lattre
Andre Pang
Anthony Loiseau
Cyril Deguet
André Weber
Boris Dorès
Brieuc Jeunhomme
Benjamin Drung
Hugo Beauzée-Luyssen
Benoit Steiner
Benjamin Pracht
Bernie Purcell
Przemyslaw Fiala
Arnaud de Bossoreille de Ribou
Brad Smith
Nick Briggs
Christopher Rath
Christophe Courtaut
Christopher Mueller
Clement Chesnin
Andres Krapf
Damien Fouilleul
David Flynn
Sebastien Zwickert
Antoine Cellerier
Jérôme Decoodt
Jérome Decoodt
Dylan Yudaken
Eduard Babayan
Eugenio Jarosiewicz
Elliot Murphy
Eric Petit
Erwan Tulou
Etienne Membrives
Ludovic Fauvet
Fabio Ritrovato
Tobias Güntner
Jakub Wieczorek
Frédéric Crozat
Francois Cartegnie
Laurent Aimar
Florian G. Pflug
Felix Paul Kühne
Frank Enderle
Rafaël Carré
Simon Latapie
Gildas Bazin
Geoffroy Couprie
Julien / Gellule
Gildas Bazin
Arnaud Schauly
Toralf Niebuhr
Vicente Jimenez Aguilar
Derk-Jan Hartman
Henri Fallon
Ilkka Ollakka
Olivier Teulière
Rémi Duraffort
Jakob Leben
Jean-Baptiste Kempf
Jean-Paul Saman
Jean-Philippe Grimaldi
Jean-François Massol
Gaël Hendryckx
Jakob Leben
Jean-Marc Dressler
Jai Menon
Johan Bilien
Johann Ransay
Joris van Rooij
JP Dinger
Jean-Philippe André
Adrien Grand
Juha Jeronen
Juho Vähä-Herttua
Kaarlo Raiha
Kaarlo Raiha
Kamil Baldyga
Keary Griffin
Ken Self
KO Myung-Hun
Pierre Ynard
Filippo Carone
Loïc Minier
Luca Barbato
Lucas C. Villa Real
Lukas Durfina
Adrien Maglo
Marc Ariberti
Mark Lee
Mark Moriarty
Martin Storsjö
Christophe Massiot
Michel Kaempf
Marian Ďurkovič
Mirsal Ennaime
Carlo Calabrò
Damien Lucas
Naohiro Koriyama
Basos G
Pierre Baillet
Vincent Penquerc'h
Olivier Aubert
Pankaj Yadav
Paul Corke
Pierre d'Herbemont
Philippe Morin
Antoine Lejeune
Michael Ploujnikov
Jean-Marc Dressler
Michael Hanselmann
Rafaël Carré
Ramiro Polla
Rémi Denis-Courmont
Renaud Dartus
Richard Shepherd
Faustino Osuna
Arnaud Vallat
Rob Jonson
Robert Jedrzejczyk
Steve Lhomme
Rocky Bernstein
Romain Goyet
Rov Juvano
Sam Hocevar
Martin T. H. Sandsmark
Sebastian Birk
Sébastien Escudier
Vincent Seguin
Fabio Ritrovato
Sigmund Augdal Helberg
Casian Andrei
Srikanth Raju
Hannes Domani
Stéphane Borel
Stephan Krempel
Stephan Assmus
Tony Castley
Pavlov Konstantin
Eric Petit
Tanguy Krotoff
Dennis van Amerongen
Michel Lespinasse
Can Wu
Xavier Marchesini
Sébastien Toque
Christophe Mutricy
Yoann Peronneau
Yohann Martineau
Yuval Tze
Scott Caudle
Clément Stenac
It is possible, that some minor piece of code was badly tracked, for
some reasons (SVN, mainly) or that some small developers did not answer.
However, as an "œuvre collective", defined as in "CPI 113-2 alinéa 3",
and seeing "Cour. Cass. 17 Mai 1978", and seeing that the editor and
the very vast majority of developers have agreed (> 99.99% of the code,
> 99% of developers), we are fine here.
2011-11-27 21:44:15 +01:00
|
|
|
* Copyright (C) 2004-2006 VLC authors and VideoLAN
|
2007-04-15 10:20:45 +02:00
|
|
|
* Copyright © 2006-2007 Rémi Denis-Courmont
|
2006-09-07 21:49:30 +02:00
|
|
|
*
|
2005-12-05 10:36:39 +01:00
|
|
|
*
|
|
|
|
* Authors: Laurent Aimar <fenrir@videolan.org>
|
2019-09-04 21:10:51 +02:00
|
|
|
* Rémi Denis-Courmont
|
2005-12-05 10:36:39 +01:00
|
|
|
*
|
LGPL
Re-license almost all of libVLC and libVLCcore to LGPLv2.1+
This move was authorized by the developers, either:
- by e-mail,
- by vote at the VideoLAN Dev Days 2011,
- on the license website,
- in a contract, oral or written.
No objection was raised, so far.
The developers agreeing are:
Justus Piater
Alexis Ballier
Alexander Bethke
Mohammed Adnène Trojette
Alex Converse
Alexey Sokolov
Alexis de Lattre
Andre Pang
Anthony Loiseau
Cyril Deguet
André Weber
Boris Dorès
Brieuc Jeunhomme
Benjamin Drung
Hugo Beauzée-Luyssen
Benoit Steiner
Benjamin Pracht
Bernie Purcell
Przemyslaw Fiala
Arnaud de Bossoreille de Ribou
Brad Smith
Nick Briggs
Christopher Rath
Christophe Courtaut
Christopher Mueller
Clement Chesnin
Andres Krapf
Damien Fouilleul
David Flynn
Sebastien Zwickert
Antoine Cellerier
Jérôme Decoodt
Jérome Decoodt
Dylan Yudaken
Eduard Babayan
Eugenio Jarosiewicz
Elliot Murphy
Eric Petit
Erwan Tulou
Etienne Membrives
Ludovic Fauvet
Fabio Ritrovato
Tobias Güntner
Jakub Wieczorek
Frédéric Crozat
Francois Cartegnie
Laurent Aimar
Florian G. Pflug
Felix Paul Kühne
Frank Enderle
Rafaël Carré
Simon Latapie
Gildas Bazin
Geoffroy Couprie
Julien / Gellule
Gildas Bazin
Arnaud Schauly
Toralf Niebuhr
Vicente Jimenez Aguilar
Derk-Jan Hartman
Henri Fallon
Ilkka Ollakka
Olivier Teulière
Rémi Duraffort
Jakob Leben
Jean-Baptiste Kempf
Jean-Paul Saman
Jean-Philippe Grimaldi
Jean-François Massol
Gaël Hendryckx
Jakob Leben
Jean-Marc Dressler
Jai Menon
Johan Bilien
Johann Ransay
Joris van Rooij
JP Dinger
Jean-Philippe André
Adrien Grand
Juha Jeronen
Juho Vähä-Herttua
Kaarlo Raiha
Kaarlo Raiha
Kamil Baldyga
Keary Griffin
Ken Self
KO Myung-Hun
Pierre Ynard
Filippo Carone
Loïc Minier
Luca Barbato
Lucas C. Villa Real
Lukas Durfina
Adrien Maglo
Marc Ariberti
Mark Lee
Mark Moriarty
Martin Storsjö
Christophe Massiot
Michel Kaempf
Marian Ďurkovič
Mirsal Ennaime
Carlo Calabrò
Damien Lucas
Naohiro Koriyama
Basos G
Pierre Baillet
Vincent Penquerc'h
Olivier Aubert
Pankaj Yadav
Paul Corke
Pierre d'Herbemont
Philippe Morin
Antoine Lejeune
Michael Ploujnikov
Jean-Marc Dressler
Michael Hanselmann
Rafaël Carré
Ramiro Polla
Rémi Denis-Courmont
Renaud Dartus
Richard Shepherd
Faustino Osuna
Arnaud Vallat
Rob Jonson
Robert Jedrzejczyk
Steve Lhomme
Rocky Bernstein
Romain Goyet
Rov Juvano
Sam Hocevar
Martin T. H. Sandsmark
Sebastian Birk
Sébastien Escudier
Vincent Seguin
Fabio Ritrovato
Sigmund Augdal Helberg
Casian Andrei
Srikanth Raju
Hannes Domani
Stéphane Borel
Stephan Krempel
Stephan Assmus
Tony Castley
Pavlov Konstantin
Eric Petit
Tanguy Krotoff
Dennis van Amerongen
Michel Lespinasse
Can Wu
Xavier Marchesini
Sébastien Toque
Christophe Mutricy
Yoann Peronneau
Yohann Martineau
Yuval Tze
Scott Caudle
Clément Stenac
It is possible, that some minor piece of code was badly tracked, for
some reasons (SVN, mainly) or that some small developers did not answer.
However, as an "œuvre collective", defined as in "CPI 113-2 alinéa 3",
and seeing "Cour. Cass. 17 Mai 1978", and seeing that the editor and
the very vast majority of developers have agreed (> 99.99% of the code,
> 99% of developers), we are fine here.
2011-11-27 21:44:15 +01:00
|
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
|
|
* under the terms of the GNU Lesser General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2.1 of the License, or
|
2005-12-05 10:36:39 +01:00
|
|
|
* (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
|
LGPL
Re-license almost all of libVLC and libVLCcore to LGPLv2.1+
This move was authorized by the developers, either:
- by e-mail,
- by vote at the VideoLAN Dev Days 2011,
- on the license website,
- in a contract, oral or written.
No objection was raised, so far.
The developers agreeing are:
Justus Piater
Alexis Ballier
Alexander Bethke
Mohammed Adnène Trojette
Alex Converse
Alexey Sokolov
Alexis de Lattre
Andre Pang
Anthony Loiseau
Cyril Deguet
André Weber
Boris Dorès
Brieuc Jeunhomme
Benjamin Drung
Hugo Beauzée-Luyssen
Benoit Steiner
Benjamin Pracht
Bernie Purcell
Przemyslaw Fiala
Arnaud de Bossoreille de Ribou
Brad Smith
Nick Briggs
Christopher Rath
Christophe Courtaut
Christopher Mueller
Clement Chesnin
Andres Krapf
Damien Fouilleul
David Flynn
Sebastien Zwickert
Antoine Cellerier
Jérôme Decoodt
Jérome Decoodt
Dylan Yudaken
Eduard Babayan
Eugenio Jarosiewicz
Elliot Murphy
Eric Petit
Erwan Tulou
Etienne Membrives
Ludovic Fauvet
Fabio Ritrovato
Tobias Güntner
Jakub Wieczorek
Frédéric Crozat
Francois Cartegnie
Laurent Aimar
Florian G. Pflug
Felix Paul Kühne
Frank Enderle
Rafaël Carré
Simon Latapie
Gildas Bazin
Geoffroy Couprie
Julien / Gellule
Gildas Bazin
Arnaud Schauly
Toralf Niebuhr
Vicente Jimenez Aguilar
Derk-Jan Hartman
Henri Fallon
Ilkka Ollakka
Olivier Teulière
Rémi Duraffort
Jakob Leben
Jean-Baptiste Kempf
Jean-Paul Saman
Jean-Philippe Grimaldi
Jean-François Massol
Gaël Hendryckx
Jakob Leben
Jean-Marc Dressler
Jai Menon
Johan Bilien
Johann Ransay
Joris van Rooij
JP Dinger
Jean-Philippe André
Adrien Grand
Juha Jeronen
Juho Vähä-Herttua
Kaarlo Raiha
Kaarlo Raiha
Kamil Baldyga
Keary Griffin
Ken Self
KO Myung-Hun
Pierre Ynard
Filippo Carone
Loïc Minier
Luca Barbato
Lucas C. Villa Real
Lukas Durfina
Adrien Maglo
Marc Ariberti
Mark Lee
Mark Moriarty
Martin Storsjö
Christophe Massiot
Michel Kaempf
Marian Ďurkovič
Mirsal Ennaime
Carlo Calabrò
Damien Lucas
Naohiro Koriyama
Basos G
Pierre Baillet
Vincent Penquerc'h
Olivier Aubert
Pankaj Yadav
Paul Corke
Pierre d'Herbemont
Philippe Morin
Antoine Lejeune
Michael Ploujnikov
Jean-Marc Dressler
Michael Hanselmann
Rafaël Carré
Ramiro Polla
Rémi Denis-Courmont
Renaud Dartus
Richard Shepherd
Faustino Osuna
Arnaud Vallat
Rob Jonson
Robert Jedrzejczyk
Steve Lhomme
Rocky Bernstein
Romain Goyet
Rov Juvano
Sam Hocevar
Martin T. H. Sandsmark
Sebastian Birk
Sébastien Escudier
Vincent Seguin
Fabio Ritrovato
Sigmund Augdal Helberg
Casian Andrei
Srikanth Raju
Hannes Domani
Stéphane Borel
Stephan Krempel
Stephan Assmus
Tony Castley
Pavlov Konstantin
Eric Petit
Tanguy Krotoff
Dennis van Amerongen
Michel Lespinasse
Can Wu
Xavier Marchesini
Sébastien Toque
Christophe Mutricy
Yoann Peronneau
Yohann Martineau
Yuval Tze
Scott Caudle
Clément Stenac
It is possible, that some minor piece of code was badly tracked, for
some reasons (SVN, mainly) or that some small developers did not answer.
However, as an "œuvre collective", defined as in "CPI 113-2 alinéa 3",
and seeing "Cour. Cass. 17 Mai 1978", and seeing that the editor and
the very vast majority of developers have agreed (> 99.99% of the code,
> 99% of developers), we are fine here.
2011-11-27 21:44:15 +01:00
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU Lesser General Public License for more details.
|
2005-12-05 10:36:39 +01:00
|
|
|
*
|
LGPL
Re-license almost all of libVLC and libVLCcore to LGPLv2.1+
This move was authorized by the developers, either:
- by e-mail,
- by vote at the VideoLAN Dev Days 2011,
- on the license website,
- in a contract, oral or written.
No objection was raised, so far.
The developers agreeing are:
Justus Piater
Alexis Ballier
Alexander Bethke
Mohammed Adnène Trojette
Alex Converse
Alexey Sokolov
Alexis de Lattre
Andre Pang
Anthony Loiseau
Cyril Deguet
André Weber
Boris Dorès
Brieuc Jeunhomme
Benjamin Drung
Hugo Beauzée-Luyssen
Benoit Steiner
Benjamin Pracht
Bernie Purcell
Przemyslaw Fiala
Arnaud de Bossoreille de Ribou
Brad Smith
Nick Briggs
Christopher Rath
Christophe Courtaut
Christopher Mueller
Clement Chesnin
Andres Krapf
Damien Fouilleul
David Flynn
Sebastien Zwickert
Antoine Cellerier
Jérôme Decoodt
Jérome Decoodt
Dylan Yudaken
Eduard Babayan
Eugenio Jarosiewicz
Elliot Murphy
Eric Petit
Erwan Tulou
Etienne Membrives
Ludovic Fauvet
Fabio Ritrovato
Tobias Güntner
Jakub Wieczorek
Frédéric Crozat
Francois Cartegnie
Laurent Aimar
Florian G. Pflug
Felix Paul Kühne
Frank Enderle
Rafaël Carré
Simon Latapie
Gildas Bazin
Geoffroy Couprie
Julien / Gellule
Gildas Bazin
Arnaud Schauly
Toralf Niebuhr
Vicente Jimenez Aguilar
Derk-Jan Hartman
Henri Fallon
Ilkka Ollakka
Olivier Teulière
Rémi Duraffort
Jakob Leben
Jean-Baptiste Kempf
Jean-Paul Saman
Jean-Philippe Grimaldi
Jean-François Massol
Gaël Hendryckx
Jakob Leben
Jean-Marc Dressler
Jai Menon
Johan Bilien
Johann Ransay
Joris van Rooij
JP Dinger
Jean-Philippe André
Adrien Grand
Juha Jeronen
Juho Vähä-Herttua
Kaarlo Raiha
Kaarlo Raiha
Kamil Baldyga
Keary Griffin
Ken Self
KO Myung-Hun
Pierre Ynard
Filippo Carone
Loïc Minier
Luca Barbato
Lucas C. Villa Real
Lukas Durfina
Adrien Maglo
Marc Ariberti
Mark Lee
Mark Moriarty
Martin Storsjö
Christophe Massiot
Michel Kaempf
Marian Ďurkovič
Mirsal Ennaime
Carlo Calabrò
Damien Lucas
Naohiro Koriyama
Basos G
Pierre Baillet
Vincent Penquerc'h
Olivier Aubert
Pankaj Yadav
Paul Corke
Pierre d'Herbemont
Philippe Morin
Antoine Lejeune
Michael Ploujnikov
Jean-Marc Dressler
Michael Hanselmann
Rafaël Carré
Ramiro Polla
Rémi Denis-Courmont
Renaud Dartus
Richard Shepherd
Faustino Osuna
Arnaud Vallat
Rob Jonson
Robert Jedrzejczyk
Steve Lhomme
Rocky Bernstein
Romain Goyet
Rov Juvano
Sam Hocevar
Martin T. H. Sandsmark
Sebastian Birk
Sébastien Escudier
Vincent Seguin
Fabio Ritrovato
Sigmund Augdal Helberg
Casian Andrei
Srikanth Raju
Hannes Domani
Stéphane Borel
Stephan Krempel
Stephan Assmus
Tony Castley
Pavlov Konstantin
Eric Petit
Tanguy Krotoff
Dennis van Amerongen
Michel Lespinasse
Can Wu
Xavier Marchesini
Sébastien Toque
Christophe Mutricy
Yoann Peronneau
Yohann Martineau
Yuval Tze
Scott Caudle
Clément Stenac
It is possible, that some minor piece of code was badly tracked, for
some reasons (SVN, mainly) or that some small developers did not answer.
However, as an "œuvre collective", defined as in "CPI 113-2 alinéa 3",
and seeing "Cour. Cass. 17 Mai 1978", and seeing that the editor and
the very vast majority of developers have agreed (> 99.99% of the code,
> 99% of developers), we are fine here.
2011-11-27 21:44:15 +01:00
|
|
|
* You should have received a copy of the GNU Lesser 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.
|
2005-12-05 10:36:39 +01:00
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
* Preamble
|
|
|
|
*****************************************************************************/
|
2008-01-23 22:50:58 +01:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
|
|
|
|
2008-05-31 20:56:22 +02:00
|
|
|
#include <vlc_common.h>
|
2005-12-05 10:36:39 +01:00
|
|
|
|
|
|
|
#include <errno.h>
|
2011-08-22 16:57:51 +02:00
|
|
|
#include <assert.h>
|
2005-12-05 10:36:39 +01:00
|
|
|
|
2006-11-26 15:20:34 +01:00
|
|
|
#include <vlc_network.h>
|
2005-12-05 10:36:39 +01:00
|
|
|
|
2013-06-05 15:41:18 +02:00
|
|
|
#ifdef _WIN32
|
2013-11-29 17:41:32 +01:00
|
|
|
# undef EAFNOSUPPORT
|
2005-12-05 17:46:49 +01:00
|
|
|
# define EAFNOSUPPORT WSAEAFNOSUPPORT
|
2017-12-14 17:51:37 +01:00
|
|
|
# include <wincrypt.h>
|
2017-12-05 18:39:42 +01:00
|
|
|
# include <iphlpapi.h>
|
2006-02-11 11:42:48 +01:00
|
|
|
#else
|
|
|
|
# include <unistd.h>
|
2006-02-12 17:36:41 +01:00
|
|
|
# ifdef HAVE_NET_IF_H
|
|
|
|
# include <net/if.h>
|
|
|
|
# endif
|
2005-12-05 10:36:39 +01:00
|
|
|
#endif
|
2005-12-05 11:00:14 +01:00
|
|
|
|
2007-09-19 16:51:44 +02:00
|
|
|
#ifdef HAVE_LINUX_DCCP_H
|
|
|
|
# include <linux/dccp.h>
|
|
|
|
# ifndef SOCK_DCCP /* provisional API */
|
|
|
|
# define SOCK_DCCP 6
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
|
2005-12-05 11:00:14 +01:00
|
|
|
#ifndef SOL_IP
|
|
|
|
# define SOL_IP IPPROTO_IP
|
|
|
|
#endif
|
|
|
|
#ifndef SOL_IPV6
|
|
|
|
# define SOL_IPV6 IPPROTO_IPV6
|
|
|
|
#endif
|
|
|
|
#ifndef IPPROTO_IPV6
|
2007-09-09 21:20:39 +02:00
|
|
|
# define IPPROTO_IPV6 41 /* IANA */
|
|
|
|
#endif
|
|
|
|
#ifndef SOL_DCCP
|
|
|
|
# define SOL_DCCP IPPROTO_DCCP
|
|
|
|
#endif
|
|
|
|
#ifndef IPPROTO_DCCP
|
|
|
|
# define IPPROTO_DCCP 33 /* IANA */
|
|
|
|
#endif
|
|
|
|
#ifndef SOL_UDPLITE
|
|
|
|
# define SOL_UDPLITE IPPROTO_UDPLITE
|
|
|
|
#endif
|
|
|
|
#ifndef IPPROTO_UDPLITE
|
|
|
|
# define IPPROTO_UDPLITE 136 /* IANA */
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined (HAVE_NETINET_UDPLITE_H)
|
|
|
|
# include <netinet/udplite.h>
|
|
|
|
#elif defined (__linux__)
|
|
|
|
/* still missing from glibc 2.6 */
|
|
|
|
# define UDPLITE_SEND_CSCOV 10
|
|
|
|
# define UDPLITE_RECV_CSCOV 11
|
2005-12-05 10:36:39 +01:00
|
|
|
#endif
|
|
|
|
|
2008-09-04 23:02:41 +02:00
|
|
|
/* */
|
2012-08-19 15:29:53 +02:00
|
|
|
static int net_SetupDgramSocket (vlc_object_t *p_obj, int fd,
|
|
|
|
const struct addrinfo *ptr)
|
2008-09-04 23:02:41 +02:00
|
|
|
{
|
|
|
|
#ifdef SO_REUSEPORT
|
|
|
|
setsockopt (fd, SOL_SOCKET, SO_REUSEPORT, &(int){ 1 }, sizeof (int));
|
|
|
|
#endif
|
|
|
|
|
2013-06-05 15:41:18 +02:00
|
|
|
#if defined (_WIN32)
|
2015-03-19 07:52:30 +01:00
|
|
|
|
|
|
|
/* Check windows version so we know if we need to increase receive buffers
|
|
|
|
* for Windows 7 and earlier
|
|
|
|
|
|
|
|
* SetSocketMediaStreamingMode is present in win 8 and later, so we set
|
|
|
|
* receive buffer if that isn't present
|
|
|
|
*/
|
2016-11-23 22:56:34 +01:00
|
|
|
#if (_WIN32_WINNT < _WIN32_WINNT_WIN8)
|
|
|
|
HINSTANCE h_Network = LoadLibrary(TEXT("Windows.Networking.dll"));
|
2015-03-19 07:52:30 +01:00
|
|
|
if( (h_Network == NULL) ||
|
|
|
|
(GetProcAddress( h_Network, "SetSocketMediaStreamingMode" ) == NULL ) )
|
|
|
|
{
|
|
|
|
setsockopt (fd, SOL_SOCKET, SO_RCVBUF,
|
|
|
|
(void *)&(int){ 0x80000 }, sizeof (int));
|
|
|
|
}
|
|
|
|
if( h_Network )
|
|
|
|
FreeLibrary( h_Network );
|
2015-03-20 15:47:04 +01:00
|
|
|
#endif
|
2015-03-19 07:52:30 +01:00
|
|
|
|
2008-09-04 23:02:41 +02:00
|
|
|
if (net_SockAddrIsMulticast (ptr->ai_addr, ptr->ai_addrlen)
|
|
|
|
&& (sizeof (struct sockaddr_storage) >= ptr->ai_addrlen))
|
|
|
|
{
|
|
|
|
// This works for IPv4 too - don't worry!
|
|
|
|
struct sockaddr_in6 dumb =
|
|
|
|
{
|
|
|
|
.sin6_family = ptr->ai_addr->sa_family,
|
|
|
|
.sin6_port = ((struct sockaddr_in *)(ptr->ai_addr))->sin_port
|
|
|
|
};
|
|
|
|
|
|
|
|
bind (fd, (struct sockaddr *)&dumb, ptr->ai_addrlen);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
if (bind (fd, ptr->ai_addr, ptr->ai_addrlen))
|
|
|
|
{
|
2013-12-28 17:46:52 +01:00
|
|
|
msg_Err( p_obj, "socket bind error: %s", vlc_strerror_c(net_errno) );
|
2008-09-04 23:02:41 +02:00
|
|
|
net_Close (fd);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return fd;
|
|
|
|
}
|
|
|
|
|
2018-11-10 10:43:19 +01:00
|
|
|
static int net_Subscribe(vlc_object_t *obj, int fd,
|
|
|
|
const struct sockaddr *addr, socklen_t addrlen);
|
|
|
|
|
2008-09-04 23:02:41 +02:00
|
|
|
/* */
|
2018-07-11 14:55:34 +02:00
|
|
|
static int net_ListenSingle (vlc_object_t *obj, const char *host, unsigned port,
|
2011-08-22 16:31:40 +02:00
|
|
|
int protocol)
|
2007-04-15 10:20:45 +02:00
|
|
|
{
|
2012-08-19 15:29:53 +02:00
|
|
|
struct addrinfo hints = {
|
|
|
|
.ai_socktype = SOCK_DGRAM,
|
|
|
|
.ai_protocol = protocol,
|
2012-08-19 15:36:03 +02:00
|
|
|
.ai_flags = AI_PASSIVE | AI_NUMERICSERV | AI_IDN,
|
2012-08-19 15:29:53 +02:00
|
|
|
}, *res;
|
2007-04-15 10:20:45 +02:00
|
|
|
|
|
|
|
if (host && !*host)
|
|
|
|
host = NULL;
|
|
|
|
|
2018-07-11 15:24:42 +02:00
|
|
|
msg_Dbg (obj, "net: opening %s datagram port %u",
|
2009-05-17 10:16:03 +02:00
|
|
|
host ? host : "any", port);
|
2007-04-15 10:20:45 +02:00
|
|
|
|
2012-08-19 15:22:39 +02:00
|
|
|
int val = vlc_getaddrinfo (host, port, &hints, &res);
|
2007-04-15 10:20:45 +02:00
|
|
|
if (val)
|
|
|
|
{
|
2018-07-11 15:24:42 +02:00
|
|
|
msg_Err (obj, "Cannot resolve %s port %u : %s", host, port,
|
2010-04-28 22:48:30 +02:00
|
|
|
gai_strerror (val));
|
2007-04-15 10:20:45 +02:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
val = -1;
|
|
|
|
|
|
|
|
for (const struct addrinfo *ptr = res; ptr != NULL; ptr = ptr->ai_next)
|
|
|
|
{
|
|
|
|
int fd = net_Socket (obj, ptr->ai_family, ptr->ai_socktype,
|
2010-02-01 22:13:26 +01:00
|
|
|
ptr->ai_protocol);
|
2007-04-15 10:20:45 +02:00
|
|
|
if (fd == -1)
|
|
|
|
{
|
2013-12-28 17:46:52 +01:00
|
|
|
msg_Dbg (obj, "socket error: %s", vlc_strerror_c(net_errno));
|
2007-04-15 10:20:45 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef IPV6_V6ONLY
|
2011-08-22 16:31:40 +02:00
|
|
|
/* Try dual-mode IPv6 if available. */
|
2009-07-19 21:00:16 +02:00
|
|
|
if (ptr->ai_family == AF_INET6)
|
2011-08-22 16:31:40 +02:00
|
|
|
setsockopt (fd, SOL_IPV6, IPV6_V6ONLY, &(int){ 0 }, sizeof (int));
|
2010-03-28 19:40:45 +02:00
|
|
|
#endif
|
2008-09-04 23:02:41 +02:00
|
|
|
fd = net_SetupDgramSocket( obj, fd, ptr );
|
|
|
|
if( fd == -1 )
|
2007-04-15 10:20:45 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
if (net_SockAddrIsMulticast (ptr->ai_addr, ptr->ai_addrlen)
|
|
|
|
&& net_Subscribe (obj, fd, ptr->ai_addr, ptr->ai_addrlen))
|
|
|
|
{
|
|
|
|
net_Close (fd);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
val = fd;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2010-04-28 22:50:08 +02:00
|
|
|
freeaddrinfo (res);
|
2007-04-15 10:20:45 +02:00
|
|
|
return val;
|
|
|
|
}
|
2005-12-05 11:00:14 +01:00
|
|
|
|
2006-11-24 21:10:36 +01:00
|
|
|
|
2005-12-05 17:46:49 +01:00
|
|
|
static int net_SetMcastHopLimit( vlc_object_t *p_this,
|
|
|
|
int fd, int family, int hlim )
|
2005-12-05 11:00:14 +01:00
|
|
|
{
|
|
|
|
int proto, cmd;
|
|
|
|
|
2007-09-10 20:56:52 +02:00
|
|
|
/* There is some confusion in the world whether IP_MULTICAST_TTL
|
2005-12-05 11:00:14 +01:00
|
|
|
* 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 */
|
|
|
|
switch( family )
|
|
|
|
{
|
2006-11-24 17:35:23 +01:00
|
|
|
#ifdef IP_MULTICAST_TTL
|
2005-12-05 11:00:14 +01:00
|
|
|
case AF_INET:
|
|
|
|
proto = SOL_IP;
|
|
|
|
cmd = IP_MULTICAST_TTL;
|
|
|
|
break;
|
2006-11-24 17:35:23 +01:00
|
|
|
#endif
|
2005-12-05 11:00:14 +01:00
|
|
|
|
|
|
|
#ifdef IPV6_MULTICAST_HOPS
|
|
|
|
case AF_INET6:
|
|
|
|
proto = SOL_IPV6;
|
|
|
|
cmd = IPV6_MULTICAST_HOPS;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
default:
|
2007-09-18 17:44:47 +02:00
|
|
|
errno = EAFNOSUPPORT;
|
2013-12-28 17:46:52 +01:00
|
|
|
msg_Warn( p_this, "%s", vlc_strerror_c(EAFNOSUPPORT) );
|
2005-12-05 17:46:49 +01:00
|
|
|
return VLC_EGENERIC;
|
2005-12-05 11:00:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if( setsockopt( fd, proto, cmd, &hlim, sizeof( hlim ) ) < 0 )
|
|
|
|
{
|
|
|
|
/* BSD compatibility */
|
|
|
|
unsigned char buf;
|
|
|
|
|
2013-12-28 17:46:52 +01:00
|
|
|
msg_Dbg( p_this, "cannot set hop limit (%d): %s", hlim,
|
|
|
|
vlc_strerror_c(net_errno) );
|
2005-12-05 11:00:14 +01:00
|
|
|
buf = (unsigned char)(( hlim > 255 ) ? 255 : hlim);
|
2005-12-05 17:46:49 +01:00
|
|
|
if( setsockopt( fd, proto, cmd, &buf, sizeof( buf ) ) )
|
2010-04-11 21:42:11 +02:00
|
|
|
{
|
2013-12-28 17:46:52 +01:00
|
|
|
msg_Err( p_this, "cannot set hop limit (%d): %s", hlim,
|
|
|
|
vlc_strerror_c(net_errno) );
|
2005-12-05 17:46:49 +01:00
|
|
|
return VLC_EGENERIC;
|
2010-04-11 21:42:11 +02:00
|
|
|
}
|
2005-12-05 11:00:14 +01:00
|
|
|
}
|
2006-11-24 17:35:23 +01:00
|
|
|
|
2005-12-05 17:46:49 +01:00
|
|
|
return VLC_SUCCESS;
|
2005-12-05 11:00:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-08-22 17:08:17 +02:00
|
|
|
static int net_SetMcastOut (vlc_object_t *p_this, int fd, int family,
|
|
|
|
const char *iface)
|
2005-12-05 17:46:49 +01:00
|
|
|
{
|
2011-08-22 17:08:17 +02:00
|
|
|
int scope = if_nametoindex (iface);
|
|
|
|
if (scope == 0)
|
|
|
|
{
|
|
|
|
msg_Err (p_this, "invalid multicast interface: %s", iface);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2006-10-20 21:16:25 +02:00
|
|
|
switch (family)
|
2005-12-05 17:46:49 +01:00
|
|
|
{
|
2006-10-20 21:16:25 +02:00
|
|
|
#ifdef IPV6_MULTICAST_IF
|
|
|
|
case AF_INET6:
|
2011-08-22 17:08:17 +02:00
|
|
|
if (setsockopt (fd, SOL_IPV6, IPV6_MULTICAST_IF,
|
2012-08-08 06:43:31 +02:00
|
|
|
&scope, sizeof (scope)) == 0)
|
2011-08-22 17:08:17 +02:00
|
|
|
return 0;
|
2013-08-09 17:41:52 +02:00
|
|
|
break;
|
2006-10-20 21:16:25 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef __linux__
|
2005-12-05 17:46:49 +01:00
|
|
|
case AF_INET:
|
|
|
|
{
|
2006-10-20 21:16:25 +02:00
|
|
|
struct ip_mreqn req = { .imr_ifindex = scope };
|
2011-08-22 17:08:17 +02:00
|
|
|
if (setsockopt (fd, SOL_IP, IP_MULTICAST_IF,
|
|
|
|
&req, sizeof (req)) == 0)
|
2006-10-20 21:16:25 +02:00
|
|
|
return 0;
|
2013-08-09 17:41:52 +02:00
|
|
|
break;
|
2006-10-20 21:16:25 +02:00
|
|
|
}
|
2011-08-22 17:08:17 +02:00
|
|
|
#endif
|
|
|
|
default:
|
|
|
|
errno = EAFNOSUPPORT;
|
2005-12-05 17:46:49 +01:00
|
|
|
}
|
2013-12-28 17:46:52 +01:00
|
|
|
msg_Err (p_this, "cannot force multicast interface %s: %s", iface,
|
|
|
|
vlc_strerror_c(errno));
|
2006-10-20 21:16:25 +02:00
|
|
|
return -1;
|
2005-12-05 17:46:49 +01:00
|
|
|
}
|
|
|
|
|
2006-09-07 21:49:30 +02:00
|
|
|
|
2019-04-14 08:53:18 +02:00
|
|
|
#ifdef MCAST_JOIN_GROUP
|
2011-08-22 16:57:51 +02:00
|
|
|
static unsigned var_GetIfIndex (vlc_object_t *obj)
|
2006-11-24 21:10:36 +01:00
|
|
|
{
|
2011-08-22 16:57:51 +02:00
|
|
|
char *ifname = var_InheritString (obj, "miface");
|
|
|
|
if (ifname == NULL)
|
2006-11-24 21:10:36 +01:00
|
|
|
return 0;
|
|
|
|
|
2011-08-22 16:57:51 +02:00
|
|
|
unsigned ifindex = if_nametoindex (ifname);
|
|
|
|
if (ifindex == 0)
|
|
|
|
msg_Err (obj, "invalid multicast interface: %s", ifname);
|
|
|
|
free (ifname);
|
|
|
|
return ifindex;
|
2006-11-24 21:10:36 +01:00
|
|
|
}
|
2019-04-14 08:53:18 +02:00
|
|
|
#endif
|
2006-11-05 20:20:52 +01:00
|
|
|
|
|
|
|
|
2006-11-24 21:10:36 +01:00
|
|
|
/**
|
|
|
|
* IP-agnostic multicast join,
|
|
|
|
* with fallback to old APIs, and fallback from SSM to ASM.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
net_SourceSubscribe (vlc_object_t *obj, int fd,
|
|
|
|
const struct sockaddr *src, socklen_t srclen,
|
|
|
|
const struct sockaddr *grp, socklen_t grplen)
|
|
|
|
{
|
2014-07-12 12:14:39 +02:00
|
|
|
/* MCAST_JOIN_SOURCE_GROUP was introduced to OS X in v10.7, but it doesn't work,
|
|
|
|
* so ignore it to use the same code path as on 10.5 or 10.6 */
|
|
|
|
#if defined (MCAST_JOIN_SOURCE_GROUP) && !defined (__APPLE__)
|
2016-10-27 22:57:12 +02:00
|
|
|
/* Family-agnostic Source-Specific Multicast join */
|
2011-08-22 16:57:51 +02:00
|
|
|
int level;
|
|
|
|
struct group_source_req gsr;
|
2006-11-24 21:10:36 +01:00
|
|
|
|
2011-08-22 16:57:51 +02:00
|
|
|
memset (&gsr, 0, sizeof (gsr));
|
|
|
|
gsr.gsr_interface = var_GetIfIndex (obj);
|
2006-11-05 20:20:52 +01:00
|
|
|
|
2006-11-24 21:10:36 +01:00
|
|
|
switch (grp->sa_family)
|
|
|
|
{
|
2006-11-24 21:33:26 +01:00
|
|
|
#ifdef AF_INET6
|
2006-11-05 20:20:52 +01:00
|
|
|
case AF_INET6:
|
2011-08-22 16:57:51 +02:00
|
|
|
{
|
|
|
|
const struct sockaddr_in6 *g6 = (const struct sockaddr_in6 *)grp;
|
|
|
|
|
2006-11-24 21:10:36 +01:00
|
|
|
level = SOL_IPV6;
|
2019-04-14 08:52:35 +02:00
|
|
|
assert(grplen >= (socklen_t)sizeof (struct sockaddr_in6));
|
2011-08-22 16:57:51 +02:00
|
|
|
if (g6->sin6_scope_id != 0)
|
|
|
|
gsr.gsr_interface = g6->sin6_scope_id;
|
2006-11-24 21:10:36 +01:00
|
|
|
break;
|
2011-08-22 16:57:51 +02:00
|
|
|
}
|
2006-11-24 21:33:26 +01:00
|
|
|
#endif
|
2006-11-24 21:10:36 +01:00
|
|
|
case AF_INET:
|
|
|
|
level = SOL_IP;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
errno = EAFNOSUPPORT;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2019-04-14 08:52:35 +02:00
|
|
|
assert(grplen <= (socklen_t)sizeof (gsr.gsr_group));
|
2011-08-22 16:57:51 +02:00
|
|
|
memcpy (&gsr.gsr_source, src, srclen);
|
2019-04-14 08:52:35 +02:00
|
|
|
assert(srclen <= (socklen_t)sizeof (gsr.gsr_source));
|
2011-08-22 16:57:51 +02:00
|
|
|
memcpy (&gsr.gsr_group, grp, grplen);
|
|
|
|
if (setsockopt (fd, level, MCAST_JOIN_SOURCE_GROUP,
|
|
|
|
&gsr, sizeof (gsr)) == 0)
|
|
|
|
return 0;
|
2006-11-26 23:29:33 +01:00
|
|
|
|
2011-08-22 16:57:51 +02:00
|
|
|
#else
|
|
|
|
if (src->sa_family != grp->sa_family)
|
2006-11-24 21:33:26 +01:00
|
|
|
{
|
2011-08-22 16:57:51 +02:00
|
|
|
errno = EAFNOSUPPORT;
|
|
|
|
return -1;
|
|
|
|
}
|
2006-11-24 21:33:26 +01:00
|
|
|
|
2011-08-22 16:57:51 +02:00
|
|
|
switch (grp->sa_family)
|
2006-11-24 21:10:36 +01:00
|
|
|
{
|
2011-08-22 16:57:51 +02:00
|
|
|
# ifdef IP_ADD_SOURCE_MEMBERSHIP
|
|
|
|
/* IPv4-specific API */
|
|
|
|
case AF_INET:
|
|
|
|
{
|
|
|
|
struct ip_mreq_source imr;
|
|
|
|
|
|
|
|
memset (&imr, 0, sizeof (imr));
|
2019-04-14 08:52:35 +02:00
|
|
|
assert(grplen >= (socklen_t)sizeof (struct sockaddr_in));
|
2011-08-22 16:57:51 +02:00
|
|
|
imr.imr_multiaddr = ((const struct sockaddr_in *)grp)->sin_addr;
|
2019-04-14 08:52:35 +02:00
|
|
|
assert(srclen >= (socklen_t)sizeof (struct sockaddr_in));
|
2011-08-22 16:57:51 +02:00
|
|
|
imr.imr_sourceaddr = ((const struct sockaddr_in *)src)->sin_addr;
|
|
|
|
if (setsockopt (fd, SOL_IP, IP_ADD_SOURCE_MEMBERSHIP,
|
|
|
|
&imr, sizeof (imr)) == 0)
|
|
|
|
return 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
# endif
|
|
|
|
default:
|
|
|
|
errno = EAFNOSUPPORT;
|
2006-11-24 21:10:36 +01:00
|
|
|
}
|
|
|
|
|
2011-08-22 16:57:51 +02:00
|
|
|
#endif
|
2013-12-28 17:46:52 +01:00
|
|
|
msg_Err (obj, "cannot join source multicast group: %s",
|
|
|
|
vlc_strerror_c(net_errno));
|
2011-08-22 16:57:51 +02:00
|
|
|
msg_Warn (obj, "trying ASM instead of SSM...");
|
|
|
|
return net_Subscribe (obj, fd, grp, grplen);
|
|
|
|
}
|
2006-11-24 21:10:36 +01:00
|
|
|
|
|
|
|
|
2018-11-10 10:43:19 +01:00
|
|
|
static int net_Subscribe(vlc_object_t *obj, int fd,
|
|
|
|
const struct sockaddr *grp, socklen_t grplen)
|
2011-08-22 16:57:51 +02:00
|
|
|
{
|
2012-03-04 12:42:00 +01:00
|
|
|
/* MCAST_JOIN_GROUP was introduced to OS X in v10.7, but it doesn't work,
|
|
|
|
* so ignore it to use the same code as on 10.5 or 10.6 */
|
|
|
|
#if defined (MCAST_JOIN_GROUP) && !defined (__APPLE__)
|
2016-10-27 22:57:12 +02:00
|
|
|
/* Family-agnostic Any-Source Multicast join */
|
2011-08-22 16:57:51 +02:00
|
|
|
int level;
|
|
|
|
struct group_req gr;
|
2006-11-24 21:10:36 +01:00
|
|
|
|
2011-08-22 16:57:51 +02:00
|
|
|
memset (&gr, 0, sizeof (gr));
|
|
|
|
gr.gr_interface = var_GetIfIndex (obj);
|
2006-11-24 21:10:36 +01:00
|
|
|
|
|
|
|
switch (grp->sa_family)
|
|
|
|
{
|
|
|
|
#ifdef AF_INET6
|
|
|
|
case AF_INET6:
|
2011-08-22 16:57:51 +02:00
|
|
|
{
|
|
|
|
const struct sockaddr_in6 *g6 = (const struct sockaddr_in6 *)grp;
|
2006-11-24 21:10:36 +01:00
|
|
|
|
2011-08-22 16:57:51 +02:00
|
|
|
level = SOL_IPV6;
|
2019-04-14 08:52:35 +02:00
|
|
|
assert(grplen >= (socklen_t)sizeof (struct sockaddr_in6));
|
2011-08-22 16:57:51 +02:00
|
|
|
if (g6->sin6_scope_id != 0)
|
|
|
|
gr.gr_interface = g6->sin6_scope_id;
|
2006-11-24 21:10:36 +01:00
|
|
|
break;
|
2011-08-22 16:57:51 +02:00
|
|
|
}
|
2006-11-05 20:20:52 +01:00
|
|
|
#endif
|
2011-08-22 16:57:51 +02:00
|
|
|
case AF_INET:
|
|
|
|
level = SOL_IP;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
errno = EAFNOSUPPORT;
|
|
|
|
return -1;
|
2006-11-05 20:20:52 +01:00
|
|
|
}
|
|
|
|
|
2019-04-14 08:52:35 +02:00
|
|
|
assert(grplen <= (socklen_t)sizeof (gr.gr_group));
|
2011-08-22 16:57:51 +02:00
|
|
|
memcpy (&gr.gr_group, grp, grplen);
|
|
|
|
if (setsockopt (fd, level, MCAST_JOIN_GROUP, &gr, sizeof (gr)) == 0)
|
|
|
|
return 0;
|
2006-11-24 21:10:36 +01:00
|
|
|
|
2011-08-22 16:57:51 +02:00
|
|
|
#else
|
|
|
|
switch (grp->sa_family)
|
2006-11-24 21:10:36 +01:00
|
|
|
{
|
2011-08-22 16:57:51 +02:00
|
|
|
# ifdef IPV6_JOIN_GROUP
|
|
|
|
case AF_INET6:
|
|
|
|
{
|
|
|
|
struct ipv6_mreq ipv6mr;
|
|
|
|
const struct sockaddr_in6 *g6 = (const struct sockaddr_in6 *)grp;
|
|
|
|
|
|
|
|
memset (&ipv6mr, 0, sizeof (ipv6mr));
|
2019-04-14 08:52:35 +02:00
|
|
|
assert(grplen >= (socklen_t)sizeof (struct sockaddr_in6));
|
2011-08-22 16:57:51 +02:00
|
|
|
ipv6mr.ipv6mr_multiaddr = g6->sin6_addr;
|
|
|
|
ipv6mr.ipv6mr_interface = g6->sin6_scope_id;
|
|
|
|
if (!setsockopt (fd, SOL_IPV6, IPV6_JOIN_GROUP,
|
|
|
|
&ipv6mr, sizeof (ipv6mr)))
|
|
|
|
return 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
# endif
|
|
|
|
# ifdef IP_ADD_MEMBERSHIP
|
|
|
|
case AF_INET:
|
|
|
|
{
|
|
|
|
struct ip_mreq imr;
|
|
|
|
|
|
|
|
memset (&imr, 0, sizeof (imr));
|
2019-04-14 08:52:35 +02:00
|
|
|
assert(grplen >= (socklen_t)sizeof (struct sockaddr_in));
|
2011-08-22 16:57:51 +02:00
|
|
|
imr.imr_multiaddr = ((const struct sockaddr_in *)grp)->sin_addr;
|
|
|
|
if (setsockopt (fd, SOL_IP, IP_ADD_MEMBERSHIP,
|
|
|
|
&imr, sizeof (imr)) == 0)
|
|
|
|
return 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
# endif
|
|
|
|
default:
|
|
|
|
errno = EAFNOSUPPORT;
|
2006-11-24 21:10:36 +01:00
|
|
|
}
|
|
|
|
|
2011-08-22 16:57:51 +02:00
|
|
|
#endif
|
2013-12-28 17:46:52 +01:00
|
|
|
msg_Err (obj, "cannot join multicast group: %s",
|
|
|
|
vlc_strerror_c(net_errno));
|
2006-11-05 20:20:52 +01:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-08-16 22:05:06 +02:00
|
|
|
static int net_SetDSCP( int fd, uint8_t dscp )
|
2006-09-07 21:49:30 +02:00
|
|
|
{
|
|
|
|
struct sockaddr_storage addr;
|
|
|
|
if( getsockname( fd, (struct sockaddr *)&addr, &(socklen_t){ sizeof (addr) }) )
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
int level, cmd;
|
|
|
|
|
|
|
|
switch( addr.ss_family )
|
|
|
|
{
|
|
|
|
#ifdef IPV6_TCLASS
|
|
|
|
case AF_INET6:
|
|
|
|
level = SOL_IPV6;
|
|
|
|
cmd = IPV6_TCLASS;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
case AF_INET:
|
|
|
|
level = SOL_IP;
|
|
|
|
cmd = IP_TOS;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
#ifdef ENOPROTOOPT
|
|
|
|
errno = ENOPROTOOPT;
|
|
|
|
#endif
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return setsockopt( fd, level, cmd, &(int){ dscp }, sizeof (int));
|
|
|
|
}
|
|
|
|
|
2010-02-07 11:51:50 +01:00
|
|
|
#undef net_ConnectDgram
|
2005-12-05 10:36:39 +01:00
|
|
|
/*****************************************************************************
|
2010-02-07 11:51:50 +01:00
|
|
|
* net_ConnectDgram:
|
2005-12-05 10:36:39 +01:00
|
|
|
*****************************************************************************
|
2007-02-05 18:21:56 +01:00
|
|
|
* Open a datagram socket to send data to a defined destination, with an
|
|
|
|
* optional hop limit.
|
2005-12-05 10:36:39 +01:00
|
|
|
*****************************************************************************/
|
2018-07-11 15:00:06 +02:00
|
|
|
int net_ConnectDgram( vlc_object_t *p_this, const char *psz_host, unsigned i_port,
|
2010-02-07 11:51:50 +01:00
|
|
|
int i_hlim, int proto )
|
2005-12-05 10:36:39 +01:00
|
|
|
{
|
2012-08-19 15:29:53 +02:00
|
|
|
struct addrinfo hints = {
|
|
|
|
.ai_socktype = SOCK_DGRAM,
|
|
|
|
.ai_protocol = proto,
|
2012-08-19 15:36:03 +02:00
|
|
|
.ai_flags = AI_NUMERICSERV | AI_IDN,
|
2012-08-19 15:29:53 +02:00
|
|
|
}, *res;
|
2012-08-19 15:22:39 +02:00
|
|
|
int i_handle = -1;
|
2008-04-14 00:08:29 +02:00
|
|
|
bool b_unreach = false;
|
2005-12-05 10:36:39 +01:00
|
|
|
|
2008-09-19 15:48:05 +02:00
|
|
|
if( i_hlim < 0 )
|
2010-11-10 17:41:38 +01:00
|
|
|
i_hlim = var_InheritInteger( p_this, "ttl" );
|
2005-12-05 11:00:14 +01:00
|
|
|
|
2018-07-11 15:24:42 +02:00
|
|
|
msg_Dbg( p_this, "net: connecting to [%s]:%u", psz_host, i_port );
|
2005-12-05 10:36:39 +01:00
|
|
|
|
2012-08-19 15:22:39 +02:00
|
|
|
int val = vlc_getaddrinfo (psz_host, i_port, &hints, &res);
|
|
|
|
if (val)
|
2005-12-05 10:36:39 +01:00
|
|
|
{
|
2018-07-11 15:24:42 +02:00
|
|
|
msg_Err (p_this, "cannot resolve [%s]:%u : %s", psz_host, i_port,
|
2012-08-19 15:22:39 +02:00
|
|
|
gai_strerror (val));
|
2005-12-05 10:36:39 +01:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2012-08-19 15:29:53 +02:00
|
|
|
for (struct addrinfo *ptr = res; ptr != NULL; ptr = ptr->ai_next)
|
2005-12-05 10:36:39 +01:00
|
|
|
{
|
2006-10-20 21:16:25 +02:00
|
|
|
char *str;
|
|
|
|
int fd = net_Socket (p_this, ptr->ai_family, ptr->ai_socktype,
|
2010-02-01 22:13:26 +01:00
|
|
|
ptr->ai_protocol);
|
2006-10-20 21:16:25 +02:00
|
|
|
if (fd == -1)
|
2005-12-05 10:36:39 +01:00
|
|
|
continue;
|
2006-10-20 21:16:25 +02:00
|
|
|
|
|
|
|
/* Allow broadcast sending */
|
|
|
|
setsockopt (fd, SOL_SOCKET, SO_BROADCAST, &(int){ 1 }, sizeof (int));
|
2005-12-05 10:36:39 +01:00
|
|
|
|
2008-09-19 15:48:05 +02:00
|
|
|
if( i_hlim >= 0 )
|
2005-12-05 18:33:11 +01:00
|
|
|
net_SetMcastHopLimit( p_this, fd, ptr->ai_family, i_hlim );
|
2006-10-20 21:16:25 +02:00
|
|
|
|
2010-11-10 17:41:38 +01:00
|
|
|
str = var_InheritString (p_this, "miface");
|
2006-10-20 21:16:25 +02:00
|
|
|
if (str != NULL)
|
|
|
|
{
|
2011-08-22 17:08:17 +02:00
|
|
|
net_SetMcastOut (p_this, fd, ptr->ai_family, str);
|
2006-10-20 21:16:25 +02:00
|
|
|
free (str);
|
2005-12-05 17:46:49 +01:00
|
|
|
}
|
2005-12-05 11:00:14 +01:00
|
|
|
|
2010-11-10 17:41:38 +01:00
|
|
|
net_SetDSCP (fd, var_InheritInteger (p_this, "dscp"));
|
2006-10-20 21:16:25 +02:00
|
|
|
|
2005-12-05 10:36:39 +01:00
|
|
|
if( connect( fd, ptr->ai_addr, ptr->ai_addrlen ) == 0 )
|
|
|
|
{
|
|
|
|
/* success */
|
|
|
|
i_handle = fd;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2013-06-05 15:41:18 +02:00
|
|
|
#if defined( _WIN32 )
|
2005-12-05 10:36:39 +01:00
|
|
|
if( WSAGetLastError () == WSAENETUNREACH )
|
|
|
|
#else
|
|
|
|
if( errno == ENETUNREACH )
|
|
|
|
#endif
|
2008-04-14 00:08:29 +02:00
|
|
|
b_unreach = true;
|
2005-12-05 10:36:39 +01:00
|
|
|
else
|
2018-07-11 15:24:42 +02:00
|
|
|
msg_Warn( p_this, "%s port %u : %s", psz_host, i_port,
|
2013-12-28 17:46:52 +01:00
|
|
|
vlc_strerror_c(errno) );
|
2013-07-19 21:24:50 +02:00
|
|
|
net_Close( fd );
|
2005-12-05 10:36:39 +01:00
|
|
|
}
|
|
|
|
|
2010-04-28 22:50:08 +02:00
|
|
|
freeaddrinfo( res );
|
2005-12-05 10:36:39 +01:00
|
|
|
|
|
|
|
if( i_handle == -1 )
|
|
|
|
{
|
|
|
|
if( b_unreach )
|
2018-07-11 15:24:42 +02:00
|
|
|
msg_Err( p_this, "Host %s port %u is unreachable", psz_host,
|
2005-12-05 10:36:39 +01:00
|
|
|
i_port );
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return i_handle;
|
|
|
|
}
|
|
|
|
|
2010-02-07 11:51:50 +01:00
|
|
|
#undef net_OpenDgram
|
2005-12-05 10:36:39 +01:00
|
|
|
/*****************************************************************************
|
2010-02-07 11:51:50 +01:00
|
|
|
* net_OpenDgram:
|
2005-12-05 10:36:39 +01:00
|
|
|
*****************************************************************************
|
2007-02-05 17:32:31 +01:00
|
|
|
* OpenDgram a datagram socket and return a handle
|
2005-12-05 10:36:39 +01:00
|
|
|
*****************************************************************************/
|
2018-07-11 14:55:34 +02:00
|
|
|
int net_OpenDgram( vlc_object_t *obj, const char *psz_bind, unsigned i_bind,
|
|
|
|
const char *psz_server, unsigned i_server, int protocol )
|
2005-12-05 10:36:39 +01:00
|
|
|
{
|
2007-04-15 10:20:45 +02:00
|
|
|
if ((psz_server == NULL) || (psz_server[0] == '\0'))
|
2011-08-22 16:31:40 +02:00
|
|
|
return net_ListenSingle (obj, psz_bind, i_bind, protocol);
|
2006-11-24 21:10:36 +01:00
|
|
|
|
2018-07-11 15:24:42 +02:00
|
|
|
msg_Dbg (obj, "net: connecting to [%s]:%u from [%s]:%u",
|
2007-04-15 10:20:45 +02:00
|
|
|
psz_server, i_server, psz_bind, i_bind);
|
2007-01-05 12:21:12 +01:00
|
|
|
|
2012-08-19 15:29:53 +02:00
|
|
|
struct addrinfo hints = {
|
|
|
|
.ai_socktype = SOCK_DGRAM,
|
|
|
|
.ai_protocol = protocol,
|
2012-08-19 15:36:03 +02:00
|
|
|
.ai_flags = AI_NUMERICSERV | AI_IDN,
|
2012-08-19 15:29:53 +02:00
|
|
|
}, *loc, *rem;
|
2005-12-05 10:36:39 +01:00
|
|
|
|
2012-08-19 15:22:39 +02:00
|
|
|
int val = vlc_getaddrinfo (psz_server, i_server, &hints, &rem);
|
2006-11-24 21:10:36 +01:00
|
|
|
if (val)
|
2006-11-23 12:12:49 +01:00
|
|
|
{
|
2018-07-11 15:24:42 +02:00
|
|
|
msg_Err (obj, "cannot resolve %s port %u : %s", psz_server, i_server,
|
2010-04-28 22:48:30 +02:00
|
|
|
gai_strerror (val));
|
2006-11-24 21:10:36 +01:00
|
|
|
return -1;
|
2006-11-23 12:12:49 +01:00
|
|
|
}
|
2005-12-05 10:36:39 +01:00
|
|
|
|
2012-08-19 15:29:53 +02:00
|
|
|
hints.ai_flags |= AI_PASSIVE;
|
2012-08-19 15:22:39 +02:00
|
|
|
val = vlc_getaddrinfo (psz_bind, i_bind, &hints, &loc);
|
2006-11-24 21:10:36 +01:00
|
|
|
if (val)
|
2006-11-23 12:22:15 +01:00
|
|
|
{
|
2018-07-11 15:24:42 +02:00
|
|
|
msg_Err (obj, "cannot resolve %s port %u : %s", psz_bind, i_bind,
|
2010-04-28 22:48:30 +02:00
|
|
|
gai_strerror (val));
|
2010-04-28 22:50:08 +02:00
|
|
|
freeaddrinfo (rem);
|
2006-11-24 21:10:36 +01:00
|
|
|
return -1;
|
2006-11-23 12:22:15 +01:00
|
|
|
}
|
|
|
|
|
2010-10-21 08:48:49 +02:00
|
|
|
val = -1;
|
2006-11-24 21:10:36 +01:00
|
|
|
for (struct addrinfo *ptr = loc; ptr != NULL; ptr = ptr->ai_next)
|
|
|
|
{
|
|
|
|
int fd = net_Socket (obj, ptr->ai_family, ptr->ai_socktype,
|
2010-02-01 22:13:26 +01:00
|
|
|
ptr->ai_protocol);
|
2006-11-24 21:10:36 +01:00
|
|
|
if (fd == -1)
|
|
|
|
continue; // usually, address family not supported
|
2005-12-05 10:36:39 +01:00
|
|
|
|
2008-09-04 23:02:41 +02:00
|
|
|
fd = net_SetupDgramSocket( obj, fd, ptr );
|
|
|
|
if( fd == -1 )
|
2006-11-24 21:10:36 +01:00
|
|
|
continue;
|
2005-12-05 10:36:39 +01:00
|
|
|
|
2007-02-05 18:04:55 +01:00
|
|
|
for (struct addrinfo *ptr2 = rem; ptr2 != NULL; ptr2 = ptr2->ai_next)
|
2006-11-24 21:10:36 +01:00
|
|
|
{
|
|
|
|
if ((ptr2->ai_family != ptr->ai_family)
|
|
|
|
|| (ptr2->ai_socktype != ptr->ai_socktype)
|
|
|
|
|| (ptr2->ai_protocol != ptr->ai_protocol))
|
|
|
|
continue;
|
2005-12-05 10:36:39 +01:00
|
|
|
|
2007-02-05 18:04:55 +01:00
|
|
|
if (net_SockAddrIsMulticast (ptr->ai_addr, ptr->ai_addrlen)
|
|
|
|
? net_SourceSubscribe (obj, fd,
|
|
|
|
ptr2->ai_addr, ptr2->ai_addrlen,
|
|
|
|
ptr->ai_addr, ptr->ai_addrlen)
|
|
|
|
: connect (fd, ptr2->ai_addr, ptr2->ai_addrlen))
|
2006-11-24 21:10:36 +01:00
|
|
|
{
|
2018-07-11 15:24:42 +02:00
|
|
|
msg_Err (obj, "cannot connect to %s port %u: %s",
|
2013-12-28 17:46:52 +01:00
|
|
|
psz_server, i_server, vlc_strerror_c(net_errno));
|
2007-02-05 18:04:55 +01:00
|
|
|
continue;
|
2006-11-24 21:10:36 +01:00
|
|
|
}
|
2007-02-05 18:04:55 +01:00
|
|
|
val = fd;
|
|
|
|
break;
|
2006-11-24 21:10:36 +01:00
|
|
|
}
|
2005-12-05 10:36:39 +01:00
|
|
|
|
2007-02-05 18:04:55 +01:00
|
|
|
if (val != -1)
|
|
|
|
break;
|
2005-12-05 10:36:39 +01:00
|
|
|
|
2008-09-13 21:20:13 +02:00
|
|
|
net_Close (fd);
|
2005-12-05 10:36:39 +01:00
|
|
|
}
|
|
|
|
|
2010-04-28 22:50:08 +02:00
|
|
|
freeaddrinfo (rem);
|
|
|
|
freeaddrinfo (loc);
|
2007-02-05 18:04:55 +01:00
|
|
|
return val;
|
2005-12-05 10:36:39 +01:00
|
|
|
}
|
2007-02-05 18:04:55 +01:00
|
|
|
|
2007-09-09 21:20:39 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* net_SetCSCov:
|
|
|
|
* Sets the send and receive checksum coverage of a socket:
|
|
|
|
* @param fd socket
|
|
|
|
* @param sendcov payload coverage of sent packets (bytes), -1 for full
|
|
|
|
* @param recvcov minimum payload coverage of received packets, -1 for full
|
|
|
|
*/
|
|
|
|
int net_SetCSCov (int fd, int sendcov, int recvcov)
|
|
|
|
{
|
|
|
|
int type;
|
|
|
|
|
|
|
|
if (getsockopt (fd, SOL_SOCKET, SO_TYPE,
|
|
|
|
&type, &(socklen_t){ sizeof (type) }))
|
|
|
|
return VLC_EGENERIC;
|
|
|
|
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
#ifdef UDPLITE_RECV_CSCOV
|
|
|
|
case SOCK_DGRAM: /* UDP-Lite */
|
|
|
|
if (sendcov == -1)
|
|
|
|
sendcov = 0;
|
|
|
|
else
|
|
|
|
sendcov += 8; /* partial */
|
|
|
|
if (setsockopt (fd, SOL_UDPLITE, UDPLITE_SEND_CSCOV, &sendcov,
|
|
|
|
sizeof (sendcov)))
|
|
|
|
return VLC_EGENERIC;
|
|
|
|
|
|
|
|
if (recvcov == -1)
|
|
|
|
recvcov = 0;
|
|
|
|
else
|
|
|
|
recvcov += 8;
|
|
|
|
if (setsockopt (fd, SOL_UDPLITE, UDPLITE_RECV_CSCOV,
|
|
|
|
&recvcov, sizeof (recvcov)))
|
|
|
|
return VLC_EGENERIC;
|
|
|
|
|
|
|
|
return VLC_SUCCESS;
|
|
|
|
#endif
|
|
|
|
#ifdef DCCP_SOCKOPT_SEND_CSCOV
|
|
|
|
case SOCK_DCCP: /* DCCP and its ill-named socket type */
|
|
|
|
if ((sendcov == -1) || (sendcov > 56))
|
|
|
|
sendcov = 0;
|
|
|
|
else
|
|
|
|
sendcov = (sendcov + 3) / 4;
|
|
|
|
if (setsockopt (fd, SOL_DCCP, DCCP_SOCKOPT_SEND_CSCOV,
|
|
|
|
&sendcov, sizeof (sendcov)))
|
|
|
|
return VLC_EGENERIC;
|
|
|
|
|
2007-09-09 22:04:14 +02:00
|
|
|
if ((recvcov == -1) || (recvcov > 56))
|
|
|
|
recvcov = 0;
|
2007-09-09 21:20:39 +02:00
|
|
|
else
|
2007-09-09 22:04:14 +02:00
|
|
|
recvcov = (recvcov + 3) / 4;
|
2007-09-09 21:20:39 +02:00
|
|
|
if (setsockopt (fd, SOL_DCCP, DCCP_SOCKOPT_RECV_CSCOV,
|
|
|
|
&recvcov, sizeof (recvcov)))
|
|
|
|
return VLC_EGENERIC;
|
|
|
|
|
|
|
|
return VLC_SUCCESS;
|
|
|
|
#endif
|
|
|
|
}
|
2008-01-28 17:40:32 +01:00
|
|
|
#if !defined( UDPLITE_RECV_CSCOV ) && !defined( DCCP_SOCKOPT_SEND_CSCOV )
|
|
|
|
VLC_UNUSED(sendcov);
|
|
|
|
VLC_UNUSED(recvcov);
|
|
|
|
#endif
|
2007-09-09 21:20:39 +02:00
|
|
|
|
|
|
|
return VLC_EGENERIC;
|
|
|
|
}
|