⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 downloader.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *					GPAC Multimedia Framework * *			Authors: Jean Le Feuvre *				Copyright (c) 2005-2005 ENST *					All rights reserved * *  This file is part of GPAC / common tools sub-project * *  GPAC is free software; you can redistribute it and/or modify *  it under the terms of the GNU Lesser General Public License as published by *  the Free Software Foundation; either version 2, or (at your option) *  any later version. *    *  GPAC 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 Lesser General Public License for more details. *    *  You should have received a copy of the GNU Lesser General Public *  License along with this library; see the file COPYING.  If not, write to *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  * */#include <gpac/download.h>#include <gpac/network.h>#include <gpac/token.h>#include <gpac/thread.h>#include <gpac/list.h>#include <gpac/base_coding.h>#ifdef WIN32//#define GPAC_HAS_SSL#endif#ifdef GPAC_HAS_SSL#include <openssl/ssl.h>#include <openssl/x509.h>#include <openssl/err.h>#include <openssl/rand.h>#endifstatic void gf_dm_connect(GF_DownloadSession *sess);#define GF_DOWNLOAD_AGENT_NAME		"GPAC/" GPAC_VERSION#define GF_DOWNLOAD_BUFFER_SIZE		8192/*internal flags*/enum{	GF_DOWNLOAD_SESSION_USE_SSL		=	1<<10,	GF_DOWNLOAD_SESSION_THREAD_DEAD	=	1<<11,	GF_DOWNLOAD_IS_ICY				=	1<<12,};struct __gf_download_session{	/*this is always 0 and helps differenciating downloads from other interfaces (interfaceType != 0)*/	u32 reserved;	struct __gf_download_manager *dm;	GF_Thread *th;	GF_Mutex *mx;	Bool in_callback, destroy;	char *server_name;	u16 port;	char *remote_path;	char *user;	char *passwd;	char cookie[GF_MAX_PATH];	FILE *cache;	char *cache_name;	/*cache size if existing*/	u32 cache_start_size;	GF_Socket *sock;	u32 num_retry, status;	char *mime_type;	u32 flags;	u32 total_size, bytes_done, start_time, icy_metaint, icy_count, icy_bytes;	u32 bytes_per_sec, window_start, bytes_in_wnd;	u32 limit_data_rate;		/*0: GET	  1: HEAD	  2: all the rest	*/	u32 http_read_type;	GF_Err last_error;	char *init_data;	u32 init_data_size;#ifdef GPAC_HAS_SSL	SSL *ssl;#endif	void (*do_requests)(struct __gf_download_session *);	/*callback for data reception - may not be NULL*/	gf_dm_user_io user_proc;	void *usr_cbk;	/*private extension*/	void *ext;};struct __gf_download_manager{	char *cache_directory;	char szCookieDir[GF_MAX_PATH];	Bool (*GetUserPassword)(void *usr_cbk, const char *site_url, char *usr_name, char *password);	void *usr_cbk;	GF_Config *cfg;	GF_List *sessions;#ifdef GPAC_HAS_SSL	SSL_CTX *ssl_ctx;#endif};#ifdef GPAC_HAS_SSLstatic void init_prng (void){	char namebuf[256];	const char *random_file;		if (RAND_status ()) return;	namebuf[0] = '\0';	random_file = RAND_file_name (namebuf, sizeof (namebuf));	if (random_file && *random_file)		RAND_load_file(random_file, 16384);		if (RAND_status ()) return;#ifdef WIN32	RAND_screen ();	if (RAND_status ())	return;#endif}static int ssl_init(GF_DownloadManager *dm, u32 mode){	SSL_METHOD *meth;		if (!dm) return 0;    /* The SSL has already been initialized. */	if (dm->ssl_ctx) return 1;	/* Init the PRNG.  If that fails, bail out.  */	init_prng();	if (RAND_status() != 1) goto error;	SSL_library_init();	SSL_load_error_strings();	SSLeay_add_all_algorithms();	SSLeay_add_ssl_algorithms();		switch (mode) {	case 0:		meth = SSLv23_client_method();		break;	case 1:		meth = SSLv2_client_method();		break;	case 2:		meth = SSLv3_client_method();		break;	case 3:		meth = TLSv1_client_method();		break;	default:		goto error;	}		dm->ssl_ctx = SSL_CTX_new(meth);	if (!dm->ssl_ctx) goto error;	SSL_CTX_set_default_verify_paths(dm->ssl_ctx);	SSL_CTX_load_verify_locations (dm->ssl_ctx, NULL, NULL);	/* SSL_VERIFY_NONE instructs OpenSSL not to abort SSL_connect if the     certificate is invalid.  We verify the certificate separately in     ssl_check_certificate, which provides much better diagnostics     than examining the error stack after a failed SSL_connect.  */	SSL_CTX_set_verify(dm->ssl_ctx, SSL_VERIFY_NONE, NULL);	/* Since fd_write unconditionally assumes partial writes (and handles them correctly), 	allow them in OpenSSL.  */	SSL_CTX_set_mode(dm->ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);	return 1;error:	if (dm->ssl_ctx) SSL_CTX_free(dm->ssl_ctx);	dm->ssl_ctx = NULL;	return 0;}#endifstatic Bool gf_dm_is_local(GF_DownloadManager *dm, const char *url){	if (!strnicmp(url, "file://", 7)) return 1;	if (!strnicmp(url, "file:///", 8)) return 1;	if (!strstr(url, "://")) return 1;	return 0;}static Bool gf_dm_can_handle_url(GF_DownloadManager *dm, const char *url){	if (!strnicmp(url, "http://", 7)) return 1;#ifdef GPAC_HAS_SSL	if (!strnicmp(url, "https://", 8)) return 1;#endif	return 0;}void gf_dm_configure_cache(GF_DownloadSession *sess){	u32 i, last_sep;	char cache_name[GF_MAX_PATH], tmp[GF_MAX_PATH];	const char *opt;	char *doubledots;	if (!sess->dm->cache_directory) return;	if (sess->flags & GF_NETIO_SESSION_NOT_CACHED) return;	strcpy(cache_name, sess->dm->cache_directory);	strcpy(tmp, sess->server_name);	while ( (doubledots = strchr(tmp, ':')) )		*doubledots = '_';	strcat(tmp, sess->remote_path);	last_sep = 0;	for (i=0; i<strlen(tmp); i++) {		if (tmp[i] == '/') tmp[i] = '_';		else if (tmp[i] == '.') {			tmp[i] = '_';			last_sep = i;		}	}	if (last_sep) tmp[last_sep] = '.';	strcat(cache_name, tmp);	/*first try, check cached file*/	if (!sess->cache_start_size) {		/*if file present figure out how much of the file is downloaded - we assume 2^31 byte file max*/		FILE *the_cache = fopen(cache_name, "rb");		if (the_cache) {			fseek(the_cache, 0, SEEK_END);			sess->cache_start_size = ftell(the_cache);			fclose(the_cache);		}	}	/*second try, disable cached file*/	else {		sess->cache_start_size = 0;	}	sess->cache_name = strdup(cache_name);	/*are we using existing cached files ?*/	opt = gf_cfg_get_key(sess->dm->cfg, "Downloader", "RestartFiles");	if (opt && !stricmp(opt, "yes")) sess->cache_start_size = 0;}static void gf_dm_disconnect(GF_DownloadSession *sess){#ifdef GPAC_HAS_SSL	if (sess->ssl) {		SSL_shutdown(sess->ssl);		SSL_free(sess->ssl);		sess->ssl = NULL;	}#endif	if (sess->sock) {		gf_sk_del(sess->sock);		sess->sock = NULL;	}	if (sess->cache) fclose(sess->cache);	sess->cache = NULL;	sess->status = GF_NETIO_DISCONNECTED;	if (sess->num_retry) sess->num_retry--;}void gf_dm_sess_del(GF_DownloadSession *sess){	const char *opt;	/*self-destruction, let the download manager destroy us*/	if (sess->th && sess->in_callback) {		sess->destroy = 1;		return;	}	gf_dm_disconnect(sess);	/*if threaded wait for thread exit*/	if (sess->th) {		while (!(sess->flags & GF_DOWNLOAD_SESSION_THREAD_DEAD)) 			gf_sleep(1);		gf_th_del(sess->th);		gf_mx_del(sess->mx);	}		gf_list_del_item(sess->dm->sessions, sess);	if (sess->cache_name) {		opt = gf_cfg_get_key(sess->dm->cfg, "Downloader", "CleanCache");		if (opt && !stricmp(opt, "yes")) gf_delete_file(sess->cache_name);		free(sess->cache_name);	}		if (sess->server_name) free(sess->server_name);	if (sess->remote_path) free(sess->remote_path);	if (sess->user) free(sess->user);	if (sess->passwd) free(sess->passwd);	if (sess->mime_type) free(sess->mime_type);	if (sess->cache) fclose(sess->cache);	if (sess->init_data) free(sess->init_data);	free(sess);}void http_do_requests(GF_DownloadSession *sess);static void gf_dm_sess_notify_state(GF_DownloadSession *sess, u32 dnload_status, GF_Err error){	GF_NETIO_Parameter par;	sess->in_callback = 1;	memset(&par, 0, sizeof(GF_NETIO_Parameter));	par.msg_type = dnload_status;	par.error = error;	sess->user_proc(sess->usr_cbk, &par);	sess->in_callback = 0;}static void gf_dm_sess_user_io(GF_DownloadSession *sess, GF_NETIO_Parameter *par){	sess->in_callback = 1;	sess->user_proc(sess->usr_cbk, par);	sess->in_callback = 0;}GF_Err gf_dm_sess_last_error(GF_DownloadSession *sess){	if (!sess) return GF_BAD_PARAM;	return sess->last_error;}static GF_Err gf_dm_setup_from_url(GF_DownloadSession *sess, char *url){	char *tmp, tmp_url[GF_MAX_PATH];	const char *opt;	if (!strnicmp(url, "http://", 7)) {		url += 7;		sess->port = 80;		sess->do_requests = http_do_requests;	} 	else if (!strnicmp(url, "https://", 8)) {		url += 8;		sess->port = 443;#ifndef GPAC_HAS_SSL		return GF_NOT_SUPPORTED;#endif		sess->flags |= GF_DOWNLOAD_SESSION_USE_SSL;		sess->do_requests = http_do_requests;	}	else if (!strnicmp(url, "ftp://", 6)) {		url += 6;		sess->port = 21;		sess->do_requests = NULL;		return GF_NOT_SUPPORTED;	} 	/*relative URL*/	else if (!strstr(url, "://")) {		u32 i;		if (!sess->remote_path) return GF_BAD_PARAM;		tmp = gf_url_concatenate(sess->remote_path, url);		free(sess->remote_path);		sess->remote_path = tmp;		for (i=0; i<strlen(sess->remote_path); i++)			if (sess->remote_path[i]=='\\') sess->remote_path[i]='/';	} else {		return GF_BAD_PARAM;	}	tmp = strchr(url, '/');	sess->remote_path = strdup(tmp ? tmp : "/");	if (tmp) {		tmp[0] = 0;		strcpy(tmp_url, url);		tmp[0] = '/';	} else {		strcpy(tmp_url, url);	}		tmp = strrchr(tmp_url, ':');	if (tmp) {		sess->port = atoi(tmp+1);		tmp[0] = 0;	}	tmp = strrchr(tmp_url, '@');	if (tmp) {		sess->server_name = strdup(tmp+1);		tmp[0] = 0;		tmp = strchr(tmp_url, ':');		if (sess->user) free(sess->user);		sess->user = NULL;		if (sess->passwd) free(sess->passwd);		sess->passwd = NULL;		if (tmp) {			sess->passwd = strdup(tmp+1);			tmp[0] = 0;		}		sess->user = strdup(tmp_url);	} else {		sess->server_name = strdup(tmp_url);	}	/*setup BW limiter*/	sess->limit_data_rate = 0;	opt = gf_cfg_get_key(sess->dm->cfg, "Downloader", "MaxRate");	if (opt) {		/*use it in in BYTES per second*/		sess->limit_data_rate = 1024 * atoi(opt) / 8;	}	return GF_OK;}#define GF_WAIT_REPLY_SLEEP	20static u32 gf_dm_session_thread(void *par){	GF_DownloadSession *sess = (GF_DownloadSession *)par;	GF_LOG(GF_LOG_DEBUG, GF_LOG_CORE, ("[Downloader] Entering thread ID %d\n", gf_th_id() ));	sess->flags &= ~GF_DOWNLOAD_SESSION_THREAD_DEAD;	while (!sess->destroy) {		gf_mx_p(sess->mx);		if (sess->status >= GF_NETIO_DISCONNECTED) {			gf_mx_v(sess->mx);			break;		}		if (sess->status < GF_NETIO_CONNECTED) {			gf_dm_connect(sess);		} else {			if (sess->status == GF_NETIO_WAIT_FOR_REPLY) gf_sleep(GF_WAIT_REPLY_SLEEP);			sess->do_requests(sess);		}		gf_mx_v(sess->mx);		gf_sleep(2);	}	/*destroy all sessions*/	gf_dm_disconnect(sess);	sess->status = GF_NETIO_STATE_ERROR;	sess->last_error = 0;	sess->flags |= GF_DOWNLOAD_SESSION_THREAD_DEAD;	return 1;}#define SESSION_RETRY_COUNT	20GF_DownloadSession *gf_dm_sess_new(GF_DownloadManager *dm, char *url, u32 dl_flags,									  gf_dm_user_io user_io,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -