-/*******************************************************************************
- * 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,
&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
&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 )
{
/* 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;
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 );
}
}
+