Commit 38656e1f authored by Marc Ariberti's avatar Marc Ariberti

* added IPv6 support to vlcs (thanks to Alexis Guillard for his help)

* in order to do this in a clean way, I began to translate vlcs into C++ :
  * one generic C_Socket object which contains the interface
  * two derived objects :
    * C_IPv4Socket
    * C_IPv6Socket

This is a first draft, further C++ adaptations will be made soon.
parent b2b35e73
......@@ -3,7 +3,7 @@
###############################################################################
VERSION=0.1.2
CC=gcc
CC=c++
CFLAGS=-O3 -g -I. -Wall
all: vlcs
......@@ -11,14 +11,17 @@ all: vlcs
vlcs.o: vlcs.c vlcs.h logger.h
$(CC) $(CFLAGS) -c -o vlcs.o vlcs.c
socket.o: socket.c socket.h logger.h vlcs.h
$(CC) $(CFLAGS) -c -o socket.o socket.c
logger.o: logger.c logger.h vlcs.h
$(CC) $(CFLAGS) -c -o logger.o logger.c
config.o: config.c config.h logger.h vlcs.h
$(CC) $(CFLAGS) -c -o config.o config.c
vlcs: vlcs.o logger.o config.o
$(CC) $(CFLAGS) -o vlcs vlcs.o logger.o config.o
vlcs: vlcs.o logger.o config.o socket.o
$(CC) $(CFLAGS) -o vlcs vlcs.o logger.o config.o socket.o
tar: all
mkdir miniVLCS-$(VERSION)
......
......@@ -2,7 +2,7 @@
* config.c: mini-VideoLAN Channel Server, configuration system
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: config.c,v 1.1 2002/05/25 20:59:15 marcari Exp $
* $Id: config.c,v 1.2 2002/06/08 17:40:41 marcari Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Marc Ariberti <marcari@via.ecp.fr>
......@@ -98,7 +98,7 @@ void config_AddList( char * psz_item )
}
p_new = malloc( sizeof( channel_t ) );
p_new = (channel_t *)malloc( sizeof( channel_t ) );
*pp_cur = p_new;
strncpy( p_new->psz_vlc_config, psz_item, 255 );
......
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#include <iostream>
#include "config.h"
#include "vlcs.h"
#include "logger.h"
#include "socket.h"
void C_Socket::Close( int i_ret )
{
close( i_handle );
}
/**
* C_IPv4Socket class implementation
*/
C_IPv4Socket::C_IPv4Socket(int port, char * bind_addr = NULL)
{
int i_opt;
struct sockaddr_in sa_server;
struct in_addr s_bind_addr;
i_handle = socket( AF_INET, SOCK_DGRAM, 0 );
if( i_handle < 0 )
{
log_Alert( "Cannot open socket (%s), exiting\n", strerror(errno) );
::Close( -1 );
}
if( setsockopt( i_handle, SOL_SOCKET, SO_REUSEADDR, &i_opt, sizeof(i_opt) )
< 0 )
{
log_Alert("Cannot setsockopt (%s), exiting\n", strerror(errno) );
::Close( -1 );
}
sa_server.sin_family = AF_INET;
if ( bind_addr != NULL )
{
inet_aton(bind_addr, &s_bind_addr);
sa_server.sin_addr.s_addr = s_bind_addr.s_addr;
}
else
{
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 )
{
log_Alert("Cannot bind (%s), exiting\n", strerror(errno) );
::Close( -1 );
}
}
int C_IPv4Socket::Receive( char * p_buffer, int buffer_len )
{
socklen_t i_dummy = sizeof( struct sockaddr_in );
return recvfrom( i_handle, p_buffer, buffer_len, 0,
(struct sockaddr *)&m_sa_client, &i_dummy);
}
void C_IPv4Socket::Reply( char * psz_message )
{
time_t tm;
time(&tm);
/* TODO: remove this ugly kludge */
log_Info("%s : %s => %s\n",
config_RemoveLF( asctime( localtime( &tm ) ) ),
Ntop( ), psz_message );
for( ; ; )
{
if( sendto( i_handle, psz_message, strlen( psz_message ) + 1, 0,
(struct sockaddr *)&m_sa_client,
sizeof( struct sockaddr_in ) ) < 0 )
{
if( errno == EINTR )
{
continue;
}
log_Alert( "Cannot sendto (%s)\n", strerror(errno) );
}
break;
}
}
const char * C_IPv4Socket::Ntop( void )
{
return inet_ntop(AF_INET, &(m_sa_client.sin_addr), str, sizeof(str));
}
/**
* C_IPv6Socket class implementation
*/
C_IPv6Socket::C_IPv6Socket(int port, char * bind_addr = NULL)
{
int i_opt;
struct sockaddr_in6 sa_server;
struct in6_addr s_bind_addr;
i_handle = socket( AF_INET6, SOCK_DGRAM, 0 );
if( i_handle < 0 )
{
log_Alert( "Cannot open socket (%s), exiting\n", strerror(errno) );
::Close( -1 );
}
if( setsockopt( i_handle, SOL_SOCKET, SO_REUSEADDR, &i_opt, sizeof(i_opt) )
< 0 )
{
log_Alert("Cannot setsockopt (%s), exiting\n", strerror(errno) );
::Close( -1 );
}
sa_server.sin6_family = AF_INET6;
if ( bind_addr != NULL )
{
inet_pton(AF_INET6, bind_addr, &s_bind_addr);
sa_server.sin6_addr.s6_addr = s_bind_addr.s6_addr;
}
else
{
sa_server.sin6_addr = in6addr_any;
}
sa_server.sin6_port = ntohs( VLCS_PORT );
if( bind( i_handle, (struct sockaddr *)&sa_server, sizeof(sa_server) ) < 0 )
{
log_Alert("Cannot bind (%s), exiting\n", strerror(errno) );
::Close( -1 );
}
}
int C_IPv6Socket::Receive( char * p_buffer, int buffer_len )
{
socklen_t i_dummy = sizeof( struct sockaddr_in6 );
return recvfrom( i_handle, p_buffer, buffer_len, 0,
(struct sockaddr *)&m_sa_client, &i_dummy);
}
void C_IPv6Socket::Reply( char * psz_message )
{
time_t tm;
time(&tm);
/* TODO: remove this ugly kludge */
log_Info("%s : %s => %s\n",
config_RemoveLF( asctime( localtime( &tm ) ) ),
Ntop( ), psz_message );
for( ; ; )
{
if( sendto( i_handle, psz_message, strlen( psz_message ) + 1, 0,
(struct sockaddr *)&m_sa_client,
sizeof( struct sockaddr_in6 ) ) < 0 )
{
if( errno == EINTR )
{
continue;
}
log_Alert( "Cannot sendto (%s)\n", strerror(errno) );
}
break;
}
}
const char * C_IPv6Socket::Ntop( void )
{
return inet_ntop(AF_INET6, &(m_sa_client.sin6_addr), str, sizeof(str));
}
class C_Socket
{
public:
virtual int Receive( char * p_buffer, int buffer_len ) = 0;
virtual void Reply( char * psz_message ) = 0;
virtual void Close( int i_ret );
virtual const char * Ntop( ) = 0;
int i_handle;
};
class C_IPv4Socket : public C_Socket
{
public:
C_IPv4Socket( int port, char * bind_addr = NULL );
virtual int Receive( char * p_buffer, int buffer_len );
virtual void Reply( char * psz_message );
virtual const char * Ntop( );
protected:
sockaddr_in m_sa_client;
char str[INET_ADDRSTRLEN];
};
class C_IPv6Socket : public C_Socket
{
public:
C_IPv6Socket( int port, char * bind_addr = NULL );
virtual int Receive( char * p_buffer, int buffer_len );
virtual void Reply( char * psz_message );
virtual const char * Ntop( );
protected:
sockaddr_in6 m_sa_client;
char str[INET6_ADDRSTRLEN];
};
......@@ -2,7 +2,7 @@
* vlcs.c: mini-VideoLAN Channel Server
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: vlcs.c,v 1.8 2002/05/25 20:59:15 marcari Exp $
* $Id: vlcs.c,v 1.9 2002/06/08 17:40:41 marcari Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Marc Ariberti <marcari@via.ecp.fr>
......@@ -22,6 +22,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
......@@ -42,64 +43,14 @@
#include "vlcs.h"
#include "logger.h"
#include "config.h"
#include "socket.h"
#define VLCS_OK 0
#define VLCS_NOTFOUND 1
#define VLCS_PROTECTED 2
#define VLCS_FAILED 3
/* function prototypes
* grep "^[^ {#}/]" vlcs.c
*/
void socket_Init( void );
void socket_Get( void );
void socket_Send( struct sockaddr_in * p_sa, char * psz_message );
void Close( int i_ret );
int main( int argc, char ** argv );
int i_handle;
/* Socket management */
void socket_Init( void )
{
int i_opt;
struct sockaddr_in sa_server;
#ifdef BIND_ADDRESS
struct in_addr bind_addr;
#endif
i_handle = socket( AF_INET, SOCK_DGRAM, 0 );
if( i_handle < 0 )
{
log_Alert( "Cannot open socket (%s), exiting\n", strerror(errno) );
Close( -1 );
}
if( setsockopt( i_handle, SOL_SOCKET, SO_REUSEADDR, &i_opt, sizeof(i_opt) )
< 0 )
{
log_Alert("Cannot setsockopt (%s), exiting\n", strerror(errno) );
Close( -1 );
}
sa_server.sin_family = AF_INET;
#ifdef BIND_ADDRESS
inet_aton(BIND_ADDRESS, &bind_addr);
sa_server.sin_addr.s_addr = bind_addr.s_addr;
#else
sa_server.sin_addr.s_addr = INADDR_ANY;
#endif
sa_server.sin_port = ntohs( VLCS_PORT );
if( bind( i_handle, (struct sockaddr *)&sa_server, sizeof(sa_server) ) < 0 )
{
log_Alert("Cannot bind (%s), exiting\n", strerror(errno) );
Close( -1 );
}
}
C_Socket * ip_socket = NULL;
void socket_Get( void )
{
......@@ -107,13 +58,13 @@ void socket_Get( void )
struct timeval timeout;
FD_ZERO( &sockets );
FD_SET( i_handle, &sockets );
FD_SET( ip_socket->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( select( ip_socket->i_handle + 1, &sockets, NULL, NULL, &timeout ) < 0 )
{
if( errno == EINTR )
{
......@@ -145,21 +96,18 @@ void socket_Get( void )
}
}
if( FD_ISSET( i_handle, &sockets ) )
if( FD_ISSET( ip_socket->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_config;
channel_t * p_channel;
if( (i_len = recvfrom( i_handle, p_buffer, sizeof( p_buffer ), 0,
(struct sockaddr *)&sa_client, &i_dummy )) < 0 )
if( (i_len = ip_socket->Receive( p_buffer, sizeof( p_buffer ))) < 0 )
{
if( errno == EINTR )
{
......@@ -173,16 +121,15 @@ void socket_Get( void )
if( sscanf( p_buffer, "%2s %d %d %17s", psz_channel, &i_version,
&i_time, psz_macad ) != 4 )
{
socket_Send( &sa_client, "E: Bad request" );
ip_socket->Reply( "E: Bad request" );
log_Error( "sscanf failed (%s)\n", p_buffer );
return;
}
if ( i_version < 13 )
{
socket_Send( &sa_client, "E: Version mismatch, please upgrade your software" );
log_Alert( "Break-in attempt ! (%s)\n",
inet_ntoa( sa_client.sin_addr ) );
ip_socket->Reply( "E: Version mismatch, please upgrade your software" );
log_Alert( "Break-in attempt ! (%s)\n", ip_socket->Ntop() );
return;
}
......@@ -190,7 +137,7 @@ void socket_Get( void )
if( psz_tmp[0] != '\0' || i_channel < 0 ||
i_channel >= config_GetChannelNumber() )
{
socket_Send( &sa_client, "E: Channel doesn't exist" );
ip_socket->Reply( "E: Channel doesn't exist" );
log_Error( "Bad channel (%s)\n", psz_channel );
return;
}
......@@ -199,46 +146,22 @@ void socket_Get( void )
if( p_channel == NULL )
{
log_Error( "Bad channel (%s)\n", psz_channel );
socket_Send( &sa_client, "E: Channel doesn't exist" );
ip_socket->Reply( "E: Channel doesn't exist" );
return;
}
psz_config = p_channel->psz_vlc_config;
socket_Send( &sa_client, psz_config);
ip_socket->Reply( psz_config);
}
}
void socket_Send( struct sockaddr_in * p_sa, char * psz_message )
void Close( int i_ret )
{
time_t tm;
time(&tm);
/* TODO: remove this ugly kludge */
log_Info("%s : %s => %s\n",
config_RemoveLF( asctime( localtime( &tm ) ) ),
inet_ntoa( p_sa->sin_addr ),
psz_message
);
for( ; ; )
if (ip_socket != NULL)
{
if( sendto( i_handle, psz_message, strlen( psz_message ) + 1, 0,
(struct sockaddr *)p_sa,
sizeof( struct sockaddr_in ) ) < 0 )
{
if( errno == EINTR )
{
continue;
}
log_Alert( "Cannot sendto (%s)\n", strerror(errno) );
}
break;
ip_socket->Close( i_ret );
delete ip_socket;
}
}
void Close( int i_ret )
{
close( i_handle );
log_Close();
exit( i_ret );
}
......@@ -247,8 +170,20 @@ int main( int argc, char ** argv )
signal(SIGINT, Close);
log_Init();
config_ReadFile();
socket_Init();
#ifdef IPV6
# ifdef BIND_ADDRESS
ip_socket = new C_IPv6Socket(VLCS_PORT, BIND_ADDRESS);
# else
ip_socket = new C_IPv6Socket(VLCS_PORT);
# endif
#else
# ifdef BIND_ADDRESS
ip_socket = new C_IPv4Socket(VLCS_PORT, BIND_ADDRESS);
# else
ip_socket = new C_IPv4Socket(VLCS_PORT);
# endif
#endif
for( ; ; )
{
socket_Get();
......
......@@ -2,7 +2,7 @@
* vlcs.h: VideoLAN Channel Server configuration
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: vlcs.h,v 1.4 2002/05/25 20:59:15 marcari Exp $
* $Id: vlcs.h,v 1.5 2002/06/08 17:40:41 marcari Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Marc Ariberti <marcari@via.ecp.fr>
......@@ -23,9 +23,12 @@
*****************************************************************************/
/* precise the bind address, useful when using IP aliasing
* do not define this symbol if you want to bind to INADDR_ANY */
* do not define this symbol if you want to bind to INADDR_ANY or in6addr_any*/
/* #define BIND_ADDRESS "192.168.12.42" */
/* Uncomment this line to use IPv6 with vlcs */
#define IPV6
#define VLCS_VERSION 13
#define VLCS_PORT 6010
#define CHANNEL_CONF "vlcs.conf"
......@@ -39,4 +42,7 @@
/* #define SYSLOG_NAME "VLCS" */
#define SYSLOG_FACILITY LOG_DAEMON
int main( int argc, char ** argv );
void Close( int i_ret );
#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