📄 http.c
字号:
p_access->info.i_size = 0; p_access->info.i_pos = i_tell; p_access->info.b_eof = VLC_FALSE; /* Open connection */ p_sys->fd = net_ConnectTCP( p_access, srv.psz_host, srv.i_port ); if( p_sys->fd < 0 ) { msg_Err( p_access, "cannot connect to %s:%d", srv.psz_host, srv.i_port ); return VLC_EGENERIC; } /* Initialize TLS/SSL session */ if( p_sys->b_ssl == VLC_TRUE ) { /* CONNECT to establish TLS tunnel through HTTP proxy */ if( p_sys->b_proxy ) { char *psz; unsigned i_status = 0; if( p_sys->i_version == 0 ) { /* CONNECT is not in HTTP/1.0 */ Disconnect( p_access ); return VLC_EGENERIC; } net_Printf( VLC_OBJECT(p_access), p_sys->fd, NULL, "CONNECT %s:%d HTTP/1.%d\r\nHost: %s:%d\r\n\r\n", p_sys->url.psz_host, p_sys->url.i_port, p_sys->i_version, p_sys->url.psz_host, p_sys->url.i_port); psz = net_Gets( VLC_OBJECT(p_access), p_sys->fd, NULL ); if( psz == NULL ) { msg_Err( p_access, "cannot establish HTTP/TLS tunnel" ); Disconnect( p_access ); return VLC_EGENERIC; } sscanf( psz, "HTTP/%*u.%*u %3u", &i_status ); free( psz ); if( ( i_status / 100 ) != 2 ) { msg_Err( p_access, "HTTP/TLS tunnel through proxy denied" ); Disconnect( p_access ); return VLC_EGENERIC; } do { psz = net_Gets( VLC_OBJECT(p_access), p_sys->fd, NULL ); if( psz == NULL ) { msg_Err( p_access, "HTTP proxy connection failed" ); Disconnect( p_access ); return VLC_EGENERIC; } if( *psz == '\0' ) i_status = 0; free( psz ); } while( i_status ); } /* TLS/SSL handshake */ p_sys->p_tls = tls_ClientCreate( VLC_OBJECT(p_access), p_sys->fd, srv.psz_host ); if( p_sys->p_tls == NULL ) { msg_Err( p_access, "cannot establish HTTP/TLS session" ); Disconnect( p_access ); return VLC_EGENERIC; } p_sys->p_vs = &p_sys->p_tls->sock; } return Request( p_access, i_tell );}static int Request( access_t *p_access, int64_t i_tell ){ access_sys_t *p_sys = p_access->p_sys; char *psz ; v_socket_t *pvs = p_sys->p_vs; if( p_sys->b_proxy ) { if( p_sys->url.psz_path ) { net_Printf( VLC_OBJECT(p_access), p_sys->fd, NULL, "GET http://%s:%d%s HTTP/1.%d\r\n", p_sys->url.psz_host, p_sys->url.i_port, p_sys->url.psz_path, p_sys->i_version ); } else { net_Printf( VLC_OBJECT(p_access), p_sys->fd, NULL, "GET http://%s:%d/ HTTP/1.%d\r\n", p_sys->url.psz_host, p_sys->url.i_port, p_sys->i_version ); } } else { char *psz_path = p_sys->url.psz_path; if( !psz_path || !*psz_path ) { psz_path = "/"; } if( p_sys->url.i_port != 80) { net_Printf( VLC_OBJECT(p_access), p_sys->fd, pvs, "GET %s HTTP/1.%d\r\nHost: %s:%d\r\n", psz_path, p_sys->i_version, p_sys->url.psz_host, p_sys->url.i_port ); } else { net_Printf( VLC_OBJECT(p_access), p_sys->fd, pvs, "GET %s HTTP/1.%d\r\nHost: %s\r\n", psz_path, p_sys->i_version, p_sys->url.psz_host ); } } /* User Agent */ net_Printf( VLC_OBJECT(p_access), p_sys->fd, pvs, "User-Agent: %s\r\n", p_sys->psz_user_agent ); /* Offset */ if( p_sys->i_version == 1 ) { net_Printf( VLC_OBJECT(p_access), p_sys->fd, pvs, "Range: bytes="I64Fd"-\r\n", i_tell ); } /* Authentication */ if( p_sys->url.psz_username && *p_sys->url.psz_username ) { char *buf; char *b64; asprintf( &buf, "%s:%s", p_sys->url.psz_username, p_sys->url.psz_password ? p_sys->url.psz_password : "" ); b64 = vlc_b64_encode( buf ); free( buf ); net_Printf( VLC_OBJECT(p_access), p_sys->fd, pvs, "Authorization: Basic %s\r\n", b64 ); free( b64 ); } /* Proxy Authentication */ if( p_sys->proxy.psz_username && *p_sys->proxy.psz_username ) { char *buf; char *b64; asprintf( &buf, "%s:%s", p_sys->proxy.psz_username, p_sys->proxy.psz_password ? p_sys->proxy.psz_password : "" ); b64 = vlc_b64_encode( buf ); free( buf ); net_Printf( VLC_OBJECT(p_access), p_sys->fd, pvs, "Proxy-Authorization: Basic %s\r\n", b64 ); free( b64 ); } /* ICY meta data request */ net_Printf( VLC_OBJECT(p_access), p_sys->fd, pvs, "Icy-MetaData: 1\r\n" ); if( p_sys->b_continuous ) { net_Printf( VLC_OBJECT( p_access ), p_sys->fd, pvs, "Connection: Keep-Alive\r\n" ); } else if( p_sys->i_version == 1 ) { net_Printf( VLC_OBJECT( p_access ), p_sys->fd, pvs, "Connection: Close\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 = VLC_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 = VLC_FALSE; } if( p_sys->i_code != 206 ) { p_sys->b_seekable = VLC_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; } /* 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" ) ) { if( p_sys->b_continuous ) { p_access->info.i_size = -1; msg_Dbg( p_access, "this frame size="I64Fd, atoll(p ) ); p_sys->i_remaining = atoll( p ); } else { p_access->info.i_size = i_tell + atoll( p ); msg_Dbg( p_access, "stream size="I64Fd, p_access->info.i_size ); } } else if( !strcasecmp( psz, "Location" ) ) { if( p_sys->psz_location ) free( p_sys->psz_location ); p_sys->psz_location = strdup( p ); } else if( !strcasecmp( psz, "Content-Type" ) ) { if( p_sys->psz_mime ) 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, "Pragma" ) ) { if( !strcasecmp( psz, "Pragma: features" ) ) p_sys->b_mms = VLC_TRUE; if( p_sys->psz_pragma ) 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 = VLC_TRUE; p_sys->b_pace_control = VLC_FALSE; p_sys->b_icecast = VLC_TRUE; } } else if( !strcasecmp( psz, "Transfer-Encoding" ) ) { msg_Dbg( p_access, "Transfer-Encoding: %s", p ); if( !strncasecmp( p, "chunked", 7 ) ) { p_sys->b_chunked = VLC_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; msg_Warn( p_access, "ICY metaint=%d", p_sys->i_icy_meta ); } else if( !strcasecmp( psz, "Icy-Name" ) ) { if( p_sys->psz_icy_name ) free( p_sys->psz_icy_name ); p_sys->psz_icy_name = strdup( p ); msg_Dbg( p_access, "Icy-Name: %s", p_sys->psz_icy_name ); p_sys->b_icecast = VLC_TRUE; /* be on the safeside. set it here as well. */ p_sys->b_reconnect = VLC_TRUE; p_sys->b_pace_control = VLC_FALSE; } else if( !strcasecmp( psz, "Icy-Genre" ) ) { if( p_sys->psz_icy_genre ) free( p_sys->psz_icy_genre ); p_sys->psz_icy_genre = 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 ); } free( psz ); } 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; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -