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

📄 sched.c

📁 ELinks is an advanced and well-established feature-rich text mode web (HTTP/FTP/..) browser. ELinks
💻 C
📖 第 1 页 / 共 2 页
字号:
		c->prev_error = c->state;		run_connection(c);	}}void abort_connection(struct connection *c){	if (c->running) interrupt_connection(c);	/*send_connection_info(c);*/	del_connection(c);#ifdef DEBUG	check_queue_bugs();#endif	register_bottom_half(check_queue, NULL);}int try_connection(struct connection *c){	struct h_conn *hc = NULL;	if ((hc = is_host_on_list(c))) {		if (hc->conn >= max_connections_to_host) {			if (try_to_suspend_connection(c, hc->host)) return 0;			else return -1;		}	}	if (active_connections >= max_connections) {		if (try_to_suspend_connection(c, NULL)) return 0;		else return -1;	}	run_connection(c);	return 1;}#ifdef DEBUGvoid check_queue_bugs(void){	struct connection *d;	int p = 0, ps = 0;	int cc;	again:	cc = 0;	foreach(d, queue) {		int q = getpri(d);		cc += d->running;		if (q < p) if (!ps) {			internal("queue is not sorted");			sort_queue();			ps = 1;			goto again;		} else {			internal("queue is not sorted even after sort_queue!");			break;		} else p = q;		if (d->state < 0) {			internal("interrupted connection on queue (conn %s, state %d)", d->url, d->state);			d = d->prev;			abort_connection(d->next);		}	}	if (cc != active_connections) {		internal("bad number of active connections (counted %d, stored %d)", cc, active_connections);		active_connections = cc;	}}#endifvoid check_queue(void *dummy){	struct connection *c;	again:	c = queue.next;#ifdef DEBUG	check_queue_bugs();#endif	check_keepalive_connections();	while (c != (struct connection *)(void *)&queue) {		struct connection *d;		int cp = getpri(c);		for (d = c; d != (struct connection *)(void *)&queue && getpri(d) == cp;) {			struct connection *dd = d; d = d->next;			if (!dd->state) if (is_host_on_keepalive_list(dd)) {				if (try_connection(dd)) goto again;			}		}		for (d = c; d != (struct connection *)(void *)&queue && getpri(d) == cp;) {			struct connection *dd = d; d = d->next;			if (!dd->state) {				if (try_connection(dd)) goto again;			}		}		c = d;	}	again2:	foreachback(c, queue) {		if (getpri(c) < PRI_CANCEL) break;		if (c->state == S_WAIT) {			setcstate(c, S_INTERRUPTED);			del_connection(c);			goto again2;		} else if (c->est_length > memory_cache_size * MAX_CACHED_OBJECT || c->from > memory_cache_size * MAX_CACHED_OBJECT) {			setcstate(c, S_INTERRUPTED);			abort_connection(c);			goto again2;		}	}#ifdef DEBUG	check_queue_bugs();#endif}unsigned char *get_proxy(unsigned char *url){	size_t l = strlen(url);	unsigned char *proxy = NULL;	unsigned char *u;	if (*proxies.http_proxy && l >= 7 && !casecmp(url, "http://", 7)) proxy = proxies.http_proxy;	if (*proxies.ftp_proxy && l >= 6 && !casecmp(url, "ftp://", 6)) proxy = proxies.ftp_proxy;	u = mem_alloc(l + 1 + (proxy ? strlen(proxy) + 9 : 0));	if (proxy) strcpy(u, "proxy://"), strcat(u, proxy), strcat(u, "/");	else *u = 0;	strcat(u, url);	return u;}/* prev_url is a pointer to previous url or NULL *//* prev_url will NOT be deallocated */int load_url(unsigned char *url, unsigned char * prev_url, struct status *stat, int pri, int no_cache){	struct cache_entry *e = NULL;	struct connection *c;	unsigned char *u;	if (stat) stat->c = NULL, stat->ce = NULL, stat->pri = pri;#ifdef DEBUG	foreach(c, queue) {		struct status *st;		foreach (st, c->statuss) {			if (st == stat) {				internal("status already assigned to '%s'", c->url);				stat->state = S_INTERNAL;				if (stat->end) stat->end(stat, stat->data);				return 0;			}		}	}#endif	if (stat) stat->state = S_OUT_OF_MEM, stat->prev_error = 0;	if (no_cache <= NC_CACHE && !find_in_cache(url, &e) && !e->incomplete) {		if (!http_bugs.aggressive_cache && no_cache > NC_ALWAYS_CACHE) {			if (e->expire_time && e->expire_time < time(NULL)) {				if (no_cache < NC_IF_MOD) no_cache = NC_IF_MOD;				goto skip_cache;			}		}		if (stat) {			stat->ce = e;			stat->state = S_OK;			if (stat->end) stat->end(stat, stat->data);		}		return 0;	}	skip_cache:	if (!casecmp(url, "proxy://", 8)) {		if (stat) {			stat->state = S_BAD_URL;			if (stat->end) stat->end(stat, stat->data);		}		return 0;	}	u = get_proxy(url);	foreach(c, queue) if (!c->detached && !strcmp(c->url, u)) {		mem_free(u);		if (getpri(c) > pri) {			del_from_list(c);			c->pri[pri]++;			add_to_queue(c);			register_bottom_half(check_queue, NULL);		} else c->pri[pri]++;		if (stat) {			stat->prg = &c->prg;			stat->c = c;			stat->ce = c->cache;			add_to_list(c->statuss, stat);			setcstate(c, c->state);		}#ifdef DEBUG		check_queue_bugs();#endif		return 0;	}	c = mem_calloc(sizeof(struct connection));	c->count = connection_count++;	c->url = u;	c->prev_url = stracpy(prev_url);	c->running = 0;	c->prev_error = 0;	c->from = no_cache >= NC_IF_MOD || !e || e->frag.next == &e->frag || ((struct fragment *)e->frag.next)->offset ? 0 : ((struct fragment *)e->frag.next)->length;	memset(c->pri, 0, sizeof c->pri);	c->pri[pri] = 1;	c->no_cache = no_cache;	c->sock1 = c->sock2 = -1;	c->dnsquery = NULL;	c->info = NULL;	c->buffer = NULL;	c->newconn = NULL;	c->cache = NULL;	c->tries = 0;	init_list(c->statuss);	c->est_length = -1;	c->unrestartable = 0;	c->prg.timer = -1;	c->timer = -1;	if (stat) {		stat->prg = &c->prg;		stat->c = c;		stat->ce = NULL;		add_to_list(c->statuss, stat);	}	add_to_queue(c);	setcstate(c, S_WAIT);#ifdef DEBUG	check_queue_bugs();#endif	register_bottom_half(check_queue, NULL);	return 0;}void change_connection(struct status *oldstat, struct status *newstat, int newpri){		/* !!! FIXME: one object in more connections */	struct connection *c;	int oldpri;	if (!oldstat) {		internal("change_connection: oldstat == NULL");		return;	}	oldpri = oldstat->pri;	if (oldstat->state < 0) {		if (newstat) {			newstat->ce = oldstat->ce;			newstat->state = oldstat->state;			newstat->prev_error = oldstat->prev_error;			if (newstat->end) newstat->end(newstat, newstat->data);		}		return;	}#ifdef DEBUG	check_queue_bugs();#endif	c = oldstat->c;	if (--c->pri[oldpri] < 0) {		internal("priority counter underflow");		c->pri[oldpri] = 0;	}	c->pri[newpri]++;	del_from_list(oldstat);	oldstat->state = S_INTERRUPTED;	if (newstat) {		newstat->prg = &c->prg;		add_to_list(c->statuss, newstat);		newstat->state = c->state;		newstat->prev_error = c->prev_error;		newstat->pri = newpri;		newstat->c = c;		newstat->ce = c->cache;	}	if (c->detached && !newstat) {		setcstate(c, S_INTERRUPTED);		abort_connection(c);	}	sort_queue();#ifdef DEBUG	check_queue_bugs();#endif	register_bottom_half(check_queue, NULL);}void detach_connection(struct status *stat, off_t pos){	struct connection *c;	int i;	off_t l;	if (stat->state < 0) return;	c = stat->c;	if (c->detached) goto detach_done;	if (!c->cache) return;	if (c->est_length == -1) l = c->from;	else l = c->est_length;	if (l < memory_cache_size * MAX_CACHED_OBJECT) return;	l = 0;	for (i = 0; i < PRI_CANCEL; i++) l += c->pri[i];	if (!l) internal("detaching free connection");	if (l != 1 || c->cache->refcount) return;	shrink_memory(SH_CHECK_QUOTA);	c->cache->url[0] = 0;	c->detached = 1;	detach_done:	free_entry_to(c->cache, pos);}void connection_timeout(struct connection *c){	c->timer = -1;	setcstate(c, S_TIMEOUT);	if (c->dnsquery) abort_connection(c);	else retry_connection(c);}void connection_timeout_1(struct connection *c){	c->timer = install_timer((c->unrestartable ? unrestartable_receive_timeout : receive_timeout) * 500, (void (*)(void *))connection_timeout, c);}void set_timeout(struct connection *c){	if (c->timer != -1) kill_timer(c->timer);	c->timer = install_timer((c->unrestartable ? unrestartable_receive_timeout : receive_timeout) * 500, (void (*)(void *))connection_timeout_1, c);}void reset_timeout(struct connection *c){	if (c->timer != -1) kill_timer(c->timer), c->timer = -1;}void abort_all_connections(void){	while(queue.next != &queue) {		setcstate(queue.next, S_INTERRUPTED);		abort_connection(queue.next);	}	abort_all_keepalive_connections();}void abort_background_connections(void){	int i = 0;	while (1) {		int j;		struct connection *c = (void *)&queue;		for (j = 0; j <= i; j++) if ((c = c->next) == (void *)&queue) goto brk;		if (getpri(c) >= PRI_CANCEL) {			setcstate(c, S_INTERRUPTED);			abort_connection(c);		} else i++;	}	brk:	abort_all_keepalive_connections();}int is_entry_used(struct cache_entry *e){	struct connection *c;	foreach(c, queue) if (c->cache == e) return 1;	return 0;}struct blacklist_entry {	struct blacklist_entry *next;	struct blacklist_entry *prev;	int flags;	unsigned char host[1];};struct list_head blacklist = { &blacklist, &blacklist };void add_blacklist_entry(unsigned char *host, int flags){	struct blacklist_entry *b;	foreach(b, blacklist) if (!strcasecmp(host, b->host)) {		b->flags |= flags;		return;	}	b = mem_alloc(sizeof(struct blacklist_entry) + strlen(host) + 1);	b->flags = flags;	strcpy(b->host, host);	add_to_list(blacklist, b);}void del_blacklist_entry(unsigned char *host, int flags){	struct blacklist_entry *b;	foreach(b, blacklist) if (!strcasecmp(host, b->host)) {		b->flags &= ~flags;		if (!b->flags) {			del_from_list(b);			mem_free(b);		}		return;	}}int get_blacklist_flags(unsigned char *host){	struct blacklist_entry *b;	foreach(b, blacklist) if (!strcasecmp(host, b->host)) return b->flags;	return 0;}void free_blacklist(void){	free_list(blacklist);}struct s_msg_dsc msg_dsc[] = {	{S_WAIT,		TEXT(T_WAITING_IN_QUEUE)},	{S_DNS,			TEXT(T_LOOKING_UP_HOST)},	{S_CONN,		TEXT(T_MAKING_CONNECTION)},	{S_SOCKS_NEG,		TEXT(T_SOCKS_NEGOTIATION)},	{S_SSL_NEG,		TEXT(T_SSL_NEGOTIATION)},	{S_SENT,		TEXT(T_REQUEST_SENT)},	{S_LOGIN,		TEXT(T_LOGGING_IN)},	{S_GETH,		TEXT(T_GETTING_HEADERS)},	{S_PROC,		TEXT(T_SERVER_IS_PROCESSING_REQUEST)},	{S_TRANS,		TEXT(T_TRANSFERRING)},	{S_WAIT_REDIR,		TEXT(T_WAITING_FOR_REDIRECT_CONFIRMATION)},	{S_OK,			TEXT(T_OK)},	{S_INTERRUPTED,		TEXT(T_INTERRUPTED)},	{S_EXCEPT,		TEXT(T_SOCKET_EXCEPTION)},	{S_INTERNAL,		TEXT(T_INTERNAL_ERROR)},	{S_OUT_OF_MEM,		TEXT(T_OUT_OF_MEMORY)},	{S_NO_DNS,		TEXT(T_HOST_NOT_FOUND)},	{S_CANT_WRITE,		TEXT(T_ERROR_WRITING_TO_SOCKET)},	{S_CANT_READ,		TEXT(T_ERROR_READING_FROM_SOCKET)},	{S_MODIFIED,		TEXT(T_DATA_MODIFIED)},	{S_BAD_URL,		TEXT(T_BAD_URL_SYNTAX)},	{S_TIMEOUT,		TEXT(T_RECEIVE_TIMEOUT)},	{S_RESTART,		TEXT(T_REQUEST_MUST_BE_RESTARTED)},	{S_STATE,		TEXT(T_CANT_GET_SOCKET_STATE)},	{S_CYCLIC_REDIRECT,	TEXT(T_CYCLIC_REDIRECT)},	{S_LARGE_FILE,		TEXT(T_TOO_LARGE_FILE)},	{S_HTTP_ERROR,		TEXT(T_BAD_HTTP_RESPONSE)},	{S_HTTP_100,		TEXT(T_HTTP_100)},	{S_HTTP_204,		TEXT(T_NO_CONTENT)},	{S_FILE_TYPE,		TEXT(T_UNKNOWN_FILE_TYPE)},	{S_FILE_ERROR,		TEXT(T_ERROR_OPENING_FILE)},	{S_FTP_ERROR,		TEXT(T_BAD_FTP_RESPONSE)},	{S_FTP_UNAVAIL,		TEXT(T_FTP_SERVICE_UNAVAILABLE)},	{S_FTP_LOGIN,		TEXT(T_BAD_FTP_LOGIN)},	{S_FTP_PORT,		TEXT(T_FTP_PORT_COMMAND_FAILED)},	{S_FTP_NO_FILE,		TEXT(T_FILE_NOT_FOUND)},	{S_FTP_FILE_ERROR,	TEXT(T_FTP_FILE_ERROR)},	{S_SSL_ERROR,		TEXT(T_SSL_ERROR)},	{S_NO_SSL,		TEXT(T_NO_SSL)},	{S_BAD_SOCKS_VERSION,	TEXT(T_BAD_SOCKS_VERSION)},	{S_SOCKS_REJECTED,	TEXT(T_SOCKS_REJECTED_OR_FAILED)},	{S_SOCKS_NO_IDENTD,	TEXT(T_SOCKS_NO_IDENTD)},	{S_SOCKS_BAD_USERID,	TEXT(T_SOCKS_BAD_USERID)},	{S_SOCKS_UNKNOWN_ERROR,	TEXT(T_SOCKS_UNKNOWN_ERROR)},	{S_BLOCKED_URL,		TEXT(T_BLOCKED_URL)},	{S_NO_PROXY,		TEXT(T_NO_PROXY)},	{S_NO_SMB_CLIENT,	TEXT(T_NO_SMB_CLIENT)},	{0,			NULL}};

⌨️ 快捷键说明

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