@ -110,6 +110,15 @@ static int http_open_cnx(URLContext *h)
path1 , sizeof ( path1 ) , s - > location ) ;
ff_url_join ( hoststr , sizeof ( hoststr ) , NULL , NULL , hostname , port , NULL ) ;
if ( ! strcmp ( proto , " https " ) ) {
lower_proto = " tls " ;
use_proxy = 0 ;
if ( port < 0 )
port = 443 ;
}
if ( port < 0 )
port = 80 ;
if ( path1 [ 0 ] = = ' \0 ' )
path = " / " ;
else
@ -124,13 +133,6 @@ static int http_open_cnx(URLContext *h)
av_url_split ( NULL , 0 , proxyauth , sizeof ( proxyauth ) ,
hostname , sizeof ( hostname ) , & port , NULL , 0 , proxy_path ) ;
}
if ( ! strcmp ( proto , " https " ) ) {
lower_proto = " tls " ;
if ( port < 0 )
port = 443 ;
}
if ( port < 0 )
port = 80 ;
ff_url_join ( buf , sizeof ( buf ) , lower_proto , NULL , hostname , port , NULL ) ;
err = ffurl_open ( & hd , buf , AVIO_FLAG_READ_WRITE ,
@ -413,10 +415,33 @@ static int http_connect(URLContext *h, const char *path, const char *local_path,
}
static int http_read ( URLContext * h , uint8_t * buf , int size )
static int http_buf_ read ( URLContext * h , uint8_t * buf , int size )
{
HTTPContext * s = h - > priv_data ;
int len ;
/* read bytes from input buffer first */
len = s - > buf_end - s - > buf_ptr ;
if ( len > 0 ) {
if ( len > size )
len = size ;
memcpy ( buf , s - > buf_ptr , len ) ;
s - > buf_ptr + = len ;
} else {
if ( ! s - > willclose & & s - > filesize > = 0 & & s - > off > = s - > filesize )
return AVERROR_EOF ;
len = ffurl_read ( s - > hd , buf , size ) ;
}
if ( len > 0 ) {
s - > off + = len ;
if ( s - > chunksize > 0 )
s - > chunksize - = len ;
}
return len ;
}
static int http_read ( URLContext * h , uint8_t * buf , int size )
{
HTTPContext * s = h - > priv_data ;
if ( s - > chunksize > = 0 ) {
if ( ! s - > chunksize ) {
@ -439,24 +464,7 @@ static int http_read(URLContext *h, uint8_t *buf, int size)
}
size = FFMIN ( size , s - > chunksize ) ;
}
/* read bytes from input buffer first */
len = s - > buf_end - s - > buf_ptr ;
if ( len > 0 ) {
if ( len > size )
len = size ;
memcpy ( buf , s - > buf_ptr , len ) ;
s - > buf_ptr + = len ;
} else {
if ( ! s - > willclose & & s - > filesize > = 0 & & s - > off > = s - > filesize )
return AVERROR_EOF ;
len = ffurl_read ( s - > hd , buf , size ) ;
}
if ( len > 0 ) {
s - > off + = len ;
if ( s - > chunksize > 0 )
s - > chunksize - = len ;
}
return len ;
return http_buf_read ( h , buf , size ) ;
}
/* used only when posting data */
@ -572,3 +580,118 @@ URLProtocol ff_https_protocol = {
. priv_data_class = & https_context_class ,
} ;
# endif
# if CONFIG_HTTPPROXY_PROTOCOL
static int http_proxy_close ( URLContext * h )
{
HTTPContext * s = h - > priv_data ;
if ( s - > hd )
ffurl_close ( s - > hd ) ;
return 0 ;
}
static int http_proxy_open ( URLContext * h , const char * uri , int flags )
{
HTTPContext * s = h - > priv_data ;
char hostname [ 1024 ] , hoststr [ 1024 ] ;
char auth [ 1024 ] , pathbuf [ 1024 ] , * path ;
char line [ 1024 ] , lower_url [ 100 ] ;
int port , ret = 0 ;
HTTPAuthType cur_auth_type ;
char * authstr ;
h - > is_streamed = 1 ;
av_url_split ( NULL , 0 , auth , sizeof ( auth ) , hostname , sizeof ( hostname ) , & port ,
pathbuf , sizeof ( pathbuf ) , uri ) ;
ff_url_join ( hoststr , sizeof ( hoststr ) , NULL , NULL , hostname , port , NULL ) ;
path = pathbuf ;
if ( * path = = ' / ' )
path + + ;
ff_url_join ( lower_url , sizeof ( lower_url ) , " tcp " , NULL , hostname , port ,
NULL ) ;
redo :
ret = ffurl_open ( & s - > hd , lower_url , AVIO_FLAG_READ_WRITE ,
& h - > interrupt_callback , NULL ) ;
if ( ret < 0 )
return ret ;
authstr = ff_http_auth_create_response ( & s - > proxy_auth_state , auth ,
path , " CONNECT " ) ;
snprintf ( s - > buffer , sizeof ( s - > buffer ) ,
" CONNECT %s HTTP/1.1 \r \n "
" Host: %s \r \n "
" Connection: close \r \n "
" %s%s "
" \r \n " ,
path ,
hoststr ,
authstr ? " Proxy- " : " " , authstr ? authstr : " " ) ;
av_freep ( & authstr ) ;
if ( ( ret = ffurl_write ( s - > hd , s - > buffer , strlen ( s - > buffer ) ) ) < 0 )
goto fail ;
s - > buf_ptr = s - > buffer ;
s - > buf_end = s - > buffer ;
s - > line_count = 0 ;
s - > filesize = - 1 ;
cur_auth_type = s - > proxy_auth_state . auth_type ;
for ( ; ; ) {
int new_loc ;
// Note: This uses buffering, potentially reading more than the
// HTTP header. If tunneling a protocol where the server starts
// the conversation, we might buffer part of that here, too.
// Reading that requires using the proper ffurl_read() function
// on this URLContext, not using the fd directly (as the tls
// protocol does). This shouldn't be an issue for tls though,
// since the client starts the conversation there, so there
// is no extra data that we might buffer up here.
if ( http_get_line ( s , line , sizeof ( line ) ) < 0 ) {
ret = AVERROR ( EIO ) ;
goto fail ;
}
av_dlog ( h , " header='%s' \n " , line ) ;
ret = process_line ( h , line , s - > line_count , & new_loc ) ;
if ( ret < 0 )
goto fail ;
if ( ret = = 0 )
break ;
s - > line_count + + ;
}
if ( s - > http_code = = 407 & & cur_auth_type = = HTTP_AUTH_NONE & &
s - > proxy_auth_state . auth_type ! = HTTP_AUTH_NONE ) {
ffurl_close ( s - > hd ) ;
s - > hd = NULL ;
goto redo ;
}
if ( s - > http_code < 400 )
return 0 ;
ret = AVERROR ( EIO ) ;
fail :
http_proxy_close ( h ) ;
return ret ;
}
static int http_proxy_write ( URLContext * h , const uint8_t * buf , int size )
{
HTTPContext * s = h - > priv_data ;
return ffurl_write ( s - > hd , buf , size ) ;
}
URLProtocol ff_httpproxy_protocol = {
. name = " httpproxy " ,
. url_open = http_proxy_open ,
. url_read = http_buf_read ,
. url_write = http_proxy_write ,
. url_close = http_proxy_close ,
. url_get_file_handle = http_get_file_handle ,
. priv_data_size = sizeof ( HTTPContext ) ,
} ;
# endif