Commit 4cf2f458 authored by Laurent Aimar's avatar Laurent Aimar

* asf: fixed unintialised variable, cleaned up some stuffs.

 * mmsh: big rework of the mmsh module.
parent a9ddba27
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* asf.c: MMS access plug-in * asf.c: MMS access plug-in
***************************************************************************** *****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN * Copyright (C) 2001, 2002 VideoLAN
* $Id: asf.c,v 1.3 2004/02/12 20:09:38 fenrir Exp $ * $Id$
* *
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* *
...@@ -73,6 +73,8 @@ void E_( asf_HeaderParse ) ( asf_header_t *hdr, ...@@ -73,6 +73,8 @@ void E_( asf_HeaderParse ) ( asf_header_t *hdr,
for( i = 0; i < 128; i++ ) for( i = 0; i < 128; i++ )
{ {
hdr->stream[i].i_cat = ASF_STREAM_UNKNOWN; hdr->stream[i].i_cat = ASF_STREAM_UNKNOWN;
hdr->stream[i].i_selected = 0;
hdr->stream[i].i_bitrate = -1;
} }
//fprintf( stderr, " ---------------------header:%d\n", i_header ); //fprintf( stderr, " ---------------------header:%d\n", i_header );
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* asf.h: MMS access plug-in * asf.h: MMS access plug-in
***************************************************************************** *****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN * Copyright (C) 2001, 2002 VideoLAN
* $Id: asf.h,v 1.5 2003/04/20 19:29:43 fenrir Exp $ * $Id$
* *
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* *
...@@ -34,11 +34,9 @@ ...@@ -34,11 +34,9 @@
typedef struct asf_stream_s typedef struct asf_stream_s
{ {
int i_id; /* 1 -> 127 */
int i_cat; /* ASF_STREAM_VIDEO, ASF_STREAM_AUDIO */ int i_cat; /* ASF_STREAM_VIDEO, ASF_STREAM_AUDIO */
int i_bitrate; /* -1 if unknown */ int i_bitrate; /* -1 if unknown */
int i_selected; int i_selected;
} asf_stream_t; } asf_stream_t;
typedef struct typedef struct
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* mmsh.c: * mmsh.c:
***************************************************************************** *****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN * Copyright (C) 2001, 2002 VideoLAN
* $Id: mmsh.c,v 1.8 2004/01/26 16:30:34 fenrir Exp $ * $Id$
* *
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* *
...@@ -21,12 +21,6 @@ ...@@ -21,12 +21,6 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/ *****************************************************************************/
/*
* TODO:
* * http_proxy
*
*/
/***************************************************************************** /*****************************************************************************
* Preamble * Preamble
*****************************************************************************/ *****************************************************************************/
...@@ -35,6 +29,8 @@ ...@@ -35,6 +29,8 @@
#include <vlc/vlc.h> #include <vlc/vlc.h>
#include <vlc/input.h> #include <vlc/input.h>
#include "vlc_playlist.h"
#include "network.h" #include "network.h"
#include "asf.h" #include "asf.h"
#include "buffer.h" #include "buffer.h"
...@@ -42,25 +38,24 @@ ...@@ -42,25 +38,24 @@
#include "mms.h" #include "mms.h"
#include "mmsh.h" #include "mmsh.h"
/* TODO:
* - http_proxy
* - authentication
*/
/***************************************************************************** /*****************************************************************************
* Local prototypes * Local prototypes
*****************************************************************************/ *****************************************************************************/
int E_(MMSHOpen) ( input_thread_t * ); int E_(MMSHOpen) ( input_thread_t * );
void E_(MMSHClose) ( input_thread_t * ); void E_(MMSHClose) ( input_thread_t * );
static ssize_t Read( input_thread_t *, byte_t *, size_t );
static void Seek( input_thread_t *, off_t );
static ssize_t NetFill( input_thread_t *, access_sys_t *, int );
static int mmsh_start ( input_thread_t *, off_t );
static void mmsh_stop ( input_thread_t * );
static int mmsh_get_packet( input_thread_t *, chunk_t * );
static http_answer_t *http_answer_parse( uint8_t *, int ); static ssize_t Read( input_thread_t *, byte_t *, size_t );
static void http_answer_free ( http_answer_t * ); static ssize_t ReadRedirect( input_thread_t *, byte_t *, size_t );
static http_field_t *http_field_find ( http_field_t *, char * ); static void Seek( input_thread_t *, off_t );
static int chunk_parse( chunk_t *, uint8_t *, int ); static int Start( input_thread_t *, off_t );
static void Stop( input_thread_t * );
static int GetPacket( input_thread_t *, chunk_t * );
/**************************************************************************** /****************************************************************************
* Open: connect to ftp server and ask for file * Open: connect to ftp server and ask for file
...@@ -69,10 +64,9 @@ int E_( MMSHOpen ) ( input_thread_t *p_input ) ...@@ -69,10 +64,9 @@ int E_( MMSHOpen ) ( input_thread_t *p_input )
{ {
access_sys_t *p_sys; access_sys_t *p_sys;
uint8_t *p; char *psz;
http_answer_t *p_ans; char *psz_location = NULL;
http_field_t *p_field; int i_code;
chunk_t ck;
vlc_value_t val; vlc_value_t val;
...@@ -82,8 +76,6 @@ int E_( MMSHOpen ) ( input_thread_t *p_input ) ...@@ -82,8 +76,6 @@ int E_( MMSHOpen ) ( input_thread_t *p_input )
p_sys->fd = -1; p_sys->fd = -1;
p_sys->i_request_context = 1; p_sys->i_request_context = 1;
p_sys->i_buffer = 0;
p_sys->i_buffer_pos = 0;
p_sys->b_broadcast = VLC_TRUE; p_sys->b_broadcast = VLC_TRUE;
p_sys->p_packet = NULL; p_sys->p_packet = NULL;
p_sys->i_packet_sequence = 0; p_sys->i_packet_sequence = 0;
...@@ -94,141 +86,191 @@ int E_( MMSHOpen ) ( input_thread_t *p_input ) ...@@ -94,141 +86,191 @@ int E_( MMSHOpen ) ( input_thread_t *p_input )
E_( GenerateGuid )( &p_sys->guid ); E_( GenerateGuid )( &p_sys->guid );
/* open a tcp connection */ /* open a tcp connection */
p_sys->p_url = E_( url_new )( p_input->psz_name ); vlc_UrlParse( &p_sys->url, p_input->psz_name, 0 );
if( p_sys->url.psz_host == NULL && *p_sys->url.psz_host == '\0' )
if( *p_sys->p_url->psz_host == '\0' )
{ {
msg_Err( p_input, "invalid server addresse" ); msg_Err( p_input, "invalid host" );
goto exit_error; goto error;
} }
if( p_sys->p_url->i_port <= 0 ) if( p_sys->url.i_port <= 0 )
{ {
p_sys->p_url->i_port = 80; p_sys->url.i_port = 80;
} }
if( ( p_sys->fd = net_OpenTCP( p_input, p_sys->p_url->psz_host, if( ( p_sys->fd = net_OpenTCP( p_input, p_sys->url.psz_host,
p_sys->p_url->i_port ) ) < 0 ) p_sys->url.i_port ) ) < 0 )
{ {
msg_Err( p_input, "cannot connect" ); msg_Err( p_input, "cannot connect to%s:%d", p_sys->url.psz_host, p_sys->url.i_port );
goto exit_error; goto error;
} }
/* *** send first request *** */ /* send first request */
p = &p_sys->buffer[0]; net_Printf( VLC_OBJECT(p_input), p_sys->fd,
p += sprintf( p, "GET %s HTTP/1.0\r\n", p_sys->p_url->psz_path ); "GET %s HTTP/1.0\r\n"
p += sprintf( p,"Accept: */*\r\n" ); "Accept: */*\r\n"
p += sprintf( p, "User-Agent: NSPlayer/4.1.0.3856\r\n" ); "User-Agent: NSPlayer/4.1.0.3856\r\n"
p += sprintf( p, "Host: %s:%d\r\n", "Host: %s:%d\r\n"
p_sys->p_url->psz_host, p_sys->p_url->i_port ); "Pragma: no-cache,rate=1.000000,stream-time=0,stream-offset=0:0,request-context=%d,max-duration=0\r\n"
p += sprintf( p, "Pragma: no-cache,rate=1.000000,stream-time=0,stream-offset=0:0,request-context=%d,max-duration=0\r\n", "Pragma: xClientGUID={"GUID_FMT"}\r\n"
p_sys->i_request_context++ ); "Connection: Close\r\n",
p += sprintf( p, "Pragma: xClientGUID={"GUID_FMT"}\r\n", ( p_sys->url.psz_path == NULL || *p_sys->url.psz_path == '\0' ) ? "/" : p_sys->url.psz_path,
GUID_PRINT( p_sys->guid ) ); p_sys->url.psz_host, p_sys->url.i_port,
p += sprintf( p, "Connection: Close\r\n\r\n" ); p_sys->i_request_context++,
GUID_PRINT( p_sys->guid ) );
net_Write( p_input, p_sys->fd, p_sys->buffer, p - p_sys->buffer );
if( NetFill ( p_input, p_sys, BUFFER_SIZE ) <= 0 ) if( net_Printf( VLC_OBJECT(p_input), p_sys->fd, "\r\n" ) < 0 )
{ {
msg_Err( p_input, "cannot read answer" ); msg_Err( p_input, "failed to send request" );
goto exit_error; goto error;
} }
net_Close( p_sys->fd ); p_sys->fd = -1;
p_ans = http_answer_parse( p_sys->buffer, p_sys->i_buffer ); /* Receive the http header */
if( !p_ans ) if( ( psz = net_Gets( VLC_OBJECT(p_input), p_sys->fd ) ) == NULL )
{ {
msg_Err( p_input, "cannot parse answer" ); msg_Err( p_input, "failed to read answer" );
goto exit_error; goto error;
} }
if( strncmp( psz, "HTTP/1.", 7 ) )
if( p_ans->i_error >= 400 )
{ {
msg_Err( p_input, "error %d (server return=`%s')", msg_Err( p_input, "invalid HTTP reply '%s'", psz );
p_ans->i_error, p_ans->psz_answer ); free( psz );
http_answer_free( p_ans ); goto error;
goto exit_error;
} }
else if( p_ans->i_error >= 300 ) i_code = atoi( &psz[9] );
if( i_code >= 400 )
{ {
msg_Err( p_input, "FIXME redirect unsuported %d (server return=`%s')", msg_Err( p_input, "error: %s", psz );
p_ans->i_error, p_ans->psz_answer ); free( psz );
http_answer_free( p_ans ); goto error;
goto exit_error;
}
else if( p_ans->i_body <= 0 )
{
msg_Err( p_input, "empty answer" );
http_answer_free( p_ans );
goto exit_error;
} }
/* now get features */ msg_Dbg( p_input, "HTTP reply '%s'", psz );
/* FIXME FIXME test Content-Type to see if it's a plain stream or an free( psz );
* asx FIXME */ for( ;; )
for( p_field = p_ans->p_fields;
p_field != NULL;
p_field = http_field_find( p_field->p_next, "Pragma" ) )
{ {
if( !strncasecmp( p_field->psz_value, "features", 8 ) ) char *psz = net_Gets( p_input, p_sys->fd );
char *p;
if( psz == NULL )
{ {
if( strstr( p_field->psz_value, "broadcast" ) ) msg_Err( p_input, "failed to read answer" );
{ goto error;
msg_Dbg( p_input, "stream type = broadcast" ); }
p_sys->b_broadcast = VLC_TRUE;
} if( *psz == '\0' )
else if( strstr( p_field->psz_value, "seekable" ) ) {
{ free( psz );
msg_Dbg( p_input, "stream type = seekable" ); break;
p_sys->b_broadcast = VLC_FALSE; }
}
else if( ( p = strchr( psz, ':' ) ) == NULL )
{
msg_Err( p_input, "malformed header line: %s", psz );
free( psz );
goto error;
}
*p++ = '\0';
while( *p == ' ' ) p++;
/* FIXME FIXME test Content-Type to see if it's a plain stream or an
* asx FIXME */
if( !strcasecmp( psz, "Pragma" ) )
{
if( !strncasecmp( p, "features", 8 ) )
{ {
msg_Warn( p_input, "unknow stream types (%s)", if( strstr( p, "broadcast" ) )
p_field->psz_value ); {
p_sys->b_broadcast = VLC_FALSE; msg_Dbg( p_input, "stream type = broadcast" );
p_sys->b_broadcast = VLC_TRUE;
}
else if( strstr( p, "seekable" ) )
{
msg_Dbg( p_input, "stream type = seekable" );
p_sys->b_broadcast = VLC_FALSE;
}
else
{
msg_Warn( p_input, "unknow stream types (%s)", p );
p_sys->b_broadcast = VLC_FALSE;
}
} }
} }
else if( !strcasecmp( psz, "Location" ) )
{
psz_location = strdup( p );
}
free( psz );
} }
/* gather header */ /* Handle the redirection */
p_sys->i_header = 0; if( ( i_code == 301 || i_code == 302 ||
p_sys->p_header = malloc( p_ans->i_body ); i_code == 303 || i_code == 307 ) &&
do psz_location && *psz_location )
{ {
if( chunk_parse( &ck, p_ans->p_body, p_ans->i_body ) ) playlist_t * p_playlist;
msg_Dbg( p_input, "redirection to %s", psz_location );
net_Close( p_sys->fd ); p_sys->fd = -1;
p_playlist = vlc_object_find( p_input, VLC_OBJECT_PLAYLIST, FIND_PARENT );
if( !p_playlist )
{ {
msg_Err( p_input, "invalid chunk answer" ); msg_Err( p_input, "redirection failed: can't find playlist" );
goto exit_error; goto error;
} }
if( ck.i_type != 0x4824 ) p_playlist->pp_items[p_playlist->i_index]->b_autodeletion = VLC_TRUE;
playlist_Add( p_playlist, psz_location, psz_location,
PLAYLIST_INSERT | PLAYLIST_GO,
p_playlist->i_index + 1 );
vlc_object_release( p_playlist );
p_input->pf_read = ReadRedirect;
p_input->pf_seek = NULL;
p_input->pf_set_program = input_SetProgram;
p_input->pf_set_area = NULL;
/* *** finished to set some variable *** */
vlc_mutex_lock( &p_input->stream.stream_lock );
p_input->stream.b_pace_control = 0;
p_input->stream.p_selected_area->i_size = 0;
p_input->stream.b_seekable = 0;
p_input->stream.p_selected_area->i_tell = 0;
p_input->stream.i_method = INPUT_METHOD_NETWORK;
vlc_mutex_unlock( &p_input->stream.stream_lock );
return VLC_SUCCESS;
}
/* Read the asf header */
p_sys->i_header = 0;
p_sys->p_header = NULL;
for( ;; )
{
chunk_t ck;
if( GetPacket( p_input, &ck ) ||
ck.i_type != 0x4824 )
{ {
msg_Err( p_input, "invalid chunk (0x%x)", ck.i_type );
break; break;
} }
if( ck.i_data > 0 ) if( ck.i_data > 0 )
{ {
memcpy( &p_sys->p_header[p_sys->i_header],
ck.p_data,
ck.i_data );
p_sys->i_header += ck.i_data; p_sys->i_header += ck.i_data;
p_sys->p_header = realloc( p_sys->p_header, p_sys->i_header );
memcpy( &p_sys->p_header[p_sys->i_header - ck.i_data],
ck.p_data, ck.i_data );
} }
}
/* BEURK */
p_ans->p_body += 12 + ck.i_data;
p_ans->i_body -= 12 + ck.i_data;
} while( p_ans->i_body > 12 );
http_answer_free( p_ans );
msg_Dbg( p_input, "complete header size=%d", p_sys->i_header ); msg_Dbg( p_input, "complete header size=%d", p_sys->i_header );
if( p_sys->i_header <= 0 ) if( p_sys->i_header <= 0 )
{ {
msg_Err( p_input, "header size == 0" ); msg_Err( p_input, "header size == 0" );
goto exit_error; goto error;
} }
/* close this connection */
net_Close( p_sys->fd ); p_sys->fd = -1;
/* *** parse header and get stream and their id *** */ /* *** parse header and get stream and their id *** */
/* get all streams properties, /* get all streams properties,
* *
...@@ -246,10 +288,10 @@ int E_( MMSHOpen ) ( input_thread_t *p_input ) ...@@ -246,10 +288,10 @@ int E_( MMSHOpen ) ( input_thread_t *p_input )
config_GetInt( p_input, "audio" ), config_GetInt( p_input, "audio" ),
config_GetInt( p_input, "video" ) ); config_GetInt( p_input, "video" ) );
if( mmsh_start( p_input, 0 ) ) if( Start( p_input, 0 ) )
{ {
msg_Err( p_input, "cannot start stream" ); msg_Err( p_input, "cannot start stream" );
goto exit_error; goto error;
} }
/* *** set exported functions *** */ /* *** set exported functions *** */
...@@ -284,9 +326,8 @@ int E_( MMSHOpen ) ( input_thread_t *p_input ) ...@@ -284,9 +326,8 @@ int E_( MMSHOpen ) ( input_thread_t *p_input )
return VLC_SUCCESS; return VLC_SUCCESS;
exit_error: error:
E_( url_free )( p_sys->p_url ); vlc_UrlClean( &p_sys->url );
if( p_sys->fd > 0 ) if( p_sys->fd > 0 )
{ {
net_Close( p_sys->fd ); net_Close( p_sys->fd );
...@@ -298,13 +339,13 @@ exit_error: ...@@ -298,13 +339,13 @@ exit_error:
/***************************************************************************** /*****************************************************************************
* Close: free unused data structures * Close: free unused data structures
*****************************************************************************/ *****************************************************************************/
void E_( MMSHClose ) ( input_thread_t *p_input ) void E_( MMSHClose )( input_thread_t *p_input )
{ {
access_sys_t *p_sys = p_input->p_access_data; access_sys_t *p_sys = p_input->p_access_data;
msg_Dbg( p_input, "stopping stream" ); msg_Dbg( p_input, "stopping stream" );
mmsh_stop( p_input ); Stop( p_input );
free( p_sys ); free( p_sys );
} }
...@@ -326,12 +367,12 @@ static void Seek( input_thread_t * p_input, off_t i_pos ) ...@@ -326,12 +367,12 @@ static void Seek( input_thread_t * p_input, off_t i_pos )
vlc_mutex_lock( &p_input->stream.stream_lock ); vlc_mutex_lock( &p_input->stream.stream_lock );
mmsh_stop( p_input ); Stop( p_input );
mmsh_start( p_input, i_packet * p_sys->asfh.i_min_data_packet_size ); Start( p_input, i_packet * p_sys->asfh.i_min_data_packet_size );
for( ;; ) for( ;; )
{ {
if( mmsh_get_packet( p_input, &ck ) ) if( GetPacket( p_input, &ck ) )
{ {
break; break;
} }
...@@ -351,6 +392,14 @@ static void Seek( input_thread_t * p_input, off_t i_pos ) ...@@ -351,6 +392,14 @@ static void Seek( input_thread_t * p_input, off_t i_pos )
vlc_mutex_unlock( &p_input->stream.stream_lock ); vlc_mutex_unlock( &p_input->stream.stream_lock );
} }
/*****************************************************************************
* Read:
*****************************************************************************/
static ssize_t ReadRedirect( input_thread_t *p_input, byte_t *p, size_t i )
{
return 0;
}
/***************************************************************************** /*****************************************************************************
* Read: * Read:
*****************************************************************************/ *****************************************************************************/
...@@ -389,14 +438,9 @@ static ssize_t Read ( input_thread_t * p_input, byte_t * p_buffer, ...@@ -389,14 +438,9 @@ static ssize_t Read ( input_thread_t * p_input, byte_t * p_buffer,
else else
{ {
chunk_t ck; chunk_t ck;
/* get a new packet */ if( GetPacket( p_input, &ck ) )
/* fill enought data (>12) */
msg_Dbg( p_input, "waiting data (buffer = %d bytes)",
p_sys->i_buffer );
if( mmsh_get_packet( p_input, &ck ) )
{ {
return 0; return -1;
} }
} }
} }
...@@ -406,71 +450,20 @@ static ssize_t Read ( input_thread_t * p_input, byte_t * p_buffer, ...@@ -406,71 +450,20 @@ static ssize_t Read ( input_thread_t * p_input, byte_t * p_buffer,
return( i_data ); return( i_data );
} }
/*****************************************************************************
* NetFill:
*****************************************************************************/
static ssize_t NetFill( input_thread_t *p_input, access_sys_t *p_sys, int i_size )
{
int i_try = 0;
int i_total = 0;
i_size = __MIN( i_size, BUFFER_SIZE - p_sys->i_buffer );
if( i_size <= 0 )
{
return 0;
}
for( ;; )
{
int i_read;
i_read = net_Read( p_input, p_sys->fd,
&p_sys->buffer[p_sys->i_buffer], i_size, VLC_FALSE );
if( i_read == 0 )
{
if( i_try++ > 2 )
{
break;
}
msg_Dbg( p_input, "another try %d/2", i_try );
continue;
}
if( i_read < 0 || p_input->b_die || p_input->b_error )
{
break;
}
i_total += i_read;
p_sys->i_buffer += i_read;
if( i_total >= i_size )
{
break;
}
}
p_sys->buffer[p_sys->i_buffer] = '\0';
return i_total;
}
/***************************************************************************** /*****************************************************************************
* *
*****************************************************************************/ *****************************************************************************/
static int mmsh_start( input_thread_t *p_input, off_t i_pos ) static int Start( input_thread_t *p_input, off_t i_pos )
{ {
access_sys_t *p_sys = p_input->p_access_data; access_sys_t *p_sys = p_input->p_access_data;
uint8_t *p; int i_streams = 0;
int i_streams = 0; int i;
int i; char *psz;
http_answer_t *p_ans;
msg_Dbg( p_input, "starting stream" ); msg_Dbg( p_input, "starting stream" );
if( ( p_sys->fd = net_OpenTCP( p_input, p_sys->p_url->psz_host, if( ( p_sys->fd = net_OpenTCP( p_input, p_sys->url.psz_host,
p_sys->p_url->i_port ) ) < 0 ) p_sys->url.i_port ) ) < 0 )
{ {
/* should not occur */ /* should not occur */
msg_Err( p_input, "cannot connect to the server" ); msg_Err( p_input, "cannot connect to the server" );
...@@ -490,113 +483,89 @@ static int mmsh_start( input_thread_t *p_input, off_t i_pos ) ...@@ -490,113 +483,89 @@ static int mmsh_start( input_thread_t *p_input, off_t i_pos )
msg_Err( p_input, "no stream selected" ); msg_Err( p_input, "no stream selected" );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
net_Printf( VLC_OBJECT(p_input), p_sys->fd,
p = &p_sys->buffer[0]; "GET %s HTTP/1.0\r\n"
p += sprintf( p, "GET %s HTTP/1.0\r\n", p_sys->p_url->psz_path ); "Accept: */*\r\n"
p += sprintf( p,"Accept: */*\r\n" ); "User-Agent: NSPlayer/4.1.0.3856\r\n"
p += sprintf( p, "User-Agent: NSPlayer/4.1.0.3856\r\n" ); "Host: %s:%d\r\n",
p += sprintf( p, "Host: %s:%d\r\n", ( p_sys->url.psz_path == NULL || *p_sys->url.psz_path == '\0' ) ? "/" : p_sys->url.psz_path,
p_sys->p_url->psz_host, p_sys->p_url->i_port ); p_sys->url.psz_host, p_sys->url.i_port );
if( p_sys->b_broadcast ) if( p_sys->b_broadcast )
{ {
p += sprintf( p,"Pragma: no-cache,rate=1.000000,request-context=%d\r\n", net_Printf( VLC_OBJECT(p_input), p_sys->fd,
p_sys->i_request_context++ ); "Pragma: no-cache,rate=1.000000,request-context=%d\r\n",
p_sys->i_request_context++ );
} }
else else
{ {
p += sprintf( p, "Pragma: no-cache,rate=1.000000,stream-time=0,stream-offset=%u:%u,request-context=%d,max-duration=0\r\n", net_Printf( VLC_OBJECT(p_input), p_sys->fd,
(uint32_t)((i_pos >> 32)&0xffffffff), "Pragma: no-cache,rate=1.000000,stream-time=0,stream-offset=%u:%u,request-context=%d,max-duration=0\r\n",
(uint32_t)(i_pos&0xffffffff), (uint32_t)((i_pos >> 32)&0xffffffff),
p_sys->i_request_context++ ); (uint32_t)(i_pos&0xffffffff),
p_sys->i_request_context++ );
} }
p += sprintf( p, "Pragma: xPlayStrm=1\r\n" ); net_Printf( VLC_OBJECT(p_input), p_sys->fd,
p += sprintf( p, "Pragma: xClientGUID={"GUID_FMT"}\r\n", "Pragma: xPlayStrm=1\r\n"
GUID_PRINT( p_sys->guid ) ); "Pragma: xClientGUID={"GUID_FMT"}\r\n"
p += sprintf( p, "Pragma: stream-switch-count=%d\r\n", i_streams ); "Pragma: stream-switch-count=%d\r\n"
p += sprintf( p, "Pragma: stream-switch-entry=" ); "Pragma: stream-switch-entry=",
for( i = 0; i < i_streams; i++ ) GUID_PRINT( p_sys->guid ),
{ i_streams);
if( p_sys->asfh.stream[i].i_selected )
{
p += sprintf( p, "ffff:%d:0 ", p_sys->asfh.stream[i].i_id );
}
else
{
p += sprintf( p, "ffff:%d:2 ", p_sys->asfh.stream[i].i_id );
}
}
p += sprintf( p, "\r\n" );
p += sprintf( p, "Connection: Close\r\n\r\n" );
net_Write( p_input, p_sys->fd, p_sys->buffer, p - p_sys->buffer );
msg_Dbg( p_input, "filling buffer" ); for( i = 1; i < 128; i++ )
/* we read until we found a \r\n\r\n or \n\n */
p_sys->i_buffer = 0;
p_sys->i_buffer_pos = 0;
for( ;; )
{ {
int i_try = 0; if( p_sys->asfh.stream[i].i_cat != ASF_STREAM_UNKNOWN )
int i_read;
uint8_t *p;
p = &p_sys->buffer[p_sys->i_buffer];
i_read = net_Read( p_input, p_sys->fd, &p_sys->buffer[p_sys->i_buffer], 1024, VLC_FALSE );
if( i_read == 0 )
{ {
if( i_try++ > 12 ) int i_select = 2;
if( p_sys->asfh.stream[i].i_selected )
{ {
break; i_select = 0;
} }
msg_Dbg( p_input, "another try (%d/12)", i_try );
continue;
}
if( i_read <= 0 || p_input->b_die || p_input->b_error )
{
break;
}
p_sys->i_buffer += i_read;
p_sys->buffer[p_sys->i_buffer] = '\0';
if( strstr( p, "\r\n\r\n" ) || strstr( p, "\n\n" ) ) net_Printf( VLC_OBJECT(p_input), p_sys->fd,
{ "ffff:%d:%d ", i, i_select );
msg_Dbg( p_input, "body found" );
break;
}
if( p_sys->i_buffer >= BUFFER_SIZE - 1024 )
{
msg_Dbg( p_input, "buffer size exeded" );
break;
} }
} }
net_Printf( VLC_OBJECT(p_input), p_sys->fd, "\r\n" );
net_Printf( VLC_OBJECT(p_input), p_sys->fd, "Connection: Close\r\n" );
p_ans = http_answer_parse( p_sys->buffer, p_sys->i_buffer ); if( net_Printf( VLC_OBJECT(p_input), p_sys->fd, "\r\n" ) < 0 )
if( !p_ans )
{ {
msg_Err( p_input, "cannot parse answer" ); msg_Err( p_input, "failed to send request" );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
if( p_ans->i_error < 200 || p_ans->i_error >= 300 ) if( ( psz = net_Gets( VLC_OBJECT(p_input), p_sys->fd ) ) == NULL )
{ {
msg_Err( p_input, "error %d (server return=`%s')", msg_Err( p_input, "cannot read data" );
p_ans->i_error, p_ans->psz_answer );
http_answer_free( p_ans );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
if( atoi( &psz[9] ) >= 400 )
if( !p_ans->p_body )
{ {
p_sys->i_buffer_pos = 0; msg_Err( p_input, "error: %s", psz );
p_sys->i_buffer = 0; free( psz );
return VLC_EGENERIC;
} }
else msg_Dbg( p_input, "HTTP reply '%s'", psz );
free( psz );
/* FIXME check HTTP code */
for( ;; )
{ {
p_sys->i_buffer_pos = p_ans->p_body - p_sys->buffer; char *psz = net_Gets( p_input, p_sys->fd );
if( psz == NULL )
{
msg_Err( p_input, "cannot read data" );
return VLC_EGENERIC;
}
if( *psz == '\0' )
{
free( psz );
break;
}
msg_Dbg( p_input, "%s", psz );
free( psz );
} }
http_answer_free( p_ans );
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -604,7 +573,7 @@ static int mmsh_start( input_thread_t *p_input, off_t i_pos ) ...@@ -604,7 +573,7 @@ static int mmsh_start( input_thread_t *p_input, off_t i_pos )
/***************************************************************************** /*****************************************************************************
* *
*****************************************************************************/ *****************************************************************************/
static void mmsh_stop( input_thread_t *p_input ) static void Stop( input_thread_t *p_input )
{ {
access_sys_t *p_sys = p_input->p_access_data; access_sys_t *p_sys = p_input->p_access_data;
...@@ -615,33 +584,24 @@ static void mmsh_stop( input_thread_t *p_input ) ...@@ -615,33 +584,24 @@ static void mmsh_stop( input_thread_t *p_input )
/***************************************************************************** /*****************************************************************************
* *
*****************************************************************************/ *****************************************************************************/
static int mmsh_get_packet( input_thread_t * p_input, chunk_t *p_ck ) static int GetPacket( input_thread_t * p_input, chunk_t *p_ck )
{ {
access_sys_t *p_sys = p_input->p_access_data; access_sys_t *p_sys = p_input->p_access_data;
int i_mov = p_sys->i_buffer - p_sys->i_buffer_pos; /* Read the chunk header */
if( net_Read( p_input, p_sys->fd, p_sys->buffer, 12, VLC_TRUE ) < 12 )
if( p_sys->i_buffer_pos > BUFFER_SIZE / 2 )
{ {
if( i_mov > 0 ) /* msg_Err( p_input, "cannot read data" ); */
{
memmove( &p_sys->buffer[0],
&p_sys->buffer[p_sys->i_buffer_pos],
i_mov );
}
p_sys->i_buffer = i_mov;
p_sys->i_buffer_pos = 0;
}
if( NetFill( p_input, p_sys, 12 ) < 12 )
{
msg_Warn( p_input, "cannot fill buffer" );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
chunk_parse( p_ck, &p_sys->buffer[p_sys->i_buffer_pos], p_ck->i_type = GetWLE( p_sys->buffer);
p_sys->i_buffer - p_sys->i_buffer_pos ); p_ck->i_size = GetWLE( p_sys->buffer + 2);
p_ck->i_sequence = GetDWLE( p_sys->buffer + 4);
p_ck->i_unknown = GetWLE( p_sys->buffer + 8);
p_ck->i_size2 = GetWLE( p_sys->buffer + 10);
p_ck->p_data = p_sys->buffer + 12;
p_ck->i_data = p_ck->i_size2 - 8;
if( p_ck->i_type == 0x4524 ) // Transfer complete if( p_ck->i_type == 0x4524 ) // Transfer complete
{ {
...@@ -654,15 +614,10 @@ static int mmsh_get_packet( input_thread_t * p_input, chunk_t *p_ck ) ...@@ -654,15 +614,10 @@ static int mmsh_get_packet( input_thread_t * p_input, chunk_t *p_ck )
return VLC_EGENERIC; return VLC_EGENERIC;
} }
if( p_ck->i_data < p_ck->i_size2 - 8 ) if( net_Read( p_input, p_sys->fd, &p_sys->buffer[12], p_ck->i_data, VLC_TRUE ) < p_ck->i_data )
{ {
if( NetFill( p_input, p_sys, p_ck->i_size2 - 8 - p_ck->i_data ) <= 0 ) msg_Err( p_input, "cannot read data" );
{ return VLC_EGENERIC;
msg_Warn( p_input, "cannot fill buffer" );
return VLC_EGENERIC;
}
chunk_parse( p_ck, &p_sys->buffer[p_sys->i_buffer_pos],
p_sys->i_buffer - p_sys->i_buffer_pos );
} }
if( p_sys->i_packet_sequence != 0 && if( p_sys->i_packet_sequence != 0 &&
...@@ -676,185 +631,5 @@ static int mmsh_get_packet( input_thread_t * p_input, chunk_t *p_ck ) ...@@ -676,185 +631,5 @@ static int mmsh_get_packet( input_thread_t * p_input, chunk_t *p_ck )
p_sys->i_packet_length = p_ck->i_data; p_sys->i_packet_length = p_ck->i_data;
p_sys->p_packet = p_ck->p_data; p_sys->p_packet = p_ck->p_data;
p_sys->i_buffer_pos += 12 + p_ck->i_data;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
/*****************************************************************************
*
*****************************************************************************/
static int http_next_line( uint8_t **pp_data, int *pi_data )
{
char *p, *p_end = *pp_data + *pi_data;
for( p = *pp_data; p < p_end; p++ )
{
if( p + 1 < p_end && *p == '\n' )
{
*pi_data = p_end - p - 1;
*pp_data = p + 1;
return VLC_SUCCESS;
}
if( p + 2 < p_end && p[0] == '\r' && p[1] == '\n' )
{
*pi_data = p_end - p - 2;
*pp_data = p + 2;
return VLC_SUCCESS;
}
}
*pi_data = 0;
*pp_data = p_end;
return VLC_EGENERIC;
}
/*****************************************************************************
*
*****************************************************************************/
static http_answer_t *http_answer_parse( uint8_t *p_data, int i_data )
{
http_answer_t *ans = malloc( sizeof( http_answer_t ) );
http_field_t **pp_last;
char *p, *end;
if( strncmp( p_data, "HTTP/1.", 7 ) )
{
free( ans );
return NULL;
}
ans->i_version = atoi( &p_data[7] );
ans->i_error = strtol( p_data + 8, &p, 0 );
while( *p == ' ' )
{
p++;
}
if( ( ( end = strchr( p, '\r' ) ) == NULL )&&
( ( end = strchr( p, '\n' ) ) == NULL ) )
{
end = &p_data[i_data];
}
ans->psz_answer = strndup( p, end - p );
fprintf( stderr, "version=%d error=%d answer=%s\n",
ans->i_version, ans->i_error, ans->psz_answer );
ans->p_fields = NULL;
ans->i_body = 0;
ans->p_body = 0;
pp_last = &ans->p_fields;
for( ;; )
{
http_field_t *p_field;
uint8_t *colon;
if( http_next_line( &p_data, &i_data ) )
{
return ans;
}
if( !strncmp( p_data, "\r\n", 2 ) || !strncmp( p_data, "\n", 1 ) )
{
break;
}
colon = strstr( p_data, ": " );
if( colon )
{
uint8_t *end;
end = strstr( colon, "\n" ) - 1;
if( *end != '\r' )
{
end++;
}
p_field = malloc( sizeof( http_field_t ) );
p_field->psz_name = strndup( p_data, colon - p_data );
p_field->psz_value = strndup( colon + 2, end - colon - 2 );
p_field->p_next = NULL;
*pp_last = p_field;
pp_last = &p_field->p_next;
fprintf( stderr, "field name=`%s' value=`%s'\n",
p_field->psz_name, p_field->psz_value );
}
}
if( http_next_line( &p_data, &i_data ) )
{
return ans;
}
ans->p_body = p_data;
ans->i_body = i_data;
fprintf( stderr, "body size=%d\n", i_data );
return ans;
}
/*****************************************************************************
*
*****************************************************************************/
static void http_answer_free( http_answer_t *ans )
{
http_field_t *p_field = ans->p_fields;
while( p_field )
{
http_field_t *p_next;
p_next = p_field->p_next;
free( p_field->psz_name );
free( p_field->psz_value );
free( p_field );
p_field = p_next;
}
free( ans->psz_answer );
free( ans );
}
/*****************************************************************************
*
*****************************************************************************/
static http_field_t *http_field_find( http_field_t *p_field, char *psz_name )
{
while( p_field )
{
if( !strcasecmp( p_field->psz_name, psz_name ) )
{
return p_field;
}
p_field = p_field->p_next;
}
return NULL;
}
/*****************************************************************************
*
*****************************************************************************/
static int chunk_parse( chunk_t *ck, uint8_t *p_data, int i_data )
{
if( i_data < 12 )
{
return VLC_EGENERIC;
}
ck->i_type = GetWLE( p_data );
ck->i_size = GetWLE( p_data + 2);
ck->i_sequence = GetDWLE( p_data + 4);
ck->i_unknown = GetWLE( p_data + 8);
ck->i_size2 = GetWLE( p_data + 10);
ck->p_data = p_data + 12;
ck->i_data = __MIN( i_data - 12, ck->i_size2 - 8 );
return VLC_SUCCESS;
}
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* mmsh.h: * mmsh.h:
***************************************************************************** *****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN * Copyright (C) 2001, 2002 VideoLAN
* $Id: mmsh.h,v 1.5 2004/01/21 16:56:16 fenrir Exp $ * $Id$
* *
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* *
...@@ -36,18 +36,16 @@ typedef struct ...@@ -36,18 +36,16 @@ typedef struct
} chunk_t; } chunk_t;
#define BUFFER_SIZE 150000 #define BUFFER_SIZE 65536
struct access_sys_t struct access_sys_t
{ {
int i_proto; int i_proto;
int fd; int fd;
url_t *p_url; vlc_url_t url;
int i_request_context; int i_request_context;
int i_buffer;
int i_buffer_pos;
uint8_t buffer[BUFFER_SIZE + 1]; uint8_t buffer[BUFFER_SIZE + 1];
vlc_bool_t b_broadcast; vlc_bool_t b_broadcast;
...@@ -65,27 +63,3 @@ struct access_sys_t ...@@ -65,27 +63,3 @@ struct access_sys_t
asf_header_t asfh; asf_header_t asfh;
guid_t guid; guid_t guid;
}; };
typedef struct http_field_s
{
char *psz_name;
char *psz_value;
struct http_field_s *p_next;
} http_field_t;
typedef struct
{
int i_version;
int i_error;
char *psz_answer;
http_field_t *p_fields;
uint8_t *p_body;
int i_body;
} http_answer_t;
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