-
- if( i_recv < 0 )
- {
- msg_Err( p_input, "recv failed (%s)", strerror(errno) );
- }
-
- return i_recv;
- }
-
- return 0;
-
-#endif
-}
-
-static void asf_HeaderParse( mms_stream_t stream[128],
- uint8_t *p_header, int i_header )
-{
- var_buffer_t buffer;
- guid_t guid;
- uint64_t i_size;
- int i;
-
- for( i = 0; i < 128; i++ )
- {
- stream[i].i_cat = MMS_STREAM_UNKNOWN;
- }
-
- var_buffer_initread( &buffer, p_header, i_header );
-
- var_buffer_getguid( &buffer, &guid );
- if( !CmpGuid( &guid, &asf_object_header_guid ) )
- {
-// XXX Error
- }
- var_buffer_getmemory( &buffer, NULL, 30 - 16 );
-
- for( ;; )
- {
- if( var_buffer_readempty( &buffer ) )
- {
- return;
- }
-
- var_buffer_getguid( &buffer, &guid );
- i_size = var_buffer_get64( &buffer );
- if( CmpGuid( &guid, &asf_object_stream_properties_guid ) )
- {
- int i_stream_id;
- guid_t stream_type;
-
-// msg_Dbg( p_input, "found stream_properties" );
-
- var_buffer_getguid( &buffer, &stream_type );
- var_buffer_getmemory( &buffer, NULL, 32 );
- i_stream_id = var_buffer_get8( &buffer ) & 0x7f;
- var_buffer_getmemory( &buffer, NULL, i_size - 24 - 32 - 16 - 1 );
-
- if( CmpGuid( &stream_type, &asf_object_stream_type_video ) )
- {
-// msg_Dbg( p_input, "video stream[%d] found", i_stream_id );
- stream[i_stream_id].i_cat = MMS_STREAM_VIDEO;
- }
- else if( CmpGuid( &stream_type, &asf_object_stream_type_audio ) )
- {
-// msg_Dbg( p_input, "audio stream[%d] found", i_stream_id );
- stream[i_stream_id].i_cat = MMS_STREAM_AUDIO;
- }
- else
- {
-// msg_Dbg( p_input, "unknown stream[%d] found", i_stream_id );
- stream[i_stream_id].i_cat = MMS_STREAM_UNKNOWN;
- }
- }
- else if ( CmpGuid( &guid, &asf_object_bitrate_properties_guid ) )
- {
- int i_count;
- uint8_t i_stream_id;
-
- i_count = var_buffer_get16( &buffer );
- i_size -= 2;
- while( i_count > 0 )
- {
- i_stream_id = var_buffer_get16( &buffer )&0x7f;
- stream[i_stream_id].i_bitrate = var_buffer_get32( &buffer );
- i_count--;
- i_size -= 6;
- }
- var_buffer_getmemory( &buffer, NULL, i_size - 24 );
- }
- else
- {
- // skip unknown guid
- var_buffer_getmemory( &buffer, NULL, i_size - 24 );
- }
- }
-}
-
-/****************************************************************************
- * MMSOpen : Open a connection with the server over mmst or mmsu(not yet)
- ****************************************************************************/
-static int MMSOpen( input_thread_t *p_input,
- url_t *p_url,
- int i_proto,
- char *psz_network ) /* "", "ipv4", "ipv6" */
-{
- module_t *p_network;
- access_t *p_access = (access_t*)p_input->p_access_data;
-
- network_socket_t socket_desc;
- int b_udp = ( i_proto == MMS_PROTO_UDP ) ? 1 : 0;
-
- var_buffer_t buffer;
- char tmp[4096];
- uint16_t *p;
- int i_server_version;
- int i_tool_version;
- int i_update_player_url;
- int i_encryption_type;
- int i;
- int i_streams;
- int i_first;
- int b_audio;
- int b_video;
-
-
- /* *** Open a TCP connection with server *** */
- msg_Dbg( p_input, "waiting for connection..." );
- socket_desc.i_type = NETWORK_TCP;
- socket_desc.psz_server_addr = p_url->psz_server_addr;
- socket_desc.i_server_port = p_url->i_server_port;
- socket_desc.psz_bind_addr = "";
- socket_desc.i_bind_port = 0;
- p_input->p_private = (void*)&socket_desc;
- if( !( p_network = module_Need( p_input, "network", psz_network ) ) )
- {
- msg_Err( p_input, "failed to open a connection" );
- return( -1 );
- }
- module_Unneed( p_input, p_network );
- p_access->socket_server.i_handle = socket_desc.i_handle;
- p_input->i_mtu = socket_desc.i_mtu; // FIXME
- msg_Dbg( p_input,
- "connection with \"%s:%d\" successful",
- p_url->psz_server_addr,
- p_url->i_server_port );
-
- /* *** Bind port if UDP protocol is selected *** */
- // TODO
- if( b_udp )
- {
- msg_Err( p_input,
- "MMS/UDP not yet implemented" );
- // close socket
-#if defined( UNDER_CE )
- CloseHandle( (HANDLE)p_access->socket_server.i_handle );
-#elif defined( WIN32 )
- closesocket( p_access->socket_server.i_handle );
-#else
- close( p_access->socket_server.i_handle );
-#endif
- return( -1 );
- }
-
- /* *** Init context for mms prototcol *** */
- GenerateGuid( &p_access->guid ); // used to identify client by server
- msg_Dbg( p_input,
- "generated guid: "GUID_FMT,
- GUID_PRINT( p_access->guid ) );
- p_access->i_command_level = 1; // updated after 0x1A command
- p_access->i_seq_num = 0;
- p_access->i_media_packet_id_type = 0x04;
- p_access->i_header_packet_id_type = 0x02;
- p_access->i_proto = i_proto;
- p_access->i_packet_seq_num = 0;
- p_access->p_header = NULL;
- p_access->i_header = 0;
- p_access->p_media = NULL;
- p_access->i_media = 0;
- p_access->i_media_used = 0;
-
- p_access->i_pos = 0;
-
- /* *** send command 1 : connection request *** */
- var_buffer_initwrite( &buffer, 0 );
- var_buffer_add16( &buffer, 0x001c );
- var_buffer_add16( &buffer, 0x0003 );
- sprintf( tmp,
- "NSPlayer/7.0.0.1956; {"GUID_FMT"}; Host: %s",
- GUID_PRINT( p_access->guid ),
- p_url->psz_server_addr );
- var_buffer_addUTF16( &buffer, tmp );
-
- mms_CommandSend( p_input,
- 0x01, /* connexion request */
- 0x00000000, /* flags, FIXME */
- 0x0004000b, /* ???? */
- buffer.p_data,
- buffer.i_data );
-
- mms_CommandRead( p_input, 0x01, 0 );
- i_server_version = GetDWLE( p_access->p_cmd + MMS_CMD_HEADERSIZE + 32 );
- i_tool_version = GetDWLE( p_access->p_cmd + MMS_CMD_HEADERSIZE + 36 );
- i_update_player_url = GetDWLE( p_access->p_cmd + MMS_CMD_HEADERSIZE + 40 );
- i_encryption_type = GetDWLE( p_access->p_cmd + MMS_CMD_HEADERSIZE + 44 );
- p = (uint16_t*)( p_access->p_cmd + MMS_CMD_HEADERSIZE + 48 );
-#define GETUTF16( psz, size ) \
- { \
- int i; \
- psz = malloc( size + 1); \
- for( i = 0; i < size; i++ ) \
- { \
- psz[i] = p[i]; \
- } \
- psz[size] = '\0'; \
- p += 2 * ( size ); \
- }
- GETUTF16( p_access->psz_server_version, i_server_version );
- GETUTF16( p_access->psz_tool_version, i_tool_version );
- GETUTF16( p_access->psz_update_player_url, i_update_player_url );
- GETUTF16( p_access->psz_encryption_type, i_encryption_type );
-#undef GETUTF16
- msg_Dbg( p_input,
- "0x01 --> server_version:\"%s\" tool_version:\"%s\" update_player_url:\"%s\" encryption_type:\"%s\"",
- p_access->psz_server_version,
- p_access->psz_tool_version,
- p_access->psz_update_player_url,
- p_access->psz_encryption_type );
-
- /* *** should make an 18 command to make data timing *** */
-
- /* *** send command 2 : transport protocol selection *** */
- var_buffer_reinitwrite( &buffer, 0 );
- var_buffer_add32( &buffer, 0x00000000 );
- var_buffer_add32( &buffer, 0x000a0000 );
- var_buffer_add32( &buffer, 0x00000002 );
- // FIXME wrong for UDP FIXME
- sprintf( tmp, "\\\\127.0.0.1\\%s\\1242", b_udp ? "UDP" : "TCP" );
- var_buffer_addUTF16( &buffer, tmp );
- var_buffer_add16( &buffer, '0' );
-
- mms_CommandSend( p_input,
- 0x02, /* connexion request */
- 0x00000000, /* flags, FIXME */
- 0xffffffff, /* ???? */
- buffer.p_data,
- buffer.i_data );
-
- /* *** response from server, should be 0x02 or 0x03 *** */
- mms_CommandRead( p_input, 0x02, 0 );
- if( p_access->i_command == 0x03 )
- {
- msg_Err( p_input,
- "%s protocol selection failed", b_udp ? "UDP" : "TCP" );
- var_buffer_free( &buffer );
- MMSClose( p_input );
- return( -1 );
- }
- else if( p_access->i_command != 0x02 )
- {
- msg_Warn( p_input, "received command isn't 0x02 in reponse to 0x02" );
- }
-
- /* *** send command 5 : media file name/path requested *** */
- var_buffer_reinitwrite( &buffer, 0 );
- var_buffer_add64( &buffer, 0 );
-// var_buffer_addUTF16( &buffer, "/" );
- var_buffer_addUTF16( &buffer, p_url->psz_path );
-
- mms_CommandSend( p_input,
- 0x05,
- p_access->i_command_level,
- 0xffffffff,
- buffer.p_data,
- buffer.i_data );
-
- /* *** wait for reponse *** */
- mms_CommandRead( p_input, 0x1a, 0x06 );
-
- /* test if server send 0x1A answer */
- if( p_access->i_command == 0x1A )
- {
- msg_Err( p_input, "id/password requested (not yet supported)" );
- // FIXME
- var_buffer_free( &buffer );
- MMSClose( p_input );
- return( -1 );
- }
- if( p_access->i_command != 0x06 )
- {
- msg_Err( p_input,
- "unknown answer (0x%x instead of 0x06)",
- p_access->i_command );
- var_buffer_free( &buffer );
- MMSClose( p_input );
- return( -1 );
- }
-
- // 1 for file ok, 2 for authen ok
- switch( GetDWLE( p_access->p_cmd + MMS_CMD_HEADERSIZE ) )
- {
- case 0x0001:
- msg_Dbg( p_input, "Media file name/path accepted" );
- break;
- case 0x0002:
- msg_Dbg( p_input, "Authentication accepted" );
- break;
- case -1:
- default:
- msg_Err( p_input, "error while asking for file %d",
- GetDWLE( p_access->p_cmd + MMS_CMD_HEADERSIZE ) );
- var_buffer_free( &buffer );
- MMSClose( p_input );
- return( -1 );
- }
-
- p_access->i_flags_broadcast =
- GetDWLE( p_access->p_cmd + MMS_CMD_HEADERSIZE + 12 );
- p_access->i_media_length =
- GetDWLE( p_access->p_cmd + MMS_CMD_HEADERSIZE + 24 );
- p_access->i_packet_length =
- GetDWLE( p_access->p_cmd + MMS_CMD_HEADERSIZE + 44 );
- p_access->i_packet_count =
- GetDWLE( p_access->p_cmd + MMS_CMD_HEADERSIZE + 48 );
- p_access->i_max_bit_rate =
- GetDWLE( p_access->p_cmd + MMS_CMD_HEADERSIZE + 56 );
- p_access->i_header_size =
- GetDWLE( p_access->p_cmd + MMS_CMD_HEADERSIZE + 60 );
-
- msg_Dbg( p_input,
- "answer 0x06 flags:0x%8.8x media_length:%ds packet_length:%d packet_count:%d max_bit_rate:%d header_size:%d",
- p_access->i_flags_broadcast,
- p_access->i_media_length,
- p_access->i_packet_length,
- p_access->i_packet_count,
- p_access->i_max_bit_rate,
- p_access->i_header_size );
-
- /* *** send command 15 *** */
-
- var_buffer_reinitwrite( &buffer, 0 );
- var_buffer_add32( &buffer, 0 );
- var_buffer_add32( &buffer, 0x8000 );
- var_buffer_add32( &buffer, 0xffffffff );
- var_buffer_add32( &buffer, 0x00 );
- var_buffer_add32( &buffer, 0x00 );
- var_buffer_add32( &buffer, 0x00 );
- var_buffer_add64( &buffer, 0x40ac200000000000 );
- var_buffer_add32( &buffer, p_access->i_header_packet_id_type );
- mms_CommandSend( p_input, 0x15, p_access->i_command_level, 0x00,
- buffer.p_data, buffer.i_data );
-
- /* *** wait for reponse *** */
- mms_CommandRead( p_input, 0x11, 0 );
-
- if( p_access->i_command != 0x11 )
- {
- msg_Err( p_input,
- "unknown answer (0x%x instead of 0x11)",
- p_access->i_command );
- var_buffer_free( &buffer );
- MMSClose( p_input );
- return( -1 );
- }
- /* *** now read header packet *** */
- if( mms_HeaderMediaRead( p_input, MMS_PACKET_HEADER ) < 0 )
- {
- msg_Err( p_input, "cannot receive header" );
- var_buffer_free( &buffer );
- MMSClose( p_input );
- return( -1 );
- }
- /* *** parse header and get stream and their id *** */
- // get all streams properties,
- //
- // TODO : stream bitrates properties(optional)
- // and bitrate mutual exclusion(optional)
- asf_HeaderParse( p_access->stream,
- p_access->p_header, p_access->i_header );
-
- /* *** now select stream we want to receive *** */
- // TODO take care of stream bitrate TODO
- i_streams = 0;
- i_first = -1;
- var_buffer_reinitwrite( &buffer, 0 );
- /* for now, select first audio and video stream */
- b_audio = 0;
- b_video = 0;
- for( i = 1; i < 128; i++ )
- {
-
- if( ( p_access->stream[i].i_cat == MMS_STREAM_AUDIO && !b_audio )||
- ( p_access->stream[i].i_cat == MMS_STREAM_VIDEO && !b_video ) )