Commit a74082f5 authored by Marc Ariberti's avatar Marc Ariberti

* small Channel Server that becomes to be far from the network part :)

* it is a simplified part of the vlcs part of the miniVLANserver

* it sends back a string to the vlc when it requests for a channel

* it is useful for multicast (and plain broadcast). this is temporary
while the complete multicast solution is not fully implemented.
parent 1852d5d0
###############################################################################
# vlcs (VideoLAN Channel Server) main Makefile - (c)2001 VideoLAN
###############################################################################
all: vlcs
vlcs: vlcs.c vlcs.h
$(CC) -O3 -g -I. -Wall -o $@ vlcs.c
clean:
-rm -f vlcs
* miniVLCS : mini VideoLAN Channel Server
*
* Authors : Marc ARIBERTI <marcari@videolan.org> (current maintainer)
* Christophe MASSIOT <massiot@via.ecp.fr>
When we began developing the multicast technology for VideoLAN, we wanted
an easy way to tell the client what is the multicast address associated to
a channel. When the vlc wants to get a new channel, it sends a request
to the VLCS and the VLCS gives an answer like : udp://@239.255.255.42
I decided to do this way for sending the multicast address to the client
because it did not required any modification inside the vlc.
The protocol is the same whether the VLCS is a complete VLANserver or
this miniVLCS.
The VLANserver would change the client's VLAN by sending a SNMP request
to the switchs are answers when everything is ok. This mini-VLCS answers
immediatly with the multicast address. Then the client knows it is a
multicast address and sends request to the network itself to received
the multicast stream.
This miniVLANSERVER can also be used with broadcasted streams, it
will help the client to decide with stream to catch.
This miniVLCS is based on the VLCS part of the miniVLANSERVER. That
part has been originally written by C. Massiot.
How to install it :
* Decompress the archive
* change into the directory
* run 'make'
* edit the vlcs.conf configuration file :
- one line per channel
- lines beginning by I: are considered raw data and sent directly
to the client (ex: I: nostream)
- each lines contains :
<the server address> <the destination address> <the destination port>
/*****************************************************************************
* vlcs.c: VideoLAN Channel Server socket facility
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: vlcs.c,v 1.1 2002/01/27 22:03:32 marcari Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Marc Ariberti <marcari@via.ecp.fr>
*
* 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, USA.
*****************************************************************************/
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <errno.h>
#include <arpa/inet.h>
#include <signal.h>
#include <time.h>
#include "vlcs.h"
#define VLCS_OK 0
#define VLCS_NOTFOUND 1
#define VLCS_PROTECTED 2
#define VLCS_FAILED 3
void Close( int i_ret );
void socket_Send( struct sockaddr_in *, char * );
int i_handle;
int i_channel_min, i_channel_max;
typedef struct channel_s
{
char psz_vlc_config[256];
} channel_t;
channel_t p_channels[16];
/* Socket management */
void socket_Init( void )
{
int i_opt;
struct sockaddr_in sa_server;
i_handle = socket( AF_INET, SOCK_DGRAM, 0 );
if( i_handle < 0 )
{
syslog( LOG_ALERT, "Cannot open socket (%s), exiting\n",
strerror(errno) );
closelog();
exit( -1 );
}
if( setsockopt( i_handle, SOL_SOCKET, SO_REUSEADDR, &i_opt, sizeof(i_opt) )
< 0 )
{
syslog( LOG_ALERT, "Cannot setsockopt (%s), exiting\n",
strerror(errno) );
Close( -1 );
}
sa_server.sin_family = AF_INET;
sa_server.sin_addr.s_addr = INADDR_ANY;
sa_server.sin_port = ntohs( VLCS_PORT );
if( bind( i_handle, (struct sockaddr *)&sa_server, sizeof(sa_server) ) < 0 )
{
syslog( LOG_ALERT, "Cannot bind (%s), exiting\n", strerror(errno) );
Close( -1 );
}
}
void socket_Get( void )
{
fd_set sockets;
struct timeval timeout;
FD_ZERO( &sockets );
FD_SET( i_handle, &sockets );
FD_SET( 0, &sockets );
timeout.tv_usec = 0;
timeout.tv_sec = 1;
if( select( i_handle + 1, &sockets, NULL, NULL, &timeout ) < 0 )
{
if( errno == EINTR )
{
return;
}
syslog( LOG_ALERT, "Cannot select (%s), exiting\n", strerror(errno) );
Close( -1 );
}
if( FD_ISSET( 0, &sockets ) )
{
/* Administration socket */
char p_buffer[128];
if( read( 0, p_buffer, sizeof( p_buffer ) ) < 0 )
{
if( errno == EINTR )
{
return;
}
syslog( LOG_CRIT, "Duh my controlling terminal has gone fishing\n" );
}
else if( p_buffer[0] == 'q' )
{
/* Quit */
syslog( LOG_ALERT, "Exiting now on admin's request\n" );
Close( 0 );
}
}
if( FD_ISSET( i_handle, &sockets ) )
{
/* Client request */
char p_buffer[2048];
struct sockaddr_in sa_client;
int i_len, i_version, i_time, i_channel;
socklen_t i_dummy = sizeof( struct sockaddr_in );
char psz_macad[18];
char psz_channel[3];
char * psz_tmp;
char psz_message[80], * psz_config;
if( (i_len = recvfrom( i_handle, p_buffer, sizeof( p_buffer ), 0,
(struct sockaddr *)&sa_client, &i_dummy )) < 0 )
{
if( errno == EINTR )
{
return;
}
printf( "Cannot recvfrom (%s)\n", strerror(errno) );
return;
}
p_buffer[i_len] = '\0';
if( sscanf( p_buffer, "%2s %d %d %17s", psz_channel, &i_version,
&i_time, psz_macad ) != 4 )
{
socket_Send( &sa_client, "E: Bad request" );
printf( "sscanf failed (%s)\n", p_buffer );
return;
}
i_channel = strtol( psz_channel, &psz_tmp, 0 );
if( psz_tmp[0] != '\0' || i_channel < i_channel_min ||
i_channel > i_channel_max )
{
socket_Send( &sa_client, "E: Channel doesn't exist" );
printf( "Bad channel (%s)\n", psz_channel );
return;
}
psz_config = p_channels[i_channel].psz_vlc_config;
if ( psz_config[0] == 'I' )
{
socket_Send( &sa_client, psz_config);
return;
}
else
{
static char p_server[30];
static char p_dest[30];
static char p_port[8];
sscanf(psz_config, "%s %s %s", p_server, p_dest, p_port);
if ( i_version == 12 )
{
sprintf( psz_message, "ts://0:0/%s", p_dest );
}
else if ( i_version == 13 )
{
sprintf( psz_message, "udpstream://@%s", p_dest );
}
else
{
socket_Send( &sa_client, "E: Version mismatch" );
syslog( LOG_CRIT, "Break-in attempt ! (%s)\n",
inet_ntoa( sa_client.sin_addr ) );
return;
}
}
socket_Send( &sa_client, psz_message );
}
}
void socket_Send( struct sockaddr_in * p_sa, char * psz_message )
{
time_t tm;
time(&tm);
fprintf(stderr, "%s : %s => %s\n",
asctime( localtime( &tm ) ),
inet_ntoa( p_sa->sin_addr ),
psz_message
);
for( ; ; )
{
if( sendto( i_handle, psz_message, strlen( psz_message ) + 1, 0,
(struct sockaddr *)p_sa,
sizeof( struct sockaddr_in ) ) < 0 )
{
if( errno == EINTR )
{
continue;
}
syslog( LOG_CRIT, "Cannot sendto (%s)\n", strerror(errno) );
}
break;
}
}
void config_ReadFile( void )
{
char psz_buffer[2048];
FILE * p_config;
p_config = fopen( CHANNEL_CONF, "r" );
if( p_config == NULL )
{
syslog( LOG_ALERT, "Cannot fopen " CHANNEL_CONF " (%s)\n",
strerror(errno) );
exit( -1 );
}
i_channel_min = 0;
i_channel_max = -1;
while( fgets( psz_buffer, sizeof( psz_buffer ), p_config ) != NULL )
{
if( psz_buffer[0] != '#' && psz_buffer[0] != '\0' )
{
strncpy( p_channels[++i_channel_max].psz_vlc_config, psz_buffer,
255 );
}
}
fclose( p_config );
}
void Close( int i_ret )
{
close( i_handle );
closelog();
exit( i_ret );
}
int main( int argc, char ** argv )
{
config_ReadFile();
socket_Init();
openlog( SYSLOG_NAME, LOG_PERROR, SYSLOG_FACILITY );
for( ; ; )
{
socket_Get();
}
return( 0 );
}
I: nostream
138.195.136.160 239.255.255.42 1234
138.195.136.160 239.255.255.43 1234
138.195.136.160 239.255.255.44 1234
138.195.136.160 239.255.255.45 1234
138.195.136.160 239.255.255.46 1234
138.195.136.160 239.255.255.47 1234
138.195.136.160 239.255.255.48 1234
138.195.136.160 239.255.255.49 1234
138.195.136.160 239.255.255.50 1234
138.195.136.160 239.255.255.51 1234
138.195.136.160 239.255.255.52 1234
138.195.136.160 239.255.255.53 1234
138.195.136.160 239.255.255.54 1234
/*****************************************************************************
* vlcs.h: VideoLAN Channel Server configuration
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: vlcs.h,v 1.1 2002/01/27 22:03:32 marcari Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
* 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, USA.
*****************************************************************************/
#define VLCS_VERSION 13
#define VLCS_PORT 6010
#define CHANNEL_CONF "vlcs.conf"
#define SYSLOG_NAME "VLCS"
#define SYSLOG_FACILITY LOG_DAEMON
/* Database is reloaded at xx:12:00 */
#undef DEBUG
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