Commit 881768ad authored by Laurent Aimar's avatar Laurent Aimar

* all: begin to add mms over udp support. It begin to work (at least

for me) but it still needs some work.
parent 1158db5f
......@@ -2,7 +2,7 @@
* buffer.c: MMS access plug-in
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
* $Id: buffer.c,v 1.1 2002/11/22 18:35:57 sam Exp $
* $Id: buffer.c,v 1.2 2002/11/25 00:22:04 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
......@@ -193,7 +193,7 @@ uint64_t var_buffer_get64( var_buffer_t *p_buf )
return( i_dw1 + ( i_dw2 << 32 ) );
}
int var_buffer_getmemory ( var_buffer_t *p_buf, void *p_mem, int i_mem )
int var_buffer_getmemory ( var_buffer_t *p_buf, void *p_mem, int64_t i_mem )
{
int i_copy;
......@@ -202,6 +202,11 @@ int var_buffer_getmemory ( var_buffer_t *p_buf, void *p_mem, int i_mem )
{
memcpy( p_mem, p_buf + p_buf->i_data, i_copy );
}
if( i_copy < 0 )
{
// fprintf( stderr, "\n**************arrrrrrggggg\n" );
i_copy = 0;
}
p_buf->i_data += i_copy;
return( i_copy );
}
......
......@@ -2,7 +2,7 @@
* buffer.h: MMS access plug-in
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
* $Id: buffer.h,v 1.1 2002/11/22 18:35:57 sam Exp $
* $Id: buffer.h,v 1.2 2002/11/25 00:22:04 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
......@@ -50,7 +50,7 @@ uint8_t var_buffer_get8 ( var_buffer_t *p_buf );
uint16_t var_buffer_get16( var_buffer_t *p_buf );
uint32_t var_buffer_get32( var_buffer_t *p_buf );
uint64_t var_buffer_get64( var_buffer_t *p_buf );
int var_buffer_getmemory ( var_buffer_t *p_buf, void *p_mem, int i_mem );
int var_buffer_getmemory ( var_buffer_t *p_buf, void *p_mem, int64_t i_mem );
int var_buffer_readempty( var_buffer_t *p_buf );
void var_buffer_getguid( var_buffer_t *p_buf, guid_t *p_guid );
......@@ -2,7 +2,7 @@
* mms.c: MMS access plug-in
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
* $Id: mms.c,v 1.6 2002/11/22 18:35:57 sam Exp $
* $Id: mms.c,v 1.7 2002/11/25 00:22:04 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
......@@ -76,8 +76,6 @@ static void Close ( vlc_object_t * );
static int Read ( input_thread_t * p_input, byte_t * p_buffer,
size_t i_len );
static ssize_t NetRead ( input_thread_t * p_input, input_socket_t * p_socket,
byte_t * p_buffer, size_t i_len );
static void Seek ( input_thread_t *, off_t );
static int SetProgram ( input_thread_t *, pgrm_descriptor_t * );
......@@ -85,7 +83,7 @@ static int SetProgram ( input_thread_t *, pgrm_descriptor_t * );
static int MMSOpen( input_thread_t *, url_t *, int, char * );
static int MMSStart ( input_thread_t *, uint32_t );
static int MMSStop ( input_thread_t *p_input ); // Not used
static int MMSStop ( input_thread_t *p_input );
static int MMSClose ( input_thread_t * );
......@@ -109,7 +107,9 @@ static void mms_ParseURL( url_t *p_url, char *psz_url );
/*
* Ok, ok, j'le ferai plus...
*/
/*
* Merci :))
*/
/*****************************************************************************
* Module descriptor
......@@ -122,8 +122,6 @@ vlc_module_begin();
"force selection of all streams",
"force selection of all streams" );
// add_bool( "mms-modem", 0, NULL, "Set maxbitrate to 56Kb/s","" );
add_string( "mms-stream", NULL, NULL,
"streams selection",
"force this stream selection" );
......@@ -152,8 +150,6 @@ static int Open( vlc_object_t *p_this )
(void*)p_access = malloc( sizeof( access_t ) );
memset( p_access, 0, sizeof( access_t ) );
p_access->p_cmd = malloc( BUF_SIZE );
/* *** Parse URL and get server addr/port and path *** */
mms_ParseURL( &p_access->url, p_input->psz_name );
......@@ -161,13 +157,16 @@ static int Open( vlc_object_t *p_this )
!( *p_access->url.psz_server_addr ) )
{
FREE( p_access->url.psz_private );
FREE( p_access->p_cmd );
msg_Err( p_input, "invalid server name" );
return( -1 );
}
if( p_access->url.i_server_port == 0 )
{
p_access->url.i_server_port = 1755; // default port
p_access->url.i_server_port = 1755; /* default port */
}
if( p_access->url.i_bind_port == 0 )
{
p_access->url.i_bind_port = 7000; /* default port */
}
......@@ -197,11 +196,11 @@ static int Open( vlc_object_t *p_this )
}
/* 3: connect */
if( i_proto == MMS_PROTO_AUTO )
{ // first try with TCP
{ /* first try with TCP */
i_status =
MMSOpen( p_input, &p_access->url, MMS_PROTO_TCP, psz_network );
if( i_status < 0 )
{ // then with UDP
{ /* then with UDP */
i_status =
MMSOpen( p_input, &p_access->url, MMS_PROTO_UDP, psz_network );
}
......@@ -215,16 +214,12 @@ static int Open( vlc_object_t *p_this )
if( i_status < 0 )
{
// all sockets are closed
msg_Err( p_input, "cannot connect to server" );
FREE( p_access->url.psz_private );
FREE( p_access->p_cmd );
return( -1 );
}
msg_Dbg( p_input, "connected to %s", p_access->url.psz_server_addr );
// all sockets are open
/* *** set exported functions *** */
p_input->pf_read = Read;
......@@ -232,7 +227,7 @@ static int Open( vlc_object_t *p_this )
p_input->pf_set_program = SetProgram;
p_input->pf_set_area = NULL;
p_input->p_private = NULL; // XXX ??
p_input->p_private = NULL;
/* *** finished to set some variable *** */
vlc_mutex_lock( &p_input->stream.stream_lock );
......@@ -261,7 +256,6 @@ static int Open( vlc_object_t *p_this )
msg_Err( p_input, "cannot start stream" );
MMSClose( p_input );
FREE( p_access->url.psz_private );
FREE( p_access->p_cmd );
return( -1 );
}
......@@ -281,7 +275,6 @@ static void Close( vlc_object_t *p_this )
/* free memory */
FREE( p_access->url.psz_private );
FREE( p_access->p_cmd );
}
/*****************************************************************************
......@@ -404,60 +397,6 @@ static int Read ( input_thread_t * p_input, byte_t * p_buffer,
return( i_data );
}
/*****************************************************************************
* NetRead: read on a file descriptor, checking b_die periodically
*****************************************************************************/
static ssize_t NetRead( input_thread_t * p_input, input_socket_t * p_socket,
byte_t * p_buffer, size_t i_len )
{
#ifdef UNDER_CE
return -1;
#else
struct timeval timeout;
fd_set fds;
int i_ret;
/* Initialize file descriptor set */
FD_ZERO( &fds );
FD_SET( p_socket->i_handle, &fds );
/* We'll wait 0.5 second if nothing happens */
timeout.tv_sec = 0;
timeout.tv_usec = 500000;
/* Find if some data is available */
i_ret = select( p_socket->i_handle + 1, &fds,
NULL, NULL, &timeout );
if( i_ret == -1 && errno != EINTR )
{
msg_Err( p_input, "network select error (%s)", strerror(errno) );
}
else if( i_ret > 0 )
{
ssize_t i_recv = recv( p_socket->i_handle, p_buffer, i_len, 0 );
if( i_recv > 0 )
{
vlc_mutex_lock( &p_input->stream.stream_lock );
p_input->stream.p_selected_area->i_tell += i_recv;
vlc_mutex_unlock( &p_input->stream.stream_lock );
}
if( i_recv < 0 )
{
msg_Err( p_input, "recv failed (%s)", strerror(errno) );
}
return i_recv;
}
return 0;
#endif
}
static void asf_HeaderParse( mms_stream_t stream[128],
uint8_t *p_header, int i_header )
{
......@@ -471,17 +410,21 @@ static void asf_HeaderParse( mms_stream_t stream[128],
stream[i].i_cat = MMS_STREAM_UNKNOWN;
}
// fprintf( stderr, " ---------------------header:%d\n", i_header );
var_buffer_initread( &buffer, p_header, i_header );
var_buffer_getguid( &buffer, &guid );
if( !CmpGuid( &guid, &asf_object_header_guid ) )
{
// XXX Error
// fprintf( stderr, " ---------------------ERROR------\n" );
}
var_buffer_getmemory( &buffer, NULL, 30 - 16 );
for( ;; )
{
// fprintf( stderr, " ---------------------data:%d\n", buffer.i_data );
if( var_buffer_readempty( &buffer ) )
{
return;
......@@ -493,13 +436,14 @@ static void asf_HeaderParse( mms_stream_t stream[128],
{
int i_stream_id;
guid_t stream_type;
// msg_Dbg( p_input, "found stream_properties" );
var_buffer_getguid( &buffer, &stream_type );
var_buffer_getmemory( &buffer, NULL, 32 );
i_stream_id = var_buffer_get8( &buffer ) & 0x7f;
var_buffer_getmemory( &buffer, NULL, i_size - 24 - 32 - 16 - 1 );
// fprintf( stderr, " 1---------------------skip:%lld\n", i_size - 24 - 32 - 16 - 1 );
var_buffer_getmemory( &buffer, NULL, i_size - 24 - 32 - 16 - 1);
if( CmpGuid( &stream_type, &asf_object_stream_type_video ) )
{
......@@ -531,12 +475,14 @@ static void asf_HeaderParse( mms_stream_t stream[128],
i_count--;
i_size -= 6;
}
// fprintf( stderr, " 2---------------------skip:%lld\n", i_size - 24);
var_buffer_getmemory( &buffer, NULL, i_size - 24 );
}
else
{
// skip unknown guid
var_buffer_getmemory( &buffer, NULL, i_size - 24 );
// fprintf( stderr, " 3---------------------skip:%lld\n", i_size - 24);
}
}
}
......@@ -731,40 +677,64 @@ static int MMSOpen( input_thread_t *p_input,
p_input->p_private = (void*)&socket_desc;
if( !( p_network = module_Need( p_input, "network", psz_network ) ) )
{
msg_Err( p_input, "failed to open a connection" );
msg_Err( p_input, "failed to open a connection (tcp)" );
return( -1 );
}
module_Unneed( p_input, p_network );
p_access->socket_server.i_handle = socket_desc.i_handle;
p_input->i_mtu = socket_desc.i_mtu; // FIXME
p_access->socket_tcp.i_handle = socket_desc.i_handle;
p_input->i_mtu = 0; /*socket_desc.i_mtu;*/
msg_Dbg( p_input,
"connection with \"%s:%d\" successful",
"connection(tcp) with \"%s:%d\" successful",
p_url->psz_server_addr,
p_url->i_server_port );
/* *** Bind port if UDP protocol is selected *** */
// TODO
if( b_udp )
{
msg_Err( p_input,
"MMS/UDP not yet implemented" );
// close socket
"MMS/UDP not yet functionnal, anyway trying..." );
if( !p_url->psz_bind_addr || !*p_url->psz_bind_addr )
{
msg_Err( p_input, "for udp you have to provide bind address (mms://<server_addr>@<bind_addr/<path> (FIXME)" );
#if defined( UNDER_CE )
CloseHandle( (HANDLE)p_access->socket_tcp.i_handle );
#elif defined( WIN32 )
closesocket( p_access->socket_tcp.i_handle );
#else
close( p_access->socket_tcp.i_handle );
#endif
return( -1 );
}
socket_desc.i_type = NETWORK_UDP;
socket_desc.psz_server_addr = "";
socket_desc.i_server_port = 0;
socket_desc.psz_bind_addr = p_url->psz_bind_addr;
socket_desc.i_bind_port = p_url->i_bind_port;
p_input->p_private = (void*)&socket_desc;
if( !( p_network = module_Need( p_input, "network", psz_network ) ) )
{
msg_Err( p_input, "failed to open a connection (udp)" );
#if defined( UNDER_CE )
CloseHandle( (HANDLE)p_access->socket_server.i_handle );
CloseHandle( (HANDLE)p_access->socket_tcp.i_handle );
#elif defined( WIN32 )
closesocket( p_access->socket_server.i_handle );
closesocket( p_access->socket_tcp.i_handle );
#else
close( p_access->socket_server.i_handle );
close( p_access->socket_tcp.i_handle );
#endif
return( -1 );
}
module_Unneed( p_input, p_network );
p_access->socket_udp.i_handle = socket_desc.i_handle;
p_input->i_mtu = 0;/*socket_desc.i_mtu; FIXME */
}
/* *** Init context for mms prototcol *** */
GenerateGuid( &p_access->guid ); // used to identify client by server
GenerateGuid( &p_access->guid ); /* used to identify client by server */
msg_Dbg( p_input,
"generated guid: "GUID_FMT,
GUID_PRINT( p_access->guid ) );
p_access->i_command_level = 1; // updated after 0x1A command
p_access->i_command_level = 1; /* updated after 0x1A command */
p_access->i_seq_num = 0;
p_access->i_media_packet_id_type = 0x04;
p_access->i_header_packet_id_type = 0x02;
......@@ -777,6 +747,10 @@ static int MMSOpen( input_thread_t *p_input,
p_access->i_media_used = 0;
p_access->i_pos = 0;
p_access->i_buffer_tcp = 0;
p_access->i_buffer_udp = 0;
p_access->p_cmd = NULL;
p_access->i_cmd = 0;
/* *** send command 1 : connection request *** */
var_buffer_initwrite( &buffer, 0 );
......@@ -831,8 +805,17 @@ static int MMSOpen( input_thread_t *p_input,
var_buffer_add32( &buffer, 0x00000000 );
var_buffer_add32( &buffer, 0x000a0000 );
var_buffer_add32( &buffer, 0x00000002 );
// FIXME wrong for UDP FIXME
sprintf( tmp, "\\\\127.0.0.1\\%s\\1242", b_udp ? "UDP" : "TCP" );
if( b_udp )
{
sprintf( tmp,
"\\\\%s\\UDP\\%d",
p_url->psz_bind_addr,
p_url->i_bind_port );
}
else
{
sprintf( tmp, "\\\\127.0.0.1\\TCP\\1242" );
}
var_buffer_addUTF16( &buffer, tmp );
var_buffer_add16( &buffer, '0' );
......@@ -844,7 +827,7 @@ static int MMSOpen( input_thread_t *p_input,
buffer.i_data );
/* *** response from server, should be 0x02 or 0x03 *** */
mms_CommandRead( p_input, 0x02, 0 );
mms_CommandRead( p_input, 0x02, 0x03 );
if( p_access->i_command == 0x03 )
{
msg_Err( p_input,
......@@ -861,7 +844,6 @@ static int MMSOpen( input_thread_t *p_input,
/* *** send command 5 : media file name/path requested *** */
var_buffer_reinitwrite( &buffer, 0 );
var_buffer_add64( &buffer, 0 );
// var_buffer_addUTF16( &buffer, "/" );
var_buffer_addUTF16( &buffer, p_url->psz_path );
mms_CommandSend( p_input,
......@@ -878,7 +860,7 @@ static int MMSOpen( input_thread_t *p_input,
if( p_access->i_command == 0x1A )
{
msg_Err( p_input, "id/password requested (not yet supported)" );
// FIXME
/* FIXME */
var_buffer_free( &buffer );
MMSClose( p_input );
return( -1 );
......@@ -893,7 +875,7 @@ static int MMSOpen( input_thread_t *p_input,
return( -1 );
}
// 1 for file ok, 2 for authen ok
/* 1 for file ok, 2 for authen ok */
switch( GetDWLE( p_access->p_cmd + MMS_CMD_HEADERSIZE ) )
{
case 0x0001:
......@@ -933,6 +915,9 @@ static int MMSOpen( input_thread_t *p_input,
p_access->i_max_bit_rate,
p_access->i_header_size );
/* XXX XXX dirty hack XXX XXX */
p_input->i_mtu = 3 * p_access->i_packet_length;
/* *** send command 15 *** */
var_buffer_reinitwrite( &buffer, 0 );
......@@ -968,15 +953,15 @@ static int MMSOpen( input_thread_t *p_input,
return( -1 );
}
/* *** parse header and get stream and their id *** */
// get all streams properties,
//
// TODO : stream bitrates properties(optional)
// and bitrate mutual exclusion(optional)
/* get all streams properties,
*
* TODO : stream bitrates properties(optional)
* and bitrate mutual exclusion(optional) */
asf_HeaderParse( p_access->stream,
p_access->p_header, p_access->i_header );
mms_StreamSelect( p_input, p_access->stream );
/* *** now select stream we want to receive *** */
// TODO take care of stream bitrate TODO
/* TODO take care of stream bitrate TODO */
i_streams = 0;
i_first = -1;
var_buffer_reinitwrite( &buffer, 0 );
......@@ -1061,9 +1046,8 @@ static int MMSStart ( input_thread_t *p_input, uint32_t i_packet )
/* *** start stream from packet 0 *** */
var_buffer_initwrite( &buffer, 0 );
var_buffer_add64( &buffer, 0 ); // seek point in second
var_buffer_add64( &buffer, 0 ); /* seek point in second */
var_buffer_add32( &buffer, 0xffffffff );
// var_buffer_add32( &buffer, 0xffffffff ); // begin from start
var_buffer_add32( &buffer, i_packet ); // begin from start
var_buffer_add8( &buffer, 0xff ); // stream time limit
var_buffer_add8( &buffer, 0xff ); // on 3bytes ...
......@@ -1127,24 +1111,25 @@ static int MMSClose ( input_thread_t *p_input )
NULL, 0 );
/* *** close sockets *** */
#if defined( UNDER_CE )
CloseHandle( (HANDLE)p_access->socket_server.i_handle );
CloseHandle( (HANDLE)p_access->socket_tcp.i_handle );
#elif defined( WIN32 )
closesocket( p_access->socket_server.i_handle );
closesocket( p_access->socket_tcp.i_handle );
#else
close( p_access->socket_server.i_handle );
close( p_access->socket_tcp.i_handle );
#endif
if( p_access->i_proto == MMS_PROTO_UDP )
{
#if defined( UNDER_CE )
CloseHandle( (HANDLE)p_access->socket_data.i_handle );
CloseHandle( (HANDLE)p_access->socket_udp.i_handle );
#elif defined( WIN32 )
closesocket( p_access->socket_data.i_handle );
closesocket( p_access->socket_udp.i_handle );
#else
close( p_access->socket_data.i_handle );
close( p_access->socket_udp.i_handle );
#endif
}
FREE( p_access->p_cmd );
FREE( p_access->p_media );
FREE( p_access->p_header );
......@@ -1174,7 +1159,8 @@ static void mms_ParseURL( url_t *p_url, char *psz_url )
}
p_url->psz_server_addr = psz_parser;
while( *psz_parser && *psz_parser != ':' && *psz_parser != '/' )
while( *psz_parser &&
*psz_parser != ':' && *psz_parser != '/' && *psz_parser != '@' )
{
psz_parser++;
}
......@@ -1194,46 +1180,68 @@ static void mms_ParseURL( url_t *p_url, char *psz_url )
{
psz_server_port = "";
}
if( *psz_parser == '/' )
if( *psz_parser == '@' )
{
char *psz_bind_port;
*psz_parser = '\0';
psz_parser++;
p_url->psz_path = psz_parser;
p_url->psz_bind_addr = psz_parser;
while( *psz_parser && *psz_parser != ':' && *psz_parser != '/' )
{
psz_parser++;
}
if( *psz_server_port )
if( *psz_parser == ':' )
{
p_url->i_server_port = strtol( psz_server_port, &psz_parser, 10 );
*psz_parser = '\0';
psz_parser++;
psz_bind_port = psz_parser;
while( *psz_parser && *psz_parser != '/' )
{
psz_parser++;
}
}
else
{
p_url->i_server_port = 0;
psz_bind_port = "";
}
if( *psz_bind_port )
{
p_url->i_bind_port = strtol( psz_bind_port, &psz_parser, 10 );
}
else
{
p_url->i_bind_port = 0;
}
}
else
{
p_url->psz_bind_addr = "";
p_url->i_bind_port = 0;
}
}
static int mms_ReadData( input_thread_t *p_input,
uint8_t *p_data,
int i_data )
{
access_t *p_access = (access_t*)p_input->p_access_data;
int i_read;
while( i_data > 0 )
if( *psz_parser == '/' )
{
i_read = NetRead( p_input, &p_access->socket_server, p_data, i_data );
if( i_read < 0 )
*psz_parser = '\0';
psz_parser++;
p_url->psz_path = psz_parser;
}
if( *psz_server_port )
{
msg_Err( p_input, "failed to read data" );
return( -1 );
p_url->i_server_port = strtol( psz_server_port, &psz_parser, 10 );
}
i_data -= i_read;
p_data += i_read;
else
{
p_url->i_server_port = 0;
}
return( 0 );
}
/****************************************************************************
*
* MMS specific functions
......@@ -1255,11 +1263,11 @@ static int mms_CommandSend( input_thread_t *p_input,
/* first init uffer */
var_buffer_initwrite( &buffer, 0 );
var_buffer_add32( &buffer, 0x00000001 ); // start sequence
var_buffer_add32( &buffer, 0xB00BFACE ); // ...
// size after protocol type
var_buffer_add32( &buffer, 0x00000001 ); /* start sequence */
var_buffer_add32( &buffer, 0xB00BFACE );
/* size after protocol type */
var_buffer_add32( &buffer, i_data + MMS_CMD_HEADERSIZE - 16 );
var_buffer_add32( &buffer, 0x20534d4d ); // protocol "MMS "
var_buffer_add32( &buffer, 0x20534d4d ); /* protocol "MMS " */
var_buffer_add32( &buffer, i_data_by8 + 4 );
var_buffer_add32( &buffer, p_access->i_seq_num ); p_access->i_seq_num++;
var_buffer_add64( &buffer, 0 );
......@@ -1275,7 +1283,7 @@ static int mms_CommandSend( input_thread_t *p_input,
}
/* send it */
if( send( p_access->socket_server.i_handle,
if( send( p_access->socket_tcp.i_handle,
buffer.p_data,
buffer.i_data,
0 ) == -1 )
......@@ -1288,183 +1296,243 @@ static int mms_CommandSend( input_thread_t *p_input,
return( 0 );
}
static int mms_ReceiveCommand( input_thread_t *p_input )
static int NetFillBuffer( input_thread_t *p_input )
{
#define GET32( i_pos ) \
( p_access->p_cmd[i_pos] + ( p_access->p_cmd[i_pos +1] << 8 ) + \
( p_access->p_cmd[i_pos + 2] << 16 ) + \
( p_access->p_cmd[i_pos + 3] << 24 ) )
#ifdef UNDER_CE
return -1;
#else
access_t *p_access = (access_t*)p_input->p_access_data;
struct timeval timeout;
fd_set fds;
int i_ret;
do
{
int i_length;
// see for UDP mode
/* FIXME when using udp */
ssize_t i_tcp, i_udp;
ssize_t i_tcp_read, i_udp_read;
int i_handle_max;
/* Initialize file descriptor set */
FD_ZERO( &fds );
i_tcp = MMS_BUFFER_SIZE/2 - p_access->i_buffer_tcp;