/*****************************************************************************
* mmsh.c:
*****************************************************************************
- * Copyright (C) 2001, 2002 VideoLAN
- * $Id: mmsh.c,v 1.6 2003/08/26 00:51:19 fenrir Exp $
+ * Copyright (C) 2001, 2002 the VideoLAN team
+ * $Id$
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
-/*
- * TODO:
- * * http_proxy
- *
- */
-
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <vlc/vlc.h>
#include <vlc/input.h>
-#ifdef HAVE_ERRNO_H
-# include <errno.h>
-#endif
-#ifdef HAVE_FCNTL_H
-# include <fcntl.h>
-#endif
-#ifdef HAVE_SYS_TIME_H
-# include <sys/time.h>
-#endif
-
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-
-#if defined( UNDER_CE )
-# include <winsock.h>
-#elif defined( WIN32 )
-# include <winsock2.h>
-# include <ws2tcpip.h>
-# ifndef IN_MULTICAST
-# define IN_MULTICAST(a) IN_CLASSD(a)
-# endif
-#else
-# include <sys/socket.h>
-#endif
+#include "vlc_playlist.h"
#include "network.h"
#include "asf.h"
#include "mms.h"
#include "mmsh.h"
+/* TODO:
+ * - http_proxy
+ * - authentication
+ */
+
/*****************************************************************************
* Local prototypes
*****************************************************************************/
-int E_( MMSHOpen ) ( input_thread_t * );
-void E_( MMSHClose ) ( input_thread_t * );
+int E_(MMSHOpen) ( access_t * );
+void E_(MMSHClose) ( access_t * );
-static ssize_t Read ( input_thread_t * p_input, byte_t * p_buffer,
- size_t i_len );
-static void Seek ( input_thread_t *, off_t );
+static int Read( access_t *, uint8_t *, int );
+static int ReadRedirect( access_t *, uint8_t *, int );
+static int Seek( access_t *, int64_t );
+static int Control( access_t *, int, va_list );
-/****************************************************************************
- ****************************************************************************
- ******************* *******************
- ******************* Main functions *******************
- ******************* *******************
- ****************************************************************************
- ****************************************************************************/
+static int Describe( access_t *, char **ppsz_location );
+static int Start( access_t *, int64_t );
+static void Stop( access_t * );
+static int GetPacket( access_t *, chunk_t * );
/****************************************************************************
* Open: connect to ftp server and ask for file
****************************************************************************/
-int E_( MMSHOpen ) ( input_thread_t *p_input )
+int E_(MMSHOpen)( access_t *p_access )
{
access_sys_t *p_sys;
-
- uint8_t *p;
- http_answer_t *p_ans;
- http_field_t *p_field;
- chunk_t ck;
+ char *psz_location = NULL;
/* init p_sys */
- p_input->p_access_data = p_sys = malloc( sizeof( access_sys_t ) );
- p_sys->i_proto = MMS_PROTO_HTTP;
- p_sys->p_socket = NULL;
- 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->p_packet = NULL;
- p_sys->i_packet_sequence = 0;
- p_sys->i_packet_used = 0;
- p_sys->i_packet_length = 0;
- p_sys->i_pos = 0;
- p_sys->i_request_context = 1;
- E_( GenerateGuid )( &p_sys->guid );
+ /* Set up p_access */
+ p_access->pf_read = Read;
+ p_access->pf_block = NULL;
+ p_access->pf_control = Control;
+ p_access->pf_seek = Seek;
+ p_access->info.i_update = 0;
+ p_access->info.i_size = 0;
+ p_access->info.i_pos = 0;
+ p_access->info.b_eof = VLC_FALSE;
+ p_access->info.i_title = 0;
+ p_access->info.i_seekpoint = 0;
+ p_access->p_sys = p_sys = malloc( sizeof( access_sys_t ) );
+ memset( p_sys, 0, sizeof( access_sys_t ) );
+ p_sys->i_proto= MMS_PROTO_HTTP;
+ p_sys->fd = -1;
+ p_sys->i_start= 0;
/* open a tcp connection */
- p_sys->p_url = E_( url_new )( p_input->psz_name );
-
- if( *p_sys->p_url->psz_host == '\0' )
+ vlc_UrlParse( &p_sys->url, p_access->psz_path, 0 );
+ if( p_sys->url.psz_host == NULL || *p_sys->url.psz_host == '\0' )
{
- msg_Err( p_input, "invalid server addresse" );
- goto exit_error;
- }
- if( p_sys->p_url->i_port <= 0 )
- {
- p_sys->p_url->i_port = 80;
- }
-
- if( ( p_sys->p_socket = NetOpenTCP( p_input, p_sys->p_url ) ) == NULL )
- {
- msg_Err( p_input, "cannot connect" );
- goto exit_error;
- }
-
- /* *** send first request *** */
- p = &p_sys->buffer[0];
- p += sprintf( p, "GET %s HTTP/1.0\r\n", p_sys->p_url->psz_path );
- p += sprintf( p,"Accept: */*\r\n" );
- p += sprintf( p, "User-Agent: NSPlayer/4.1.0.3856\r\n" );
- p += sprintf( p, "Host: %s:%d\r\n",
- p_sys->p_url->psz_host, p_sys->p_url->i_port );
- p += sprintf( p, "Pragma: no-cache,rate=1.000000,stream-time=0,stream-offset=0:0,request-context=%d,max-duration=0\r\n",
- p_sys->i_request_context++ );
- p += sprintf( p, "Pragma: xClientGUID={"GUID_FMT"}\r\n",
- GUID_PRINT( p_sys->guid ) );
- p += sprintf( p, "Connection: Close\r\n\r\n" );
- NetWrite( p_input, p_sys->p_socket, p_sys->buffer, p - p_sys->buffer );
-
-
- if( NetFill ( p_input, p_sys, BUFFER_SIZE ) <= 0 )
- {
- msg_Err( p_input, "cannot read answer" );
- goto exit_error;
- }
- NetClose( p_input, p_sys->p_socket );
- p_sys->p_socket = NULL;
-
- p_ans = http_answer_parse( p_sys->buffer, p_sys->i_buffer );
- if( !p_ans )
- {
- msg_Err( p_input, "cannot parse answer" );
- goto exit_error;
+ msg_Err( p_access, "invalid host" );
+ vlc_UrlClean( &p_sys->url );
+ free( p_sys );
+ return VLC_EGENERIC;
}
+ if( p_sys->url.i_port <= 0 )
+ p_sys->url.i_port = 80;
- if( p_ans->i_error >= 400 )
+ if( Describe( p_access, &psz_location ) )
{
- msg_Err( p_input, "error %d (server return=`%s')",
- p_ans->i_error, p_ans->psz_answer );
- http_answer_free( p_ans );
- goto exit_error;
- }
- else if( p_ans->i_error >= 300 )
- {
- msg_Err( p_input, "FIXME redirect unsuported %d (server return=`%s')",
- p_ans->i_error, p_ans->psz_answer );
- http_answer_free( p_ans );
- goto exit_error;
+ vlc_UrlClean( &p_sys->url );
+ free( p_sys );
+ return VLC_EGENERIC;
}
- else if( p_ans->i_body <= 0 )
+ /* Handle redirection */
+ if( psz_location && *psz_location )
{
- msg_Err( p_input, "empty answer" );
- http_answer_free( p_ans );
- goto exit_error;
- }
+ playlist_t * p_playlist = vlc_object_find( p_access, VLC_OBJECT_PLAYLIST, FIND_PARENT );
- /* now get features */
- /* FIXME FIXME test Content-Type to see if it's a plain stream or an
- * asx FIXME */
- 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 ) )
- {
- if( strstr( p_field->psz_value, "broadcast" ) )
- {
- msg_Dbg( p_input, "stream type = broadcast" );
- p_sys->b_broadcast = VLC_TRUE;
- }
- else if( strstr( p_field->psz_value, "seekable" ) )
- {
- msg_Dbg( p_input, "stream type = seekable" );
- p_sys->b_broadcast = VLC_FALSE;
- }
- else
- {
- msg_Warn( p_input, "unknow stream types (%s)",
- p_field->psz_value );
- p_sys->b_broadcast = VLC_FALSE;
- }
- }
- }
+ msg_Dbg( p_access, "redirection to %s", psz_location );
- /* gather header */
- p_sys->i_header = 0;
- p_sys->p_header = malloc( p_ans->i_body );
- do
- {
- if( chunk_parse( &ck, p_ans->p_body, p_ans->i_body ) )
- {
- msg_Err( p_input, "invalid chunk answer" );
- goto exit_error;
- }
- if( ck.i_type != 0x4824 )
- {
- msg_Err( p_input, "invalid chunk (0x%x)", ck.i_type );
- break;
- }
- if( ck.i_data > 0 )
+ if( !p_playlist )
{
- memcpy( &p_sys->p_header[p_sys->i_header],
- ck.p_data,
- ck.i_data );
-
- p_sys->i_header += ck.i_data;
+ msg_Err( p_access, "redirection failed: can't find playlist" );
+ free( psz_location );
+ return VLC_EGENERIC;
}
+ 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 );
- /* BEURK */
- p_ans->p_body += 12 + ck.i_data;
- p_ans->i_body -= 12 + ck.i_data;
+ free( psz_location );
- } while( p_ans->i_body > 12 );
-
- http_answer_free( p_ans );
-
- msg_Dbg( p_input, "complete header size=%d", p_sys->i_header );
- if( p_sys->i_header <= 0 )
- {
- msg_Err( p_input, "header size == 0" );
- goto exit_error;
+ p_access->pf_read = ReadRedirect;
+ return VLC_SUCCESS;
}
- /* *** parse header and get stream and their id *** */
- /* get all streams properties,
- *
- * TODO : stream bitrates properties(optional)
- * and bitrate mutual exclusion(optional) */
- E_( asf_HeaderParse )( &p_sys->asfh,
- p_sys->p_header, p_sys->i_header );
- msg_Dbg( p_input, "packet count=%lld packet size=%d",
- p_sys->asfh.i_data_packets_count,
- p_sys->asfh.i_min_data_packet_size );
-
- E_( asf_StreamSelect)( &p_sys->asfh,
- config_GetInt( p_input, "mms-maxbitrate" ),
- config_GetInt( p_input, "mms-all" ),
- config_GetInt( p_input, "audio" ),
- config_GetInt( p_input, "video" ) );
- if( mmsh_start( p_input, 0 ) )
+ /* Start playing */
+ if( Start( p_access, 0 ) )
{
- msg_Err( p_input, "cannot start stream" );
- goto exit_error;
+ msg_Err( p_access, "cannot start stream" );
+ free( p_sys->p_header );
+ vlc_UrlClean( &p_sys->url );
+ free( p_sys );
+ return VLC_EGENERIC;
}
- /* *** set exported functions *** */
- p_input->pf_read = Read;
- p_input->pf_seek = Seek;
- p_input->pf_set_program = input_SetProgram;
- p_input->pf_set_area = NULL;
-
- p_input->p_private = NULL;
- p_input->i_mtu = 3 * p_sys->asfh.i_min_data_packet_size;
-
- /* *** finished to set some variable *** */
- vlc_mutex_lock( &p_input->stream.stream_lock );
- p_input->stream.b_pace_control = 0;
- if( p_sys->b_broadcast )
+ if( !p_sys->b_broadcast )
{
- p_input->stream.p_selected_area->i_size = 0;
- p_input->stream.b_seekable = 0;
+ p_access->info.i_size = p_sys->asfh.i_file_size;
}
- else
- {
- p_input->stream.p_selected_area->i_size = p_sys->asfh.i_file_size;
- p_input->stream.b_seekable = 1;
- }
- 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 );
-
- /* Update default_pts to a suitable value for ftp access */
- p_input->i_pts_delay = config_GetInt( p_input, "mms-caching" ) * 1000;
-
- return( VLC_SUCCESS );
-
-exit_error:
- E_( url_free )( p_sys->p_url );
-
- if( p_sys->p_socket )
- {
- NetClose( p_input, p_sys->p_socket );
- }
- free( p_sys );
- return( VLC_EGENERIC );
+ return VLC_SUCCESS;
}
/*****************************************************************************
* Close: free unused data structures
*****************************************************************************/
-void E_( MMSHClose ) ( input_thread_t *p_input )
+void E_( MMSHClose )( access_t *p_access )
{
- access_sys_t *p_sys = p_input->p_access_data;
-
- msg_Dbg( p_input, "stopping stream" );
-
- mmsh_stop( p_input );
+ access_sys_t *p_sys = p_access->p_sys;
+ Stop( p_access );
free( p_sys );
}
-static int mmsh_get_packet( input_thread_t * p_input,
- chunk_t *p_ck )
+/*****************************************************************************
+ * Control:
+ *****************************************************************************/
+static int Control( access_t *p_access, int i_query, va_list args )
{
- access_sys_t *p_sys = p_input->p_access_data;
+ access_sys_t *p_sys = p_access->p_sys;
+ vlc_bool_t *pb_bool;
+ int *pi_int;
+ int64_t *pi_64;
+ int i_int;
+
+ switch( i_query )
+ {
+ /* */
+ case ACCESS_CAN_SEEK:
+ pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
+ *pb_bool = !p_sys->b_broadcast;
+ break;
- int i_mov = p_sys->i_buffer - p_sys->i_buffer_pos;
+ case ACCESS_CAN_FASTSEEK:
+ case ACCESS_CAN_PAUSE:
+ pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
+ *pb_bool = VLC_FALSE;
+ break;
- if( p_sys->i_buffer_pos > BUFFER_SIZE / 2 )
- {
- if( i_mov > 0 )
- {
- memmove( &p_sys->buffer[0],
- &p_sys->buffer[p_sys->i_buffer_pos],
- i_mov );
- }
+ case ACCESS_CAN_CONTROL_PACE:
+ pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
- p_sys->i_buffer = i_mov;
- p_sys->i_buffer_pos = 0;
- }
+#if 0 /* Disable for now until we have a clock synchro algo
+ * which works with something else than MPEG over UDP */
+ *pb_bool = VLC_FALSE;
+#endif
+ *pb_bool = VLC_TRUE;
+ break;
- if( NetFill( p_input, p_sys, 12 ) < 12 )
- {
- msg_Warn( p_input, "cannot fill buffer" );
- return VLC_EGENERIC;
- }
+ /* */
+ case ACCESS_GET_MTU:
+ pi_int = (int*)va_arg( args, int * );
+ *pi_int = 3 * p_sys->asfh.i_min_data_packet_size;
+ break;
- chunk_parse( p_ck, &p_sys->buffer[p_sys->i_buffer_pos],
- p_sys->i_buffer - p_sys->i_buffer_pos );
+ case ACCESS_GET_PTS_DELAY:
+ pi_64 = (int64_t*)va_arg( args, int64_t * );
+ *pi_64 = (int64_t)var_GetInteger( p_access, "mms-caching" ) * I64C(1000);
+ break;
- if( p_ck->i_type == 0x4524 ) // Transfer complete
- {
- msg_Warn( p_input, "EOF" );
- return VLC_EGENERIC;
- }
- else if( p_ck->i_type != 0x4824 && p_ck->i_type != 0x4424 )
- {
- msg_Err( p_input, "invalid chunk FATAL" );
- return VLC_EGENERIC;
- }
+ case ACCESS_GET_PRIVATE_ID_STATE:
+ i_int = (int)va_arg( args, int );
+ pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t );
- if( p_ck->i_data < p_ck->i_size2 - 8 )
- {
- if( NetFill( p_input, p_sys, p_ck->i_size2 - 8 - p_ck->i_data ) <= 0 )
- {
- 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 &&
- p_ck->i_sequence != p_sys->i_packet_sequence )
- {
- msg_Warn( p_input, "packet lost ?" );
- }
+ if( i_int < 0 || i_int > 127 )
+ return VLC_EGENERIC;
+ *pb_bool = p_sys->asfh.stream[i_int].i_selected ? VLC_TRUE : VLC_FALSE;
+ break;
- p_sys->i_packet_sequence = p_ck->i_sequence + 1;
- p_sys->i_packet_used = 0;
- p_sys->i_packet_length = p_ck->i_data;
- p_sys->p_packet = p_ck->p_data;
+ /* */
+ case ACCESS_SET_PAUSE_STATE:
+ case ACCESS_GET_TITLE_INFO:
+ case ACCESS_SET_TITLE:
+ case ACCESS_SET_SEEKPOINT:
+ case ACCESS_SET_PRIVATE_ID_STATE:
+ return VLC_EGENERIC;
- p_sys->i_buffer_pos += 12 + p_ck->i_data;
+ default:
+ msg_Warn( p_access, "unimplemented query in control" );
+ return VLC_EGENERIC;
+ }
return VLC_SUCCESS;
}
-
/*****************************************************************************
* Seek: try to go at the right place
*****************************************************************************/
-static void Seek( input_thread_t * p_input, off_t i_pos )
+static int Seek( access_t *p_access, int64_t i_pos )
{
- access_sys_t *p_sys = p_input->p_access_data;
+ access_sys_t *p_sys = p_access->p_sys;
chunk_t ck;
off_t i_offset;
off_t i_packet;
+ msg_Dbg( p_access, "seeking to "I64Fd, i_pos );
+
i_packet = ( i_pos - p_sys->i_header ) / p_sys->asfh.i_min_data_packet_size;
i_offset = ( i_pos - p_sys->i_header ) % p_sys->asfh.i_min_data_packet_size;
- msg_Err( p_input, "seeking to "I64Fd, i_pos );
-
- vlc_mutex_lock( &p_input->stream.stream_lock );
-
- mmsh_stop( p_input );
- mmsh_start( p_input, i_packet * p_sys->asfh.i_min_data_packet_size );
+ Stop( p_access );
+ Start( p_access, i_packet * p_sys->asfh.i_min_data_packet_size );
- for( ;; )
+ while( !p_access->b_die )
{
- if( mmsh_get_packet( p_input, &ck ) )
- {
+ if( GetPacket( p_access, &ck ) )
break;
- }
/* skip headers */
if( ck.i_type != 0x4824 )
- {
break;
- }
- msg_Warn( p_input, "skipping header" );
+
+ msg_Warn( p_access, "skipping header" );
}
- p_sys->i_pos = i_pos;
+ p_access->info.i_pos = i_pos;
+ p_access->info.b_eof = VLC_FALSE;
p_sys->i_packet_used += i_offset;
+ return VLC_SUCCESS;
+}
- p_input->stream.p_selected_area->i_tell = i_pos;
- vlc_mutex_unlock( &p_input->stream.stream_lock );
-
+/*****************************************************************************
+ * Read:
+ *****************************************************************************/
+static int ReadRedirect( access_t *p_access, uint8_t *p, int i_len )
+{
+ return 0;
}
/*****************************************************************************
* Read:
*****************************************************************************/
-static ssize_t Read ( input_thread_t * p_input, byte_t * p_buffer,
- size_t i_len )
+static int Read( access_t *p_access, uint8_t *p_buffer, int i_len )
{
- access_sys_t *p_sys = p_input->p_access_data;
+ access_sys_t *p_sys = p_access->p_sys;
size_t i_copy;
size_t i_data = 0;
+ if( p_access->info.b_eof )
+ return 0;
+
while( i_data < i_len )
{
- if( p_sys->i_packet_used < p_sys->i_packet_length )
+ if( p_access->info.i_pos < p_sys->i_start + p_sys->i_header )
+ {
+ int i_offset = p_access->info.i_pos - p_sys->i_start;
+ i_copy = __MIN( p_sys->i_header - i_offset, i_len - i_data );
+ memcpy( &p_buffer[i_data], &p_sys->p_header[i_offset], i_copy );
+
+ i_data += i_copy;
+ p_access->info.i_pos += i_copy;
+ }
+ else if( p_sys->i_packet_used < p_sys->i_packet_length )
{
i_copy = __MIN( p_sys->i_packet_length - p_sys->i_packet_used,
i_len - i_data );
i_data += i_copy;
p_sys->i_packet_used += i_copy;
+ p_access->info.i_pos += i_copy;
}
- else if( p_sys->i_pos + i_data > p_sys->i_header &&
+ else if( p_sys->i_packet_length > 0 &&
(int)p_sys->i_packet_used < p_sys->asfh.i_min_data_packet_size )
{
i_copy = __MIN( p_sys->asfh.i_min_data_packet_size - p_sys->i_packet_used,
i_data += i_copy;
p_sys->i_packet_used += i_copy;
+ p_access->info.i_pos += i_copy;
}
else
{
chunk_t ck;
- /* get a new packet */
- /* fill enought data (>12) */
- msg_Dbg( p_input, "waiting data (buffer = %d bytes)",
- p_sys->i_buffer );
-
- if( mmsh_get_packet( p_input, &ck ) )
+ if( GetPacket( p_access, &ck ) )
{
- return 0;
+ if( ck.i_type == 0x4524 && ck.i_sequence != 0 && p_sys->b_broadcast )
+ {
+ char *psz_location = NULL;
+
+ p_sys->i_start = p_access->info.i_pos;
+
+ msg_Dbg( p_access, "stoping the stream" );
+ Stop( p_access );
+
+ msg_Dbg( p_access, "describe the stream" );
+ if( Describe( p_access, &psz_location ) )
+ {
+ msg_Err( p_access, "describe failed" );
+ p_access->info.b_eof = VLC_TRUE;
+ return 0;
+ }
+ if( Start( p_access, 0 ) )
+ {
+ msg_Err( p_access, "Start failed" );
+ p_access->info.b_eof = VLC_TRUE;
+ return 0;
+ }
+ }
+ else
+ {
+ p_access->info.b_eof = VLC_TRUE;
+ return 0;
+ }
+ }
+ if( ck.i_type != 0x4424 )
+ {
+ p_sys->i_packet_used = 0;
+ p_sys->i_packet_length = 0;
}
}
}
- p_sys->i_pos += i_data;
-
return( i_data );
}
-
-/****************************************************************************/
-/****************************************************************************/
-/****************************************************************************/
-/****************************************************************************/
-/****************************************************************************/
-
-static int mmsh_start( input_thread_t *p_input,
- off_t i_pos )
+/*****************************************************************************
+ * Describe:
+ *****************************************************************************/
+static int Describe( access_t *p_access, char **ppsz_location )
{
- access_sys_t *p_sys = p_input->p_access_data;
- uint8_t *p;
- int i_streams = 0;
- int i;
- http_answer_t *p_ans;
+ access_sys_t *p_sys = p_access->p_sys;
+ char *psz_location = NULL;
+ char *psz;
+ int i_code;
- msg_Dbg( p_input, "starting stream" );
+ /* Reinit context */
+ p_sys->b_broadcast = VLC_TRUE;
+ p_sys->i_request_context = 1;
+ p_sys->i_packet_sequence = 0;
+ p_sys->i_packet_used = 0;
+ p_sys->i_packet_length = 0;
+ p_sys->p_packet = NULL;
+ E_( GenerateGuid )( &p_sys->guid );
- if( ( p_sys->p_socket = NetOpenTCP( p_input, p_sys->p_url ) ) == NULL )
+ if( ( p_sys->fd = net_OpenTCP( p_access, p_sys->url.psz_host,
+ p_sys->url.i_port ) ) < 0 )
{
- /* should not occur */
- msg_Err( p_input, "cannot connect to the server" );
- return VLC_EGENERIC;
+ msg_Err( p_access, "cannot connect to %s:%d", p_sys->url.psz_host, p_sys->url.i_port );
+ goto error;
}
- for( i = 1; i < 128; i++ )
- {
- if( p_sys->asfh.stream[i].i_selected )
- {
- i_streams++;
- }
- }
+ /* send first request */
+ net_Printf( VLC_OBJECT(p_access), p_sys->fd, NULL,
+ "GET %s HTTP/1.0\r\n"
+ "Accept: */*\r\n"
+ "User-Agent: NSPlayer/4.1.0.3856\r\n"
+ "Host: %s:%d\r\n"
+ "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"
+ "Connection: Close\r\n",
+ ( p_sys->url.psz_path == NULL || *p_sys->url.psz_path == '\0' ) ? "/" : p_sys->url.psz_path,
+ p_sys->url.psz_host, p_sys->url.i_port,
+ p_sys->i_request_context++,
+ GUID_PRINT( p_sys->guid ) );
- if( i_streams <= 0 )
+ if( net_Printf( VLC_OBJECT(p_access), p_sys->fd, NULL, "\r\n" ) < 0 )
{
- msg_Err( p_input, "no stream selected" );
- return VLC_EGENERIC;
+ msg_Err( p_access, "failed to send request" );
+ goto error;
}
- p = &p_sys->buffer[0];
- p += sprintf( p, "GET %s HTTP/1.0\r\n", p_sys->p_url->psz_path );
- p += sprintf( p,"Accept: */*\r\n" );
- p += sprintf( p, "User-Agent: NSPlayer/4.1.0.3856\r\n" );
- p += sprintf( p, "Host: %s:%d\r\n",
- p_sys->p_url->psz_host, p_sys->p_url->i_port );
- if( p_sys->b_broadcast )
+ /* Receive the http header */
+ if( ( psz = net_Gets( VLC_OBJECT(p_access), p_sys->fd, NULL ) ) == NULL )
{
- p += sprintf( p,"Pragma: no-cache,rate=1.000000,request-context=%d\r\n",
- p_sys->i_request_context++ );
+ msg_Err( p_access, "failed to read answer" );
+ goto error;
}
- else
+ if( strncmp( psz, "HTTP/1.", 7 ) )
{
- p += sprintf( p, "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 >> 32)&0xffffffff),
- (uint32_t)(i_pos&0xffffffff),
- p_sys->i_request_context++ );
+ msg_Err( p_access, "invalid HTTP reply '%s'", psz );
+ free( psz );
+ goto error;
}
- p += sprintf( p, "Pragma: xPlayStrm=1\r\n" );
- p += sprintf( p, "Pragma: xClientGUID={"GUID_FMT"}\r\n",
- GUID_PRINT( p_sys->guid ) );
- p += sprintf( p, "Pragma: stream-switch-count=%d\r\n", i_streams );
- p += sprintf( p, "Pragma: stream-switch-entry=" );
- for( i = 0; i < i_streams; i++ )
+ i_code = atoi( &psz[9] );
+ if( i_code >= 400 )
{
- 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 );
- }
+ msg_Err( p_access, "error: %s", psz );
+ free( psz );
+ goto error;
}
- p += sprintf( p, "\r\n" );
- p += sprintf( p, "Connection: Close\r\n\r\n" );
-
- NetWrite( p_input, p_sys->p_socket, p_sys->buffer, p - p_sys->buffer );
-
- msg_Dbg( p_input, "filling buffer" );
- /* we read until we found a \r\n\r\n or \n\n */
- p_sys->i_buffer = 0;
- p_sys->i_buffer_pos = 0;
+ msg_Dbg( p_access, "HTTP reply '%s'", psz );
+ free( psz );
for( ;; )
{
- int i_try = 0;
- int i_read;
- uint8_t *p;
-
- p = &p_sys->buffer[p_sys->i_buffer];
- i_read =
- NetRead( p_input, p_sys->p_socket,
- &p_sys->buffer[p_sys->i_buffer],
- 1024 );
+ char *psz = net_Gets( p_access, p_sys->fd, NULL );
+ char *p;
- if( i_read == 0 )
+ if( psz == NULL )
{
- if( i_try++ > 12 )
- {
- break;
- }
- msg_Dbg( p_input, "another try (%d/12)", i_try );
- continue;
+ msg_Err( p_access, "failed to read answer" );
+ goto error;
}
- if( i_read <= 0 || p_input->b_die || p_input->b_error )
+ if( *psz == '\0' )
{
+ free( psz );
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" ) )
+ if( ( p = strchr( psz, ':' ) ) == NULL )
{
- msg_Dbg( p_input, "body found" );
- break;
+ msg_Err( p_access, "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( strstr( p, "features" ) )
+ {
+ /* FIXME, it is a bit badly done here ..... */
+ if( strstr( p, "broadcast" ) )
+ {
+ msg_Dbg( p_access, "stream type = broadcast" );
+ p_sys->b_broadcast = VLC_TRUE;
+ }
+ else if( strstr( p, "seekable" ) )
+ {
+ msg_Dbg( p_access, "stream type = seekable" );
+ p_sys->b_broadcast = VLC_FALSE;
+ }
+ else
+ {
+ msg_Warn( p_access, "unknow stream types (%s)", p );
+ p_sys->b_broadcast = VLC_FALSE;
+ }
+ }
}
- if( p_sys->i_buffer >= BUFFER_SIZE - 1024 )
+ else if( !strcasecmp( psz, "Location" ) )
{
- msg_Dbg( p_input, "buffer size exeded" );
- break;
+ psz_location = strdup( p );
}
- }
- p_ans = http_answer_parse( p_sys->buffer, p_sys->i_buffer );
- if( !p_ans )
- {
- msg_Err( p_input, "cannot parse answer" );
- return VLC_EGENERIC;
+ free( psz );
}
- if( p_ans->i_error < 200 || p_ans->i_error >= 300 )
+ /* Handle the redirection */
+ if( ( i_code == 301 || i_code == 302 ||
+ i_code == 303 || i_code == 307 ) &&
+ psz_location && *psz_location )
{
- msg_Err( p_input, "error %d (server return=`%s')",
- p_ans->i_error, p_ans->psz_answer );
- http_answer_free( p_ans );
- return VLC_EGENERIC;
- }
+ msg_Dbg( p_access, "redirection to %s", psz_location );
+ net_Close( p_sys->fd ); p_sys->fd = -1;
- if( !p_ans->p_body )
- {
- p_sys->i_buffer_pos = 0;
- p_sys->i_buffer = 0;
- }
- else
- {
- p_sys->i_buffer_pos = p_ans->p_body - p_sys->buffer;
- }
- http_answer_free( p_ans );
-
- return VLC_SUCCESS;
-}
-
-static void mmsh_stop( input_thread_t *p_input )
-{
- access_sys_t *p_sys = p_input->p_access_data;
-
- msg_Dbg( p_input, "closing stream" );
- NetClose( p_input, p_sys->p_socket );
- p_sys->p_socket = NULL;
-}
-
-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;
+ *ppsz_location = psz_location;
+ return VLC_SUCCESS;
}
+ /* Read the asf header */
+ p_sys->i_header = 0;
+ p_sys->p_header = NULL;
for( ;; )
{
- int i_read;
-
- i_read = NetRead( p_input, p_sys->p_socket,
- &p_sys->buffer[p_sys->i_buffer], i_size );
-
- 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 )
+ chunk_t ck;
+ if( GetPacket( p_access, &ck ) ||
+ ck.i_type != 0x4824 )
{
break;
}
- i_total += i_read;
- p_sys->i_buffer += i_read;
- if( i_total >= i_size )
+ if( ck.i_data > 0 )
{
- break;
+ 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 );
}
}
-
- p_sys->buffer[p_sys->i_buffer] = '\0';
-
- return i_total;
-}
-
-/****************************************************************************
- * NetOpenTCP:
- ****************************************************************************/
-static input_socket_t * NetOpenTCP( input_thread_t *p_input, url_t *p_url )
-{
- input_socket_t *p_socket;
- char *psz_network;
- module_t *p_network;
- network_socket_t socket_desc;
-
-
- p_socket = malloc( sizeof( input_socket_t ) );
- memset( p_socket, 0, sizeof( input_socket_t ) );
-
- psz_network = "";
- if( config_GetInt( p_input, "ipv4" ) )
- {
- psz_network = "ipv4";
- }
- else if( config_GetInt( p_input, "ipv6" ) )
+ msg_Dbg( p_access, "complete header size=%d", p_sys->i_header );
+ if( p_sys->i_header <= 0 )
{
- psz_network = "ipv6";
+ msg_Err( p_access, "header size == 0" );
+ goto error;
}
+ /* close this connection */
+ net_Close( p_sys->fd ); p_sys->fd = -1;
+
+ /* *** parse header and get stream and their id *** */
+ /* get all streams properties,
+ *
+ * TODO : stream bitrates properties(optional)
+ * and bitrate mutual exclusion(optional) */
+ E_( asf_HeaderParse )( &p_sys->asfh,
+ p_sys->p_header, p_sys->i_header );
+ msg_Dbg( p_access, "packet count=%lld packet size=%d",
+ p_sys->asfh.i_data_packets_count,
+ p_sys->asfh.i_min_data_packet_size );
- msg_Dbg( p_input, "waiting for connection..." );
+ E_( asf_StreamSelect)( &p_sys->asfh,
+ var_CreateGetInteger( p_access, "mms-maxbitrate" ),
+ var_CreateGetInteger( p_access, "mms-all" ),
+ var_CreateGetInteger( p_access, "audio" ),
+ var_CreateGetInteger( p_access, "video" ) );
+
+ return VLC_SUCCESS;
- socket_desc.i_type = NETWORK_TCP;
- socket_desc.psz_server_addr = p_url->psz_host;
- socket_desc.i_server_port = p_url->i_port;
- socket_desc.psz_bind_addr = "";
- socket_desc.i_bind_port = 0;
- socket_desc.i_ttl = 0;
- p_input->p_private = (void*)&socket_desc;
- if( !( p_network = module_Need( p_input, "network", psz_network ) ) )
+error:
+ if( p_sys->fd > 0 )
{
- msg_Err( p_input, "failed to connect with server" );
- return NULL;
+ net_Close( p_sys->fd );
+ p_sys->fd = -1;
}
- module_Unneed( p_input, p_network );
- p_socket->i_handle = socket_desc.i_handle;
- p_input->i_mtu = socket_desc.i_mtu;
-
- msg_Dbg( p_input,
- "connection with \"%s:%d\" successful",
- p_url->psz_host,
- p_url->i_port );
-
- return p_socket;
+ return VLC_EGENERIC;
}
/*****************************************************************************
- * Read: 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 )
+static int Start( access_t *p_access, off_t i_pos )
{
- struct timeval timeout;
- fd_set fds;
- ssize_t i_recv;
- int i_ret;
-
- /* Initialize file descriptor set */
- FD_ZERO( &fds );
- FD_SET( p_socket->i_handle, &fds );
-
- /* We'll wait 1 second if nothing happens */
- timeout.tv_sec = 1;
- timeout.tv_usec = 0;
-
- /* Find if some data is available */
- while( ( i_ret = select( p_socket->i_handle + 1, &fds,
- NULL, NULL, &timeout )) == 0 ||
-#ifdef HAVE_ERRNO_H
- ( i_ret < 0 && errno == EINTR )
-#endif
- )
- {
- FD_ZERO( &fds );
- FD_SET( p_socket->i_handle, &fds );
- timeout.tv_sec = 1;
- timeout.tv_usec = 0;
+ access_sys_t *p_sys = p_access->p_sys;
+ int i_streams = 0;
+ int i;
+ char *psz;
- if( p_input->b_die || p_input->b_error )
- {
- return 0;
- }
- }
+ msg_Dbg( p_access, "starting stream" );
- if( i_ret < 0 )
+ if( ( p_sys->fd = net_OpenTCP( p_access, p_sys->url.psz_host,
+ p_sys->url.i_port ) ) < 0 )
{
- msg_Err( p_input, "network select error (%s)", strerror(errno) );
- return -1;
- }
-
- i_recv = recv( p_socket->i_handle, p_buffer, i_len, 0 );
-
- if( i_recv < 0 )
- {
- msg_Err( p_input, "recv failed (%s)", strerror(errno) );
+ /* should not occur */
+ msg_Err( p_access, "cannot connect to the server" );
+ return VLC_EGENERIC;
}
- return i_recv;
-}
-
-static ssize_t NetWrite( input_thread_t *p_input,
- input_socket_t *p_socket,
- byte_t *p_buffer, size_t i_len )
-{
- struct timeval timeout;
- fd_set fds;
- ssize_t i_send;
- int i_ret;
-
- /* Initialize file descriptor set */
- FD_ZERO( &fds );
- FD_SET( p_socket->i_handle, &fds );
-
- /* We'll wait 1 second if nothing happens */
- timeout.tv_sec = 1;
- timeout.tv_usec = 0;
-
- /* Find if some data is available */
- while( ( i_ret = select( p_socket->i_handle + 1, NULL, &fds, NULL, &timeout ) ) == 0 ||
-#ifdef HAVE_ERRNO_H
- ( i_ret < 0 && errno == EINTR )
-#endif
- )
+ for( i = 1; i < 128; i++ )
{
- FD_ZERO( &fds );
- FD_SET( p_socket->i_handle, &fds );
- timeout.tv_sec = 1;
- timeout.tv_usec = 0;
-
- if( p_input->b_die || p_input->b_error )
+ if( p_sys->asfh.stream[i].i_selected )
{
- return 0;
+ i_streams++;
}
}
- if( i_ret < 0 )
+ if( i_streams <= 0 )
{
- msg_Err( p_input, "network select error (%s)", strerror(errno) );
- return -1;
+ msg_Err( p_access, "no stream selected" );
+ return VLC_EGENERIC;
}
-
- i_send = send( p_socket->i_handle, p_buffer, i_len, 0 );
-
- if( i_send < 0 )
+ net_Printf( VLC_OBJECT(p_access), p_sys->fd, NULL,
+ "GET %s HTTP/1.0\r\n"
+ "Accept: */*\r\n"
+ "User-Agent: NSPlayer/4.1.0.3856\r\n"
+ "Host: %s:%d\r\n",
+ ( p_sys->url.psz_path == NULL || *p_sys->url.psz_path == '\0' ) ? "/" : p_sys->url.psz_path,
+ p_sys->url.psz_host, p_sys->url.i_port );
+ if( p_sys->b_broadcast )
{
- msg_Err( p_input, "send failed (%s)", strerror(errno) );
+ net_Printf( VLC_OBJECT(p_access), p_sys->fd, NULL,
+ "Pragma: no-cache,rate=1.000000,request-context=%d\r\n",
+ p_sys->i_request_context++ );
}
+ else
+ {
+ net_Printf( VLC_OBJECT(p_access), p_sys->fd, NULL,
+ "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 >> 32)&0xffffffff),
+ (uint32_t)(i_pos&0xffffffff),
+ p_sys->i_request_context++ );
+ }
+ net_Printf( VLC_OBJECT(p_access), p_sys->fd, NULL,
+ "Pragma: xPlayStrm=1\r\n"
+ "Pragma: xClientGUID={"GUID_FMT"}\r\n"
+ "Pragma: stream-switch-count=%d\r\n"
+ "Pragma: stream-switch-entry=",
+ GUID_PRINT( p_sys->guid ),
+ i_streams);
- return i_send;
-}
-
-static void NetClose( input_thread_t *p_input, input_socket_t *p_socket )
-{
-#if defined( WIN32 ) || defined( UNDER_CE )
- closesocket( p_socket->i_handle );
-#else
- close( p_socket->i_handle );
-#endif
-
- free( p_socket );
-}
-
-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++ )
+ for( i = 1; i < 128; i++ )
{
- if( p + 1 < p_end && *p == '\n' )
+ if( p_sys->asfh.stream[i].i_cat != ASF_STREAM_UNKNOWN )
{
- *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;
+ int i_select = 2;
+ if( p_sys->asfh.stream[i].i_selected )
+ {
+ i_select = 0;
+ }
+
+ net_Printf( VLC_OBJECT(p_access), p_sys->fd, NULL,
+ "ffff:%d:%d ", i, i_select );
}
}
- *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;
+ net_Printf( VLC_OBJECT(p_access), p_sys->fd, NULL, "\r\n" );
+ net_Printf( VLC_OBJECT(p_access), p_sys->fd, NULL,
+ "Connection: Close\r\n" );
- if( strncmp( p_data, "HTTP/1.", 7 ) )
+ if( net_Printf( VLC_OBJECT(p_access), p_sys->fd, NULL, "\r\n" ) < 0 )
{
- free( ans );
- return NULL;
+ msg_Err( p_access, "failed to send request" );
+ return VLC_EGENERIC;
}
- ans->i_version = atoi( &p_data[7] );
- ans->i_error = strtol( p_data + 8, &p, 0 );
- while( *p == ' ' )
+
+ if( ( psz = net_Gets( VLC_OBJECT(p_access), p_sys->fd, NULL ) ) == NULL )
{
- p++;
+ msg_Err( p_access, "cannot read data" );
+ return VLC_EGENERIC;
}
- if( ( ( end = strchr( p, '\r' ) ) == NULL )&&
- ( ( end = strchr( p, '\n' ) ) == NULL ) )
+ if( atoi( &psz[9] ) >= 400 )
{
- end = &p_data[i_data];
+ msg_Err( p_access, "error: %s", psz );
+ free( psz );
+ return VLC_EGENERIC;
}
+ msg_Dbg( p_access, "HTTP reply '%s'", psz );
+ free( psz );
- 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;
-
+ /* FIXME check HTTP code */
for( ;; )
{
- http_field_t *p_field;
- uint8_t *colon;
-
- if( http_next_line( &p_data, &i_data ) )
+ char *psz = net_Gets( p_access, p_sys->fd, NULL );
+ if( psz == NULL )
{
- return ans;
+ msg_Err( p_access, "cannot read data" );
+ return VLC_EGENERIC;
}
- if( !strncmp( p_data, "\r\n", 2 ) || !strncmp( p_data, "\n", 1 ) )
+ if( *psz == '\0' )
{
+ free( psz );
break;
}
+ msg_Dbg( p_access, "%s", psz );
+ free( psz );
+ }
- 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;
+ p_sys->i_packet_used = 0;
+ p_sys->i_packet_length = 0;
- *pp_last = p_field;
- pp_last = &p_field->p_next;
+ return VLC_SUCCESS;
+}
- fprintf( stderr, "field name=`%s' value=`%s'\n",
- p_field->psz_name, p_field->psz_value );
- }
- }
+/*****************************************************************************
+ *
+ *****************************************************************************/
+static void Stop( access_t *p_access )
+{
+ access_sys_t *p_sys = p_access->p_sys;
- if( http_next_line( &p_data, &i_data ) )
+ msg_Dbg( p_access, "closing stream" );
+ if( p_sys->fd > 0 )
{
- return ans;
+ net_Close( p_sys->fd );
+ p_sys->fd = -1;
}
-
- 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 )
+/*****************************************************************************
+ *
+ *****************************************************************************/
+static int GetPacket( access_t * p_access, chunk_t *p_ck )
{
- http_field_t *p_field = ans->p_fields;
-
- while( p_field )
- {
- http_field_t *p_next;
+ access_sys_t *p_sys = p_access->p_sys;
- p_next = p_field->p_next;
- free( p_field->psz_name );
- free( p_field->psz_value );
- free( p_field );
+ /* chunk_t */
+ memset( p_ck, 0, sizeof( chunk_t ) );
- p_field = p_next;
+ /* Read the chunk header */
+ if( net_Read( p_access, p_sys->fd, NULL, p_sys->buffer, 12, VLC_TRUE ) < 12 )
+ {
+ /* msg_Err( p_access, "cannot read data" ); */
+ return VLC_EGENERIC;
}
- free( ans->psz_answer );
- free( ans );
-}
-
-static http_field_t *http_field_find( http_field_t *p_field, char *psz_name )
-{
+ p_ck->i_type = GetWLE( p_sys->buffer);
+ 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;
- while( p_field )
+ if( p_ck->i_type == 0x4524 ) // Transfer complete
{
- if( !strcasecmp( p_field->psz_name, psz_name ) )
+ if( p_ck->i_sequence == 0 )
{
- return p_field;
+ msg_Warn( p_access, "EOF" );
+ return VLC_EGENERIC;
+ }
+ else
+ {
+ msg_Warn( p_access, "Next stream follow but not supported" );
+ return VLC_EGENERIC;
}
-
- p_field = p_field->p_next;
+ }
+ else if( p_ck->i_type != 0x4824 && p_ck->i_type != 0x4424 )
+ {
+ msg_Err( p_access, "invalid chunk FATAL (0x%x)", p_ck->i_type );
+ return VLC_EGENERIC;
}
- return NULL;
-}
-
-static int chunk_parse( chunk_t *ck, uint8_t *p_data, int i_data )
-{
- if( i_data < 12 )
+ if( p_ck->i_data > 0 &&
+ net_Read( p_access, p_sys->fd, NULL, &p_sys->buffer[12], p_ck->i_data, VLC_TRUE ) < p_ck->i_data )
{
+ msg_Err( p_access, "cannot read data" );
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);
+ if( p_sys->i_packet_sequence != 0 &&
+ p_ck->i_sequence != p_sys->i_packet_sequence )
+ {
+ msg_Warn( p_access, "packet lost ? (%d != %d)", p_ck->i_sequence, p_sys->i_packet_sequence );
+ }
- ck->p_data = p_data + 12;
- ck->i_data = __MIN( i_data - 12, ck->i_size2 - 8 );
+ p_sys->i_packet_sequence = p_ck->i_sequence + 1;
+ p_sys->i_packet_used = 0;
+ p_sys->i_packet_length = p_ck->i_data;
+ p_sys->p_packet = p_ck->p_data;
return VLC_SUCCESS;
}
-