mmsh.c

来自「VLC媒体播放程序」· C语言 代码 · 共 861 行 · 第 1/2 页

C
861
字号
            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 ){    access_sys_t *p_sys = p_input->p_access_data;    uint8_t *p;    int i_streams = 0;    int i;    http_answer_t *p_ans;    msg_Dbg( p_input, "starting stream" );    if( ( p_sys->fd = net_OpenTCP( p_input, p_sys->p_url->psz_host,                                            p_sys->p_url->i_port ) ) < 0 )    {        /* should not occur */        msg_Err( p_input, "cannot connect to the server" );        return VLC_EGENERIC;    }    for( i = 1; i < 128; i++ )    {        if( p_sys->asfh.stream[i].i_selected )        {            i_streams++;        }    }    if( i_streams <= 0 )    {        msg_Err( p_input, "no stream selected" );        return VLC_EGENERIC;    }    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 )    {        p += sprintf( p,"Pragma: no-cache,rate=1.000000,request-context=%d\r\n",                      p_sys->i_request_context++ );    }    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",                         (uint32_t)((i_pos >> 32)&0xffffffff),                         (uint32_t)(i_pos&0xffffffff),                         p_sys->i_request_context++ );    }    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++ )    {        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" );    /* 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;        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 )            {                break;            }            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" ) )        {            msg_Dbg( p_input, "body found" );            break;        }        if( p_sys->i_buffer >= BUFFER_SIZE - 1024 )        {            msg_Dbg( p_input, "buffer size exeded" );            break;        }    }    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;    }    if( p_ans->i_error < 200 || p_ans->i_error >= 300 )    {        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;    }    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" );    net_Close( p_sys->fd ); p_sys->fd = -1;}/***************************************************************************** * *****************************************************************************/static int mmsh_get_packet( input_thread_t * p_input, chunk_t *p_ck ){    access_sys_t *p_sys = p_input->p_access_data;    int i_mov = p_sys->i_buffer - p_sys->i_buffer_pos;    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 );        }        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;    }    chunk_parse( p_ck, &p_sys->buffer[p_sys->i_buffer_pos],                 p_sys->i_buffer - p_sys->i_buffer_pos );    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;    }    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 ?" );    }    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;    p_sys->i_buffer_pos += 12 + p_ck->i_data;    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;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?