📄 http.c
字号:
/***************************************************************************** * http.c: HTTP input module ***************************************************************************** * Copyright (C) 2001-2005 VideoLAN * $Id: http.c 11534 2005-06-25 13:00:59Z courmisch $ * * Authors: Laurent Aimar <fenrir@via.ecp.fr> * Christophe Massiot <massiot@via.ecp.fr> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#include <stdlib.h>#include <vlc/vlc.h>#include <vlc/input.h>#include "vlc_playlist.h"#include "vlc_meta.h"#include "network.h"#include "vlc_tls.h"/***************************************************************************** * Module descriptor *****************************************************************************/static int Open ( vlc_object_t * );static void Close( vlc_object_t * );#define PROXY_TEXT N_("HTTP proxy")#define PROXY_LONGTEXT N_( \ "You can specify an HTTP proxy to use. It must be of the form " \ "http://myproxy.mydomain:myport/. If none is specified, the HTTP_PROXY " \ "environment variable will be tried." )#define CACHING_TEXT N_("Caching value in ms")#define CACHING_LONGTEXT N_( \ "Allows you to modify the default caching value for http streams. This " \ "value should be set in millisecond units." )#define USER_TEXT N_("HTTP user name")#define USER_LONGTEXT N_("Allows you to modify the user name that will " \ "be used for the connection (Basic authentication only).")#define PASS_TEXT N_("HTTP password")#define PASS_LONGTEXT N_("Allows you to modify the password that will be " \ "used for the connection.")#define AGENT_TEXT N_("HTTP user agent")#define AGENT_LONGTEXT N_("Allows you to modify the user agent that will be " \ "used for the connection.")#define RECONNECT_TEXT N_("Auto re-connect")#define RECONNECT_LONGTEXT N_("Will automatically attempt a re-connection " \ "in case it was untimely closed.")#define CONTINUOUS_TEXT N_("Continuous stream")#define CONTINUOUS_LONGTEXT N_("Enable this option to read a file that is " \ "being constantly updated (for example, a JPG file on a server)")vlc_module_begin(); set_description( _("HTTP input") ); set_capability( "access2", 0 ); set_shortname( _( "HTTP/HTTPS" ) ); set_category( CAT_INPUT ); set_subcategory( SUBCAT_INPUT_ACCESS ); add_string( "http-proxy", NULL, NULL, PROXY_TEXT, PROXY_LONGTEXT, VLC_FALSE ); add_integer( "http-caching", 4 * DEFAULT_PTS_DELAY / 1000, NULL, CACHING_TEXT, CACHING_LONGTEXT, VLC_TRUE ); add_string( "http-user", NULL, NULL, USER_TEXT, USER_LONGTEXT, VLC_FALSE ); add_string( "http-pwd", NULL , NULL, PASS_TEXT, PASS_LONGTEXT, VLC_FALSE ); add_string( "http-user-agent", COPYRIGHT_MESSAGE , NULL, AGENT_TEXT, AGENT_LONGTEXT, VLC_FALSE ); add_bool( "http-reconnect", 0, NULL, RECONNECT_TEXT, RECONNECT_LONGTEXT, VLC_TRUE ); add_bool( "http-continuous", 0, NULL, CONTINUOUS_TEXT, CONTINUOUS_LONGTEXT, VLC_TRUE ); add_shortcut( "http" ); add_shortcut( "http4" ); add_shortcut( "http6" ); add_shortcut( "https" ); add_shortcut( "unsv" ); set_callbacks( Open, Close );vlc_module_end();/***************************************************************************** * Local prototypes *****************************************************************************/struct access_sys_t{ int fd; tls_session_t *p_tls; v_socket_t *p_vs; /* From uri */ vlc_url_t url; char *psz_user; char *psz_passwd; char *psz_user_agent; /* Proxy */ vlc_bool_t b_proxy; vlc_url_t proxy; /* */ int i_code; char *psz_protocol; int i_version; char *psz_mime; char *psz_pragma; char *psz_location; vlc_bool_t b_mms; vlc_bool_t b_icecast; vlc_bool_t b_ssl; vlc_bool_t b_chunked; int64_t i_chunk; int i_icy_meta; char *psz_icy_name; char *psz_icy_genre; char *psz_icy_title; int i_remaining; vlc_bool_t b_seekable; vlc_bool_t b_reconnect; vlc_bool_t b_continuous; vlc_bool_t b_pace_control;};/* */static int Read( access_t *, uint8_t *, int );static int Seek( access_t *, int64_t );static int Control( access_t *, int, va_list );/* */static void ParseURL( access_sys_t *, char *psz_url );static int Connect( access_t *, int64_t );static int Request( access_t *p_access, int64_t i_tell );static void Disconnect( access_t * );/***************************************************************************** * Open: *****************************************************************************/static int Open( vlc_object_t *p_this ){ access_t *p_access = (access_t*)p_this; access_sys_t *p_sys; char *psz; /* First set ipv4/ipv6 */ var_Create( p_access, "ipv4", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); var_Create( p_access, "ipv6", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); if( *p_access->psz_access ) { vlc_value_t val; /* Find out which shortcut was used */ if( !strncmp( p_access->psz_access, "http4", 6 ) ) { val.b_bool = VLC_TRUE; var_Set( p_access, "ipv4", val ); val.b_bool = VLC_FALSE; var_Set( p_access, "ipv6", val ); } else if( !strncmp( p_access->psz_access, "http6", 6 ) ) { val.b_bool = VLC_TRUE; var_Set( p_access, "ipv6", val ); val.b_bool = VLC_FALSE; var_Set( p_access, "ipv4", val ); } } /* Set up p_access */ p_access->pf_read = Read; p_access->pf_block = NULL; p_access->pf_control = Control; p_access->pf_seek = Seek; p_access->info.i_update = 0; p_access->info.i_size = 0; p_access->info.i_pos = 0; p_access->info.b_eof = VLC_FALSE; p_access->info.i_title = 0; p_access->info.i_seekpoint = 0; p_access->p_sys = p_sys = malloc( sizeof( access_sys_t ) ); memset( p_sys, 0, sizeof( access_sys_t ) ); p_sys->fd = -1; p_sys->b_proxy = VLC_FALSE; p_sys->i_version = 1; p_sys->b_seekable = VLC_TRUE; p_sys->psz_mime = NULL; p_sys->psz_pragma = NULL; p_sys->b_mms = VLC_FALSE; p_sys->b_icecast = VLC_FALSE; p_sys->psz_location = NULL; p_sys->psz_user_agent = NULL; p_sys->b_pace_control = VLC_TRUE; p_sys->b_ssl = VLC_FALSE; p_sys->p_tls = NULL; p_sys->p_vs = NULL; p_sys->i_icy_meta = 0; p_sys->psz_icy_name = NULL; p_sys->psz_icy_genre = NULL; p_sys->psz_icy_title = NULL; p_sys->i_remaining = 0; /* Parse URI */ if( vlc_UrlIsNotEncoded( p_access->psz_path ) ) { psz = vlc_UrlEncode( p_access->psz_path ); if( psz == NULL ) { free( p_sys ); return VLC_ENOMEM; } ParseURL( p_sys, psz ); free( psz ); } else ParseURL( p_sys, p_access->psz_path ); if( p_sys->url.psz_host == NULL || *p_sys->url.psz_host == '\0' ) { msg_Warn( p_access, "invalid host" ); goto error; } if( !strncmp( p_access->psz_access, "https", 5 ) ) { /* SSL over HTTP */ p_sys->b_ssl = VLC_TRUE; if( p_sys->url.i_port <= 0 ) p_sys->url.i_port = 443; } else { if( p_sys->url.i_port <= 0 ) p_sys->url.i_port = 80; } if( !p_sys->psz_user || *p_sys->psz_user == '\0' ) { p_sys->psz_user = var_CreateGetString( p_access, "http-user" ); p_sys->psz_passwd = var_CreateGetString( p_access, "http-pwd" ); } /* Do user agent */ p_sys->psz_user_agent = var_CreateGetString( p_access, "http-user-agent" ); /* Check proxy */ psz = var_CreateGetString( p_access, "http-proxy" ); if( *psz ) { p_sys->b_proxy = VLC_TRUE; vlc_UrlParse( &p_sys->proxy, psz, 0 ); }#ifdef HAVE_GETENV else { char *psz_proxy = getenv( "http_proxy" ); if( psz_proxy && *psz_proxy ) { p_sys->b_proxy = VLC_TRUE; vlc_UrlParse( &p_sys->proxy, psz_proxy, 0 ); } }#endif free( psz ); if( p_sys->b_proxy ) { if( p_sys->proxy.psz_host == NULL || *p_sys->proxy.psz_host == '\0' ) { msg_Warn( p_access, "invalid proxy host" ); goto error; } if( p_sys->proxy.i_port <= 0 ) { p_sys->proxy.i_port = 80; } } msg_Dbg( p_access, "http: server='%s' port=%d file='%s", p_sys->url.psz_host, p_sys->url.i_port, p_sys->url.psz_path ); if( p_sys->b_proxy ) { msg_Dbg( p_access, " proxy %s:%d", p_sys->proxy.psz_host, p_sys->proxy.i_port ); } if( p_sys->psz_user && *p_sys->psz_user ) { msg_Dbg( p_access, " user='%s', pwd='%s'", p_sys->psz_user, p_sys->psz_passwd ); } p_sys->b_reconnect = var_CreateGetBool( p_access, "http-reconnect" ); p_sys->b_continuous = var_CreateGetBool( p_access, "http-continuous" ); /* Connect */ if( Connect( p_access, 0 ) ) { /* Retry with http 1.0 */ p_sys->i_version = 0; if( p_access->b_die || Connect( p_access, 0 ) ) { goto error; } } if( ( p_sys->i_code == 301 || p_sys->i_code == 302 || p_sys->i_code == 303 || p_sys->i_code == 307 ) && p_sys->psz_location && *p_sys->psz_location ) { playlist_t * p_playlist; input_item_t *p_input_item; msg_Dbg( p_access, "redirection to %s", p_sys->psz_location ); p_playlist = vlc_object_find( p_access, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); if( !p_playlist ) { msg_Err( p_access, "redirection failed: can't find playlist" ); goto error; } /* Change the uri */ vlc_mutex_lock( &p_playlist->object_lock ); p_input_item = &p_playlist->status.p_item->input; vlc_mutex_lock( &p_input_item->lock ); free( p_input_item->psz_uri ); free( p_access->psz_path ); p_input_item->psz_uri = strdup( p_sys->psz_location ); p_access->psz_path = strdup( p_sys->psz_location ); vlc_mutex_unlock( &p_input_item->lock ); vlc_mutex_unlock( &p_playlist->object_lock ); vlc_object_release( p_playlist ); /* Clean up current Open() run */ vlc_UrlClean( &p_sys->url ); vlc_UrlClean( &p_sys->proxy ); if( p_sys->psz_mime ) free( p_sys->psz_mime ); if( p_sys->psz_pragma ) free( p_sys->psz_pragma ); if( p_sys->psz_location ) free( p_sys->psz_location ); if( p_sys->psz_user_agent ) free( p_sys->psz_user_agent ); if( p_sys->psz_user ) free( p_sys->psz_user ); if( p_sys->psz_passwd ) free( p_sys->psz_passwd ); Disconnect( p_access ); free( p_sys ); /* Do new Open() run with new data */ return Open( p_this ); } if( p_sys->b_mms ) { msg_Dbg( p_access, "This is actually a live mms server, BAIL" ); goto error; } if( !strcmp( p_sys->psz_protocol, "ICY" ) || p_sys->b_icecast ) { if( p_sys->psz_mime && strcasecmp( p_sys->psz_mime, "application/ogg" ) ) { if( !strcasecmp( p_sys->psz_mime, "video/nsv" ) || !strcasecmp( p_sys->psz_mime, "video/nsa" ) ) p_access->psz_demux = strdup( "nsv" ); else if( !strcasecmp( p_sys->psz_mime, "audio/aac" ) || !strcasecmp( p_sys->psz_mime, "audio/aacp" ) ) p_access->psz_demux = strdup( "m4a" ); else if( !strcasecmp( p_sys->psz_mime, "audio/mpeg" ) ) p_access->psz_demux = strdup( "mp3" ); msg_Info( p_access, "Raw-audio server found, %s demuxer selected", p_access->psz_demux );#if 0 /* Doesn't work really well because of the pre-buffering in * shoutcast servers (the buffer content will be sent as fast as * possible). */ p_sys->b_pace_control = VLC_FALSE;#endif } else if( !p_sys->psz_mime ) { /* Shoutcast */ p_access->psz_demux = strdup( "mp3" ); } /* else probably Ogg Vorbis */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -