]> git.sesse.net Git - vlc/commitdiff
Major rewrite of the network layer. The following syntax ARE NO LONGER
authorChristophe Massiot <massiot@videolan.org>
Fri, 23 Nov 2001 18:47:51 +0000 (18:47 +0000)
committerChristophe Massiot <massiot@videolan.org>
Fri, 23 Nov 2001 18:47:51 +0000 (18:47 +0000)
SUPPORTED :
ts:toto:1234/meuh
--server toto --broadcast meuh --port 1234

The only supported syntax is :
udp[stream]:[//][serveraddr:[serverport]][@[bindaddr][:bindport]]
example : udpstream:toto@meuh:toto

In most cases, simply passing "udpstream:" should work, since it enables
unicast and broadcast reception on port 1234 from any server. Other
options are only used for fine tuning and multicast.

TODO :
* The GTK interface is broken (glade knowledge wanted !)
* Test this on all supported platforms (and fix them :)
[this won't work with current channel servers - fix needed]

include/netutils.h
plugins/mpeg/input_ts.c
src/input/input.c
src/interface/main.c
src/misc/netutils.c

index 4f994d61a07d64f512bb55674e366296f7e362fb..b9c2f2ed2484e006b05ea24bde810f5334cb32bc 100644 (file)
@@ -4,7 +4,7 @@
  * modules.
  *****************************************************************************
  * Copyright (C) 1999, 2000, 2001 VideoLAN
- * $Id: netutils.h,v 1.16 2001/11/12 04:12:37 sam Exp $
+ * $Id: netutils.h,v 1.17 2001/11/23 18:47:51 massiot Exp $
  *
  * Authors: Vincent Seguin <seguin@via.ecp.fr>
  *          Henri Fallon <henri@videolan.org>
@@ -31,8 +31,7 @@
  * Prototypes
  *****************************************************************************/
 struct sockaddr_in;
-int   network_BuildLocalAddr  ( struct sockaddr_in *, int, char * ); 
-int   network_BuildRemoteAddr ( struct sockaddr_in *, char * );
+int   network_BuildAddr       ( struct sockaddr_in *, char *, int ); 
 int   network_ChannelJoin     ( int );
 int   network_ChannelCreate   ( void );
 
index 9516d2e7da5d0d9150c8fe31ac24acf5eeb19292..30050dfe4dcd0ce08a5f7979a199af24d5755e10 100644 (file)
@@ -2,7 +2,7 @@
  * input_ts.c: TS demux and netlist management
  *****************************************************************************
  * Copyright (C) 1998, 1999, 2000 VideoLAN
- * $Id: input_ts.c,v 1.36 2001/11/11 01:32:03 stef Exp $
+ * $Id: input_ts.c,v 1.37 2001/11/23 18:47:51 massiot Exp $
  *
  * Authors: Henri Fallon <henri@videolan.org>
  *
@@ -133,9 +133,10 @@ static int TSProbe( probedata_t * p_data )
         return( 999 );
     }
 
-    if( ( strlen(psz_name) > 3 ) && !strncasecmp( psz_name, "ts:", 3 ) )
+    if( ( strlen(psz_name) >= 10 && !strncasecmp( psz_name, "udpstream:", 10 ) )
+            || ( strlen(psz_name) >= 4 && !strncasecmp( psz_name, "udp:", 4 ) ) )
     {
-        /* If the user specified "ts:" then it's probably a network stream */
+        /* If the user specified "udp:" then it's probably a network stream */
         return( 999 );
     }
 
index f15b9d80e4c1e708da28463a1bfd671edc6ae9aa..be51d8a5456d74f971d66331f6fb7a8047fc2c54 100644 (file)
@@ -4,7 +4,7 @@
  * decoders.
  *****************************************************************************
  * Copyright (C) 1998, 1999, 2000 VideoLAN
- * $Id: input.c,v 1.157 2001/11/21 16:47:46 massiot Exp $
+ * $Id: input.c,v 1.158 2001/11/23 18:47:51 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
@@ -419,8 +419,10 @@ static int InitThread( input_thread_t * p_input )
 
 #if !defined( SYS_BEOS ) && !defined( SYS_NTO )
     /* FIXME : this is waaaay too kludgy */
-    if( ( strlen( p_input->p_source ) > 3)
-          && !strncasecmp( p_input->p_source, "ts:", 3 ) )
+    if( ( strlen( p_input->p_source ) >= 10
+          && !strncasecmp( p_input->p_source, "udpstream:", 10 ) )
+          || ( strlen( p_input->p_source ) >= 4
+                && !strncasecmp( p_input->p_source, "udp:", 4 ) ) )
     {
         /* Network stream */
         NetworkOpen( p_input );
@@ -549,8 +551,10 @@ static void CloseThread( input_thread_t * p_input )
 
 #if !defined( SYS_BEOS ) && !defined( SYS_NTO )
     /* Close stream */
-    if( ( strlen( p_input->p_source ) > 3)
-          && !strncasecmp( p_input->p_source, "ts:", 3 ) )
+    if( ( strlen( p_input->p_source ) > 10
+          && !strncasecmp( p_input->p_source, "udpstream:", 10 ) )
+          || ( strlen( p_input->p_source ) > 4
+                && !strncasecmp( p_input->p_source, "udp:", 4 ) ) )
     {
         NetworkClose( p_input );
     }
@@ -726,77 +730,107 @@ static void FileClose( input_thread_t * p_input )
 static void NetworkOpen( input_thread_t * p_input )
 {
     char                *psz_server = NULL;
-    char                *psz_broadcast = NULL;
-    int                 i_port = 0;
+    char                *psz_bind = NULL;
+    int                 i_server_port = 0;
+    int                 i_bind_port = 0;
     int                 i_opt;
     int                 i_opt_size;
     struct sockaddr_in  sock;
 
-    /* Get the remote server */
+    /* Get the remote server. Syntax is :
+     * udp[stream]:[/][/][serveraddr[:serverport]][@[bindaddr]:[bindport]] */
     if( p_input->p_source != NULL )
     {
-        psz_server = p_input->p_source;
+        char * psz_parser = p_input->p_source;
+        char * psz_server_port = NULL;
+        char * psz_bind_port = NULL;
 
         /* Skip the protocol name */
-        while( *psz_server && *psz_server != ':' )
+        while( *psz_parser && *psz_parser != ':' )
         {
-            psz_server++;
+            psz_parser++;
         }
 
         /* Skip the "://" part */
-        while( *psz_server && (*psz_server == ':' || *psz_server == '/') )
+        while( *psz_parser && (*psz_parser == ':' || *psz_parser == '/') )
         {
-            psz_server++;
+            psz_parser++;
         }
 
-        /* Found a server name */
-        if( *psz_server )
+        if( *psz_parser && *psz_parser != '@' )
         {
-            char *psz_port = psz_server;
+            /* Found server */
+            psz_server = psz_parser;
 
-            /* Skip the hostname part */
-            while( *psz_port && *psz_port != ':' && *psz_port != '/' )
+            while( *psz_parser && *psz_parser != ':' && *psz_parser != '@' )
             {
-                psz_port++;
+                psz_parser++;
             }
 
-            /* Found a port name or a broadcast addres */
-            if( *psz_port )
+            if( *psz_parser == ':' )
             {
-                /* That's a port name */
-                if( *psz_port == ':' )
-                {
-                    *psz_port = '\0';
-                    psz_port++;
-                    i_port = atoi( psz_port );
-                }
+                /* Found server port */
+                *psz_parser = '\0'; /* Terminate server name */
+                psz_parser++;
+                psz_server_port = psz_parser;
 
-                /* Search for '/' just after the port in case
-                 * we also have a broadcast address */
-                psz_broadcast = psz_port;
-                while( *psz_broadcast && *psz_broadcast != '/' )
+                while( *psz_parser && *psz_parser != '@' )
                 {
-                    psz_broadcast++;
+                    psz_parser++;
                 }
+            }
+        }
 
-                if( *psz_broadcast )
-                {
-                    *psz_broadcast = '\0';
-                    psz_broadcast++;
-                    while( *psz_broadcast && *psz_broadcast == '/' )
-                    {
-                        psz_broadcast++;
-                    }
-                }
-                else
+        if( *psz_parser == '@' )
+        {
+            /* Found bind address or bind port */
+            *psz_parser = '\0'; /* Terminate server port or name if necessary */
+            psz_parser++;
+
+            if( *psz_parser && *psz_parser != ':' )
+            {
+                /* Found bind address */
+                psz_bind = psz_parser;
+
+                while( *psz_parser && *psz_parser != ':' )
                 {
-                    psz_broadcast = NULL;
+                    psz_parser++;
                 }
             }
+
+            if( *psz_parser == ':' )
+            {
+                /* Found bind port */
+                *psz_parser = '\0'; /* Terminate bind address if necessary */
+                psz_parser++;
+
+                psz_bind_port = psz_parser;
+            }
         }
-        else
+
+        /* Convert ports format */
+        if( psz_server_port != NULL )
         {
-            psz_server = NULL;
+            i_server_port = strtol( psz_server_port, &psz_parser, 10 );
+            if( *psz_parser )
+            {
+                intf_ErrMsg( "input error: cannot parse server port near %s",
+                             psz_parser );
+                p_input->b_error = 1;
+                return;
+            }
+        }
+
+        if( psz_bind_port != NULL )
+        {
+            i_bind_port = strtol( psz_bind_port, &psz_parser, 10 );
+            if( *psz_parser )
+            {
+                intf_ErrMsg( "input error: cannot parse bind port near %s",
+                             psz_parser );
+                p_input->b_error = 1;
+                return;
+            }
         }
     }
     else
@@ -805,36 +839,14 @@ static void NetworkOpen( input_thread_t * p_input )
         p_input->p_source = "ts: network input";
     }
 
-    /* Check that we got a valid server */
-    if( psz_server == NULL )
-    {
-        psz_server = main_GetPszVariable( INPUT_SERVER_VAR, 
-                                          INPUT_SERVER_DEFAULT );
-    }
-
     /* Check that we got a valid port */
-    if( i_port == 0 )
-    {
-        i_port = main_GetIntVariable( INPUT_PORT_VAR, INPUT_PORT_DEFAULT );
-    }
-
-    if( psz_broadcast == NULL )
+    if( i_bind_port == 0 )
     {
-        /* Are we broadcasting ? */
-        if( main_GetIntVariable( INPUT_BROADCAST_VAR,
-                                 INPUT_BROADCAST_DEFAULT ) )
-        {
-            psz_broadcast = main_GetPszVariable( INPUT_BCAST_ADDR_VAR,
-                                                 INPUT_BCAST_ADDR_DEFAULT );
-        }
-        else
-        {
-            psz_broadcast = NULL; 
-        }
+        i_bind_port = main_GetIntVariable( INPUT_PORT_VAR, INPUT_PORT_DEFAULT );
     }
 
-    intf_WarnMsg( 2, "input: server=%s port=%d broadcast=%s",
-                     psz_server, i_port, psz_broadcast );
+    intf_WarnMsg( 2, "input: server=%s:%d local=%s:%d",
+                     psz_server, i_server_port, psz_bind, i_bind_port );
 
     /* Open a SOCK_DGRAM (UDP) socket, in the AF_INET domain, automatic (0)
      * protocol */
@@ -864,7 +876,7 @@ static void NetworkOpen( input_thread_t * p_input )
     if( setsockopt( p_input->i_handle, SOL_SOCKET, SO_RCVBUF,
                     (void *) &i_opt, sizeof( i_opt ) ) == -1 )
     {
-        intf_WarnMsg( 1, "input error: can't configure socket (SO_RCVBUF: %s)", 
+        intf_WarnMsg( 1, "input warning: can't configure socket (SO_RCVBUF: %s)", 
                          strerror(errno));
     }
 
@@ -876,7 +888,7 @@ static void NetworkOpen( input_thread_t * p_input )
     if( getsockopt( p_input->i_handle, SOL_SOCKET, SO_RCVBUF,
                     (void*) &i_opt, &i_opt_size ) == -1 )
     {
-        intf_WarnMsg( 1, "input error: can't query socket (SO_RCVBUF: %s)", 
+        intf_WarnMsg( 1, "input warning: can't query socket (SO_RCVBUF: %s)", 
                          strerror(errno));
     }
     else if( i_opt < 0x80000 )
@@ -886,7 +898,7 @@ static void NetworkOpen( input_thread_t * p_input )
     }
 
     /* Build the local socket */
-    if ( network_BuildLocalAddr( &sock, i_port, psz_broadcast ) == -1 )
+    if ( network_BuildAddr( &sock, psz_bind, i_bind_port ) == -1 )
     {
         intf_ErrMsg( "input error: can't build local address" );
         close( p_input->i_handle );
@@ -904,14 +916,26 @@ static void NetworkOpen( input_thread_t * p_input )
         return;
     }
 
-    /* Join the multicast group if the socket is a multicast address */
+    /* Allow broadcast reception if we bound on INADDR_ANY */
+    if( psz_bind == NULL )
+    {
+        i_opt = 1;
+        if( setsockopt( p_input->i_handle, SOL_SOCKET, SO_BROADCAST,
+                        (void*) &i_opt, sizeof( i_opt ) ) == -1 )
+        {
+            intf_WarnMsg( 1, "input warning: can't configure socket (SO_BROADCAST: %s)", 
+                             strerror(errno));
+        }
+    }
 
-#if defined( WIN32 )
+    /* Join the multicast group if the socket is a multicast address */
+#ifndef IN_MULTICAST
 #   define IN_MULTICAST(a)         IN_CLASSD(a)
 #endif
 
     /* TODO : make this compile under Win32 */
-#ifndef WIN32    
+    /* Enabled this so that windows people have a serious look at it :)) */
+//#ifndef WIN32    
     if( IN_MULTICAST( ntohl(sock.sin_addr.s_addr) ) )
     {
         struct ip_mreq imr;
@@ -923,24 +947,23 @@ static void NetworkOpen( input_thread_t * p_input )
         {
             intf_ErrMsg( "input error: failed to join IP multicast group (%s)",
                          strerror(errno) );
-            close( p_input->i_handle);
+            close( p_input->i_handle );
             p_input->b_error = 1;
             return;
         }
     }
     
-    /* Build socket for remote connection */
-    if ( network_BuildRemoteAddr( &sock, psz_server ) == -1 )
+    if( psz_server != NULL )
     {
-        intf_ErrMsg( "input error: can't build remote address" );
-        close( p_input->i_handle );
-        p_input->b_error = 1;
-        return;
-    }
+        /* Build socket for remote connection */
+        if ( network_BuildAddr( &sock, psz_server, i_server_port ) == -1 )
+        {
+            intf_ErrMsg( "input error: can't build remote address" );
+            close( p_input->i_handle );
+            p_input->b_error = 1;
+            return;
+        }
 
-    /* Only connect if the user has passed a valid host */
-    if( sock.sin_addr.s_addr != INADDR_ANY )
-    {
         /* Connect the socket */
         if( connect( p_input->i_handle, (struct sockaddr *) &sock,
                      sizeof( sock ) ) == (-1) )
@@ -952,7 +975,7 @@ static void NetworkOpen( input_thread_t * p_input )
             return;
         }
     }
-#endif
+//#endif
 
     p_input->stream.b_pace_control = 0;
     p_input->stream.b_seekable = 0;
@@ -1153,26 +1176,24 @@ static void HTTPOpen( input_thread_t * p_input )
         }
 
         /* Build socket for proxy connection */
-        if ( network_BuildRemoteAddr( &sock, psz_proxy ) == -1 )
+        if ( network_BuildAddr( &sock, psz_proxy, i_proxy_port ) == -1 )
         {
             intf_ErrMsg( "input error: can't build remote address" );
             close( p_input->i_handle );
             p_input->b_error = 1;
             return;
         }
-        sock.sin_port = htons( i_proxy_port );
     }
     else
     {
         /* No proxy, direct connection */
-        if ( network_BuildRemoteAddr( &sock, psz_server ) == -1 )
+        if ( network_BuildAddr( &sock, psz_server, i_port ) == -1 )
         {
             intf_ErrMsg( "input error: can't build remote address" );
             close( p_input->i_handle );
             p_input->b_error = 1;
             return;
         }
-        sock.sin_port = htons( i_port );
     }
 
     /* Connect the socket */
index 1f2d4a4b7b40a30f0c64e09d42eb12c57cfd6143..aaaa16484048060ccf64c08b22c77790fe8b4ec6 100644 (file)
@@ -4,7 +4,7 @@
  * and spawn threads.
  *****************************************************************************
  * Copyright (C) 1998, 1999, 2000 VideoLAN
- * $Id: main.c,v 1.125 2001/11/14 00:01:36 jlj Exp $
+ * $Id: main.c,v 1.126 2001/11/23 18:47:51 massiot Exp $
  *
  * Authors: Vincent Seguin <seguin@via.ecp.fr>
  *          Samuel Hocevar <sam@zoy.org>
@@ -213,9 +213,6 @@ static const struct option longopts[] =
     
     /* Input options */
     {   "input",            1,          0,      OPT_INPUT },
-    {   "server",           1,          0,      OPT_SERVER },
-    {   "port",             1,          0,      OPT_PORT },
-    {   "broadcast",        1,          0,      OPT_BROADCAST },
     {   "channels",         0,          0,      OPT_CHANNELS },
     {   "channelserver",    1,          0,      OPT_CHANNELSERVER },
 
@@ -792,16 +789,6 @@ static int GetConfiguration( int *pi_argc, char *ppsz_argv[], char *ppsz_env[] )
         case OPT_CHANNELSERVER:                           /* --channelserver */
             main_PutPszVariable( INPUT_CHANNEL_SERVER_VAR, optarg );
             break;
-        case OPT_SERVER:                                         /* --server */
-            main_PutPszVariable( INPUT_SERVER_VAR, optarg );
-            break;
-        case OPT_PORT:                                             /* --port */
-            main_PutPszVariable( INPUT_PORT_VAR, optarg );
-            break;
-        case OPT_BROADCAST:                                   /* --broadcast */
-            main_PutIntVariable( INPUT_BROADCAST_VAR, 1 );
-            main_PutPszVariable( INPUT_BCAST_ADDR_VAR, optarg );
-            break;
 
         /* Synchro options */
         case OPT_SYNCHRO:                                      
@@ -916,9 +903,6 @@ static void Usage( int i_fashion )
           "\n      --input                    \tinput method"
           "\n      --channels                 \tenable channels"
           "\n      --channelserver <host>     \tchannel server address"
-          "\n      --server <host>            \tvideo server address"
-          "\n      --port <port>              \tvideo server port"
-          "\n      --broadcast                \tlisten to a broadcast"
           "\n"
           "\n  -h, --help                     \tprint help and exit"
           "\n  -H, --longhelp                 \tprint long help and exit"
@@ -974,10 +958,7 @@ static void Usage( int i_fashion )
 
     /* Input parameters */
     intf_MsgImm( "\nInput parameters:"
-        "\n  " INPUT_SERVER_VAR "=<hostname>          \tvideo server"
-        "\n  " INPUT_PORT_VAR "=<port>            \tvideo server port"
         "\n  " INPUT_IFACE_VAR "=<interface>          \tnetwork interface"
-        "\n  " INPUT_BCAST_ADDR_VAR "=<addr>          \tbroadcast mode"
         "\n  " INPUT_CHANNEL_SERVER_VAR "=<hostname>  \tchannel server"
         "\n  " INPUT_CHANNEL_PORT_VAR "=<port>        \tchannel server port" );
 
index 9fad55069289b7f4abfbad407f1655f348043399..0e3479d3f05424575cbf404362ce82d03b4f0fbb 100644 (file)
@@ -2,7 +2,7 @@
  * netutils.c: various network functions
  *****************************************************************************
  * Copyright (C) 1999, 2000, 2001 VideoLAN
- * $Id: netutils.c,v 1.48 2001/11/21 22:33:03 jlj Exp $
+ * $Id: netutils.c,v 1.49 2001/11/23 18:47:51 massiot Exp $
  *
  * Authors: Vincent Seguin <seguin@via.ecp.fr>
  *          Benoit Steiner <benny@via.ecp.fr>
@@ -109,10 +109,10 @@ static int GetAdapterInfo  ( int i_adapter, char *psz_string );
 #endif
 
 /*****************************************************************************
- * network_BuildLocalAddr : fill a sockaddr_in structure for local binding
+ * network_BuildAddr : fill a sockaddr_in structure
  *****************************************************************************/
-int network_BuildLocalAddr( struct sockaddr_in * p_socket, int i_port,
-                            char * psz_broadcast )
+int network_BuildAddr( struct sockaddr_in * p_socket,
+                       char * psz_address, int i_port )
 {
 #if defined( SYS_BEOS )
     intf_ErrMsg( "error: networking is not yet supported under BeOS" );
@@ -123,7 +123,7 @@ int network_BuildLocalAddr( struct sockaddr_in * p_socket, int i_port,
     memset( p_socket, 0, sizeof( struct sockaddr_in ) );
     p_socket->sin_family = AF_INET;                                /* family */
     p_socket->sin_port = htons( i_port );
-    if( psz_broadcast == NULL )
+    if( psz_address == NULL )
     {
         p_socket->sin_addr.s_addr = INADDR_ANY;
     }
@@ -134,15 +134,15 @@ int network_BuildLocalAddr( struct sockaddr_in * p_socket, int i_port,
         /* Try to convert address directly from in_addr - this will work if
          * psz_broadcast is dotted decimal. */
 #ifdef HAVE_ARPA_INET_H
-        if( !inet_aton( psz_broadcast, &p_socket->sin_addr) )
+        if( !inet_aton( psz_address, &p_socket->sin_addr) )
 #else
-        if( (p_socket->sin_addr.s_addr = inet_addr( psz_broadcast )) == -1 )
+        if( (p_socket->sin_addr.s_addr = inet_addr( psz_address )) == -1 )
 #endif
         {
             /* We have a fqdn, try to find its address */
-            if ( (p_hostent = gethostbyname( psz_broadcast )) == NULL )
+            if ( (p_hostent = gethostbyname( psz_address )) == NULL )
             {
-                intf_ErrMsg( "BuildLocalAddr: unknown host %s", psz_broadcast );
+                intf_ErrMsg( "BuildLocalAddr: unknown host %s", psz_address );
                 return( -1 );
             }
 
@@ -155,48 +155,6 @@ int network_BuildLocalAddr( struct sockaddr_in * p_socket, int i_port,
 #endif
 }
 
-/*****************************************************************************
- * network_BuildRemoteAddr : fill a sockaddr_in structure for remote host
- *****************************************************************************/
-int network_BuildRemoteAddr( struct sockaddr_in * p_socket, char * psz_server )
-{
-#if defined( SYS_BEOS )
-    intf_ErrMsg( "error: networking is not yet supported under BeOS" );
-    return( 1 );
-
-#else
-    struct hostent            * p_hostent;
-
-    /* Reset structure */
-    memset( p_socket, 0, sizeof( struct sockaddr_in ) );
-    p_socket->sin_family = AF_INET;                                /* family */
-    p_socket->sin_port = htons( 0 );               /* This is for remote end */
-
-     /* Try to convert address directly from in_addr - this will work if
-      * psz_in_addr is dotted decimal. */
-
-#ifdef HAVE_ARPA_INET_H
-    if( !inet_aton( psz_server, &p_socket->sin_addr) )
-#else
-    if( (p_socket->sin_addr.s_addr = inet_addr( psz_server )) == -1 )
-#endif
-    {
-        /* We have a fqdn, try to find its address */
-        if ( (p_hostent = gethostbyname(psz_server)) == NULL )
-        {
-            intf_ErrMsg( "BuildRemoteAddr: unknown host %s",
-                         psz_server );
-            return( -1 );
-        }
-
-        /* Copy the first address of the host in the socket address */
-        memcpy( &p_socket->sin_addr, p_hostent->h_addr_list[0],
-                 p_hostent->h_length );
-    }
-    return( 0 );
-#endif
-}
-
 /*****************************************************************************
  * network_ChannelCreate: initialize global channel method data
  *****************************************************************************