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 + -
显示快捷键?