]> git.sesse.net Git - vlc/blobdiff - src/input/input_network.c
Encore un commit venu tout droit des abysses de l'enfer, d�sol� pour
[vlc] / src / input / input_network.c
index b57d7e0b155058ef3df24723b8d9f76dbbdb221b..9e932ff43ec6279a5877bd25fb9676bbed2138e4 100644 (file)
@@ -1,29 +1,48 @@
-/*******************************************************************************
- * network.c: functions to read from the network 
- * (c)1999 VideoLAN
- *******************************************************************************
+/*****************************************************************************
+ * network.c: functions to read from the network
  * Manages a socket.
- *******************************************************************************/
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ *
+ * Authors:
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *****************************************************************************/
 
-/*******************************************************************************
+/*****************************************************************************
  * Preamble
- *******************************************************************************/
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <string.h>
-#include <stdio.h>
-#include <netdb.h>      /* servent, getservbyname(), hostent, gethostbyname() */
-#include <sys/socket.h>          /* socket(), setsockopt(), bind(), connect() */
-#include <unistd.h>                                                /* close() */
-#include <netinet/in.h>                      /* sockaddr_in, htons(), htonl() */
-#include <errno.h>
-#include <sys/time.h>
-#include <unistd.h>
+ *****************************************************************************/
+#include <sys/types.h>                        /* on BSD, uio.h needs types.h */
+#include <sys/uio.h>                                            /* "input.h" */
+#include <string.h>                                            /* strerror() */
+#include <unistd.h>                                               /* close() */
+#include <errno.h>                                                  /* errno */
+#include <sys/time.h>                                   /* "input_network.h" */
+
+#ifdef SYS_BSD
+#include <sys/socket.h>                                   /* struct sockaddr */
+#endif
+
+#include <netdb.h>     /* servent, getservbyname(), hostent, gethostbyname() */
+#include <netinet/in.h>                     /* sockaddr_in, htons(), htonl() */
 
 #include "common.h"
 #include "config.h"
 #include "mtime.h"
-#include "vlc_thread.h"
+#include "threads.h"
 #include "netutils.h"
 
 #include "input.h"
 #include "input_vlan.h"
 
 #include "intf_msg.h"
+#include "main.h"
 
-/******************************************************************************
- * Local prototypes
- ******************************************************************************/
-
-
-/******************************************************************************
- * input_NetworkCreateMethod: initialize a network stream
- ******************************************************************************/
-int input_NetworkCreateMethod( input_thread_t *p_input,
-                               input_cfg_t *p_cfg )
+/*****************************************************************************
+ * input_NetworkOpen: initialize a network stream
+ *****************************************************************************/
+int input_NetworkOpen( input_thread_t *p_input )
 {
-    int                     i_socket_option, i_port, i_dummy;
+    int                     i_socket_option;
     struct sockaddr_in      sa_in;
-    char                    psz_hostname[INPUT_MAX_HOSTNAME_LENGTH];
+    char                    psz_hostname[INPUT_MAX_SOURCE_LENGTH];
 
-    /* First and foremost, in the VLAN method, we join the desired VLAN. */
+    /* First and foremost, in the VLAN method, join the desired VLAN. */
     if( p_input->i_method == INPUT_METHOD_TS_VLAN_BCAST )
     {
-        /* Get a VLAN ID (VlanLib). */
-        if( ( p_input->i_vlan_id = input_VlanId( NULL, p_cfg->i_vlan ) )
-                == (-1) )
-        {
-            intf_ErrMsg("input error: VlanId() failed (%d)\n",
-                        p_input->i_vlan_id);
-            return( -1 );
-        }
-        /* Join the VLAN. */
-        if( ( i_dummy = input_VlanJoin( p_input->i_vlan_id ) ) != 0 )
+        if( input_VlanJoin( p_input->i_vlan ) )
         {
-            intf_ErrMsg("input error: VlanJoin() failed (%d)\n",
-                        i_dummy);
-            return( -1 );
+            intf_ErrMsg("error: can't join vlan %d\n", p_input->i_vlan);
+            return( 1 );
         }
     }
 
-    /* We open a SOCK_DGRAM (UDP) socket, in the AF_INET domain, automatic (0)
+    /* Open a SOCK_DGRAM (UDP) socket, in the AF_INET domain, automatic (0)
      * protocol */
     if( (p_input->i_handle = socket( AF_INET, SOCK_DGRAM, 0 )) == (-1) )
     {
-        intf_ErrMsg("input error: socket() error (%s)\n",
-                    strerror(errno));
-        return( -1 );
+        intf_ErrMsg("error: can't create socket (%s)\n", strerror(errno));
+        return( 1 );
     }
 
-    intf_DbgMsg("input debug: socket %d opened (cfg: %p)\n", p_input->i_handle,
-               p_cfg);
+    /*
+     * Set up the options of the socket
+     */
 
-    /* we set up the options of our socket. It doesn't need to be non-blocking,
-     * on the contrary (when this thread is waiting for data, it doesn't have
-     * the lock, so decoders can work. */
-
-    /* set SO_REUSEADDR option which allows to re-bind() a busy port */
+    /* Set SO_REUSEADDR option which allows to re-bind() a busy port */
     i_socket_option = 1;
     if( setsockopt( p_input->i_handle,
                     SOL_SOCKET,
@@ -91,10 +91,9 @@ int input_NetworkCreateMethod( input_thread_t *p_input,
                     &i_socket_option,
                     sizeof( i_socket_option ) ) == (-1) )
     {
-        intf_ErrMsg("input error: setsockopt(SO_REUSEADDR) error (%s)\n",
-                    strerror(errno));
+        intf_ErrMsg("error: can't configure socket (%s)\n", strerror(errno));
         close( p_input->i_handle );
-        return( -1 );
+        return( 1 );
     }
 
     /* Increase the receive buffer size to 1/2MB (8Mb/s during 1/2s) to avoid
@@ -106,148 +105,115 @@ int input_NetworkCreateMethod( input_thread_t *p_input,
                     &i_socket_option,
                     sizeof( i_socket_option ) ) == (-1) )
     {
-        intf_ErrMsg("input error: setsockopt(SO_RCVBUF) error (%s)\n",
-                    strerror(errno));
+        intf_ErrMsg("error: can't configure socket (%s)\n", strerror(errno));
         close( p_input->i_handle );
-        return( -1 );
+        return( 1 );
     }
-    
-    /* Now, we bind the socket. */
 
-    /* Find the port. */
-    if( p_cfg->i_properties & INPUT_CFG_PORT )
+    /*
+     * Bind the socket
+     */
+
+    /* Use default port if not specified */
+    if( p_input->i_port == 0 )
     {
-        i_port = p_cfg->i_port;
-        intf_DbgMsg("input debug: using port %d\n", i_port);
-    }
-    else
-    {
-#ifdef VIDEOLAN_DEFAULT_PORT
-        /* default port */
-        i_port = VIDEOLAN_DEFAULT_PORT;
-        intf_DbgMsg("input debug: using default port (%d)\n", i_port);
-#else
-        intf_ErrMsg("input error: no default port\n");
-        return( -1 );
-#endif
+        p_input->i_port = main_GetIntVariable( INPUT_PORT_VAR, INPUT_PORT_DEFAULT );
     }
 
     /* Find the address. */
     switch( p_input->i_method )
     {
-        case INPUT_METHOD_TS_BCAST:
-        case INPUT_METHOD_TS_VLAN_BCAST:
-            /* In that case, we have to bind with the broadcast address.
-             * broadcast addresses are very hard to find and depends on
-             * implementation, so we thought using a #define would be much
-             * simpler. */
+    case INPUT_METHOD_TS_BCAST:
+    case INPUT_METHOD_TS_VLAN_BCAST:
+        /* In that case, we have to bind with the broadcast address.
+         * broadcast addresses are very hard to find and depends on
+         * implementation, so we thought using a #define would be much
+         * simpler. */
 #ifdef INPUT_BCAST_ADDR
-            if( BuildInetAddr( &sa_in, INPUT_BCAST_ADDR, i_port ) == (-1) )
-            {                                               /* see netutils.c */
-                close( p_input->i_handle );
-                return( -1 );
-            }
+        if( BuildInetAddr( &sa_in, INPUT_BCAST_ADDR, p_input->i_port ) == (-1) )
+        {
+            close( p_input->i_handle );
+            return( 1 );
+        }
 #else
-            /* We bind with any address. Security problem ! */
-            if( BuildInetAddr( &sa_in, NULL, i_port ) == (-1) )
-            {
-                close( p_input->i_handle );
-                return( -1 ),
-            }
+        /* We bind with any address. Security problem ! */
+        if( BuildInetAddr( &sa_in, NULL, p_input->i_port ) == (-1) )
+        {
+            close( p_input->i_handle );
+            return( -1 );
+        }
 #endif
-            break;
+        break;
 
-        case INPUT_METHOD_TS_UCAST:
-            /* We bind with the local address. */
-            if( gethostname( psz_hostname, sizeof( psz_hostname ) ) == (-1) )
-            {
-                intf_ErrMsg("input error: gethostname failed (%s)\n",
-                            strerror(errno));
-                close( p_input->i_handle );
-                return( -1 );
-            }
-            if( BuildInetAddr( &sa_in, psz_hostname, i_port ) == (-1) )
-            {
-                close( p_input->i_handle );
-                return( -1 );
-            }
-            break;
-        case INPUT_METHOD_TS_MCAST:
-            /* We bind with 239.0.0.1. */
-            if( BuildInetAddr( &sa_in, "239.0.0.1", i_port ) == (-1) )
-            {
-                close( p_input->i_handle );
-                return( -1 );
-            }
-            break;
+    case INPUT_METHOD_TS_UCAST:
+        /* Unicast: bind with the local address. */
+        if( gethostname( psz_hostname, sizeof( psz_hostname ) ) == (-1) )
+        {
+            intf_ErrMsg("error: can't get hostname (%s)\n", strerror(errno));
+            close( p_input->i_handle );
+            return( 1 );
+        }
+        if( BuildInetAddr( &sa_in, psz_hostname, p_input->i_port ) == (-1) )
+        {
+            close( p_input->i_handle );
+            return( 1 );
+        }
+        break;
+
+    case INPUT_METHOD_TS_MCAST:
+        /* Multicast: bind with 239.0.0.1. */
+        if( BuildInetAddr( &sa_in, "239.0.0.1", p_input->i_port ) == (-1) )
+        {
+            close( p_input->i_handle );
+            return( 1 );
+        }
+        break;
     }
 
     /* Effectively bind the socket. */
-    if( bind( p_input->i_handle,
-              (struct sockaddr *) &sa_in,
-              sizeof( sa_in ) ) < 0 )
+    if( bind( p_input->i_handle, (struct sockaddr *) &sa_in, sizeof( sa_in ) ) < 0 )
     {
-        intf_ErrMsg("input error: bind() failed (%s)\n",
-                    strerror(errno));
+        intf_ErrMsg("error: can't bind socket (%s)\n", strerror(errno));
         close( p_input->i_handle );
-        return( -1 );
+        return( 1 );
     }
 
-    /* Connect the socket to the remote server. */
+    /*
+     * Connect the socket to the remote server
+     */
 
-    /* Find which server we have to use. */
-    if( p_cfg->i_properties & INPUT_CFG_HOSTNAME )
+    /* Use default host if not specified */
+    if( p_input->psz_source == NULL )
     {
-        if( BuildInetAddr( &sa_in, p_cfg->psz_hostname, htons(0) ) == (-1) )
-        {
-            close( p_input->i_handle );
-            return( -1 );
-        }
-    }
-    else if( p_cfg->i_properties & INPUT_CFG_IP )
-    {
-        if( BuildInetAddr( &sa_in, p_cfg->psz_ip, htons(0) ) == (-1) )
-        {
-            close( p_input->i_handle );
-            return( -1 );
-        }
+        p_input->psz_source = main_GetPszVariable( INPUT_SERVER_VAR, INPUT_SERVER_DEFAULT );
     }
-    else
+
+    if( BuildInetAddr( &sa_in, p_input->psz_source, htons(0) ) == (-1) )
     {
-#ifdef VIDEOLAN_DEFAULT_SERVER
-        /* default server */
-        if( BuildInetAddr( &sa_in, VIDEOLAN_DEFAULT_SERVER, htons(0) ) == (-1) )
-        {
-            close( p_input->i_handle );
-            return( -1 );
-        }
-#else
-        intf_ErrMsg("input error: no default videolan server\n");
+        close( p_input->i_handle );
         return( -1 );
-#endif
     }
 
-    /* Effectively connect the socket. */
-    if( connect( p_input->i_handle,
-                 (struct sockaddr *) &sa_in,
+    /* Connect the socket. */
+    if( connect( p_input->i_handle, (struct sockaddr *) &sa_in,
                  sizeof( sa_in ) ) == (-1) )
     {
-        intf_ErrMsg("input error: connect() failed\n");
+        intf_ErrMsg("error: can't connect socket\n" );
         close( p_input->i_handle );
-        return( -1 );
+        return( 1 );
     }
     return( 0 );
 }
 
-/******************************************************************************
+/*****************************************************************************
  * input_NetworkRead: read a stream from the network
- ******************************************************************************
+ *****************************************************************************
  * Wait for data during up to 1 second and then abort if none is arrived. The
  * number of bytes read is returned or -1 if an error occurs (so 0 is returned
  * after a timeout)
  * We don't have to make any test on presentation times, since we suppose
  * the network server sends us data when we need it.
- ******************************************************************************/
+ *****************************************************************************/
 int input_NetworkRead( input_thread_t *p_input, const struct iovec *p_vector,
                        size_t i_count )
 {
@@ -258,7 +224,7 @@ int input_NetworkRead( input_thread_t *p_input, const struct iovec *p_vector,
     /* Watch the given fd to see when it has input */
     FD_ZERO(&rfds);
     FD_SET(p_input->i_handle, &rfds);
-  
+
     /* Wait up to 1 second */
     tv.tv_sec = 1;
     tv.tv_usec = 0;
@@ -274,24 +240,21 @@ int input_NetworkRead( input_thread_t *p_input, const struct iovec *p_vector,
     return( i_rc );
 }
 
-/******************************************************************************
- * input_NetworkDestroyMethod: close a network stream
- ******************************************************************************/
-void input_NetworkDestroyMethod( input_thread_t *p_input )
+/*****************************************************************************
+ * input_NetworkClose: close a network stream
+ *****************************************************************************/
+void input_NetworkClose( input_thread_t *p_input )
 {
     /* Close local socket. */
     if( p_input->i_handle )
     {
-        if( close( p_input->i_handle) == (-1) )
-        {
-            intf_ErrMsg("input error: can't close network socket (%s)\n",
-                        strerror(errno) );
-        }
+        close( p_input->i_handle );
     }
 
-    /* In case of VLAN method, leave the current VLAN. */
+    /* Leave vlan if required */
     if( p_input->i_method == INPUT_METHOD_TS_VLAN_BCAST )
     {
-        input_VlanLeave( p_input->i_vlan_id );
+        input_VlanLeave( p_input->i_vlan );
     }
 }
+