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

📄 downloader.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 3 页
字号:
									  void *usr_cbk,									  GF_Err *e){	GF_DownloadSession *sess;	*e = GF_OK;	if (gf_dm_is_local(dm, url)) return NULL;	if (!gf_dm_can_handle_url(dm, url)) {		*e = GF_NOT_SUPPORTED;		return NULL;	}	if (!user_io) {		*e = GF_BAD_PARAM;		return NULL;	}	sess = (GF_DownloadSession *)malloc(sizeof(GF_DownloadSession));	memset((void *)sess, 0, sizeof(GF_DownloadSession));	sess->flags = dl_flags;	sess->user_proc = user_io;	sess->usr_cbk = usr_cbk;	sess->dm = dm;	gf_list_add(dm->sessions, sess);	*e = gf_dm_setup_from_url(sess, url);	if (*e) {		gf_dm_sess_del(sess);		return NULL;	}	if (!(sess->flags & GF_NETIO_SESSION_NOT_THREADED) ) {		sess->th = gf_th_new();		sess->mx = gf_mx_new();		gf_th_run(sess->th, gf_dm_session_thread, sess);	}	sess->num_retry = SESSION_RETRY_COUNT;	return sess;}static GF_Err gf_dm_read_data(GF_DownloadSession *sess, char *data, u32 data_size, u32 *out_read){	GF_Err e;	#ifdef GPAC_HAS_SSL	if (sess->ssl) {		u32 size = SSL_read(sess->ssl, data, data_size);		e = GF_OK;		data[size] = 0;		if (!size) e = GF_IP_NETWORK_EMPTY;		*out_read = size;	} else #endif		e = gf_sk_receive(sess->sock, data, data_size, 0, out_read);		return e;}#ifdef GPAC_HAS_SSL/*pattern comp taken from wget*/#define ASTERISK_EXCLUDES_DOT	/* mandated by rfc2818 */#define TOLOWER(x) ('A' <= (x) && (x) <= 'Z' ? (x) - 32 : (x))static Bool pattern_match(const char *pattern, const char *string){	const char *p = pattern, *n = string;	char c;	for (; (c = TOLOWER (*p++)) != '\0'; n++) {		if (c == '*') {			for (c = TOLOWER (*p); c == '*'; c = TOLOWER (*++p))				;			for (; *n != '\0'; n++)				if (TOLOWER (*n) == c && pattern_match (p, n))					return 1;#ifdef ASTERISK_EXCLUDES_DOT				else if (*n == '.')					return 0;#endif				return c == '\0';		} else {			if (c != TOLOWER (*n))				return 0;		}	}	return *n == '\0';}#undef TOLOWER#endifstatic void gf_dm_connect(GF_DownloadSession *sess){	GF_Err e;	u16 proxy_port = 0;	const char *proxy;	if (!sess->sock) {		//sess->num_retry = 40;		sess->sock = gf_sk_new(GF_SOCK_TYPE_TCP);	}	/*connect*/	sess->status = GF_NETIO_SETUP;	gf_dm_sess_notify_state(sess, sess->status, GF_OK);		/*PROXY setup*/	proxy = gf_cfg_get_key(sess->dm->cfg, "HTTPProxy", "Enabled");	if (proxy && !strcmp(proxy, "yes")) {		proxy = gf_cfg_get_key(sess->dm->cfg, "HTTPProxy", "Port");		proxy_port = proxy ? atoi(proxy) : 80;				proxy = gf_cfg_get_key(sess->dm->cfg, "HTTPProxy", "Name");	} else {		proxy = NULL;	}	if (proxy) {		e = gf_sk_connect(sess->sock, (char *) proxy, proxy_port);	} else {		e = gf_sk_connect(sess->sock, sess->server_name, sess->port);	}	/*retry*/	if ((e == GF_IP_SOCK_WOULD_BLOCK) && sess->num_retry) {		sess->status = GF_NETIO_SETUP;		sess->num_retry--;		return;	}	/*failed*/	if (e) {		sess->status = GF_NETIO_STATE_ERROR;		sess->last_error = e;		gf_dm_sess_notify_state(sess, sess->status, e);		return;	} 		sess->status = GF_NETIO_CONNECTED;	gf_dm_sess_notify_state(sess, GF_NETIO_CONNECTED, GF_OK);	gf_sk_set_block_mode(sess->sock, 1);	gf_dm_configure_cache(sess);#ifdef GPAC_HAS_SSL	/*socket is connected, configure SSL layer*/	if (!sess->ssl && sess->dm->ssl_ctx && (sess->flags & GF_DOWNLOAD_SESSION_USE_SSL)) {		int ret;		long vresult;		char common_name[256];	    X509 *cert;		Bool success = 1;		sess->ssl = SSL_new(sess->dm->ssl_ctx);		SSL_set_fd(sess->ssl, gf_sk_get_handle(sess->sock));		SSL_set_connect_state(sess->ssl);		ret = SSL_connect(sess->ssl);		assert(ret>0);		cert = SSL_get_peer_certificate(sess->ssl);       		/*if we have a cert, check it*/		if (cert) {			vresult = SSL_get_verify_result(sess->ssl);			if (vresult != X509_V_OK) success = 0;			else {				common_name[0] = 0;				X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_commonName, common_name, sizeof (common_name));				if (!pattern_match(common_name, sess->server_name)) success = 0;			}			X509_free(cert);			if (!success) {				gf_dm_disconnect(sess);				sess->status = GF_NETIO_STATE_ERROR;				sess->last_error = GF_AUTHENTICATION_FAILURE;				gf_dm_sess_notify_state(sess, sess->status, sess->last_error);			}		}	}#endif}const char *gf_dm_sess_mime_type(GF_DownloadSession *sess){	Bool go;	u32 flags = sess->flags;	sess->flags |= GF_NETIO_SESSION_NOT_CACHED;	go = 1;	while (go) {		switch (sess->status) {		/*setup download*/		case GF_NETIO_SETUP:			gf_dm_connect(sess);			break;		case GF_NETIO_WAIT_FOR_REPLY:			gf_sleep(20);		case GF_NETIO_CONNECTED:			sess->do_requests(sess);			break;		case GF_NETIO_DATA_EXCHANGE:		case GF_NETIO_DISCONNECTED:		case GF_NETIO_STATE_ERROR:			go = 0;			break;		}	}	sess->flags = flags;	if (sess->status==GF_NETIO_STATE_ERROR) return NULL;	return sess->mime_type;}GF_DownloadManager *gf_dm_new(GF_Config *cfg){	const char *opt;	GF_DownloadManager *dm;	if (!cfg) return NULL;	GF_SAFEALLOC(dm, GF_DownloadManager);	dm->sessions = gf_list_new();	dm->cfg = cfg;	opt = gf_cfg_get_key(cfg, "General", "CacheDirectory");	if (opt) {		if (opt[strlen(opt)-1] != GF_PATH_SEPARATOR) {			dm->cache_directory = (char *) malloc(sizeof(char)* (strlen(opt)+2));			sprintf(dm->cache_directory, "%s%c", opt, GF_PATH_SEPARATOR);		} else {			dm->cache_directory = strdup(opt);		}	}#ifdef GPAC_HAS_SSL	ssl_init(dm, 0);#endif	return dm;}void gf_dm_set_auth_callback(GF_DownloadManager *dm,							  Bool (*GetUserPassword)(void *usr_cbk, const char *site_url, char *usr_name, char *password), 							  void *usr_cbk){	if (dm) {		dm->GetUserPassword = GetUserPassword;		dm->usr_cbk = usr_cbk;	}}void gf_dm_del(GF_DownloadManager *dm){	/*destroy all pending sessions*/	while (gf_list_count(dm->sessions)) {		GF_DownloadSession *sess = (GF_DownloadSession *) gf_list_get(dm->sessions, 0);		gf_dm_sess_del(sess);	}	gf_list_del(dm->sessions);	free(dm->cache_directory);#ifdef GPAC_HAS_SSL	if (dm->ssl_ctx) SSL_CTX_free(dm->ssl_ctx);#endif	free(dm);}static GFINLINE void gf_dm_data_recieved(GF_DownloadSession *sess, char *data, u32 nbBytes){	GF_NETIO_Parameter par;	u32 runtime, rcv;		rcv = nbBytes;	if (! (sess->flags & GF_NETIO_SESSION_NOT_CACHED)) {		if (sess->cache) {			fwrite(data, nbBytes, 1, sess->cache);			fflush(sess->cache);		}		sess->bytes_done += nbBytes;		/*if not threaded don't signal data to user*/		if (sess->th) {			par.msg_type = GF_NETIO_DATA_EXCHANGE;			par.error = GF_OK;			par.data = NULL;			par.size = nbBytes;			gf_dm_sess_user_io(sess, &par);		}	} else if (sess->icy_metaint) {		while (nbBytes) {			if (sess->icy_bytes == sess->icy_metaint) {				sess->icy_count = 1 + 16* (u8) data[0];								/*skip icy metadata*/				if (sess->icy_count >= nbBytes) {					sess->icy_count -= nbBytes;					nbBytes = 0;				} else {					if (sess->icy_count > 1) {						GF_NETIO_Parameter par;						char szData[4096];						memcpy(szData, data+1, sess->icy_count-1);						szData[sess->icy_count] = 0;							par.error = 0;						par.msg_type = GF_NETIO_PARSE_HEADER;						par.name = "icy-meta";						par.value = szData;						gf_dm_sess_user_io(sess, &par);					}					nbBytes -= sess->icy_count;					data += sess->icy_count;					sess->icy_count = 0;					sess->icy_bytes = 0;				}			} else {				u32 left = sess->icy_metaint - sess->icy_bytes;				if (left > nbBytes) {					left = nbBytes;					sess->icy_bytes += left;					nbBytes = 0;				} else {					sess->icy_bytes = sess->icy_metaint;					nbBytes -= left;				}				par.msg_type = GF_NETIO_DATA_EXCHANGE;				par.error = GF_OK;				par.data = data;				par.size = left;				gf_dm_sess_user_io(sess, &par);				data += left;			}		}	} else {		sess->bytes_done += nbBytes;		/*if not threaded don't signal data to user*/		if (sess->th) {			par.msg_type = GF_NETIO_DATA_EXCHANGE;			par.error = GF_OK;			par.data = data;			par.size = nbBytes;			gf_dm_sess_user_io(sess, &par);		}	}	if (sess->total_size && (sess->bytes_done == sess->total_size)) {		gf_dm_disconnect(sess);		par.msg_type = GF_NETIO_DATA_TRANSFERED;		par.error = GF_OK;		gf_dm_sess_user_io(sess, &par);		return;	}	/*update state if not done*/	if (rcv) {		sess->bytes_in_wnd += rcv;		runtime = gf_sys_clock() - sess->window_start;		if (!runtime) {			sess->bytes_per_sec = 0;		} else {			sess->bytes_per_sec = (1000 * (sess->bytes_in_wnd)) / runtime;			if (runtime>1000) {				sess->window_start += runtime/2;				sess->bytes_in_wnd = sess->bytes_per_sec / 2;			}		}	}}GF_EXPORTGF_Err gf_dm_sess_fetch_data(GF_DownloadSession *sess, char *buffer, u32 buffer_size, u32 *read_size){	GF_Err e;	if (sess->cache || !buffer || !buffer_size) return GF_BAD_PARAM;	if (sess->th) return GF_BAD_PARAM;	if (sess->status == GF_NETIO_DISCONNECTED) return GF_EOS;	if (sess->status > GF_NETIO_DATA_TRANSFERED) return GF_BAD_PARAM;	*read_size = 0;	if (sess->status == GF_NETIO_DATA_TRANSFERED) return GF_EOS;	if (sess->status == GF_NETIO_SETUP) {		gf_dm_connect(sess);		return GF_OK;	} else if (sess->status < GF_NETIO_DATA_EXCHANGE) {		sess->do_requests(sess);		return GF_OK;	}	/*we're running but we had data previously*/	if (sess->init_data) {		memcpy(buffer, sess->init_data, sizeof(char)*sess->init_data_size);		*read_size = sess->init_data_size;		free(sess->init_data);		sess->init_data = NULL;		sess->init_data_size = 0;		return GF_OK;	}	e = gf_dm_read_data(sess, buffer, buffer_size, read_size);	if (e) return e;	gf_dm_data_recieved(sess, buffer, *read_size);	return GF_OK;}GF_EXPORTGF_Err gf_dm_sess_get_stats(GF_DownloadSession * sess, const char **server, const char **path, u32 *total_size, u32 *bytes_done, u32 *bytes_per_sec, u32 *net_status){	if (!sess) return GF_BAD_PARAM;	if (server) *server = sess->server_name;	if (path) *path = sess->remote_path;	if (total_size) *total_size = sess->total_size;	if (bytes_done) *bytes_done = sess->bytes_done;	if (bytes_per_sec) *bytes_per_sec = sess->bytes_per_sec;	if (net_status) *net_status = sess->status;	if (sess->status == GF_NETIO_DISCONNECTED) return GF_EOS;	else if (sess->status == GF_NETIO_STATE_ERROR) return GF_SERVICE_ERROR;	return GF_OK;}GF_EXPORTconst char *gf_dm_sess_get_cache_name(GF_DownloadSession * sess){	if (!sess) return NULL;	return sess->cache_name;}void gf_dm_sess_abort(GF_DownloadSession * sess){	if (sess->mx) {		gf_mx_p(sess->mx);		gf_dm_disconnect(sess);		sess->status = GF_NETIO_STATE_ERROR;		gf_mx_v(sess->mx);	} else {		gf_dm_disconnect(sess);	}}void *gf_dm_sess_get_private(GF_DownloadSession * sess){	return sess ? sess->ext : NULL;}void gf_dm_sess_set_private(GF_DownloadSession * sess, void *private_data){	if (sess) sess->ext = private_data;}/* HTTP(S) stuff*/static GFINLINE u32 http_skip_space(char *val){	u32 ret = 0;	while (val[ret] == ' ') ret+=1;	return ret;}static GFINLINE char *http_is_header(char *line, char *header_name){	char *res;	if (strnicmp(line, header_name, strlen(header_name))) return NULL;	res = line + strlen(header_name);	while ((res[0] == ':') || (res[0] == ' ')) res+=1;	return res;}void http_do_requests(GF_DownloadSession *sess){	GF_Err e;	Bool is_ice;	GF_NETIO_Parameter par;	char sHTTP[GF_DOWNLOAD_BUFFER_SIZE];	char buf[1024];	char comp[400];	char *new_location;	char *hdr, *hdr_val;	u32 bytesRead, res;	s32 LinePos, Pos;	u32 rsp_code, ContentLength, first_byte, last_byte, total_size, range, no_range;	s32 BodyStart;	/*sent HTTP request*/	if (sess->status==GF_NETIO_CONNECTED) {		char range_buf[1024];		char pass_buf[1024];		const char *user_agent;

⌨️ 快捷键说明

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