Commit 92c69994 authored by Vincent Seguin's avatar Vincent Seguin

Changement de chaine. Delicat encore, mais il marche. Quelques corrections

esthetiques, un timeout pour les vlans et le frame buffer et c'est la
release d�mo (en ce qui me concerne) !
parent 07686534
......@@ -47,11 +47,11 @@ typedef struct intf_msg_s * p_intf_msg_t;
/* Input */
struct input_thread_s;
struct input_vlan_method_s;
struct input_vlan_s;
struct input_cfg_s;
typedef struct input_thread_s * p_input_thread_t;
typedef struct input_vlan_method_s * p_input_vlan_method_t;
typedef struct input_vlan_s * p_input_vlan_t;
typedef struct input_cfg_s * p_input_cfg_t;
/* Audio */
......
......@@ -181,18 +181,18 @@
/* Use a LIFO or FIFO for PES netlist ? */
#undef INPUT_LIFO_PES_NETLIST
/* Maximum length of a hostname */
#define INPUT_MAX_HOSTNAME_LENGTH 100
/* Maximum length of a hostname or source name */
#define INPUT_MAX_SOURCE_LENGTH 100
/* Default input method */
#define INPUT_DEFAULT_METHOD INPUT_METHOD_TS_UCAST
/* Default remote server */
#define VIDEOLAN_DEFAULT_SERVER "vod.via.ecp.fr"
#define INPUT_DEFAULT_SERVER "138.195.143.220"
/* Default videolan port */
#define VIDEOLAN_DEFAULT_PORT 1234
/* Default input port */
#define INPUT_DEFAULT_PORT 1234
/* Default videolan VLAN */
#define VIDEOLAN_DEFAULT_VLAN 3
......@@ -201,9 +201,15 @@
* Vlan method
*/
/* Default VLAN server */
#define VLAN_DEFAULT_SERVER "vlanserver.via.ecp.fr"
#define VLAN_DEFAULT_SERVER_PORT 6010
/* Default network interface and environment variable */
#define INPUT_IFACE_VAR "vlc_iface"
#define INPUT_IFACE_DEFAULT "eth0"
/* Default server and port */
#define INPUT_VLAN_SERVER_VAR "vlc_vlan_server"
#define INPUT_VLAN_SERVER_DEFAULT "138.195.140.31"
#define INPUT_VLAN_PORT_VAR "vlc_vlan_port"
#define INPUT_VLAN_PORT_DEFAULT 6010
/*******************************************************************************
* Audio configuration
......
......@@ -3,21 +3,6 @@
* (c)1999 VideoLAN
******************************************************************************/
/* needs : "netlist.h", "config.h", "mtime.h" */
/* ?? missing:
* tables version control */
/******************************************************************************
* External structures
******************************************************************************
* These structures, required here only as pointers destinations, are declared
* in other headers.
******************************************************************************/
struct video_cfg_s; /* video configuration descriptor */
struct vout_thread_s; /* video output thread */
struct stream_descriptor_s; /* PSI tables */
/******************************************************************************
* Constants related to input
******************************************************************************/
......@@ -30,7 +15,7 @@ struct stream_descriptor_s; /* PSI tables */
******************************************************************************
* Describe a TS packet.
******************************************************************************/
typedef struct ts_packet_struct
typedef struct ts_packet_s
{
/* Nothing before this line, the code relies on that */
byte_t buffer[TS_PACKET_SIZE]; /* raw TS data packet */
......@@ -41,18 +26,17 @@ typedef struct ts_packet_struct
unsigned int i_payload_end; /* guess ? :-) */
/* Used to chain the TS packets that carry data for a same PES or PSI */
struct ts_packet_struct * p_prev_ts;
struct ts_packet_struct * p_next_ts;
struct ts_packet_s * p_prev_ts;
struct ts_packet_s * p_next_ts;
} ts_packet_t;
/******************************************************************************
* pes_packet_t
******************************************************************************
* Describes an PES packet, with its properties, and pointers to the TS packets
* containing it.
******************************************************************************/
typedef struct
typedef struct pes_packet_s
{
/* PES properties */
boolean_t b_data_loss; /* The previous (at least) PES packet
......@@ -82,14 +66,13 @@ typedef struct
* (used by the demultiplexer). */
} pes_packet_t;
/******************************************************************************
* psi_section_t
******************************************************************************
* Describes a PSI section. Beware, it doesn't contain pointers to the TS
* packets that contain it as for a PES, but the data themselves
******************************************************************************/
typedef struct
typedef struct psi_section_s
{
byte_t buffer[PSI_SECTION_SIZE];
......@@ -106,7 +89,7 @@ typedef struct
* Describes an elementary stream, and includes fields required to handle and
* demultiplex this elementary stream.
******************************************************************************/
typedef struct
typedef struct es_descriptor_t
{
u16 i_id; /* stream ID, PID for TS streams */
u8 i_type; /* stream type */
......@@ -293,6 +276,8 @@ typedef struct
#endif
} input_netlist_t;
/******************************************************************************
* input_thread_t
******************************************************************************
......@@ -302,30 +287,32 @@ typedef struct
* update all reference to it each time the table would be reallocated
******************************************************************************/
/* function pointers */
struct input_thread_s;
struct input_cfg_s;
typedef int (*f_open_t)( struct input_thread_s *, struct input_cfg_s *);
typedef int (*f_read_t)( struct input_thread_s *, const struct iovec *,
size_t );
typedef void (*f_clean_t)( struct input_thread_s * );
/* Function pointers used in structure */
typedef int (input_open_t) ( p_input_thread_t p_input );
typedef int (input_read_t) ( p_input_thread_t p_input, const struct iovec *p_vector,
size_t i_count );
typedef void (input_close_t) ( p_input_thread_t p_input );
/* Structure */
typedef struct input_thread_s
{
/* Thread properties and locks */
boolean_t b_die; /* 'die' flag */
boolean_t b_error; /* deadlock */
vlc_thread_t thread_id; /* id for thread functions */
vlc_mutex_t programs_lock; /* programs modification lock */
vlc_mutex_t es_lock; /* es modification lock */
boolean_t b_die; /* 'die' flag */
boolean_t b_error; /* deadlock */
vlc_thread_t thread_id; /* id for thread functions */
vlc_mutex_t programs_lock; /* programs modification lock */
vlc_mutex_t es_lock; /* es modification lock */
int * pi_status; /* temporary status flag */
/* Input method description */
int i_method; /* input method */
int i_handle; /* file/socket descriptor */
int i_vlan_id; /* id for vlan method */
f_open_t p_open; /* pointer to the opener of the method */
f_read_t p_read; /* pointer to the reading function */
f_clean_t p_clean; /* pointer to the destroying function */
int i_method; /* input method */
int i_handle; /* file/socket descriptor */
char * psz_source; /* source */
int i_port; /* port number */
int i_vlan; /* id for vlan method */
input_open_t * p_Open; /* opener of the method */
input_read_t * p_Read; /* reading function */
input_close_t * p_Close; /* destroying function */
/* General stream description */
stream_descriptor_t * p_stream; /* PAT tables */
......@@ -338,17 +325,17 @@ typedef struct input_thread_s
/* Netlists */
input_netlist_t netlist; /* see above */
/* ?? default settings for new decoders */
struct aout_thread_s * p_aout; /* audio output thread structure */
/* Default settings for spawned decoders */
p_aout_thread_t p_aout; /* audio output thread structure */
p_vout_thread_t p_vout; /* video output thread */
#ifdef STATS
/* Stats */
count_t c_loops; /* number of loops */
count_t c_bytes; /* total of bytes read */
count_t c_payload_bytes; /* total of payload useful bytes */
count_t c_ts_packets_read; /* total of packets read */
count_t c_ts_packets_trashed; /* total of trashed packets */
/* ?? ... other stats */
/* Statistics */
count_t c_loops; /* number of loops */
count_t c_bytes; /* bytes read */
count_t c_payload_bytes; /* payload useful bytes */
count_t c_packets_read; /* packets read */
count_t c_packets_trashed; /* trashed packets */
#endif
} input_thread_t;
......@@ -360,52 +347,16 @@ typedef struct input_thread_s
#define INPUT_METHOD_TS_BCAST 22 /* TS UDP broadcast */
#define INPUT_METHOD_TS_VLAN_BCAST 32 /* TS UDP broadcast with VLANs */
/******************************************************************************
* input_cfg_t: input thread configuration structure
******************************************************************************
* This structure is passed as a parameter to input_CreateTtread(). It includes
* several fields describing potential properties of a new object.
* The 'i_properties' field allow to set only a subset of the required
* properties, asking the called function to use default settings for
* the other ones.
******************************************************************************/
typedef struct input_cfg_s
{
u64 i_properties;
/* Input method properties */
int i_method; /* input method */
char * psz_filename; /* filename */
char * psz_hostname; /* server hostname */
char * psz_ip; /* server IP */
int i_port; /* port */
int i_vlan; /* vlan number */
/* ??... default settings for new decoders */
struct aout_thread_s * p_aout; /* audio output thread structure */
} input_cfg_t;
/* Properties flags */
#define INPUT_CFG_METHOD (1 << 0)
#define INPUT_CFG_FILENAME (1 << 4)
#define INPUT_CFG_HOSTNAME (1 << 8)
#define INPUT_CFG_IP (1 << 9)
#define INPUT_CFG_PORT (1 << 10)
#define INPUT_CFG_VLAN (1 << 11)
/*****************************************************************************
* Prototypes
*****************************************************************************/
input_thread_t *input_CreateThread ( input_cfg_t *p_cfg );
void input_DestroyThread ( input_thread_t *p_input );
input_thread_t *input_CreateThread ( int i_method, char *psz_source, int i_port,
int i_vlan, p_vout_thread_t p_vout,
p_aout_thread_t p_aout, int *pi_status );
void input_DestroyThread ( input_thread_t *p_input, int *pi_status );
int input_OpenAudioStream ( input_thread_t *p_input, int i_pid
/* ?? , struct audio_cfg_s * p_cfg */ );
int input_OpenAudioStream ( input_thread_t *p_input, int i_pid );
void input_CloseAudioStream ( input_thread_t *p_input, int i_pid );
int input_OpenVideoStream ( input_thread_t *p_input,
struct vout_thread_s *p_vout, struct video_cfg_s * p_cfg );
int input_OpenVideoStream ( input_thread_t *p_input, int i_pid );
void input_CloseVideoStream ( input_thread_t *p_input, int i_pid );
/* ?? settings functions */
/* ?? info functions */
/*******************************************************************************
* file.h: file streams functions interface
* input_file.h: file streams functions interface
* (c)1999 VideoLAN
*******************************************************************************/
/******************************************************************************
* Prototypes
******************************************************************************/
int input_FileCreateMethod( input_thread_t *p_input ,
input_cfg_t *p_cfg );
int input_FileRead( input_thread_t *p_input, const struct iovec *p_vector,
size_t i_count );
void input_FileDestroyMethod( input_thread_t *p_input );
int input_FileOpen ( input_thread_t *p_input );
int input_FileRead ( input_thread_t *p_input, const struct iovec *p_vector,
size_t i_count );
void input_FileClose ( input_thread_t *p_input );
......@@ -10,17 +10,14 @@
/******************************************************************************
* Prototypes
******************************************************************************/
int input_NetlistOpen( input_thread_t *p_input );
void input_NetlistClean( input_thread_t *p_input );
/* ?? implement also a "normal" (non inline, non static) function in input_netlist.c,
which will be used when inline is disabled */
/* ?? test */ static __inline__ void input_NetlistFreePES( input_thread_t *p_input,
pes_packet_t *p_pes_packet );
static __inline__ void input_NetlistFreeTS( input_thread_t *p_input,
ts_packet_t *p_ts_packet );
int input_NetlistInit ( input_thread_t *p_input );
void input_NetlistEnd ( input_thread_t *p_input );
static __inline__ void input_NetlistFreePES( input_thread_t *p_input, pes_packet_t *p_pes_packet );
static __inline__ void input_NetlistFreeTS( input_thread_t *p_input, ts_packet_t *p_ts_packet );
static __inline__ pes_packet_t* input_NetlistGetPES( input_thread_t *p_input );
/*******************************************************************************
/******************************************************************************
* input_NetlistFreePES: add a PES packet to the netlist
*******************************************************************************
* Add a PES packet to the PES netlist, so that the packet can immediately be
......
/*******************************************************************************
* network.h: network functions interface
* input_network.h: network functions interface
* (c)1999 VideoLAN
*******************************************************************************/
/*
needs :
- <sys/uio.h>
- <sys/socket.h>
- <unistd.h>
- <netinet/in.h>
- <netdb.h>
- <arpa/inet.h>
- <stdio.h>
- <sys/ioctl.h>
- <net/if.h>
*/
/******************************************************************************
* Prototypes
******************************************************************************/
int input_NetworkCreateMethod( input_thread_t *p_input,
input_cfg_t *p_cfg );
int input_NetworkRead( input_thread_t *p_input, const struct iovec *p_vector,
size_t i_count );
void input_NetworkDestroyMethod( input_thread_t *p_input );
int input_NetworkOpen ( input_thread_t *p_input );
int input_NetworkRead ( input_thread_t *p_input, const struct iovec *p_vector,
size_t i_count );
void input_NetworkClose ( input_thread_t *p_input );
......@@ -23,4 +23,4 @@
int input_PcrInit ( input_thread_t *p_input );
void input_PcrDecode ( input_thread_t *p_input, es_descriptor_t* p_es,
u8* p_pcr_data );
void input_PcrClean ( input_thread_t *p_input );
void input_PcrEnd ( input_thread_t *p_input );
/*******************************************************************************
* psi.h: PSI management interface
* (c)1999 VideoLAN
*******************************************************************************
* Requires:
* "config.h"
* "common.h"
* "mtime.h"
******************************************************************************/
/******************************************************************************
* Prototypes
******************************************************************************/
int input_PsiInit( input_thread_t *p_input );
void input_PsiDecode( input_thread_t *p_input, psi_section_t* p_psi_section );
void input_PsiRead( input_thread_t *p_input /* ??? */ );
int input_PsiClean( input_thread_t *p_input );
int input_PsiInit ( input_thread_t *p_input );
void input_PsiDecode ( input_thread_t *p_input, psi_section_t* p_psi_section );
void input_PsiRead ( input_thread_t *p_input );
int input_PsiEnd ( input_thread_t *p_input );
......@@ -9,46 +9,13 @@
* "vlc_thread.h"
*******************************************************************************/
/*******************************************************************************
* Vlan server related constants
*******************************************************************************/
#define VLAN_SERVER_MSG_LENGTH 256 /* maximum length of a message */
#define VLAN_CLIENT_VERSION "1.3.0" /* vlan client version */
/* Messages codes */
#define VLAN_LOGIN_REQUEST 98 /* login: <version> <login> <passwd> */
#define VLAN_LOGIN_ANSWER 97 /* login accepted: [msg] */
#define VLAN_LOGIN_REJECTED 96 /* login rejected: [msg] */
#define VLAN_LOGOUT 99 /* logout */
#define VLAN_INFO_REQUEST 31 /* info: no argument */
#define VLAN_INFO_ANSWER 32/* info ok: <switch> <port> <vlan> <sharers> */
#define VLAN_INFO_REJECTED 33 /* info rejected: [msg] */
#define VLAN_CHANGE_REQUEST 21/* change: <mac> [ip] <vlan dest> [vlan src] */
#define VLAN_CHANGE_ANSWER 22 /* change ok: [msg] */
#define VLAN_CHANGE_REJECTED 23 /* change failed: [msg] */
/*******************************************************************************
* Macros to build/extract vlan_ids
*******************************************************************************/
#define VLAN_ID_IFACE( vlan_id ) ( ((vlan_id) >> 8) & 0xff )
#define VLAN_ID_VLAN( vlan_id ) ( (vlan_id) & 0xff )
#define VLAN_ID( iface, vlan ) ( ((iface) << 8) | (vlan) )
/*******************************************************************************
* Prototypes
*******************************************************************************/
int input_VlanCreate ( void );
void input_VlanDestroy ( void );
int input_VlanId ( char *psz_iface, int i_vlan );
int input_VlanCreate ( void );
void input_VlanDestroy ( void );
int input_VlanJoin ( int i_vlan_id );
void input_VlanLeave ( int i_vlan_id );
int input_VlanRequest ( char *psz_iface );
int input_VlanSynchronize ( void );
......@@ -34,7 +34,7 @@ typedef struct
/* Shared data - these structures are accessed directly from p_main by
* several modules */
p_intf_msg_t p_msg; /* messages interface data */
p_input_vlan_method_t p_input_vlan; /* vlan input method */
p_input_vlan_t p_vlan; /* vlan library data */
} main_t;
extern main_t *p_main;
......
......@@ -22,13 +22,12 @@
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <sys/shm.h>
#include <sys/soundcard.h>
......@@ -70,6 +69,7 @@
/* Video */
#include "video.h"
#include "video_output.h"
#include "vdec_idct.h"
#ifdef OLD_DECODER
#include "video_decoder.h"
......@@ -87,10 +87,14 @@
/* Interface */
#include "intf_cmd.h"
#include "intf_ctrl.h"
#ifndef OLD_DECODER
#include "intf_sys.h"
#include "intf_console.h"
#endif
#include "interface.h"
#include "main.h"
......@@ -52,179 +52,174 @@
/******************************************************************************
* Local prototypes
******************************************************************************/
static void input_Thread( input_thread_t *p_input );
static void ErrorThread( input_thread_t *p_input );
static void EndThread( input_thread_t *p_input );
static __inline__ int input_ReadPacket( input_thread_t *p_input );
static __inline__ void input_SortPacket( input_thread_t *p_input,
ts_packet_t *ts_packet );
static __inline__ void input_DemuxTS( input_thread_t *p_input,
ts_packet_t *ts_packet,
es_descriptor_t *es_descriptor );
static __inline__ void input_DemuxPES( input_thread_t *p_input,
ts_packet_t *ts_packet,
es_descriptor_t *p_es_descriptor,
boolean_t b_unit_start, boolean_t b_packet_lost );
static __inline__ void input_DemuxPSI( input_thread_t *p_input,
static void RunThread ( input_thread_t *p_input );
static void ErrorThread ( input_thread_t *p_input );
static void EndThread ( input_thread_t *p_input );
static __inline__ int input_ReadPacket( input_thread_t *p_input );
static __inline__ void input_SortPacket( input_thread_t *p_input,
ts_packet_t *ts_packet );
static __inline__ void input_DemuxTS( input_thread_t *p_input,
ts_packet_t *ts_packet,
es_descriptor_t *p_es_descriptor,
boolean_t b_unit_start, boolean_t b_packet_lost );
es_descriptor_t *es_descriptor );
static __inline__ void input_DemuxPES( input_thread_t *p_input,
ts_packet_t *ts_packet,
es_descriptor_t *p_es_descriptor,
boolean_t b_unit_start, boolean_t b_packet_lost );
static __inline__ void input_DemuxPSI( input_thread_t *p_input,
ts_packet_t *ts_packet,
es_descriptor_t *p_es_descriptor,
boolean_t b_unit_start, boolean_t b_packet_lost );
/*******************************************************************************
* input_CreateThread: initialize and spawn an input thread
* input_CreateThread: creates a new input thread
*******************************************************************************
* This function initializes and spawns an input thread. It returns NULL on
* failure. If you want a better understanding of the input thread, don't start
* by reading this function :-).
* This function creates a new input, and returns a pointer
* to its description. On error, it returns NULL.
* If pi_status is NULL, then the function will block until the thread is ready.
* If not, it will be updated using one of the THREAD_* constants.
*******************************************************************************/
input_thread_t *input_CreateThread( input_cfg_t *p_cfg )
input_thread_t *input_CreateThread ( int i_method, char *psz_source, int i_port, int i_vlan,
p_vout_thread_t p_vout, p_aout_thread_t p_aout, int *pi_status )
{
input_thread_t * p_input;
int i_index;
input_thread_t * p_input; /* thread descriptor */
int i_status; /* thread status */
int i_index; /* index for tables initialization */
intf_DbgMsg("input debug 1-1: creating thread (cfg : %p)\n", p_cfg );
/* Allocate input_thread_t structure. */
if( !( p_input = (input_thread_t *)malloc(sizeof(input_thread_t)) ) )
/* Allocate descriptor */
intf_DbgMsg("\n");
p_input = (input_thread_t *)malloc( sizeof(input_thread_t) );
if( p_input == NULL )
{
intf_ErrMsg("input error: can't allocate input thread structure (%s)\n",
strerror(errno));
intf_ErrMsg("error: %s\n", strerror(ENOMEM));
return( NULL );
}
/* Init it */
bzero( p_input, sizeof(input_thread_t));
for( i_index = 0; i_index < INPUT_MAX_ES; i_index++ )
/* Initialize thread properties */
p_input->b_die = 0;
p_input->b_error = 0;
p_input->pi_status = (pi_status != NULL) ? pi_status : &i_status;
*p_input->pi_status = THREAD_CREATE;
/* Initialize input method description */
p_input->i_method = i_method;
p_input->psz_source = psz_source;
p_input->i_port = i_port;
p_input->i_vlan = i_vlan;
switch( i_method )
{
p_input->p_es[i_index].i_id = EMPTY_PID;
case INPUT_METHOD_TS_FILE: /* file methods */
p_input->p_Open = input_FileOpen;
p_input->p_Read = input_FileRead;
p_input->p_Close = input_FileClose;
break;
case INPUT_METHOD_TS_VLAN_BCAST: /* vlan network method */
if( !p_main->b_vlans )
{
intf_ErrMsg("error: vlans are not activated\n");
free( p_input );
return( NULL );
}
/* ... pass through */
case INPUT_METHOD_TS_UCAST: /* network methods */
case INPUT_METHOD_TS_MCAST:
case INPUT_METHOD_TS_BCAST:
p_input->p_Open = input_NetworkOpen;
p_input->p_Read = input_NetworkRead;
p_input->p_Close = input_NetworkClose;
break;
default:
intf_ErrMsg("error: unknow input method\n");
free( p_input );
return( NULL );
break;
}
/* Find out which method we are gonna use and retrieve pointers. */
if( !((p_cfg->i_properties) & INPUT_CFG_METHOD) )
/* Initialize stream description */
for( i_index = 0; i_index < INPUT_MAX_ES; i_index++ )
{
/* i_method is not set. */
intf_DbgMsg("input debug: using default method (%d)\n",
INPUT_DEFAULT_METHOD);
p_cfg->i_method = INPUT_DEFAULT_METHOD;
p_cfg->i_properties |= INPUT_CFG_METHOD;
p_input->p_es[i_index].i_id = EMPTY_PID;
}
p_input->i_method = p_cfg->i_method;
switch( p_cfg->i_method )
{
/* File methods */
case INPUT_METHOD_TS_FILE:
#ifdef OLD_DECODER
p_input->p_open = &input_FileCreateMethod;
p_input->p_read = &input_FileRead;
p_input->p_clean = &input_FileDestroyMethod;
#else
p_input->p_open = input_FileCreateMethod;
p_input->p_read = input_FileRead;
p_input->p_clean = input_FileDestroyMethod;
#endif
break;
/* Network methods */
case INPUT_METHOD_TS_UCAST:
case INPUT_METHOD_TS_MCAST:
case INPUT_METHOD_TS_BCAST:
case INPUT_METHOD_TS_VLAN_BCAST:
#ifdef OLD_DECODER
p_input->p_open = &input_NetworkCreateMethod;
p_input->p_read = &input_NetworkRead;
p_input->p_clean = &input_NetworkDestroyMethod;
#else
p_input->p_open = input_NetworkCreateMethod;
p_input->p_read = input_NetworkRead;
p_input->p_clean = input_NetworkDestroyMethod;
#endif
break;
/* Initialize default settings for spawned decoders */
p_input->p_aout = p_aout;
p_input->p_vout = p_vout;
case INPUT_METHOD_NONE:
default:
#ifdef DEBUG
/* Internal error, which should never happen */
intf_DbgMsg("input debug: unknow method type %d\n",
p_cfg->i_method);
return( NULL );
#ifdef STATS
/* Initialize statistics */
p_input->c_loops = 0;
p_input->c_bytes = 0;
p_input->c_payload_bytes = 0;
p_input->c_packets_read = 0;
p_input->c_packets_trashed = 0;
#endif
break;
}
/* Initialize PSI decoder. */
intf_DbgMsg("Initializing PSI decoder\n");
if( input_PsiInit( p_input ) == -1 )
/* Initialize PSI and PCR decoders */
if( input_PsiInit( p_input ) )
{
free( p_input );
return( NULL );
}
/* Initialize PCR decoder. */
intf_DbgMsg("Initializing PCR decoder\n");
if( input_PcrInit( p_input ) == -1 )
if( input_PcrInit( p_input ) )
{
input_PsiClean( p_input );
input_PsiEnd( p_input );
free( p_input );
return( NULL );
}
/* Initialize netlists. */
if( input_NetlistOpen( p_input ) )
/* Initialize netlists */
if( input_NetlistInit( p_input ) )
{
input_PsiClean( p_input );
input_PcrClean( p_input );
input_PsiEnd( p_input );
input_PcrEnd( p_input );
free( p_input );
return( NULL );
}
#ifdef STATS
/* Initialize counters. */
p_input->c_bytes = 0;
p_input->c_payload_bytes = 0;
p_input->c_ts_packets_read = 0;
p_input->c_ts_packets_trashed = 0;
#ifdef DEBUG
p_input->c_loops = 0;
#endif
#endif
intf_DbgMsg("configuration: method=%d, source=%s, port=%d, vlan=%d\n",
i_method, psz_source, i_port, i_vlan );
/* Let the appropriate method open the socket. */
if( (*(p_input->p_open))( p_input, p_cfg ) == -1 )
if( p_input->p_Open( p_input ) )
{
input_NetlistClean( p_input );
input_PsiClean( p_input );
input_PcrClean( p_input );
input_NetlistEnd( p_input );
input_PsiEnd( p_input );
input_PcrEnd( p_input );
free( p_input );
return( NULL );
}
intf_DbgMsg("input debug: method %d properly initialized the socket\n",
p_input->i_method);
/* Create thread and set locks. */
p_input->b_die = 0;
vlc_mutex_init( &p_input->netlist.lock );
vlc_mutex_init( &p_input->programs_lock );
vlc_mutex_init( &p_input->es_lock );
#ifdef NO_THREAD
input_Thread( p_input );
#else
if( vlc_thread_create(&p_input->thread_id, "input", (vlc_thread_func_t)input_Thread,
(void *) p_input) )
if( vlc_thread_create(&p_input->thread_id, "input", (void *) RunThread, (void *) p_input) )
{
intf_ErrMsg("input error: can't spawn input thread (%s)\n",
strerror(errno) );
(*p_input->p_clean)( p_input );
input_NetlistClean( p_input );;
input_PsiClean( p_input );
input_PcrClean( p_input );
intf_ErrMsg("error: %s\n", strerror(errno) );
p_input->p_Close( p_input );
input_NetlistEnd( p_input );;
input_PsiEnd( p_input );
input_PcrEnd( p_input );
free( p_input );
return( NULL );
}
#endif
/* Default setting for new decoders */
p_input->p_aout = p_cfg->p_aout;
intf_Msg("Input initialized\n");
/* If status is NULL, wait until the thread is created */
if( pi_status == NULL )
{
do
{
msleep( THREAD_SLEEP );
}while( (i_status != THREAD_READY) && (i_status != THREAD_ERROR)
&& (i_status != THREAD_FATAL) );
if( i_status != THREAD_READY )
{
return( NULL );
}
}
return( p_input );
}
......@@ -233,13 +228,26 @@ input_thread_t *input_CreateThread( input_cfg_t *p_cfg )
******************************************************************************
* This function should not return until the thread is effectively cancelled.
******************************************************************************/
void input_DestroyThread( input_thread_t *p_input )
void input_DestroyThread( input_thread_t *p_input, int *pi_status )
{
intf_DbgMsg("input debug: requesting termination of input thread\n");
p_input->b_die = 1; /* ask thread to kill itself */
int i_status; /* thread status */
/* Set status */
p_input->pi_status = (pi_status != NULL) ? pi_status : &i_status;
*p_input->pi_status = THREAD_DESTROY;
/* Request thread destruction */
p_input->b_die = 1;
/* Remove this as soon as the "status" flag is implemented */
vlc_thread_join( p_input->thread_id ); /* wait until it's done */
/* If status is NULL, wait until thread has been destroyed */
if( pi_status == NULL )
{
do
{
msleep( THREAD_SLEEP );
}while( (i_status != THREAD_OVER) && (i_status != THREAD_ERROR)
&& (i_status != THREAD_FATAL) );
}
}
#if 0
......@@ -289,13 +297,42 @@ void input_CloseVideoStream( input_thread_t *p_input, int i_id )
/* following functions are local */
/*******************************************************************************
* input_Thread: input thread
* InitThread: initialize input thread
*******************************************************************************
* This function is called from RunThread and performs the second step of the
* initialization. It returns 0 on success. Note that the thread's flag are not
* modified inside this function.
*******************************************************************************/
static int InitThread( input_thread_t *p_input )
{
/* Mark thread as running and return */
intf_DbgMsg("\n");
*p_input->pi_status = THREAD_READY;
intf_DbgMsg("thread ready\n");
return( 0 );
}
/*******************************************************************************
* RunThread: main thread loop
*******************************************************************************
* Thread in charge of processing the network packets and demultiplexing.
*******************************************************************************/
static void input_Thread( input_thread_t *p_input )
static void RunThread( input_thread_t *p_input )
{
intf_DbgMsg("input debug 11-1: thread %p is active\n", p_input);
/*
* Initialize thread and free configuration
*/
p_input->b_error = InitThread( p_input );
if( p_input->b_error )
{
free( p_input ); /* destroy descriptor */
return;
}
/*
* Main loop
*/
intf_DbgMsg("\n");
while( !p_input->b_die && !p_input->b_error )
{
/* Scatter read the UDP packet from the network or the file. */
......@@ -311,27 +348,33 @@ static void input_Thread( input_thread_t *p_input )
#endif
}
/*
* Error loop
*/
if( p_input->b_error )
{
ErrorThread( p_input );
}
/* Ohoh, we have to die as soon as possible. */
/* End of thread */
EndThread( p_input );
intf_DbgMsg("input debug: thread %p destroyed\n", p_input);
vlc_thread_exit();
intf_DbgMsg("thread end\n");
}
/******************************************************************************
* ErrorThread: RunThread() error loop
*******************************************************************************
* This function is called when an error occured during thread main's loop.
******************************************************************************/
static void ErrorThread( input_thread_t *p_input )
{
/* Wait until a `die' order */
intf_DbgMsg("\n");
while( !p_input->b_die )
{
msleep( INPUT_IDLE_SLEEP );
/* Sleep a while */
msleep( VOUT_IDLE_SLEEP );
}
}
......@@ -340,52 +383,54 @@ static void ErrorThread( input_thread_t *p_input )
*******************************************************************************/
static void EndThread( input_thread_t * p_input )
{
int i_es_loop;
int * pi_status; /* threas status */
int i_es_loop; /* es index */
/* Store status */
intf_DbgMsg("\n");
pi_status = p_input->pi_status;
*pi_status = THREAD_END;
(*p_input->p_clean)( p_input ); /* close input method */
/* Close input method */
p_input->p_Close( p_input );
/* Destroy all decoder threads. */
for( i_es_loop = 0; i_es_loop < INPUT_MAX_ES; i_es_loop++ )
/* Destroy all decoder threads */
for( i_es_loop = 0;
(i_es_loop < INPUT_MAX_ES) && (p_input->pp_selected_es[i_es_loop] != NULL) ;
i_es_loop++ )
{
if( p_input->pp_selected_es[i_es_loop] )
switch( p_input->pp_selected_es[i_es_loop]->i_type )
{
switch( p_input->pp_selected_es[i_es_loop]->i_type )
{
case MPEG1_VIDEO_ES:
case MPEG2_VIDEO_ES:
case MPEG1_VIDEO_ES:
case MPEG2_VIDEO_ES:
#ifdef OLD_DECODER
vdec_DestroyThread( (vdec_thread_t*)(p_input->pp_selected_es[i_es_loop]->p_dec) /*, NULL */ );
vdec_DestroyThread( (vdec_thread_t*)(p_input->pp_selected_es[i_es_loop]->p_dec) /*, NULL */ );
#else
vpar_DestroyThread( (vpar_thread_t*)(p_input->pp_selected_es[i_es_loop]->p_dec) /*, NULL */ );
vpar_DestroyThread( (vpar_thread_t*)(p_input->pp_selected_es[i_es_loop]->p_dec) /*, NULL */ );
#endif
break;
case MPEG1_AUDIO_ES:
case MPEG2_AUDIO_ES:
adec_DestroyThread( (adec_thread_t*)(p_input->pp_selected_es[i_es_loop]->p_dec) );
break;
case AC3_AUDIO_ES:
ac3dec_DestroyThread( (ac3dec_thread_t *)(p_input->pp_selected_es[i_es_loop]->p_dec) );
break;
default:
break;
}
}
else
{
/* pp_selected_es should not contain any hole. */
break;
case MPEG1_AUDIO_ES:
case MPEG2_AUDIO_ES:
adec_DestroyThread( (adec_thread_t*)(p_input->pp_selected_es[i_es_loop]->p_dec) );
break;
case AC3_AUDIO_ES:
ac3dec_DestroyThread( (ac3dec_thread_t *)(p_input->pp_selected_es[i_es_loop]->p_dec) );
break;
#ifdef DEBUG
default:
intf_DbgMsg("error: unknown decoder type %d\n", p_input->pp_selected_es[i_es_loop]->i_type );
break;
#endif
}
}
input_NetlistClean( p_input ); /* clean netlist */
input_PsiClean( p_input ); /* clean PSI information */
input_PcrClean( p_input ); /* clean PCR information */
free( p_input ); /* free input_thread structure */
input_NetlistEnd( p_input ); /* clean netlist */
input_PsiEnd( p_input ); /* clean PSI information */
input_PcrEnd( p_input ); /* clean PCR information */
free( p_input ); /* free input_thread structure */
intf_DbgMsg("input debug: EndThread(%p)\n", p_input);
/* Update status */
*pi_status = THREAD_OVER;
}
/*******************************************************************************
......@@ -438,7 +483,7 @@ static __inline__ int input_ReadPacket( input_thread_t *p_input )
#endif /* FIFO netlist */
/* Scatter read the buffer. */
i_packet_size = (*p_input->p_read)( p_input,
i_packet_size = (*p_input->p_Read)( p_input,
&p_input->netlist.p_ts_free[i_base_index],
INPUT_TS_READ_ONCE );
if( i_packet_size == (-1) )
......@@ -530,10 +575,10 @@ static __inline__ int input_ReadPacket( input_thread_t *p_input )
#endif
#ifdef STATS
p_input->c_ts_packets_read += i_current_index - i_base_index;
p_input->c_packets_read += i_current_index - i_base_index;
p_input->c_bytes += (i_current_index - i_base_index) * TS_PACKET_SIZE;
#endif
return( 0 );
return( 0 );
}
/*******************************************************************************
......@@ -600,7 +645,7 @@ static __inline__ void input_SortPacket( input_thread_t *p_input,
// U16_AT(&p_ts_packet->buffer[1]) & 0x1fff);
input_NetlistFreeTS( p_input, p_ts_packet );
#ifdef STATS
p_input->c_ts_packets_trashed++;
p_input->c_packets_trashed++;
#endif
}
......@@ -758,7 +803,7 @@ static __inline__ void input_DemuxTS( input_thread_t *p_input,
{
input_NetlistFreeTS( p_input, p_ts_packet );
#ifdef STATS
p_input->c_ts_packets_trashed++;
p_input->c_packets_trashed++;
#endif
}
else
......@@ -1035,7 +1080,7 @@ static __inline__ void input_DemuxPES( input_thread_t *p_input,
{
/* The FIFO is full !!! This should not happen. */
#ifdef STATS
p_input->c_ts_packets_trashed += p_pes->i_ts_packets;
p_input->c_packets_trashed += p_pes->i_ts_packets;
p_es_descriptor->c_invalid_packets += p_pes->i_ts_packets;
#endif
input_NetlistFreePES( p_input, p_pes );
......@@ -1058,7 +1103,7 @@ static __inline__ void input_DemuxPES( input_thread_t *p_input,
{
intf_DbgMsg("No fifo to receive PES %p: trash\n", p_pes);
#ifdef STATS
p_input->c_ts_packets_trashed += p_pes->i_ts_packets;
p_input->c_packets_trashed += p_pes->i_ts_packets;
p_es_descriptor->c_invalid_packets += p_pes->i_ts_packets;
#endif
input_NetlistFreePES( p_input, p_pes );
......
/*******************************************************************************
* file.c: functions to read from a file
* input_file.c: functions to read from a file
* (c)1999 VideoLAN
*******************************************************************************/
......@@ -18,12 +18,12 @@
#include "input_file.h"
/******************************************************************************
* input_FileCreateMethod : open a file descriptor
* input_FileOpen : open a file descriptor
******************************************************************************/
int input_FileCreateMethod( input_thread_t *p_input ,
input_cfg_t *p_cfg )
int input_FileOpen( input_thread_t *p_input )
{
return( -1 );
//??
return( 1 );
}
/******************************************************************************
......@@ -32,12 +32,14 @@ int input_FileCreateMethod( input_thread_t *p_input ,
int input_FileRead( input_thread_t *p_input, const struct iovec *p_vector,
size_t i_count )
{
return( -1 );
//??
return( -1 );
}
/******************************************************************************
* input_FileDestroyMethod : close a file descriptor
* input_FileClose : close a file descriptor
******************************************************************************/
void input_FileDestroyMethod( input_thread_t *p_input )
void input_FileClose( input_thread_t *p_input )
{
//??
}
......@@ -31,7 +31,7 @@
/******************************************************************************
* input_NetlistOpen: initialize the netlists buffers
******************************************************************************/
int input_NetlistOpen( input_thread_t *p_input )
int input_NetlistInit( input_thread_t *p_input )
{
int i_base, i_packets, i_iovec;
......@@ -119,7 +119,7 @@ int input_NetlistOpen( input_thread_t *p_input )
/******************************************************************************
* input_NetlistClean: clean the netlists buffers
******************************************************************************/
void input_NetlistClean( input_thread_t *p_input )
void input_NetlistEnd( input_thread_t *p_input )
{
int i;
......
......@@ -33,57 +33,37 @@
#include "intf_msg.h"
/******************************************************************************
* Local prototypes
* input_NetworkOpen: initialize a network stream
******************************************************************************/
/******************************************************************************
* input_NetworkCreateMethod: initialize a network stream
******************************************************************************/
int input_NetworkCreateMethod( input_thread_t *p_input,
input_cfg_t *p_cfg )
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) )
if( input_VlanJoin( p_input->i_vlan ) )
{
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 )
{
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);
/* 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 up the options of the socket
*/
/* 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 +71,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,135 +85,102 @@ 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. */
/*
* Bind the socket
*/
/* Find the port. */
if( p_cfg->i_properties & INPUT_CFG_PORT )
/* 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 = INPUT_DEFAULT_PORT;
}
/* 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 )
{
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 )
/* Use default host if not specified */
if( p_input->psz_source == NULL )
{
if( BuildInetAddr( &sa_in, p_cfg->psz_ip, htons(0) ) == (-1) )
{
close( p_input->i_handle );
return( -1 );
}
p_input->psz_source = INPUT_DEFAULT_SERVER;
}
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 );
}
......@@ -275,23 +221,20 @@ int input_NetworkRead( input_thread_t *p_input, const struct iovec *p_vector,
}
/******************************************************************************
* input_NetworkDestroyMethod: close a network stream
* input_NetworkClose: close a network stream
******************************************************************************/
void input_NetworkDestroyMethod( input_thread_t *p_input )
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 );
}
}
......@@ -129,9 +129,9 @@ void input_PcrDecode( input_thread_t *p_input, es_descriptor_t *p_es,
}
/******************************************************************************
* input_PcrClean : Clean PCR structures before dying
* input_PcrEnd : Clean PCR structures before dying
******************************************************************************/
void input_PcrClean( input_thread_t *p_input )
void input_PcrEnd( input_thread_t *p_input )
{
ASSERT( p_input );
......
......@@ -138,7 +138,7 @@ int input_PsiInit( input_thread_t *p_input )
/******************************************************************************
* input_PsiClean: Clean PSI structures before dying
******************************************************************************/
int input_PsiClean( input_thread_t *p_input )
int input_PsiEnd( input_thread_t *p_input )
{
ASSERT(p_input);
......
/*******************************************************************************
* input_vlan.c: vlan input method
* input_vlan.c: vlan management library
* (c)1999 VideoLAN
*******************************************************************************
* ??
*******************************************************************************/
/* ???????????????????????????????????????????????????????????????????????????
* This works (well, it should :), but should have a good place in horror museum:
* - the vlan-capable interfaces are retrieved from a names list, instead
* of being read from the system
* - the vlan server sucks, and therefore the vlan clients sucks:
* - it is unable to process several operations between a login and a logout
* A lot of requests could be grouped if it could.
* - it is incoherent concerning it's messages (and what it needs to perform
* an operation
* - it is totally unable to handle several mac adresses on a single switch
* port (and therefore bridged/hubbed machines)
* - however, the API is ok, should be able to handle all futures evolutions,
* including vlan-conscient cards.
*
* So there is a lot to do in this file, but not before having reprogrammed the
* vlan server !
* What would be a good interface to the vlan server ? Here are some ideas:
* ( later ! )
* ??????????????????????????????????????????????????????????????????????????? */
/*******************************************************************************
* Preamble
*******************************************************************************/
#include "vlc.h"
/*#include <errno.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>
#include <sys/uio.h>
#include <X11/Xlib.h>
#include <X11/extensions/XShm.h>
#include <sys/socket.h>
#include "config.h"
#include "common.h"
#include "mtime.h"
#include "vlc_thread.h"
#include "netutils.h"
#include "input.h"
#include "input_vlan.h"
#include "audio_output.h"
#include "video.h"
#include "video_output.h"
#include "xconsole.h"
#include "interface.h"
#include "intf_msg.h"
#include "pgm_data.h"*/
/*******************************************************************************
* input_vlan_iface_t: vlan-capable network interface
*******************************************************************************
* This structure describes the abilities of a network interface capable of
* vlan management. Note that an interface could have several IP adresses, but
* since only the MAC address is used to change vlan, only one needs to be
* retrieved.
* ?? it could be interesting to send a port id on vlan request, to know if two
* interfaces are dependant regarding vlan changes.
*******************************************************************************/
typedef struct
{
char * psz_name; /* interface name */
struct sockaddr_in sa_in; /* interface IP */
char psz_mac[20]; /* interface MAC */
/* Hardware properties */
int i_master; /* master interface index */
int i_switch; /* switch number */
int i_port; /* port number */
int i_sharers; /* number of MACs on this port */
/* Vlan properties - these are only used if i_master is negative */
int i_refcount; /* locks counter */
int i_vlan; /* current vlan */
int i_default_vlan; /* default vlan */
} input_vlan_iface_t;
/*******************************************************************************
* input_vlan_server_t: vlan server
*******************************************************************************
* This structure describes a vlan server.
*******************************************************************************/
typedef struct
{
struct sockaddr_in sa_in; /* server address */
int i_socket; /* socket descriptor */
/* Login informations */
char * psz_login; /* server login */
char * psz_passwd; /* server password */
} input_vlan_server_t;
#include "main.h"
/*******************************************************************************
* vlan_method_data_t
* input_vlan_t: vlan library data
*******************************************************************************
* Store global vlan library data.
*******************************************************************************/
typedef struct input_vlan_method_s
typedef struct input_vlan_s
{
vlc_mutex_t lock; /* library lock */
/* Server */
input_vlan_server_t server; /* vlan server */
/* Network interfaces */
int i_ifaces; /* number of vlan-compliant interfaces */
input_vlan_iface_t * p_iface; /* interfaces */
} input_vlan_method_t;
/*
* Constants
*/
int i_dummy;
} input_vlan_t;
/* List of vlan-capable interfaces names */
static const char *psz_ifaces_names[] = { "eth0", "eth1", "eth2", "eth3", "eth4", "eth5", NULL };
/*
/*******************************************************************************
* Local prototypes
*/
static int IfaceInfo ( input_vlan_iface_t *p_iface );
static int IfaceDependance ( input_vlan_method_t *p_method, int i_iface );
static int ServerLogin ( input_vlan_server_t *p_server );
static void ServerLogout ( input_vlan_server_t *p_server );
static int ServerRequestChange ( input_vlan_server_t *p_server,
input_vlan_iface_t *p_iface, int i_vlan );
static int ServerRequestInfo ( input_vlan_server_t *p_server,
input_vlan_iface_t *p_iface );
*******************************************************************************/
static int ZeTrucMucheFunction( int Channel );
/*******************************************************************************
* input_VlanCreate: initialize global vlan method data
......@@ -154,94 +51,15 @@ static int ServerRequestInfo ( input_vlan_server_t *p_server,
*******************************************************************************/
int input_VlanCreate( void )
{
char * psz_server; // ??? get from environment
int i_port; // ??? get from environment
int i_index; /* interface/servers index */
input_vlan_iface_t * p_iface; /* interfaces */
input_vlan_method_t *p_method = p_main->p_input_vlan; //??
/* Build vlan server descriptor */
if( BuildInetAddr( &p_method->server.sa_in, psz_server, i_port ) )
{
return( -1 );
}
/* Allocate interfaces array */
for( i_index = 0; psz_ifaces_names[i_index] != NULL; i_index++ )
{
;
}
p_iface = malloc( sizeof(input_vlan_iface_t) * i_index );
if( p_iface == NULL )
{
return( ENOMEM );
}
/* Initialize interfaces array */
for( i_index = p_method->i_ifaces = 0; psz_ifaces_names[i_index] != NULL; i_index++ )
{
/* Retrieve interface name */
p_iface[p_method->i_ifaces].psz_name = (char *) psz_ifaces_names[i_index];
/* Test if interface is vlan-capable */
if( !IfaceInfo( &p_iface[p_method->i_ifaces] ) )
{
/* If interface passed first step, login to vlan server */
if( !ServerLogin( &p_method->server ) )
{
/* Request informations from server about the interface - if the interface
* pass this last test, it is vlan-capable and can be added to the list of
* interfaces. */
if( !ServerRequestInfo( &p_method->server, &p_iface[p_method->i_ifaces]) )
{
/* Check if interface is dependant */
if( !IfaceDependance( p_method, p_method->i_ifaces ) )
{
/* Interface is master: initialize properties */
p_iface[p_method->i_ifaces].i_default_vlan = p_iface[p_method->i_ifaces].i_vlan;
p_iface[p_method->i_ifaces].i_refcount = 0;
intf_DbgMsg("input debug: added vlan-capable interface %s (%s)\n",
p_iface[p_method->i_ifaces].psz_name,
p_iface[p_method->i_ifaces].psz_mac);
}
#ifdef DEBUG
else
{
/* Interface is slave */
intf_DbgMsg("input debug: added vlan-capable interface %s (%s), depends from %s\n",
p_iface[p_method->i_ifaces].psz_name,
p_iface[p_method->i_ifaces].psz_mac,
p_iface[p_iface[p_method->i_ifaces].i_master].psz_name );
}
#endif
/* Increment size counter */
p_method->i_ifaces++;
}
/* Logout from server */
ServerLogout( &p_method->server );
}
}
}
/* If number of vlan-capable interfaces is null, then desactivate vlans */
if( p_method->i_ifaces == 0 )
/* Allocate structure */
p_main->p_vlan = malloc( sizeof( input_vlan_t ) );
if( p_main->p_vlan == NULL )
{
free( p_iface );
return( -1 );
intf_ErrMsg("error: %s\n", strerror(ENOMEM));
return( 1 );
}
/* Reallocate interfaces array to save memory */
p_method->p_iface = realloc( p_iface, sizeof(input_vlan_iface_t) * p_method->i_ifaces );
if( p_method->p_iface == NULL )
{
/* Realloc failed, but the previous pointer is still valid */
p_method->p_iface = p_iface;
}
/* Initialize lock */
vlc_mutex_init( &p_method->lock );
intf_Msg("input: vlans input method installed\n", p_method->i_ifaces);
intf_Msg("VLANs initialized\n");
return( 0 );
}
......@@ -253,62 +71,8 @@ int input_VlanCreate( void )
*******************************************************************************/
void input_VlanDestroy( void )
{
int i_index; /* server/interface index */
input_vlan_method_t *p_method = p_main->p_input_vlan; // ??
/* Leave all remaining vlans */
for( i_index = 0; i_index < p_method->i_ifaces; i_index++ )
{
#ifdef DEBUG
/* Check if interface is still locked */
if( p_method->p_iface[i_index].i_refcount )
{
intf_DbgMsg("input debug: interface %s is still vlan-locked\n",
p_method->p_iface[i_index].psz_name);
p_method->p_iface[i_index].i_refcount = 0;
}
#endif
/* Join default (starting) vlan */
input_VlanJoin( VLAN_ID( i_index, p_method->p_iface[i_index].i_default_vlan ) );
}
/* Free interfaces array */
free( p_method->p_iface );
intf_DbgMsg("input debug: vlan method terminated\n");
}
/*******************************************************************************
* input_VlanId: get a vlan_id for a given interface
*******************************************************************************
* Get a vlan_id given a network interface and a vlan number. If psz_iface is
* NULL, then the default network interface will be used. A negative value
* will be returned in case of error.
*******************************************************************************/
int input_VlanId( char *psz_iface, int i_vlan )
{
input_vlan_method_t * p_method; /* method global data */
int i_index; /* interface index */
p_method = p_main->p_input_vlan;
/* If psz_iface is NULL, use first (default) interface (if there is one) */
if( psz_iface == NULL )
{
return( p_method->i_ifaces ? VLAN_ID( 0, i_vlan ) : -1 );
}
/* Browse all interfaces */
for( i_index = 0; i_index < p_main->p_input_vlan->i_ifaces ; i_index++ )
{
/* If interface has been found, return */
if( !strcmp( p_main->p_input_vlan->p_iface[i_index].psz_name, psz_iface ) )
{
return( VLAN_ID( i_index, i_vlan ) );
}
}
return( -1 );
/* Free structure */
free( p_main->p_vlan );
}
/*******************************************************************************
......@@ -324,53 +88,8 @@ int input_VlanId( char *psz_iface, int i_vlan )
*******************************************************************************/
int input_VlanJoin( int i_vlan_id )
{
input_vlan_method_t * p_method; /* method global data */
input_vlan_iface_t * p_iface; /* interface (shortcut) */
int i_err; /* error indicator */
/* Initialize shortcuts, and use master if interface is dependant */
i_err = 0;
p_method = p_main->p_input_vlan;
p_iface = &p_method->p_iface[ VLAN_ID_IFACE( i_vlan_id ) ];
if( p_iface->i_master >= 0 )
{
p_iface = &p_method->p_iface[ p_iface->i_master ];
}
/* Get lock */
vlc_mutex_lock( &p_method->lock );
/* If the interface is in the wished vlan, increase lock counter */
if( p_iface->i_vlan != VLAN_ID_VLAN( i_vlan_id ) )
{
p_iface->i_refcount++;
}
/* If not, if it is not locked, the vlan can be changed */
else if( !p_iface->i_refcount )
{
/* Login to server */
if( (i_err = !ServerLogin( &p_method->server )) )
{
/* Request vlan change */
if( (i_err = !ServerRequestChange( &p_method->server,
p_iface, VLAN_ID_VLAN( i_vlan_id ) ) ) )
{
p_iface->i_refcount++;
}
/* Logout */
ServerLogout( &p_method->server );
}
}
/* Else, the vlan is locked and can't be changed */
else
{
i_err = 1;
}
/* Release lock (if this point is reached, the function succeeded) */
vlc_mutex_unlock( &p_method->lock );
return( i_err );
intf_Msg("Joining VLAN %d (channel %d)\n", i_vlan_id + 2, i_vlan_id );
return( ZeTrucMucheFunction( i_vlan_id ) ); // ?? join vlan
}
/*******************************************************************************
......@@ -381,453 +100,94 @@ int input_VlanJoin( int i_vlan_id )
*******************************************************************************/
void input_VlanLeave( int i_vlan_id )
{
input_vlan_method_t * p_method; /* method global data */
input_vlan_iface_t * p_iface; /* interface (shortcut) */
int i_err; /* error indicator */
/* Initialize shortcuts, and use master if interface is dependant */
i_err = 0;
p_method = p_main->p_input_vlan;
p_iface = &p_method->p_iface[ VLAN_ID_IFACE( i_vlan_id ) ];
if( p_iface->i_master >= 0 )
{
p_iface = &p_method->p_iface[ p_iface->i_master ];
}
/* Get lock */
vlc_mutex_lock( &p_method->lock );
/* Decrease reference counter */
p_method->p_iface[ VLAN_ID_IFACE( i_vlan_id ) ].i_refcount--;
/* Release lock */
vlc_mutex_unlock( &p_method->lock );
}
/*******************************************************************************
* input_VlanRequest: request vlan number for a given interface
*******************************************************************************
* Request the vlan number (and not id) of a given network interface. A
* connection to the server can eventually occur, event if it not the case in
* current implementation. A negative number can be returned on error.
*******************************************************************************/
int input_VlanRequest( char *psz_iface )
{
input_vlan_method_t * p_method; /* method global data */
int i_index; /* interface index */
p_method = p_main->p_input_vlan;
/* If psz_iface is NULL, use first (default) interface (if there is one) -
* note that interface 0 can't be dependant, so dependance does not need
* to be tested */
if( psz_iface == NULL )
{
return( p_method->i_ifaces ? p_method->p_iface[0].i_vlan : -1 );
}
/* Browse all interfaces */
for( i_index = 0; i_index < p_method->i_ifaces ; i_index++ )
{
/* If interface has been found, return vlan */
if( !strcmp( p_method->p_iface[i_index].psz_name, psz_iface ) )
{
/* If interface is dependant, use master, else return own vlan */
return( (p_method->p_iface[i_index].i_master >= 0) ?
p_method->p_iface[p_method->p_iface[i_index].i_master].i_vlan :
p_method->p_iface[i_index].i_vlan );
}
}
/* If not found, return an error */
return( -1 );
}
/*******************************************************************************
* input_VlanSynchronize: resynchronize with vlan server
*******************************************************************************
* Resynchronize with the vlan server. Vlans for all interfaces are requested
* and changed if required. This call may take a lot of time, and is intended
* for emergency situations.
*******************************************************************************/
int input_VlanSynchronize( void )
{
input_vlan_method_t * p_method; /* method global data */
input_vlan_iface_t * p_iface; /* interface (shortcut) */
int i_index; /* interface index */
int i_vlan; /* vlan for current interface */
/* Get lock */
p_method = p_main->p_input_vlan;
pthread_mutex_lock( &p_method->lock );
/* ??
p_method = &p_program_data->input_vlan_method;
vlc_mutex_lock( &p_method->lock );
*/
for( i_index = 0; i_index < p_method->i_ifaces; i_index++ )
{
p_iface = &p_method->p_iface[ i_index ];
/* Ignore dependant interfaces and interfaces for wich login failed */
if( (p_iface->i_master < 0) && !ServerLogin( &p_method->server ) )
{
/* Request interface informations */
i_vlan = p_iface->i_vlan;
if( !ServerRequestInfo( &p_method->server, p_iface ) )
{
/* If synchronization has been lost, then try to resynchronize -
* this part is ugly because of the vlan server bug requiring a
* logout between two requests */
if( p_iface->i_vlan != i_vlan )
{
intf_Msg("input: lost vlan synchronization for interface %s\n",
p_iface->psz_name );
ServerLogout( &p_method->server );
if( !ServerLogin( &p_method->server ) )
{
if( !ServerRequestChange( &p_method->server, p_iface, i_vlan ) )
{
intf_Msg("input: retrieved vlan synchronization for interface %s\n",
p_iface->psz_name );
}
}
/* Note that when this login fails, then the next logout will
* also fail... but I don't want to spend time finding a
* clean way to avoid this if the vlan server bug is fixed */
}
}
/* Logout */
ServerLogout( &p_method->server );
}
}
/* Release lock */
vlc_mutex_unlock( &p_method->lock );
return( 0 );
intf_Msg("Leaving VLAN %d (channel %d)\n", i_vlan_id + 2, i_vlan_id );
ZeTrucMucheFunction( 0 ); // ?? join default vlan
}
/* following functions are local */
/*******************************************************************************
* IfaceInfo: read info about an interface
*******************************************************************************
* This function reads informations about a network interface. It should return
* 0 and updated interface informations for vlan capable interfaces, and non 0
* if interface is not vlan-capable or informations request failed.
*******************************************************************************/
static int IfaceInfo( input_vlan_iface_t *p_iface )
static int ZeTrucMucheFunction( int Channel)
{
int i_socket;
struct ifreq device;
/* Copy interface name */
strcpy(device.ifr_name, p_iface->psz_name);
/* Open a datagram socket */
i_socket = socket(AF_INET, SOCK_DGRAM, 0);
if(i_socket < 0)
{
intf_ErrMsg("input error: unable to open socket on %s: %s\n",
p_iface->psz_name, strerror(errno));
return( -1 );
}
/* Read IP address */
if(ioctl(i_socket, SIOCGIFDSTADDR, &device) < 0)
{
intf_ErrMsg("input error: can not read IP address for %s: %s\n",
p_iface->psz_name, strerror(errno));
return( -1 );
}
memcpy( &p_iface->sa_in, &device.ifr_hwaddr, sizeof(struct sockaddr_in));
/* Read MAC address */
if(ioctl(i_socket, SIOCGIFHWADDR, &device) < 0)
{
intf_ErrMsg("input error: can not read MAC address for %s: %s\n",
p_iface->psz_name, strerror(errno));
return( -1 );
}
/* Translate MAC address to ASCII standard */
sprintf(p_iface->psz_mac, "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
device.ifr_hwaddr.sa_data[0]&0xff,
device.ifr_hwaddr.sa_data[1]&0xff,
device.ifr_hwaddr.sa_data[2]&0xff,
device.ifr_hwaddr.sa_data[3]&0xff,
device.ifr_hwaddr.sa_data[4]&0xff,
device.ifr_hwaddr.sa_data[5]&0xff);
return( 0 );
}
/*******************************************************************************
* IfaceDependance: check interface dependance
*******************************************************************************
* Check if an interface designed by it's index is dependant from another one.
* All the interfaces from 0 to i_index excluded are tested. If a 'master'
* interface is found, then the 'i_master' field is set to a positive value.
* Non 0 is returned if the interface is dependant.
*******************************************************************************/
static int IfaceDependance( input_vlan_method_t *p_method, int i_iface )
{
int i_index; /* interface index */
for( i_index = 0; i_index < i_iface; i_index++ )
{
/* Two interface are dependant if they are on the same switch and
* port */
if( ( p_method->p_iface[i_index].i_switch == p_method->p_iface[i_iface].i_switch )
&& ( p_method->p_iface[i_index].i_port == p_method->p_iface[i_iface].i_port ) )
{
/* Interface is slave */
p_method->p_iface[i_iface].i_master = i_index;
return( 1 );
}
}
/* Interface is master */
p_method->p_iface[i_iface].i_master = -1;
return( 0 );
}
/*******************************************************************************
* ServerLogin: login to a vlan server
*******************************************************************************
* Initiate login sequence to a vlan server: open a socket, bind it and send
* login sequence. If the login fails for any reason, non 0 is returned.
*******************************************************************************/
static int ServerLogin( input_vlan_server_t *p_server )
{
struct sockaddr_in sa_client; /* client address */
char psz_msg[VLAN_SERVER_MSG_LENGTH + 1];/* server message */
int i_bytes; /* number of bytes read */
psz_msg[VLAN_SERVER_MSG_LENGTH] = '\0'; /* make sure the string ends */
/* Initialize local socket */
BuildInetAddr( &sa_client, NULL, 0 );
p_server->i_socket = socket(AF_INET, SOCK_STREAM, 0);
if( p_server->i_socket < 0 )
{
/* Error: return an error */
intf_ErrMsg("input error: can not open socket (%s)\n", strerror(errno));
return( errno );
}
/* Bind the server socket to client */
if( bind( p_server->i_socket, (struct sockaddr *) &sa_client, sizeof(sa_client)) < 0)
{
/* Error: close socket and return an error */
intf_ErrMsg("input error: can not bind socket (%s)\n", strerror(errno));
close( p_server->i_socket );
return( errno );
}
/* Try to connect to the VLANserver */
if( connect( p_server->i_socket, (struct sockaddr *) &p_server->sa_in,
sizeof(p_server->sa_in)) < 0)
{
/* Error: close socket and return an error */
intf_ErrMsg("input error: unable to connect to the VLAN server (%s)\n",
strerror(errno));
close( p_server->i_socket );
return( errno );
}
/* Send login message */
snprintf(psz_msg, VLAN_SERVER_MSG_LENGTH, "%d %s %s %s\n",
VLAN_LOGIN_REQUEST, VLAN_CLIENT_VERSION,
p_server->psz_login, p_server->psz_passwd );
if( send(p_server->i_socket, psz_msg, sizeof(char) * strlen( psz_msg ), 0) < 0)
{
intf_ErrMsg("input error: unable to login to the VLANserver: %s",
strerror(errno));
close( p_server->i_socket );
return( errno );
}
/* Listen to response */
i_bytes = recv(p_server->i_socket, psz_msg, VLAN_SERVER_MSG_LENGTH, 0);
if( i_bytes < 0 )
{
intf_ErrMsg("input error: no response from VLANserver: %s\n",
strerror(errno));
ServerLogout( p_server );
return( -1 );
}
/* Parse answer to login request */
psz_msg[ i_bytes ] = '\0'; /* terminate string */
if( atoi(psz_msg) == VLAN_LOGIN_REJECTED )
{
intf_ErrMsg("input error: login rejected by VLANserver: %s\n", psz_msg);
ServerLogout( p_server );
return( -1 );
}
else if( atoi(psz_msg) != VLAN_LOGIN_ANSWER )
{
intf_ErrMsg("input error: unexpected answer from VLAN server: %s\n", psz_msg);
ServerLogout( p_server );
return( -1 );
}
intf_DbgMsg("input debug: VLANserver login ok.\n");
return 0;
int i_socket;
char * ipaddr;
struct ifreq interface;
struct sockaddr_in sa_server;
struct sockaddr_in sa_client;
char mess[80];
/*
*Looking for informations about the eth0 interface
*/
interface.ifr_addr.sa_family = AF_INET;
strcpy( interface.ifr_name, main_GetPszVariable( INPUT_IFACE_VAR, INPUT_IFACE_DEFAULT ) );
i_socket = socket( AF_INET, SOCK_DGRAM, 0 );
/* Looking for the interface IP address */
ioctl( i_socket, SIOCGIFDSTADDR, &interface );
ipaddr = inet_ntoa((*(struct sockaddr_in *)(&(interface.ifr_addr))).sin_addr );
/* Looking for the interface MAC address */
ioctl( i_socket, SIOCGIFHWADDR, &interface );
close( i_socket );
/*
* Getting address, port, ... of the server
*/
/* Initialize */
bzero( &sa_server, sizeof(struct sockaddr_in) );
/* sin_family is ALWAYS set to AF_INET (see in man 7 ip)*/
sa_server.sin_family = AF_INET;
/* Giving port on to connect after having convert it*/
sa_server.sin_port = htons ( main_GetIntVariable( INPUT_VLAN_PORT_VAR, INPUT_VLAN_PORT_DEFAULT ));
/* Giving address after having convert it into binary data*/
inet_aton( main_GetPszVariable( INPUT_VLAN_SERVER_VAR, INPUT_VLAN_SERVER_DEFAULT ), &(sa_server.sin_addr) );
/*
* Getting address, port, ... of the client
*/
/* Initialize */
bzero( &sa_client, sizeof(struct sockaddr_in) );
/* sin_family is ALWAYS set to AF_INET (see in man 7 ip)*/
sa_client.sin_family = AF_INET;
/* Giving port on to connect after having convert it*/
sa_client.sin_port = htons( 0 );
/* Giving address after having convert it into binary data*/
inet_aton( ipaddr, &(sa_client.sin_addr) );
/* Initialization of the socket */
i_socket = socket(AF_INET, SOCK_DGRAM, 17 ); // ?? UDP
/* SOCK_DGRAM because here we use DATAGRAM
* Sachant qu'il y a un #define AF_INET = PF_INET dans sys/socket.h et que PF_INET est le IP protocol family ...
* Protocol is in #define, should be 17 for udp */
/* Elaborate the message to send */
sprintf( mess , "%d %s %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x \n",
Channel, ipaddr,
interface.ifr_hwaddr.sa_data[0] & 0xff,
interface.ifr_hwaddr.sa_data[1] & 0xff,
interface.ifr_hwaddr.sa_data[2] & 0xff,
interface.ifr_hwaddr.sa_data[3] & 0xff,
interface.ifr_hwaddr.sa_data[4] & 0xff,
interface.ifr_hwaddr.sa_data[5] & 0xff,
interface.ifr_hwaddr.sa_data[0] & 0xff,
interface.ifr_hwaddr.sa_data[1] & 0xff,
interface.ifr_hwaddr.sa_data[2] & 0xff,
interface.ifr_hwaddr.sa_data[3] & 0xff,
interface.ifr_hwaddr.sa_data[4] & 0xff,
interface.ifr_hwaddr.sa_data[5] & 0xff
);
/* Send the message */
intf_DbgMsg("%s\n", mess);
sendto(i_socket,mess,80,0,(struct sockaddr *)&sa_server,sizeof(struct sockaddr));
/*Close the socket */
close( i_socket );
return 0;
}
/*******************************************************************************
* ServerLogout: logout from a vlan server
*******************************************************************************
* Logout from a vlan server. This function sends the logout message to the
* server and close the socket.
*******************************************************************************/
static void ServerLogout( input_vlan_server_t *p_server )
{
char psz_msg[VLAN_SERVER_MSG_LENGTH + 1]; /* server message */
psz_msg[VLAN_SERVER_MSG_LENGTH] = '\0'; /* make sure the string ends */
/* Send logout */
snprintf(psz_msg, VLAN_SERVER_MSG_LENGTH, "%d\n", VLAN_LOGOUT);
if( send(p_server->i_socket, psz_msg, sizeof(char) * strlen(psz_msg), 0) < 0)
{
intf_ErrMsg("input error: can't send logout message to VLANserver: %s\n",
strerror(errno));
}
/* Close socket */
if( close(p_server->i_socket) < 0)
{
intf_ErrMsg("input error: unable to close socket: %s\n", strerror(errno));
}
intf_DbgMsg("input debug: VLANserver logout ok\n");
}
/*******************************************************************************
* ServerRequestChange: request vlan change from a server
*******************************************************************************
* Request vlan change from a vlan server. The client must be logged in. If the
* change succeeded, the interface structure is updated. Note that only masters
* should be sent to this function.
*******************************************************************************/
static int ServerRequestChange( input_vlan_server_t *p_server,
input_vlan_iface_t *p_iface, int i_vlan )
{
char psz_msg[VLAN_SERVER_MSG_LENGTH + 1]; /* server message */
int i_bytes; /* number of bytes read */
psz_msg[VLAN_SERVER_MSG_LENGTH] = '\0'; /* make sure the string ends */
/* Send request */
snprintf(psz_msg, VLAN_SERVER_MSG_LENGTH, "%d %s %s %d %d",
VLAN_CHANGE_REQUEST, p_iface->psz_mac,
inet_ntoa(p_iface->sa_in.sin_addr), i_vlan, p_iface->i_vlan);
if( send( p_server->i_socket, psz_msg, sizeof(char) * strlen(psz_msg), 0) < 0)
{
intf_ErrMsg("input error: unable to send request to VLANserver: %s\n",
strerror(errno));
return( -1 );
}
/* Listen to response */
i_bytes = recv(p_server->i_socket, psz_msg, VLAN_SERVER_MSG_LENGTH, 0);
if( i_bytes < 0 )
{
intf_ErrMsg("input error: no response from VLANserver: %s",
strerror(errno));
return( -1 );
}
/* Parse answer to vlan request */
psz_msg[ i_bytes ] = '\0'; /* terminate string */
if( atoi( psz_msg ) == VLAN_CHANGE_REJECTED )
{
intf_ErrMsg("input error: change request rejected by VLANserver: %s\n", psz_msg );
return( -1 );
}
else if( atoi( psz_msg ) != VLAN_CHANGE_ANSWER )
{
intf_ErrMsg("input error: unexpected answer from VLAN server: %s\n", psz_msg);
return( -1 );
}
/* ?? send packet for the switch to learn mac again */
/* Update interface and return */
intf_DbgMsg("input debug: interface %s moved to vlan %d\n",
p_iface->psz_name, i_vlan );
p_iface->i_vlan = i_vlan;
return( 0 );
}
/*******************************************************************************
* ServerRequestInfo: ask current vlan to server
*******************************************************************************
* Request current vlan from a vlan server. The client must be logged in. This
* function updates the p_iface structure or returns non 0. Note that only
* masters should be sent to this function.
*******************************************************************************/
static int ServerRequestInfo( input_vlan_server_t *p_server,
input_vlan_iface_t *p_iface )
{
char psz_msg[VLAN_SERVER_MSG_LENGTH + 1]; /* server message */
int i_bytes; /* number of bytes read */
int i_switch; /* switch number */
int i_port; /* port number */
int i_vlan; /* vlan number */
int i_sharers; /* number of mac addresses on this port */
psz_msg[VLAN_SERVER_MSG_LENGTH] = '\0'; /* make sure the string ends */
/* Send request */
snprintf(psz_msg, VLAN_SERVER_MSG_LENGTH, "%d", VLAN_INFO_REQUEST);
if( send( p_server->i_socket, psz_msg, sizeof(char) * strlen(psz_msg), 0) < 0)
{
intf_ErrMsg("input error: unable to send request to VLANserver: %s\n",
strerror(errno));
return( -1 );
}
/* Listen to response */
i_bytes = recv(p_server->i_socket, psz_msg, VLAN_SERVER_MSG_LENGTH, 0);
if( i_bytes < 0 )
{
intf_ErrMsg("input error: no response from VLANserver: %s",
strerror(errno));
return( -1 );
}
/* Parse answer to vlan request */
psz_msg[ i_bytes ] = '\0'; /* terminate string */
if( atoi( psz_msg ) == VLAN_INFO_REJECTED )
{
intf_ErrMsg("input error: info request rejected by VLANserver: %s\n", psz_msg );
return( -1 );
}
else if( atoi( psz_msg ) != VLAN_INFO_ANSWER )
{
intf_ErrMsg("input error: unexpected answer from VLAN server: %s\n", psz_msg);
return( -1 );
}
else if( sscanf(psz_msg, "%*d %d %d %d %d", &i_switch, &i_port, &i_vlan, &i_sharers) != 4 )
{
intf_ErrMsg("input error: invalid answer from VLAN server: %s\n", psz_msg);
return( -1 );
}
/* Update interface and return */
intf_DbgMsg("input debug: interface %s is on switch %d, port %d, vlan %d, %d sharers\n",
p_iface->psz_name, i_switch, i_port, i_vlan, i_sharers);
p_iface->i_switch = i_switch;
p_iface->i_port = i_port;
p_iface->i_vlan = i_vlan;
p_iface->i_sharers = i_sharers;
return( 0 );
}
......@@ -31,42 +31,6 @@
#include "intf_sys.h"
/*******************************************************************************
* Constants
*******************************************************************************/
/* INTF_INPUT_CFG: pre-configured inputs */
#define INTF_MAX_INPUT_CFG 10
static const input_cfg_t INTF_INPUT_CFG[] =
{
/* properties method
* file host ip port vlan */
/* Local input (unicast) */
{ INPUT_CFG_METHOD | INPUT_CFG_IP, INPUT_METHOD_TS_UCAST,
NULL, NULL, "127.0.0.1", 0, 0 },
/* Broadcasts */
{ INPUT_CFG_METHOD | INPUT_CFG_VLAN, INPUT_METHOD_TS_VLAN_BCAST,
NULL, NULL, NULL, 0, 0 },
{ INPUT_CFG_METHOD | INPUT_CFG_VLAN, INPUT_METHOD_TS_VLAN_BCAST,
NULL, NULL, NULL, 0, 1 },
{ INPUT_CFG_METHOD | INPUT_CFG_VLAN, INPUT_METHOD_TS_VLAN_BCAST,
NULL, NULL, NULL, 0, 2 },
{ INPUT_CFG_METHOD | INPUT_CFG_VLAN, INPUT_METHOD_TS_VLAN_BCAST,
NULL, NULL, NULL, 0, 3 },
{ INPUT_CFG_METHOD | INPUT_CFG_VLAN, INPUT_METHOD_TS_VLAN_BCAST,
NULL, NULL, NULL, 0, 4 },
{ INPUT_CFG_METHOD | INPUT_CFG_VLAN, INPUT_METHOD_TS_VLAN_BCAST,
NULL, NULL, NULL, 0, 5 },
{ INPUT_CFG_METHOD | INPUT_CFG_VLAN, INPUT_METHOD_TS_VLAN_BCAST,
NULL, NULL, NULL, 0, 6 },
{ INPUT_CFG_METHOD | INPUT_CFG_VLAN, INPUT_METHOD_TS_VLAN_BCAST,
NULL, NULL, NULL, 0, 7 },
{ INPUT_CFG_METHOD | INPUT_CFG_VLAN, INPUT_METHOD_TS_VLAN_BCAST,
NULL, NULL, NULL, 0, 8 }
};
/*******************************************************************************
* intf_Create: prepare interface before main loop
*******************************************************************************
......@@ -141,7 +105,7 @@ void intf_Run( intf_thread_t *p_intf )
}
if( (p_intf->p_input != NULL) && p_intf->p_input->b_error )
{
input_DestroyThread( p_intf->p_input /*, NULL */ );
input_DestroyThread( p_intf->p_input, NULL );
p_intf->p_input = NULL;
intf_DbgMsg("Input thread destroyed\n");
}
......@@ -175,23 +139,18 @@ void intf_Destroy( intf_thread_t *p_intf )
*******************************************************************************/
int intf_SelectInput( intf_thread_t * p_intf, int i_index )
{
intf_DbgMsg("0x%x\n", p_intf );
intf_DbgMsg("\n");
/* Kill existing input, if any */
if( p_intf->p_input != NULL )
{
input_DestroyThread( p_intf->p_input /*??, NULL*/ );
input_DestroyThread( p_intf->p_input, NULL );
}
/* Check that input index is valid */
if( (i_index < 0) || (INTF_MAX_INPUT_CFG < i_index) )
{
p_intf->p_input = NULL;
return( 1 );
}
/* Open a new input */
p_intf->p_input = input_CreateThread( &INTF_INPUT_CFG[ i_index ] /*??, NULL*/ );
intf_Msg("Switching to channel %d\n", i_index );
p_intf->p_input = input_CreateThread( INPUT_METHOD_TS_VLAN_BCAST, NULL, 0, i_index,
p_intf->p_vout, p_main->p_aout, NULL );
return( p_intf->p_input == NULL );
}
......@@ -207,7 +166,7 @@ int intf_ProcessKey( intf_thread_t *p_intf, int i_key )
{
case 'Q': /* quit order */
case 'q':
case 27:
case 27: /* escape key */
p_intf->b_die = 1;
break;
case '0': /* source change */
......
......@@ -458,15 +458,15 @@ static int SelectPID( int i_argc, intf_arg_t *p_argv )
/******************************************************************************
* SpawnInput: spawn an input thread (ok ?)
******************************************************************************
* Spawn an input thread with the correct p_cfg parameters.
* Spawn an input thread
******************************************************************************/
static int SpawnInput( int i_argc, intf_arg_t *p_argv )
{
input_cfg_t cfg;
int i_arg;
/* Erase p_cfg. */
bzero( &cfg, sizeof( cfg ) );
int i_method = 0; /* method parameter */
char * psz_source = NULL; /* source parameter */
int i_port = 0; /* port parameter */
int i_vlan = 0; /* vlan parameter */
/* Parse parameters - see command list above */
for ( i_arg = 1; i_arg < i_argc; i_arg++ )
......@@ -474,62 +474,31 @@ static int SpawnInput( int i_argc, intf_arg_t *p_argv )
switch( p_argv[i_arg].i_index )
{
case 0: /* method */
cfg.i_method = p_argv[i_arg].i_num;
break;
case 1: /* filename */
cfg.psz_filename = p_argv[i_arg].psz_str;
break;
case 2: /* hostname */
cfg.psz_hostname = p_argv[i_arg].psz_str;
i_method = p_argv[i_arg].i_num;
break;
case 3: /* ip */
cfg.psz_ip = p_argv[i_arg].psz_str;
case 1: /* filename, hostname, ip */
case 2:
case 3:
psz_source = p_argv[i_arg].psz_str;
break;
case 4: /* port */
cfg.i_port = p_argv[i_arg].i_num;
i_port = p_argv[i_arg].i_num;
break;
case 5: /* VLAN */
cfg.i_vlan = p_argv[i_arg].i_num;
i_vlan = p_argv[i_arg].i_num;
break;
}
}
/* Setting i_properties to indicate which parameters are set. */
if( cfg.i_method )
{
cfg.i_properties |= INPUT_CFG_METHOD;
}
if( cfg.psz_filename )
{
cfg.i_properties |= INPUT_CFG_FILENAME;
}
if( cfg.psz_hostname )
{
cfg.i_properties |= INPUT_CFG_HOSTNAME;
}
if( cfg.psz_ip )
{
cfg.i_properties |= INPUT_CFG_IP;
}
if( cfg.i_port )
{
cfg.i_properties |= INPUT_CFG_PORT;
}
if( cfg.i_vlan )
{
cfg.i_properties |= INPUT_CFG_VLAN;
}
/* Default settings for the decoder threads */
cfg.p_aout = p_main->p_aout;
/* Create the input thread */
/* Destroy current input, if any */
if( p_main->p_intf->p_input != NULL )
{
input_DestroyThread( p_main->p_intf->p_input /*??, NULL*/ );
input_DestroyThread( p_main->p_intf->p_input, NULL );
}
p_main->p_intf->p_input = input_CreateThread( &cfg /*??,NULL*/ );
p_main->p_intf->p_input = input_CreateThread( i_method, psz_source, i_port, i_vlan,
p_main->p_intf->p_vout, p_main->p_aout,
NULL );
return( INTF_NO_ERROR );
}
......@@ -583,18 +552,8 @@ static int Vlan( int i_argc, intf_arg_t *p_argv )
;
}
/* Command is 'synchro' */
if( !strcmp(p_argv[i_command].psz_str, "synchro") )
{
input_VlanSynchronize();
}
/* Command is 'request' */
else if( !strcmp(p_argv[i_command].psz_str, "request") )
{
/* ?? */
}
/* Command is 'join' */
else if( !strcmp(p_argv[i_command].psz_str, "join") )
if( !strcmp(p_argv[i_command].psz_str, "join") )
{
/* ?? */
}
......
......@@ -423,7 +423,9 @@ static void Usage( void )
/* Vlan parameters */
intf_Msg("VLANs (Virtual Local Aera Networks) parameters:\n" \
" vlan_server=<host>[:<port>] VLANs server address and port\n" \
" " INPUT_IFACE_VAR "=<interface> network interface\n" \
" " INPUT_VLAN_SERVER_VAR "=<hostname> vlan server\n" \
" " INPUT_VLAN_PORT_VAR "=<port> vlan server port\n" \
);
/* Interfaces keys */
......
......@@ -55,6 +55,7 @@ vout_thread_t * vout_CreateThread ( char *psz_display, int i_root_
int i_status; /* thread status */
/* Allocate descriptor */
intf_DbgMsg("\n");
p_vout = (vout_thread_t *) malloc( sizeof(vout_thread_t) );
if( p_vout == NULL )
{
......@@ -123,7 +124,7 @@ vout_thread_t * vout_CreateThread ( char *psz_display, int i_root_
return( NULL );
}
intf_Msg("Video: display initialized (%dx%d, %d bpp)\n",
intf_Msg("Video display initialized (%dx%d, %d bpp)\n",
p_vout->i_width, p_vout->i_height, p_vout->i_screen_depth );
/* If status is NULL, wait until the thread is created */
......@@ -155,6 +156,7 @@ void vout_DestroyThread( vout_thread_t *p_vout, int *pi_status )
int i_status; /* thread status */
/* Set status */
intf_DbgMsg("\n");
p_vout->pi_status = (pi_status != NULL) ? pi_status : &i_status;
*p_vout->pi_status = THREAD_DESTROY;
......@@ -544,6 +546,7 @@ static int InitThread( vout_thread_t *p_vout )
int i_index; /* generic index */
/* Update status */
intf_DbgMsg("\n");
*p_vout->pi_status = THREAD_START;
/* Initialize output method - this function issues its own error messages */
......@@ -600,6 +603,7 @@ static void RunThread( vout_thread_t *p_vout)
free( p_vout ); /* destroy descriptor */
return;
}
intf_DbgMsg("\n");
/*
* Main loop - it is not executed if an error occured during
......@@ -752,6 +756,7 @@ static void RunThread( vout_thread_t *p_vout)
static void ErrorThread( vout_thread_t *p_vout )
{
/* Wait until a `die' order */
intf_DbgMsg("\n");
while( !p_vout->b_die )
{
/* Sleep a while */
......@@ -771,6 +776,7 @@ static void EndThread( vout_thread_t *p_vout )
int i_picture;
/* Store status */
intf_DbgMsg("\n");
pi_status = p_vout->pi_status;
*pi_status = THREAD_END;
......
......@@ -136,7 +136,7 @@ int vout_SysInit( vout_thread_t *p_vout )
}
if( i_err ) /* an error occured */
{
intf_Msg("Video: XShm extension desactivated\n" );
intf_Msg("XShm video sextension desactivated\n" );
p_vout->p_sys->b_shm = 0;
}
}
......@@ -229,7 +229,7 @@ int vout_SysManage( vout_thread_t *p_vout )
intf_ErrMsg("error: can't resize display\n");
return( 1 );
}
intf_Msg("Video: display resized to %dx%d\n", p_vout->i_width, p_vout->i_height);
intf_Msg("Video display resized to %dx%d\n", p_vout->i_width, p_vout->i_height);
}
return 0;
......@@ -388,7 +388,7 @@ static int X11OpenDisplay( vout_thread_t *p_vout, char *psz_display, Window root
p_vout->p_sys->i_screen = DefaultScreen( p_vout->p_sys->p_display );
if( !p_vout->p_sys->b_shm )
{
intf_Msg("Video: XShm extension is not available\n");
intf_Msg("XShm video extension is not available\n");
}
/* Get the screen depth */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment