📄 http.c
字号:
/* ICY meta data request */ net_Printf( VLC_OBJECT(p_access), p_sys->fd, pvs, "Icy-MetaData: 1\r\n" ); if( net_Printf( VLC_OBJECT(p_access), p_sys->fd, pvs, "\r\n" ) < 0 ) { msg_Err( p_access, "failed to send request" ); Disconnect( p_access ); return VLC_EGENERIC; } /* Read Answer */ if( ( psz = net_Gets( VLC_OBJECT(p_access), p_sys->fd, pvs ) ) == NULL ) { msg_Err( p_access, "failed to read answer" ); goto error; } if( !strncmp( psz, "HTTP/1.", 7 ) ) { p_sys->psz_protocol = "HTTP"; p_sys->i_code = atoi( &psz[9] ); } else if( !strncmp( psz, "ICY", 3 ) ) { p_sys->psz_protocol = "ICY"; p_sys->i_code = atoi( &psz[4] ); p_sys->b_reconnect = true; } else { msg_Err( p_access, "invalid HTTP reply '%s'", psz ); free( psz ); goto error; } msg_Dbg( p_access, "protocol '%s' answer code %d", p_sys->psz_protocol, p_sys->i_code ); if( !strcmp( p_sys->psz_protocol, "ICY" ) ) { p_sys->b_seekable = false; } if( p_sys->i_code != 206 && p_sys->i_code != 401 ) { p_sys->b_seekable = false; } /* Authentication error - We'll have to display the dialog */ if( p_sys->i_code == 401 ) { } /* Other fatal error */ else if( p_sys->i_code >= 400 ) { msg_Err( p_access, "error: %s", psz ); free( psz ); goto error; } free( psz ); for( ;; ) { char *psz = net_Gets( VLC_OBJECT(p_access), p_sys->fd, pvs ); char *p; if( psz == NULL ) { msg_Err( p_access, "failed to read answer" ); goto error; } if( !vlc_object_alive (p_access) || p_access->b_error ) { free( psz ); goto error; } /* msg_Dbg( p_input, "Line=%s", psz ); */ if( *psz == '\0' ) { free( psz ); break; } if( ( p = strchr( psz, ':' ) ) == NULL ) { msg_Err( p_access, "malformed header line: %s", psz ); free( psz ); goto error; } *p++ = '\0'; while( *p == ' ' ) p++; if( !strcasecmp( psz, "Content-Length" ) ) { int64_t i_size = i_tell + (p_sys->i_remaining = atoll( p )); if(i_size > p_access->info.i_size) { p_access->info.i_size = i_size; } msg_Dbg( p_access, "this frame size=%"PRId64, p_sys->i_remaining ); } else if( !strcasecmp( psz, "Content-Range" ) ) { int64_t i_ntell = i_tell; int64_t i_nend = (p_access->info.i_size > 0)?(p_access->info.i_size - 1):i_tell; int64_t i_nsize = p_access->info.i_size; sscanf(p,"bytes %"PRId64"-%"PRId64"/%"PRId64,&i_ntell,&i_nend,&i_nsize); if(i_nend > i_ntell ) { p_access->info.i_pos = i_ntell; p_sys->i_remaining = i_nend+1-i_ntell; int64_t i_size = (i_nsize > i_nend) ? i_nsize : (i_nend + 1); if(i_size > p_access->info.i_size) { p_access->info.i_size = i_size; } msg_Dbg( p_access, "stream size=%"PRId64",pos=%"PRId64",remaining=%"PRId64,i_nsize,i_ntell,p_sys->i_remaining); } } else if( !strcasecmp( psz, "Connection" ) ) { msg_Dbg( p_access, "Connection: %s",p ); int i = -1; sscanf(p, "close%n",&i); if( i >= 0 ) { p_sys->b_persist = false; } } else if( !strcasecmp( psz, "Location" ) ) { char * psz_new_loc; /* This does not follow RFC 2068, but yet if the url is not absolute, * handle it as everyone does. */ if( p[0] == '/' ) { const char *psz_http_ext = p_sys->b_ssl ? "s" : "" ; if( p_sys->url.i_port == ( p_sys->b_ssl ? 443 : 80 ) ) { if( asprintf(&psz_new_loc, "http%s://%s%s", psz_http_ext, p_sys->url.psz_host, p) < 0 ) goto error; } else { if( asprintf(&psz_new_loc, "http%s://%s:%d%s", psz_http_ext, p_sys->url.psz_host, p_sys->url.i_port, p) < 0 ) goto error; } } else { psz_new_loc = strdup( p ); } free( p_sys->psz_location ); p_sys->psz_location = psz_new_loc; } else if( !strcasecmp( psz, "Content-Type" ) ) { free( p_sys->psz_mime ); p_sys->psz_mime = strdup( p ); msg_Dbg( p_access, "Content-Type: %s", p_sys->psz_mime ); } else if( !strcasecmp( psz, "Content-Encoding" ) ) { msg_Dbg( p_access, "Content-Encoding: %s", p ); if( strcasecmp( p, "identity" ) )#ifdef HAVE_ZLIB_H p_sys->b_compressed = true;#else msg_Warn( p_access, "Compressed content not supported. Rebuild with zlib support." );#endif } else if( !strcasecmp( psz, "Pragma" ) ) { if( !strcasecmp( psz, "Pragma: features" ) ) p_sys->b_mms = true; free( p_sys->psz_pragma ); p_sys->psz_pragma = strdup( p ); msg_Dbg( p_access, "Pragma: %s", p_sys->psz_pragma ); } else if( !strcasecmp( psz, "Server" ) ) { msg_Dbg( p_access, "Server: %s", p ); if( !strncasecmp( p, "Icecast", 7 ) || !strncasecmp( p, "Nanocaster", 10 ) ) { /* Remember if this is Icecast * we need to force demux in this case without breaking * autodetection */ /* Let live 365 streams (nanocaster) piggyback on the icecast * routine. They look very similar */ p_sys->b_reconnect = true; p_sys->b_pace_control = false; p_sys->b_icecast = true; } } else if( !strcasecmp( psz, "Transfer-Encoding" ) ) { msg_Dbg( p_access, "Transfer-Encoding: %s", p ); if( !strncasecmp( p, "chunked", 7 ) ) { p_sys->b_chunked = true; } } else if( !strcasecmp( psz, "Icy-MetaInt" ) ) { msg_Dbg( p_access, "Icy-MetaInt: %s", p ); p_sys->i_icy_meta = atoi( p ); if( p_sys->i_icy_meta < 0 ) p_sys->i_icy_meta = 0; if( p_sys->i_icy_meta > 0 ) p_sys->b_icecast = true; msg_Warn( p_access, "ICY metaint=%d", p_sys->i_icy_meta ); } else if( !strcasecmp( psz, "Icy-Name" ) ) { free( p_sys->psz_icy_name ); p_sys->psz_icy_name = EnsureUTF8( strdup( p )); msg_Dbg( p_access, "Icy-Name: %s", p_sys->psz_icy_name ); p_sys->b_icecast = true; /* be on the safeside. set it here as well. */ p_sys->b_reconnect = true; p_sys->b_pace_control = false; } else if( !strcasecmp( psz, "Icy-Genre" ) ) { free( p_sys->psz_icy_genre ); p_sys->psz_icy_genre = EnsureUTF8( strdup( p )); msg_Dbg( p_access, "Icy-Genre: %s", p_sys->psz_icy_genre ); } else if( !strncasecmp( psz, "Icy-Notice", 10 ) ) { msg_Dbg( p_access, "Icy-Notice: %s", p ); } else if( !strncasecmp( psz, "icy-", 4 ) || !strncasecmp( psz, "ice-", 4 ) || !strncasecmp( psz, "x-audiocast", 11 ) ) { msg_Dbg( p_access, "Meta-Info: %s: %s", psz, p ); } else if( !strcasecmp( psz, "Set-Cookie" ) ) { if( p_sys->cookies ) { msg_Dbg( p_access, "Accepting Cookie: %s", p ); cookie_append( p_sys->cookies, strdup(p) ); } else msg_Dbg( p_access, "We have a Cookie we won't remember: %s", p ); } else if( !strcasecmp( psz, "www-authenticate" ) ) { msg_Dbg( p_access, "Authentication header: %s", p ); AuthParseHeader( p_access, p, &p_sys->auth ); } else if( !strcasecmp( psz, "proxy-authenticate" ) ) { msg_Dbg( p_access, "Proxy authentication header: %s", p ); AuthParseHeader( p_access, p, &p_sys->proxy_auth ); } else if( !strcasecmp( psz, "authentication-info" ) ) { msg_Dbg( p_access, "Authentication Info header: %s", p ); if( AuthCheckReply( p_access, p, &p_sys->url, &p_sys->auth ) ) goto error; } else if( !strcasecmp( psz, "proxy-authentication-info" ) ) { msg_Dbg( p_access, "Proxy Authentication Info header: %s", p ); if( AuthCheckReply( p_access, p, &p_sys->proxy, &p_sys->proxy_auth ) ) goto error; } free( psz ); } /* We close the stream for zero length data, unless of course the * server has already promised to do this for us. */ if( p_access->info.i_size != -1 && p_sys->i_remaining == 0 && p_sys->b_persist ) { Disconnect( p_access ); } return VLC_SUCCESS;error: Disconnect( p_access ); return VLC_EGENERIC;}/***************************************************************************** * Disconnect: *****************************************************************************/static void Disconnect( access_t *p_access ){ access_sys_t *p_sys = p_access->p_sys; if( p_sys->p_tls != NULL) { tls_ClientDelete( p_sys->p_tls ); p_sys->p_tls = NULL; p_sys->p_vs = NULL; } if( p_sys->fd != -1) { net_Close(p_sys->fd); p_sys->fd = -1; }}/***************************************************************************** * Cookies (FIXME: we may want to rewrite that using a nice structure to hold * them) (FIXME: only support the "domain=" param) *****************************************************************************//* Get the NAME=VALUE part of the Cookie */static char * cookie_get_content( const char * cookie ){ char * ret = strdup( cookie ); if( !ret ) return NULL; char * str = ret; /* Look for a ';' */ while( *str && *str != ';' ) str++; /* Replace it by a end-char */ if( *str == ';' ) *str = 0; return ret;}/* Get the domain where the cookie is stored */static char * cookie_get_domain( const char * cookie ){ const char * str = cookie; static const char domain[] = "domain="; if( !str ) return NULL; /* Look for a ';' */ while( *str ) { if( !strncmp( str, domain, sizeof(domain) - 1 /* minus \0 */ ) ) { str += sizeof(domain) - 1 /* minus \0 */; char * ret = strdup( str ); /* Now remove the next ';' if present */ char * ret_iter = ret; while( *ret_iter && *ret_iter != ';' ) ret_iter++; if( *ret_iter == ';' ) *ret_iter = 0; return ret; } /* Go to next ';' field */ while( *str && *str != ';' ) str++; if( *str == ';' ) str++; /* skip blank */ while( *str && *str == ' ' ) str++; } return NULL;}/* Get NAME in the NAME=VALUE field */static char * cookie_get_name( const char * cookie ){ char * ret = cookie_get_content( cookie ); /* NAME=VALUE */ if( !ret ) return NULL; char * str = ret; while( *str && *str != '=' ) str++; *str = 0; return ret;}/* Add a cookie in cookies, checking to see how it should be added */static void cookie_append( vlc_array_t * cookies, char * cookie ){ int i; if( !cookie ) return; char * cookie_name = cookie_get_name( cookie ); /* Don't send invalid cookies */ if( !cookie_name ) return; char * cookie_domain = cookie_get_domain( cookie ); for( i = 0; i < vlc_array_count( cookies ); i++ ) { char * current_cookie = vlc_array_item_at_index( cookies, i ); char * current_cookie_name = cookie_get_name( current_cookie ); char * current_cookie_domain = cookie_get_domain( current_cookie ); assert( current_cookie_name ); bool is_domain_matching = ( cookie_domain && current_cookie_domain && !strcmp( cookie_domain, current_cookie_domain ) ); if( is_domain_matching && !strcmp( cookie_name, current_cookie_name ) ) { /* Remove previous value for this cookie */ free( current_cookie ); vlc_array_remove( cookies, i );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -