X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Faccess%2Fmms%2Fmmsh.c;h=e191b2a48f3b527096fddab344618ce59d4d011f;hb=12ade3e3bc975d5426ba4af155b7372c31093b31;hp=18d1c73bf0637ed82021420fb7dca67afeb3602d;hpb=830641e412aa599f0d1568b738214aa9752ade7b;p=vlc diff --git a/modules/access/mms/mmsh.c b/modules/access/mms/mmsh.c index 18d1c73bf0..e191b2a48f 100644 --- a/modules/access/mms/mmsh.c +++ b/modules/access/mms/mmsh.c @@ -24,14 +24,18 @@ /***************************************************************************** * Preamble *****************************************************************************/ -#include -#include +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include #include -#include "vlc_playlist.h" +#include +#include #include -#include "vlc_url.h" +#include #include "asf.h" #include "buffer.h" @@ -39,27 +43,26 @@ #include "mmsh.h" /* TODO: - * - http_proxy * - authentication */ /***************************************************************************** * Local prototypes *****************************************************************************/ -int E_(MMSHOpen) ( access_t * ); -void E_(MMSHClose) ( access_t * ); +int MMSHOpen ( access_t * ); +void MMSHClose ( access_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 block_t *Block( access_t *p_access ); +static ssize_t ReadRedirect( access_t *, uint8_t *, size_t ); +static int Seek( access_t *, uint64_t ); static int Control( access_t *, int, va_list ); static int Describe( access_t *, char **ppsz_location ); -static int Start( access_t *, int64_t ); +static int Start( access_t *, uint64_t ); static void Stop( access_t * ); static int GetPacket( access_t *, chunk_t * ); -static void GetHeader( access_t *p_access ); +static void GetHeader( access_t *p_access, int i_content_length ); static int Restart( access_t * ); static int Reset( access_t * ); @@ -70,74 +73,118 @@ static int Reset( access_t * ); /**************************************************************************** * Open: connect to ftp server and ask for file ****************************************************************************/ -int E_(MMSHOpen)( access_t *p_access ) +int MMSHOpen( access_t *p_access ) { access_sys_t *p_sys; char *psz_location = NULL; + char *psz_proxy; + + STANDARD_BLOCK_ACCESS_INIT - /* init p_sys */ - - /* 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; + + /* Handle proxy */ + p_sys->b_proxy = false; + memset( &p_sys->proxy, 0, sizeof(p_sys->proxy) ); + + /* Check proxy */ + /* TODO reuse instead http-proxy from http access ? */ + psz_proxy = var_CreateGetNonEmptyString( p_access, "mmsh-proxy" ); + if( !psz_proxy ) + { + char *psz_http_proxy = var_InheritString( p_access, "http-proxy" ); + if( psz_http_proxy ) + { + psz_proxy = psz_http_proxy; + var_SetString( p_access, "mmsh-proxy", psz_proxy ); + } + } + + if( psz_proxy ) + { + p_sys->b_proxy = true; + vlc_UrlParse( &p_sys->proxy, psz_proxy, 0 ); + free( psz_proxy ); + } +#ifdef HAVE_GETENV + else + { + const char *http_proxy = getenv( "http_proxy" ); + if( http_proxy ) + { + p_sys->b_proxy = true; + vlc_UrlParse( &p_sys->proxy, http_proxy, 0 ); + } + } +#endif + + if( p_sys->b_proxy ) + { + if( ( p_sys->proxy.psz_host == NULL ) || + ( *p_sys->proxy.psz_host == '\0' ) ) + { + msg_Warn( p_access, "invalid proxy host" ); + vlc_UrlClean( &p_sys->proxy ); + free( p_sys ); + return VLC_EGENERIC; + } + + if( p_sys->proxy.i_port <= 0 ) + p_sys->proxy.i_port = 80; + msg_Dbg( p_access, "Using http proxy %s:%d", + p_sys->proxy.psz_host, p_sys->proxy.i_port ); + } /* open a tcp connection */ - vlc_UrlParse( &p_sys->url, p_access->psz_path, 0 ); - if( p_sys->url.psz_host == NULL || *p_sys->url.psz_host == '\0' ) + vlc_UrlParse( &p_sys->url, p_access->psz_location, 0 ); + if( ( p_sys->url.psz_host == NULL ) || + ( *p_sys->url.psz_host == '\0' ) ) { msg_Err( p_access, "invalid host" ); - vlc_UrlClean( &p_sys->url ); - free( p_sys ); - return VLC_EGENERIC; + goto error; } if( p_sys->url.i_port <= 0 ) p_sys->url.i_port = 80; if( Describe( p_access, &psz_location ) ) - { - vlc_UrlClean( &p_sys->url ); - free( p_sys ); - return VLC_EGENERIC; - } + goto error; + /* Handle redirection */ if( psz_location && *psz_location ) { - playlist_t * p_playlist = pl_Yield( p_access ); msg_Dbg( p_access, "redirection to %s", psz_location ); + input_thread_t * p_input = access_GetParentInput( p_access ); + input_item_t * p_new_loc; + + if( !p_input ) + { + free( psz_location ); + goto error; + } /** \bug we do not autodelete here */ - playlist_Add( p_playlist, psz_location, psz_location, - PLAYLIST_INSERT | PLAYLIST_GO, PLAYLIST_END, VLC_TRUE, - VLC_FALSE ); - vlc_object_release( p_playlist ); + p_new_loc = input_item_New( p_access, psz_location, psz_location ); + input_item_t *p_item = input_GetItem( p_input ); + input_item_PostSubItem( p_item, p_new_loc ); + + vlc_gc_decref( p_new_loc ); + vlc_object_release( p_input ); free( psz_location ); + p_access->pf_block = NULL; p_access->pf_read = ReadRedirect; return VLC_SUCCESS; } + free( psz_location ); /* Start playing */ if( Start( p_access, 0 ) ) { msg_Err( p_access, "cannot start stream" ); free( p_sys->p_header ); - vlc_UrlClean( &p_sys->url ); - free( p_sys ); - return VLC_EGENERIC; + goto error; } if( !p_sys->b_broadcast ) @@ -146,16 +193,27 @@ int E_(MMSHOpen)( access_t *p_access ) } return VLC_SUCCESS; + +error: + vlc_UrlClean( &p_sys->proxy ); + vlc_UrlClean( &p_sys->url ); + free( p_sys ); + return VLC_EGENERIC; } /***************************************************************************** * Close: free unused data structures *****************************************************************************/ -void E_( MMSHClose )( access_t *p_access ) +void MMSHClose ( access_t *p_access ) { access_sys_t *p_sys = p_access->p_sys; Stop( p_access ); + + free( p_sys->p_header ); + + vlc_UrlClean( &p_sys->proxy ); + vlc_UrlClean( &p_sys->url ); free( p_sys ); } @@ -165,8 +223,8 @@ void E_( MMSHClose )( access_t *p_access ) static int Control( access_t *p_access, int i_query, va_list args ) { access_sys_t *p_sys = p_access->p_sys; - vlc_bool_t *pb_bool; - int *pi_int; + bool *pb_bool; + bool b_bool; int64_t *pi_64; int i_int; @@ -174,52 +232,50 @@ static int Control( access_t *p_access, int i_query, va_list args ) { /* */ case ACCESS_CAN_SEEK: - pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* ); + pb_bool = (bool*)va_arg( args, bool* ); *pb_bool = !p_sys->b_broadcast; break; case ACCESS_CAN_FASTSEEK: - case ACCESS_CAN_PAUSE: - pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* ); - *pb_bool = VLC_FALSE; + pb_bool = (bool*)va_arg( args, bool* ); + *pb_bool = false; break; + case ACCESS_CAN_PAUSE: case ACCESS_CAN_CONTROL_PACE: - pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* ); - -#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; + pb_bool = (bool*)va_arg( args, bool* ); + *pb_bool = true; break; /* */ - case ACCESS_GET_MTU: - pi_int = (int*)va_arg( args, int * ); - *pi_int = 3 * p_sys->asfh.i_min_data_packet_size; - break; - 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); + *pi_64 = var_GetInteger( p_access, "mms-caching" ) * INT64_C(1000); break; case ACCESS_GET_PRIVATE_ID_STATE: i_int = (int)va_arg( args, int ); - pb_bool = (vlc_bool_t *)va_arg( args, vlc_bool_t * ); + pb_bool = (bool *)va_arg( args, bool * ); - if( i_int < 0 || i_int > 127 ) + if( (i_int < 0) || (i_int > 127) ) return VLC_EGENERIC; - *pb_bool = p_sys->asfh.stream[i_int].i_selected ? VLC_TRUE : VLC_FALSE; + *pb_bool = p_sys->asfh.stream[i_int].i_selected ? true : false; break; /* */ case ACCESS_SET_PAUSE_STATE: + b_bool = (bool)va_arg( args, int ); + if( b_bool ) + Stop( p_access ); + else + Seek( p_access, p_access->info.i_pos ); + break; + case ACCESS_GET_TITLE_INFO: case ACCESS_SET_TITLE: case ACCESS_SET_SEEKPOINT: case ACCESS_SET_PRIVATE_ID_STATE: + case ACCESS_GET_CONTENT_TYPE: return VLC_EGENERIC; default: @@ -233,14 +289,14 @@ static int Control( access_t *p_access, int i_query, va_list args ) /***************************************************************************** * Seek: try to go at the right place *****************************************************************************/ -static int Seek( access_t *p_access, int64_t i_pos ) +static int Seek( access_t *p_access, uint64_t i_pos ) { access_sys_t *p_sys = p_access->p_sys; chunk_t ck; - off_t i_offset; - off_t i_packet; + uint64_t i_offset; + uint64_t i_packet; - msg_Dbg( p_access, "seeking to "I64Fd, i_pos ); + msg_Dbg( p_access, "seeking to %"PRId64, 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; @@ -248,7 +304,7 @@ static int Seek( access_t *p_access, int64_t i_pos ) Stop( p_access ); Start( p_access, i_packet * p_sys->asfh.i_min_data_packet_size ); - while( !p_access->b_die ) + while( vlc_object_alive (p_access) ) { if( GetPacket( p_access, &ck ) ) break; @@ -261,96 +317,92 @@ static int Seek( access_t *p_access, int64_t i_pos ) } p_access->info.i_pos = i_pos; - p_access->info.b_eof = VLC_FALSE; + p_access->info.b_eof = false; p_sys->i_packet_used += i_offset; return VLC_SUCCESS; } /***************************************************************************** - * Read: + * ReadRedirect: *****************************************************************************/ -static int ReadRedirect( access_t *p_access, uint8_t *p, int i_len ) +static ssize_t ReadRedirect( access_t *p_access, uint8_t *p, size_t i_len ) { + VLC_UNUSED(p_access); VLC_UNUSED(p); VLC_UNUSED(i_len); return 0; } /***************************************************************************** - * Read: + * Block: *****************************************************************************/ -static int Read( access_t *p_access, uint8_t *p_buffer, int i_len ) +static block_t *Block( access_t *p_access ) { access_sys_t *p_sys = p_access->p_sys; - size_t i_copy; - size_t i_data = 0; + const unsigned i_packet_min = p_sys->asfh.i_min_data_packet_size; - if( p_access->info.b_eof ) - return 0; + if( p_access->info.i_pos < p_sys->i_start + p_sys->i_header ) + { + const size_t i_offset = p_access->info.i_pos - p_sys->i_start; + const size_t i_copy = p_sys->i_header - i_offset; - while( i_data < (size_t) i_len ) + block_t *p_block = block_New( p_access, i_copy ); + if( !p_block ) + return NULL; + + memcpy( p_block->p_buffer, &p_sys->p_header[i_offset], i_copy ); + p_access->info.i_pos += i_copy; + return p_block; + } + else if( p_sys->i_packet_length > 0 && + p_sys->i_packet_used < __MAX( p_sys->i_packet_length, i_packet_min ) ) { - 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, (int)((size_t)i_len - i_data) ); - memcpy( &p_buffer[i_data], &p_sys->p_header[i_offset], i_copy ); + size_t i_copy = 0; + size_t i_padding = 0; - 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 ); + if( p_sys->i_packet_used < p_sys->i_packet_length ) + i_copy = p_sys->i_packet_length - p_sys->i_packet_used; + if( __MAX( p_sys->i_packet_used, p_sys->i_packet_length ) < i_packet_min ) + i_padding = i_packet_min - __MAX( p_sys->i_packet_used, p_sys->i_packet_length ); - memcpy( &p_buffer[i_data], - &p_sys->p_packet[p_sys->i_packet_used], - i_copy ); + block_t *p_block = block_New( p_access, i_copy + i_padding ); + if( !p_block ) + return NULL; - i_data += i_copy; - p_sys->i_packet_used += i_copy; - p_access->info.i_pos += i_copy; - } - 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_len - i_data ); + if( i_copy > 0 ) + memcpy( &p_block->p_buffer[0], &p_sys->p_packet[p_sys->i_packet_used], i_copy ); + if( i_padding > 0 ) + memset( &p_block->p_buffer[i_copy], 0, i_padding ); - memset( &p_buffer[i_data], 0, i_copy ); + p_sys->i_packet_used += i_copy + i_padding; + p_access->info.i_pos += i_copy + i_padding; + return p_block; + + } - i_data += i_copy; - p_sys->i_packet_used += i_copy; - p_access->info.i_pos += i_copy; + chunk_t ck; + if( GetPacket( p_access, &ck ) ) + { + int i_ret = -1; + if( p_sys->b_broadcast ) + { + if( (ck.i_type == 0x4524) && (ck.i_sequence != 0) ) + i_ret = Restart( p_access ); + else if( ck.i_type == 0x4324 ) + i_ret = Reset( p_access ); } - else + if( i_ret ) { - chunk_t ck; - if( GetPacket( p_access, &ck ) ) - { - int i_ret = -1; - if( p_sys->b_broadcast ) - { - if( ck.i_type == 0x4524 && ck.i_sequence != 0 ) - i_ret = Restart( p_access ); - else if( ck.i_type == 0x4324 ) - i_ret = Reset( p_access ); - } - if( i_ret ) - { - 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_access->info.b_eof = true; + return 0; } } + if( ck.i_type != 0x4424 ) + { + p_sys->i_packet_used = 0; + p_sys->i_packet_length = 0; + } - return( i_data ); + return NULL; } /* */ @@ -371,15 +423,17 @@ static int Restart( access_t *p_access ) if( Describe( p_access, &psz_location ) ) { msg_Err( p_access, "describe failed" ); - return -1; + return VLC_EGENERIC; } + free( psz_location ); + /* */ if( Start( p_access, 0 ) ) { msg_Err( p_access, "Start failed" ); - return -1; + return VLC_EGENERIC; } - return 0; + return VLC_SUCCESS; } static int Reset( access_t *p_access ) { @@ -397,21 +451,21 @@ static int Reset( access_t *p_access ) p_sys->p_packet = NULL; /* Get the next header FIXME memory loss ? */ - GetHeader( p_access ); + GetHeader( p_access, -1 ); if( p_sys->i_header <= 0 ) - return -1; + return VLC_EGENERIC; - E_( asf_HeaderParse )( &p_sys->asfh, - p_sys->p_header, p_sys->i_header ); - msg_Dbg( p_access, "packet count="I64Fd" packet size=%d", + asf_HeaderParse ( &p_sys->asfh, + p_sys->p_header, p_sys->i_header ); + msg_Dbg( p_access, "packet count=%"PRId64" packet size=%d", p_sys->asfh.i_data_packets_count, p_sys->asfh.i_min_data_packet_size ); - 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" ) ); + asf_StreamSelect( &p_sys->asfh, + var_InheritInteger( p_access, "mms-maxbitrate" ), + var_InheritBool( p_access, "mms-all" ), + var_InheritBool( p_access, "audio" ), + var_InheritBool( p_access, "video" ) ); /* Check we have comptible asfh */ for( i = 1; i < 128; i++ ) @@ -431,8 +485,62 @@ static int Reset( access_t *p_access ) /* */ p_sys->i_packet_used = 0; p_sys->i_packet_length = 0; - return 0; + return VLC_SUCCESS; } + +static int OpenConnection( access_t *p_access ) +{ + access_sys_t *p_sys = p_access->p_sys; + vlc_url_t srv = p_sys->b_proxy ? p_sys->proxy : p_sys->url; + + if( ( p_sys->fd = net_ConnectTCP( p_access, + srv.psz_host, srv.i_port ) ) < 0 ) + { + msg_Err( p_access, "cannot connect to %s:%d", + srv.psz_host, srv.i_port ); + return VLC_EGENERIC; + } + + if( p_sys->b_proxy ) + { + net_Printf( p_access, p_sys->fd, NULL, + "GET http://%s:%d%s HTTP/1.0\r\n", + p_sys->url.psz_host, p_sys->url.i_port, + ( (p_sys->url.psz_path == NULL) || + (*p_sys->url.psz_path == '\0') ) ? + "/" : p_sys->url.psz_path ); + + /* Proxy Authentication */ + if( p_sys->proxy.psz_username && *p_sys->proxy.psz_username ) + { + char *buf; + char *b64; + + if( asprintf( &buf, "%s:%s", p_sys->proxy.psz_username, + p_sys->proxy.psz_password ? p_sys->proxy.psz_password : "" ) == -1 ) + return VLC_ENOMEM; + + b64 = vlc_b64_encode( buf ); + free( buf ); + + net_Printf( p_access, p_sys->fd, NULL, + "Proxy-Authorization: Basic %s\r\n", b64 ); + free( b64 ); + } + } + else + { + net_Printf( p_access, p_sys->fd, NULL, + "GET %s HTTP/1.0\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 ); + } + return VLC_SUCCESS; +} + /***************************************************************************** * Describe: *****************************************************************************/ @@ -440,52 +548,46 @@ static int Describe( access_t *p_access, char **ppsz_location ) { access_sys_t *p_sys = p_access->p_sys; char *psz_location = NULL; + int i_content_length = -1; + bool b_keepalive = false; char *psz; int i_code; /* Reinit context */ - p_sys->b_broadcast = VLC_TRUE; + p_sys->b_broadcast = 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->fd = net_ConnectTCP( p_access, p_sys->url.psz_host, - p_sys->url.i_port ) ) < 0 ) - { - msg_Err( p_access, "cannot connect to %s:%d", p_sys->url.psz_host, - p_sys->url.i_port ); - goto error; - } + GenerateGuid ( &p_sys->guid ); + + if( OpenConnection( p_access ) ) + return VLC_EGENERIC; - /* send first request */ - net_Printf( VLC_OBJECT(p_access), p_sys->fd, NULL, - "GET %s HTTP/1.0\r\n" + net_Printf( p_access, p_sys->fd, NULL, "Accept: */*\r\n" "User-Agent: "MMSH_USER_AGENT"\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( net_Printf( VLC_OBJECT(p_access), p_sys->fd, NULL, "\r\n" ) < 0 ) + if( net_Printf( p_access, p_sys->fd, NULL, "\r\n" ) < 0 ) { msg_Err( p_access, "failed to send request" ); goto error; } /* Receive the http header */ - if( ( psz = net_Gets( VLC_OBJECT(p_access), p_sys->fd, NULL ) ) == NULL ) + if( ( psz = net_Gets( p_access, p_sys->fd, NULL ) ) == NULL ) { msg_Err( p_access, "failed to read answer" ); goto error; } + if( strncmp( psz, "HTTP/1.", 7 ) ) { msg_Err( p_access, "invalid HTTP reply '%s'", psz ); @@ -538,17 +640,17 @@ static int Describe( access_t *p_access, char **ppsz_location ) if( strstr( p, "broadcast" ) ) { msg_Dbg( p_access, "stream type = broadcast" ); - p_sys->b_broadcast = VLC_TRUE; + p_sys->b_broadcast = true; } else if( strstr( p, "seekable" ) ) { msg_Dbg( p_access, "stream type = seekable" ); - p_sys->b_broadcast = VLC_FALSE; + p_sys->b_broadcast = false; } else { msg_Warn( p_access, "unknow stream types (%s)", p ); - p_sys->b_broadcast = VLC_FALSE; + p_sys->b_broadcast = false; } } } @@ -556,13 +658,27 @@ static int Describe( access_t *p_access, char **ppsz_location ) { psz_location = strdup( p ); } + else if( !strcasecmp( psz, "Content-Length" ) ) + { + i_content_length = atoi( p ); + msg_Dbg( p_access, "content-length = %d", i_content_length ); + } + else if( !strcasecmp( psz, "Connection" ) ) + { + if( strcasestr( p, "Keep-Alive" ) ) + { + msg_Dbg( p_access, "Keep-Alive header found" ); + b_keepalive = true; + } + } + free( psz ); } /* Handle the redirection */ - if( ( i_code == 301 || i_code == 302 || - i_code == 303 || i_code == 307 ) && + if( ( (i_code == 301) || (i_code == 302) || + (i_code == 303) || (i_code == 307) ) && psz_location && *psz_location ) { msg_Dbg( p_access, "redirection to %s", psz_location ); @@ -571,33 +687,38 @@ static int Describe( access_t *p_access, char **ppsz_location ) *ppsz_location = psz_location; return VLC_SUCCESS; } + free( psz_location ); /* Read the asf header */ - GetHeader( p_access ); + GetHeader( p_access, b_keepalive ? i_content_length : -1); if( p_sys->i_header <= 0 ) { msg_Err( p_access, "header size == 0" ); goto error; } /* close this connection */ - net_Close( p_sys->fd ); p_sys->fd = -1; + 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="I64Fd" packet size=%d", + asf_HeaderParse ( &p_sys->asfh, + p_sys->p_header, p_sys->i_header ); + msg_Dbg( p_access, "packet count=%"PRId64" packet size=%d", p_sys->asfh.i_data_packets_count, p_sys->asfh.i_min_data_packet_size ); - 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" ) ); + if( p_sys->asfh.i_min_data_packet_size <= 0 ) + goto error; + + asf_StreamSelect( &p_sys->asfh, + var_InheritInteger( p_access, "mms-maxbitrate" ), + var_InheritBool( p_access, "mms-all" ), + var_InheritBool( p_access, "audio" ), + var_InheritBool( p_access, "video" ) ); return VLC_SUCCESS; error: @@ -608,23 +729,28 @@ error: } return VLC_EGENERIC; } -static void GetHeader( access_t *p_access ) + +static void GetHeader( access_t *p_access, int i_content_length ) { access_sys_t *p_sys = p_access->p_sys; + int i_read_content = 0; /* Read the asf header */ p_sys->i_header = 0; + free( p_sys->p_header ); p_sys->p_header = NULL; for( ;; ) { chunk_t ck; - if( GetPacket( p_access, &ck ) || ck.i_type != 0x4824 ) + if( (i_content_length >= 0 && i_read_content >= i_content_length) || GetPacket( p_access, &ck ) || ck.i_type != 0x4824 ) break; + i_read_content += (4+ck.i_size); + if( ck.i_data > 0 ) { p_sys->i_header += ck.i_data; - p_sys->p_header = realloc( p_sys->p_header, p_sys->i_header ); + p_sys->p_header = xrealloc( 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 ); } @@ -634,26 +760,18 @@ static void GetHeader( access_t *p_access ) /***************************************************************************** - * - *****************************************************************************/ -static int Start( access_t *p_access, off_t i_pos ) + * Start stream + ****************************************************************************/ +static int Start( access_t *p_access, uint64_t i_pos ) { access_sys_t *p_sys = p_access->p_sys; int i_streams = 0; int i_streams_selected = 0; int i; - char *psz; + char *psz = NULL; msg_Dbg( p_access, "starting stream" ); - if( ( p_sys->fd = net_ConnectTCP( p_access, p_sys->url.psz_host, - p_sys->url.i_port ) ) < 0 ) - { - /* should not occur */ - msg_Err( p_access, "cannot connect to the server" ); - return VLC_EGENERIC; - } - for( i = 1; i < 128; i++ ) { if( p_sys->asfh.stream[i].i_cat == ASF_STREAM_UNKNOWN ) @@ -662,34 +780,33 @@ static int Start( access_t *p_access, off_t i_pos ) if( p_sys->asfh.stream[i].i_selected ) i_streams_selected++; } - if( i_streams_selected <= 0 ) { msg_Err( p_access, "no stream selected" ); return VLC_EGENERIC; } - net_Printf( VLC_OBJECT(p_access), p_sys->fd, NULL, - "GET %s HTTP/1.0\r\n" + + if( OpenConnection( p_access ) ) + return VLC_EGENERIC; + + net_Printf( p_access, p_sys->fd, NULL, "Accept: */*\r\n" - "User-Agent: "MMSH_USER_AGENT"\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 ); + "User-Agent: "MMSH_USER_AGENT"\r\n" ); if( p_sys->b_broadcast ) { - net_Printf( VLC_OBJECT(p_access), p_sys->fd, NULL, + net_Printf( 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, + net_Printf( 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, + net_Printf( p_access, p_sys->fd, NULL, "Pragma: xPlayStrm=1\r\n" "Pragma: xClientGUID={"GUID_FMT"}\r\n" "Pragma: stream-switch-count=%d\r\n" @@ -706,26 +823,27 @@ static int Start( access_t *p_access, off_t i_pos ) { i_select = 0; } - - net_Printf( VLC_OBJECT(p_access), p_sys->fd, NULL, + net_Printf( p_access, p_sys->fd, NULL, "ffff:%d:%d ", i, i_select ); } } - net_Printf( VLC_OBJECT(p_access), p_sys->fd, NULL, "\r\n" ); - net_Printf( VLC_OBJECT(p_access), p_sys->fd, NULL, + net_Printf( p_access, p_sys->fd, NULL, "\r\n" ); + net_Printf( p_access, p_sys->fd, NULL, "Connection: Close\r\n" ); - if( net_Printf( VLC_OBJECT(p_access), p_sys->fd, NULL, "\r\n" ) < 0 ) + if( net_Printf( p_access, p_sys->fd, NULL, "\r\n" ) < 0 ) { msg_Err( p_access, "failed to send request" ); return VLC_EGENERIC; } - if( ( psz = net_Gets( VLC_OBJECT(p_access), p_sys->fd, NULL ) ) == NULL ) + psz = net_Gets( p_access, p_sys->fd, NULL ); + if( psz == NULL ) { - msg_Err( p_access, "cannot read data" ); + msg_Err( p_access, "cannot read data 0" ); return VLC_EGENERIC; } + if( atoi( &psz[9] ) >= 400 ) { msg_Err( p_access, "error: %s", psz ); @@ -741,7 +859,7 @@ static int Start( access_t *p_access, off_t i_pos ) char *psz = net_Gets( p_access, p_sys->fd, NULL ); if( psz == NULL ) { - msg_Err( p_access, "cannot read data" ); + msg_Err( p_access, "cannot read data 1" ); return VLC_EGENERIC; } if( *psz == '\0' ) @@ -760,7 +878,7 @@ static int Start( access_t *p_access, off_t i_pos ) } /***************************************************************************** - * + * closing stream *****************************************************************************/ static void Stop( access_t *p_access ) { @@ -775,7 +893,7 @@ static void Stop( access_t *p_access ) } /***************************************************************************** - * + * get packet *****************************************************************************/ static int GetPacket( access_t * p_access, chunk_t *p_ck ) { @@ -791,8 +909,11 @@ static int GetPacket( access_t * p_access, chunk_t *p_ck ) * (4 bytes), decode and then read up to 8 additional bytes to get the * entire header. */ - if( net_Read( p_access, p_sys->fd, NULL, p_sys->buffer, 4, VLC_TRUE ) < 4 ) + if( net_Read( p_access, p_sys->fd, NULL, p_sys->buffer, 4, true ) < 4 ) + { + msg_Err( p_access, "cannot read data 2" ); return VLC_EGENERIC; + } p_ck->i_type = GetWLE( p_sys->buffer); p_ck->i_size = GetWLE( p_sys->buffer + 2); @@ -801,9 +922,9 @@ static int GetPacket( access_t * p_access, chunk_t *p_ck ) if( restsize > 8 ) restsize = 8; - if( net_Read( p_access, p_sys->fd, NULL, p_sys->buffer + 4, restsize, VLC_TRUE ) < restsize ) + if( net_Read( p_access, p_sys->fd, NULL, p_sys->buffer + 4, restsize, true ) < restsize ) { - msg_Err( p_access, "cannot read data" ); + msg_Err( p_access, "cannot read data 3" ); return VLC_EGENERIC; } p_ck->i_sequence = GetDWLE( p_sys->buffer + 4); @@ -848,9 +969,9 @@ static int GetPacket( access_t * p_access, chunk_t *p_ck ) 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) ) + p_ck->i_data, true ) < p_ck->i_data) ) { - msg_Err( p_access, "cannot read data" ); + msg_Err( p_access, "cannot read data 4" ); return VLC_EGENERIC; }