links

lynx-like text mode web browser
git clone anongit@rnpnr.xyz:links.git
Log | Files | Refs | Feed | README | LICENSE

sched.c (26332B)


      1 /* sched.c
      2  * Links internal scheduler
      3  * (c) 2002 Mikulas Patocka
      4  * This file is a part of the Links program, released under GPL.
      5  */
      6 
      7 #include <limits.h>
      8 
      9 #include "links.h"
     10 
     11 static tcount connection_count = 0;
     12 
     13 static int active_connections = 0;
     14 
     15 tcount netcfg_stamp = 0;
     16 
     17 struct list_head queue = { &queue, &queue };
     18 
     19 struct h_conn {
     20 	list_entry_1st;
     21 	unsigned char *host;
     22 	int conn;
     23 };
     24 
     25 static struct list_head h_conns = { &h_conns, &h_conns };
     26 
     27 struct list_head keepalive_connections = { &keepalive_connections,
     28 	                                   &keepalive_connections };
     29 
     30 /* prototypes */
     31 static void send_connection_info(struct connection *c);
     32 static void del_keepalive_socket(struct k_conn *kc);
     33 static void check_keepalive_connections(void);
     34 
     35 unsigned long
     36 connect_info(int type)
     37 {
     38 	int i = 0;
     39 	struct connection *ce = NULL;
     40 	struct list_head *lce;
     41 	switch (type) {
     42 	case CI_FILES:
     43 		return list_size(&queue);
     44 	case CI_CONNECTING:
     45 		foreach (struct connection, ce, lce, queue)
     46 			i += ce->state > S_WAIT && ce->state < S_TRANS;
     47 		return i;
     48 	case CI_TRANSFER:
     49 		foreach (struct connection, ce, lce, queue)
     50 			i += ce->state == S_TRANS;
     51 		return i;
     52 	case CI_KEEP:
     53 		check_keepalive_connections();
     54 		return list_size(&keepalive_connections);
     55 	default:
     56 		internal("connect_info: bad request");
     57 	}
     58 	return 0;
     59 }
     60 
     61 static int
     62 getpri(struct connection *c)
     63 {
     64 	int i;
     65 	for (i = 0; i < N_PRI; i++)
     66 		if (c->pri[i])
     67 			return i;
     68 	internal("connection has no owner");
     69 	return N_PRI;
     70 }
     71 
     72 static int
     73 connection_disappeared(struct connection *c, tcount count)
     74 {
     75 	struct connection *d = NULL;
     76 	struct list_head *ld;
     77 	foreach (struct connection, d, ld, queue)
     78 		if (c == d && count == d->count)
     79 			return 0;
     80 	return 1;
     81 }
     82 
     83 static struct h_conn *
     84 is_host_on_list(struct connection *c)
     85 {
     86 	char *ho = (char *)get_host_name(c->url);
     87 	struct h_conn *h = NULL;
     88 	struct list_head *lh;
     89 	if (!ho)
     90 		return NULL;
     91 	foreach (struct h_conn, h, lh, h_conns)
     92 		if (!strcmp((const char *)h->host, ho)) {
     93 			free(ho);
     94 			return h;
     95 		}
     96 	free(ho);
     97 	return NULL;
     98 }
     99 
    100 static int st_r = 0;
    101 
    102 static void
    103 stat_timer(void *c_)
    104 {
    105 	struct connection *c = (struct connection *)c_;
    106 	struct remaining_info *r = &c->prg;
    107 	uttime now = get_time();
    108 	uttime a = now - r->last_time;
    109 	if (a > SPD_DISP_TIME * 100)
    110 		a = SPD_DISP_TIME * 100;
    111 	if (getpri(c) == PRI_CANCEL
    112 	    && (c->est_length > (long)memory_cache_size * MAX_CACHED_OBJECT
    113 	        || c->from > (long)memory_cache_size * MAX_CACHED_OBJECT))
    114 		register_bottom_half(check_queue, NULL);
    115 	if (c->state > S_WAIT) {
    116 		r->loaded = c->received;
    117 		if ((r->size = c->est_length) < (r->pos = c->from)
    118 		    && r->size != -1)
    119 			r->size = c->from;
    120 		r->dis_b += a;
    121 		while (r->dis_b >= SPD_DISP_TIME * CURRENT_SPD_SEC) {
    122 			r->cur_loaded -= r->data_in_secs[0];
    123 			memmove(r->data_in_secs, r->data_in_secs + 1,
    124 			        sizeof(off_t) * (CURRENT_SPD_SEC - 1));
    125 			r->data_in_secs[CURRENT_SPD_SEC - 1] = 0;
    126 			r->dis_b -= SPD_DISP_TIME;
    127 		}
    128 		r->data_in_secs[CURRENT_SPD_SEC - 1] +=
    129 		    r->loaded - r->last_loaded;
    130 		r->cur_loaded += r->loaded - r->last_loaded;
    131 		r->last_loaded = r->loaded;
    132 		r->elapsed += a;
    133 	}
    134 	r->last_time = now;
    135 	r->timer = install_timer(SPD_DISP_TIME, stat_timer, c);
    136 	if (!st_r)
    137 		send_connection_info(c);
    138 }
    139 
    140 void
    141 setcstate(struct connection *c, int state)
    142 {
    143 	struct status *stat = NULL;
    144 	struct list_head *lstat;
    145 	if (c->state < 0 && state >= 0)
    146 		c->prev_error = c->state;
    147 	if ((c->state = state) == S_TRANS) {
    148 		struct remaining_info *r = &c->prg;
    149 		if (!r->timer) {
    150 			tcount count = c->count;
    151 			if (!r->valid) {
    152 				memset(r, 0, sizeof(struct remaining_info));
    153 				r->valid = 1;
    154 			}
    155 			r->last_time = get_time();
    156 			r->last_loaded = r->loaded;
    157 			st_r = 1;
    158 			stat_timer(c);
    159 			st_r = 0;
    160 			if (connection_disappeared(c, count))
    161 				return;
    162 		}
    163 	} else {
    164 		struct remaining_info *r = &c->prg;
    165 		if (r->timer) {
    166 			kill_timer(r->timer);
    167 			r->timer = NULL;
    168 		}
    169 	}
    170 	foreach (struct status, stat, lstat, c->statuss) {
    171 		stat->state = state;
    172 		stat->prev_error = c->prev_error;
    173 	}
    174 	if (state >= 0)
    175 		send_connection_info(c);
    176 }
    177 
    178 static struct k_conn *
    179 is_host_on_keepalive_list(struct connection *c)
    180 {
    181 	char *ho = (char *)get_keepalive_id(c->url);
    182 	const int po = get_port(c->url);
    183 	void (*ph)(struct connection *);
    184 	struct k_conn *h = NULL;
    185 	struct list_head *lh;
    186 	if (!(ph = get_protocol_handle(c->url)))
    187 		return NULL;
    188 	if (!ho || po < 0)
    189 		return NULL;
    190 	foreach (struct k_conn, h, lh, keepalive_connections)
    191 		if (h->protocol == ph && h->port == po
    192 		    && !strcmp((char *)h->host, ho)) {
    193 			free(ho);
    194 			return h;
    195 		}
    196 	free(ho);
    197 	return NULL;
    198 }
    199 
    200 int
    201 get_keepalive_socket(struct connection *c, int *protocol_data)
    202 {
    203 	struct k_conn *k;
    204 	int cc;
    205 	if (c->tries > 0 || c->unrestartable)
    206 		return -1;
    207 	if (!(k = is_host_on_keepalive_list(c)))
    208 		return -1;
    209 	cc = k->conn;
    210 	if (protocol_data)
    211 		*protocol_data = k->protocol_data;
    212 	freeSSL(c->ssl);
    213 	c->ssl = k->ssl;
    214 	memcpy(&c->last_lookup_state, &k->last_lookup_state,
    215 	       sizeof(struct lookup_state));
    216 	del_from_list(k);
    217 	free(k->host);
    218 	free(k);
    219 	c->sock1 = cc;
    220 	if (max_tries == 1)
    221 		c->tries = -1;
    222 	c->keepalive = 1;
    223 	return 0;
    224 }
    225 
    226 static int
    227 abort_all_keepalive_connections(void)
    228 {
    229 	int did_something = 0;
    230 	while (!list_empty(keepalive_connections)) {
    231 		del_keepalive_socket(
    232 		    list_struct(keepalive_connections.next, struct k_conn));
    233 		did_something = 1;
    234 	}
    235 	check_keepalive_connections();
    236 	return did_something;
    237 }
    238 
    239 static void
    240 free_connection_data(struct connection *c)
    241 {
    242 	struct h_conn *h;
    243 	int rs;
    244 	if (c->sock1 != -1)
    245 		set_handlers(c->sock1, NULL, NULL, NULL);
    246 	close_socket(&c->sock2);
    247 	if (c->pid) {
    248 		EINTRLOOP(rs, kill(c->pid, SIGINT));
    249 		EINTRLOOP(rs, kill(c->pid, SIGTERM));
    250 		EINTRLOOP(rs, kill(c->pid, SIGKILL));
    251 		c->pid = 0;
    252 	}
    253 	if (!c->running)
    254 		internal("connection already suspended");
    255 	c->running = 0;
    256 	if (c->dnsquery)
    257 		kill_dns_request(&c->dnsquery);
    258 	free(c->buffer);
    259 	free(c->newconn);
    260 	free(c->info);
    261 	c->buffer = NULL;
    262 	c->newconn = NULL;
    263 	c->info = NULL;
    264 	clear_connection_timeout(c);
    265 	if (--active_connections < 0) {
    266 		internal("active connections underflow");
    267 		active_connections = 0;
    268 	}
    269 	if (c->state != S_WAIT) {
    270 		if ((h = is_host_on_list(c))) {
    271 			if (!--h->conn) {
    272 				del_from_list(h);
    273 				free(h->host);
    274 				free(h);
    275 			}
    276 		} else
    277 			internal("suspending connection that is not on the "
    278 			         "list (state %d)",
    279 			         c->state);
    280 	}
    281 }
    282 
    283 static void
    284 send_connection_info(struct connection *c)
    285 {
    286 	if (!list_empty(c->statuss)) {
    287 		const int st = c->state;
    288 		tcount count = c->count;
    289 		struct list_head *lstat = c->statuss.next;
    290 		while (1) {
    291 			int e;
    292 			struct status *xstat =
    293 			    list_struct(lstat, struct status);
    294 			xstat->ce = c->cache;
    295 			lstat = lstat->next;
    296 			e = lstat == &c->statuss;
    297 			if (xstat->end)
    298 				xstat->end(xstat, xstat->data);
    299 			if (e || (st >= 0 && connection_disappeared(c, count)))
    300 				return;
    301 		}
    302 	}
    303 }
    304 
    305 static void
    306 del_connection(struct connection *c)
    307 {
    308 	struct cache_entry *ce = c->cache;
    309 	if (ce)
    310 		ce->refcount++;
    311 	del_from_list(c);
    312 	send_connection_info(c);
    313 	if (ce)
    314 		ce->refcount--;
    315 	if (c->detached) {
    316 		if (ce && !ce->url[0] && !is_entry_used(ce) && !ce->refcount)
    317 			delete_cache_entry(ce);
    318 	} else if (ce)
    319 		trim_cache_entry(ce);
    320 	free(c->url);
    321 	free(c->prev_url);
    322 	free(c->ssl);
    323 	free(c);
    324 }
    325 
    326 void
    327 add_keepalive_socket(struct connection *c, uttime timeout, int protocol_data)
    328 {
    329 	struct k_conn *k;
    330 	int rs;
    331 	free_connection_data(c);
    332 	if (c->sock1 == -1) {
    333 		internal("keepalive connection not connected");
    334 		goto del;
    335 	}
    336 	k = xmalloc(sizeof(struct k_conn));
    337 	if (c->netcfg_stamp != netcfg_stamp || ssl_not_reusable(c->ssl)
    338 	    || (k->port = get_port(c->url)) == -1
    339 	    || !(k->protocol = get_protocol_handle(c->url))
    340 	    || !(k->host = get_keepalive_id(c->url))) {
    341 		free(k);
    342 		del_connection(c);
    343 		goto clos;
    344 	}
    345 	k->conn = c->sock1;
    346 	k->timeout = timeout;
    347 	k->add_time = get_absolute_time();
    348 	k->protocol_data = protocol_data;
    349 	k->ssl = c->ssl;
    350 	c->ssl = NULL;
    351 	memcpy(&k->last_lookup_state, &c->last_lookup_state,
    352 	       sizeof(struct lookup_state));
    353 	add_to_list(keepalive_connections, k);
    354 del:
    355 	del_connection(c);
    356 	register_bottom_half(check_queue, NULL);
    357 	return;
    358 clos:
    359 	EINTRLOOP(rs, close(c->sock1));
    360 	register_bottom_half(check_queue, NULL);
    361 }
    362 
    363 static void
    364 del_keepalive_socket(struct k_conn *kc)
    365 {
    366 	int rs;
    367 	del_from_list(kc);
    368 	freeSSL(kc->ssl);
    369 	EINTRLOOP(rs, close(kc->conn));
    370 	free(kc->host);
    371 	free(kc);
    372 }
    373 
    374 static struct timer *keepalive_timeout = NULL;
    375 
    376 static void
    377 keepalive_timer(void *x)
    378 {
    379 	keepalive_timeout = NULL;
    380 	check_keepalive_connections();
    381 }
    382 
    383 static void
    384 check_keepalive_connections(void)
    385 {
    386 	struct k_conn *kc = NULL;
    387 	struct list_head *lkc;
    388 	uttime ct = get_absolute_time();
    389 	int p = 0;
    390 	if (keepalive_timeout) {
    391 		kill_timer(keepalive_timeout);
    392 		keepalive_timeout = NULL;
    393 	}
    394 	foreach (struct k_conn, kc, lkc, keepalive_connections) {
    395 		if (can_read(kc->conn) || ct - kc->add_time > kc->timeout) {
    396 			lkc = lkc->prev;
    397 			del_keepalive_socket(kc);
    398 		} else
    399 			p++;
    400 	}
    401 	for (; p > MAX_KEEPALIVE_CONNECTIONS; p--)
    402 		if (!list_empty(keepalive_connections))
    403 			del_keepalive_socket(list_struct(
    404 			    keepalive_connections.prev, struct k_conn));
    405 		else
    406 			internal("keepalive list empty");
    407 	if (!list_empty(keepalive_connections))
    408 		keepalive_timeout =
    409 		    install_timer(KEEPALIVE_CHECK_TIME, keepalive_timer, NULL);
    410 }
    411 
    412 static void
    413 add_to_queue(struct connection *c)
    414 {
    415 	struct connection *cc = NULL;
    416 	struct list_head *lcc;
    417 	int pri = getpri(c);
    418 	foreach (struct connection, cc, lcc, queue)
    419 		if (getpri(cc) > pri)
    420 			break;
    421 	add_before_list_entry(lcc, &c->list_entry);
    422 }
    423 
    424 static void
    425 sort_queue(void)
    426 {
    427 	struct connection *c = NULL, *n;
    428 	struct list_head *lc;
    429 	int swp;
    430 	do {
    431 		swp = 0;
    432 		foreach (struct connection, c, lc, queue)
    433 			if (c->list_entry.next != &queue) {
    434 				n = list_struct(c->list_entry.next,
    435 				                struct connection);
    436 				if (getpri(n) < getpri(c)) {
    437 					del_from_list(c);
    438 					add_after_pos(n, c);
    439 					swp = 1;
    440 				}
    441 			}
    442 	} while (swp);
    443 }
    444 
    445 static void
    446 interrupt_connection(struct connection *c)
    447 {
    448 	freeSSL(c->ssl);
    449 	c->ssl = NULL;
    450 	close_socket(&c->sock1);
    451 	free_connection_data(c);
    452 }
    453 
    454 static void
    455 suspend_connection(struct connection *c)
    456 {
    457 	interrupt_connection(c);
    458 	setcstate(c, S_WAIT);
    459 }
    460 
    461 static int
    462 try_to_suspend_connection(struct connection *c, unsigned char *ho)
    463 {
    464 	int pri = getpri(c);
    465 	struct connection *d = NULL;
    466 	struct list_head *ld;
    467 	foreachback (struct connection, d, ld, queue) {
    468 		if (getpri(d) <= pri)
    469 			return -1;
    470 		if (d->state == S_WAIT)
    471 			continue;
    472 		if (d->unrestartable == 2 && getpri(d) < PRI_CANCEL)
    473 			continue;
    474 		if (ho) {
    475 			unsigned char *h;
    476 			if (!(h = get_host_name(d->url)))
    477 				continue;
    478 			if (strcmp((const char *)h, (const char *)ho)) {
    479 				free(h);
    480 				continue;
    481 			}
    482 			free(h);
    483 		}
    484 		suspend_connection(d);
    485 		return 0;
    486 	}
    487 	return -1;
    488 }
    489 
    490 int
    491 is_noproxy_url(unsigned char *url)
    492 {
    493 	unsigned char *host = get_host_name(url);
    494 	if (!proxies.only_proxies) {
    495 		unsigned char *np = proxies.no_proxy;
    496 		int host_l = (int)strlen(cast_const_char host);
    497 		if (*np)
    498 			while (1) {
    499 				int l = (int)strcspn(cast_const_char np, ",");
    500 				if (l > host_l)
    501 					goto no_match;
    502 				if (l < host_l && host[host_l - l - 1] != '.')
    503 					goto no_match;
    504 				if (casecmp(np, host + (host_l - l), l))
    505 					goto no_match;
    506 				free(host);
    507 				return 1;
    508 no_match:
    509 				if (!np[l])
    510 					break;
    511 				np += l + 1;
    512 			}
    513 	}
    514 	free(host);
    515 	return 0;
    516 }
    517 
    518 static void
    519 run_connection(struct connection *c)
    520 {
    521 	struct h_conn *hc;
    522 	void (*func)(struct connection *);
    523 	if (c->running) {
    524 		internal("connection already running");
    525 		return;
    526 	}
    527 
    528 	memset(&c->last_lookup_state, 0, sizeof(struct lookup_state));
    529 
    530 	if (is_noproxy_url(remove_proxy_prefix(c->url))) {
    531 		c->socks_proxy[0] = 0;
    532 		c->dns_append[0] = 0;
    533 	} else {
    534 		safe_strncpy((unsigned char *)c->socks_proxy,
    535 		             proxies.socks_proxy, sizeof(c->socks_proxy));
    536 		safe_strncpy(c->dns_append, proxies.dns_append,
    537 		             sizeof(c->dns_append));
    538 	}
    539 
    540 	if (proxies.only_proxies && !is_proxy_url(c->url)
    541 	    && casecmp(c->url, cast_uchar "data:", 5)
    542 	    && (!*c->socks_proxy || url_bypasses_socks(c->url))) {
    543 		setcstate(c, S_NO_PROXY);
    544 		del_connection(c);
    545 		return;
    546 	}
    547 
    548 	if (!(func = get_protocol_handle(c->url))) {
    549 s_bad_url:
    550 		if (is_proxy_url(c->url))
    551 			setcstate(c, S_BAD_PROXY);
    552 		else
    553 			setcstate(c, S_BAD_URL);
    554 		del_connection(c);
    555 		return;
    556 	}
    557 	if (!(hc = is_host_on_list(c))) {
    558 		hc = xmalloc(sizeof(struct h_conn));
    559 		if (!(hc->host = get_host_name(c->url))) {
    560 			free(hc);
    561 			goto s_bad_url;
    562 		}
    563 		hc->conn = 0;
    564 		add_to_list(h_conns, hc);
    565 	}
    566 	hc->conn++;
    567 	active_connections++;
    568 	c->keepalive = 0;
    569 	c->running = 1;
    570 	func(c);
    571 }
    572 
    573 static int
    574 is_connection_seekable(struct connection *c)
    575 {
    576 	unsigned char *protocol = get_protocol_name(c->url);
    577 	if (!casestrcmp(protocol, cast_uchar "http")
    578 	    || !casestrcmp(protocol, cast_uchar "https")
    579 	    || !casestrcmp(protocol, cast_uchar "proxy")) {
    580 		unsigned char *d;
    581 		free(protocol);
    582 		if (!c->cache || !c->cache->head)
    583 			return 1;
    584 		d = parse_http_header(c->cache->head,
    585 		                      cast_uchar "Accept-Ranges", NULL);
    586 		if (d) {
    587 			free(d);
    588 			return 1;
    589 		}
    590 		return 0;
    591 	}
    592 	if (!casestrcmp(protocol, cast_uchar "ftp")) {
    593 		free(protocol);
    594 		return 1;
    595 	}
    596 	free(protocol);
    597 	return 0;
    598 }
    599 
    600 int
    601 is_connection_restartable(struct connection *c)
    602 {
    603 	return !(c->unrestartable >= 2
    604 	         || (c->tries + 1 >= (max_tries ? max_tries : 1000)));
    605 }
    606 
    607 int
    608 is_last_try(struct connection *c)
    609 {
    610 	int is_restartable;
    611 	c->tries++;
    612 	is_restartable = is_connection_restartable(c) && c->tries < 10;
    613 	c->tries--;
    614 	return !is_restartable;
    615 }
    616 
    617 void
    618 retry_connection(struct connection *c)
    619 {
    620 	interrupt_connection(c);
    621 	if (!is_connection_restartable(c)) {
    622 		del_connection(c);
    623 		register_bottom_half(check_queue, NULL);
    624 	} else {
    625 		c->tries++;
    626 		c->prev_error = c->state;
    627 		run_connection(c);
    628 	}
    629 }
    630 
    631 void
    632 abort_connection(struct connection *c)
    633 {
    634 	if (c->running)
    635 		interrupt_connection(c);
    636 	del_connection(c);
    637 	register_bottom_half(check_queue, NULL);
    638 }
    639 
    640 static int
    641 try_connection(struct connection *c)
    642 {
    643 	struct h_conn *hc = NULL;
    644 	if ((hc = is_host_on_list(c))) {
    645 		if (hc->conn >= max_connections_to_host) {
    646 			if (try_to_suspend_connection(c, hc->host))
    647 				return 0;
    648 			else
    649 				return -1;
    650 		}
    651 	}
    652 	if (active_connections >= max_connections) {
    653 		if (try_to_suspend_connection(c, NULL))
    654 			return 0;
    655 		else
    656 			return -1;
    657 	}
    658 	run_connection(c);
    659 	return 1;
    660 }
    661 
    662 void
    663 check_queue(void *dummy)
    664 {
    665 	struct connection *c = NULL;
    666 	struct list_head *lc;
    667 again:
    668 	check_keepalive_connections();
    669 	foreach (struct connection, c, lc, queue) {
    670 		struct connection *d = NULL;
    671 		struct list_head *ld;
    672 		const int cp = getpri(c);
    673 		foreachfrom (struct connection, d, ld, queue, &c->list_entry) {
    674 			if (getpri(d) != cp)
    675 				break;
    676 			if (!d->state && is_host_on_keepalive_list(d))
    677 				if (try_connection(d))
    678 					goto again;
    679 		}
    680 		foreachfrom (struct connection, d, ld, queue, &c->list_entry) {
    681 			if (getpri(d) != cp)
    682 				break;
    683 			if (!d->state)
    684 				if (try_connection(d))
    685 					goto again;
    686 		}
    687 		lc = ld->prev;
    688 	}
    689 again2:
    690 	foreachback (struct connection, c, lc, queue) {
    691 		if (getpri(c) < PRI_CANCEL)
    692 			break;
    693 		if (c->state == S_WAIT) {
    694 			setcstate(c, S_INTERRUPTED);
    695 			del_connection(c);
    696 			goto again2;
    697 		} else if (c->est_length
    698 		               > (long)memory_cache_size * MAX_CACHED_OBJECT
    699 		           || c->from > (long)memory_cache_size
    700 		                            * MAX_CACHED_OBJECT) {
    701 			setcstate(c, S_INTERRUPTED);
    702 			abort_connection(c);
    703 			goto again2;
    704 		}
    705 	}
    706 }
    707 
    708 unsigned char *
    709 get_proxy_string(unsigned char *url)
    710 {
    711 	if (is_noproxy_url(url))
    712 		return NULL;
    713 	if (*proxies.http_proxy && !casecmp(url, cast_uchar "http://", 7))
    714 		return proxies.http_proxy;
    715 	if (*proxies.https_proxy && !casecmp(url, cast_uchar "https://", 8))
    716 		return proxies.https_proxy;
    717 	return NULL;
    718 }
    719 
    720 unsigned char *
    721 get_proxy(unsigned char *url)
    722 {
    723 	unsigned char *proxy = get_proxy_string(url);
    724 	unsigned char *u;
    725 	u = stracpy(cast_uchar "");
    726 	if (proxy) {
    727 		add_to_strn(&u, cast_uchar "proxy://");
    728 		add_to_strn(&u, proxy);
    729 		add_to_strn(&u, cast_uchar "/");
    730 	}
    731 	add_to_strn(&u, url);
    732 	return u;
    733 }
    734 
    735 int
    736 is_proxy_url(unsigned char *url)
    737 {
    738 	return !casecmp(url, cast_uchar "proxy://", 8);
    739 }
    740 
    741 unsigned char *
    742 remove_proxy_prefix(unsigned char *url)
    743 {
    744 	unsigned char *x = NULL;
    745 	if (is_proxy_url(url))
    746 		x = get_url_data(url);
    747 	if (!x)
    748 		x = url;
    749 	return x;
    750 }
    751 
    752 int
    753 get_allow_flags(unsigned char *url)
    754 {
    755 	return !casecmp(url, cast_uchar "smb://", 6)    ? ALLOW_SMB
    756 	       : !casecmp(url, cast_uchar "file://", 7) ? ALLOW_FILE
    757 	                                                : 0;
    758 }
    759 
    760 int
    761 disallow_url(unsigned char *url, int allow_flags)
    762 {
    763 	if (!casecmp(url, cast_uchar "smb://", 6) && !(allow_flags & ALLOW_SMB))
    764 		return S_SMB_NOT_ALLOWED;
    765 	if (!casecmp(url, cast_uchar "file://", 7)
    766 	    && !(allow_flags & ALLOW_FILE))
    767 		return S_FILE_NOT_ALLOWED;
    768 	return 0;
    769 }
    770 
    771 /* prev_url is a pointer to previous url or NULL */
    772 /* prev_url will NOT be deallocated */
    773 void
    774 load_url(unsigned char *url, unsigned char *prev_url, struct status *stat,
    775          int pri, int no_cache, int no_compress, int allow_flags,
    776          off_t position)
    777 {
    778 	struct cache_entry *e = NULL;
    779 	struct connection *c = NULL;
    780 	struct list_head *lc;
    781 	unsigned char *u;
    782 	int must_detach = 0;
    783 	const int err = disallow_url(url, allow_flags);
    784 
    785 	if (stat) {
    786 		stat->c = NULL;
    787 		stat->ce = NULL;
    788 		stat->state = S_OUT_OF_MEM;
    789 		stat->prev_error = 0;
    790 		stat->pri = pri;
    791 	}
    792 	if (err) {
    793 		if (stat) {
    794 			stat->state = err;
    795 			if (stat->end)
    796 				stat->end(stat, stat->data);
    797 		}
    798 		goto ret;
    799 	}
    800 	if (no_cache <= NC_CACHE && !find_in_cache(url, &e)) {
    801 		if (e->incomplete) {
    802 			e->refcount--;
    803 			goto skip_cache;
    804 		}
    805 		if (!aggressive_cache && no_cache > NC_ALWAYS_CACHE) {
    806 			if (e->expire_time && e->expire_time < time(NULL)) {
    807 				if (no_cache < NC_IF_MOD)
    808 					no_cache = NC_IF_MOD;
    809 				e->refcount--;
    810 				goto skip_cache;
    811 			}
    812 		}
    813 		if (no_compress) {
    814 			unsigned char *enc;
    815 			enc = parse_http_header(
    816 			    e->head, cast_uchar "Content-Encoding", NULL);
    817 			if (enc) {
    818 				free(enc);
    819 				e->refcount--;
    820 				must_detach = 1;
    821 				goto skip_cache;
    822 			}
    823 		}
    824 		if (stat) {
    825 			stat->ce = e;
    826 			stat->state = S__OK;
    827 			if (stat->end)
    828 				stat->end(stat, stat->data);
    829 		}
    830 		e->refcount--;
    831 		goto ret;
    832 	}
    833 skip_cache:
    834 	if (is_proxy_url(url)) {
    835 		if (stat) {
    836 			stat->state = S_BAD_URL;
    837 			if (stat->end)
    838 				stat->end(stat, stat->data);
    839 		}
    840 		goto ret;
    841 	}
    842 	u = get_proxy(url);
    843 	foreach (struct connection, c, lc, queue)
    844 		if (!c->detached
    845 		    && !strcmp((const char *)c->url, (const char *)u)) {
    846 			if (c->from < position)
    847 				continue;
    848 			if (no_compress && !c->no_compress) {
    849 				unsigned char *enc;
    850 				if ((c->state >= S_WAIT && c->state < S_TRANS)
    851 				    || !c->cache) {
    852 					must_detach = 1;
    853 					break;
    854 				}
    855 				enc = parse_http_header(
    856 				    c->cache->head,
    857 				    cast_uchar "Content-Encoding", NULL);
    858 				if (enc) {
    859 					free(enc);
    860 					must_detach = 1;
    861 					break;
    862 				}
    863 			}
    864 			free(u);
    865 			if (getpri(c) > pri) {
    866 				del_from_list(c);
    867 				c->pri[pri]++;
    868 				add_to_queue(c);
    869 				register_bottom_half(check_queue, NULL);
    870 			} else
    871 				c->pri[pri]++;
    872 			if (stat) {
    873 				stat->prg = &c->prg;
    874 				stat->c = c;
    875 				stat->ce = c->cache;
    876 				add_to_list(c->statuss, stat);
    877 				setcstate(c, c->state);
    878 			}
    879 			goto ret;
    880 		}
    881 	c = mem_calloc(sizeof(struct connection));
    882 	c->count = connection_count++;
    883 	c->url = u;
    884 	c->prev_url = stracpy(prev_url);
    885 	c->running = 0;
    886 	c->prev_error = 0;
    887 	if (position || must_detach)
    888 		c->from = position;
    889 	else if (no_cache >= NC_IF_MOD || !e)
    890 		c->from = 0;
    891 	else {
    892 		struct fragment *frag = NULL;
    893 		struct list_head *lfrag;
    894 		c->from = 0;
    895 		foreach (struct fragment, frag, lfrag, e->frag) {
    896 			if (frag->offset != c->from)
    897 				break;
    898 			c->from += frag->length;
    899 		}
    900 	}
    901 	memset(c->pri, 0, sizeof c->pri);
    902 	c->pri[pri] = 1;
    903 	c->no_cache = no_cache;
    904 	c->sock1 = c->sock2 = -1;
    905 	c->dnsquery = NULL;
    906 	c->tries = 0;
    907 	c->netcfg_stamp = netcfg_stamp;
    908 	init_list(c->statuss);
    909 	c->info = NULL;
    910 	c->buffer = NULL;
    911 	c->newconn = NULL;
    912 	c->cache = NULL;
    913 	c->est_length = -1;
    914 	c->unrestartable = 0;
    915 	c->no_compress =
    916 	    http_options.no_compression || no_compress || dmp == D_SOURCE;
    917 	c->prg.timer = NULL;
    918 	c->timer = NULL;
    919 	if (position || must_detach) {
    920 		if (new_cache_entry(cast_uchar "", &c->cache)) {
    921 			free(c->url);
    922 			free(c->prev_url);
    923 			free(c);
    924 			if (stat) {
    925 				stat->state = S_OUT_OF_MEM;
    926 				if (stat->end)
    927 					stat->end(stat, stat->data);
    928 			}
    929 			goto ret;
    930 		}
    931 		c->cache->refcount--;
    932 		detach_cache_entry(c->cache);
    933 		c->detached = 2;
    934 	}
    935 	if (stat) {
    936 		stat->prg = &c->prg;
    937 		stat->c = c;
    938 		stat->ce = NULL;
    939 		add_to_list(c->statuss, stat);
    940 	}
    941 	add_to_queue(c);
    942 	setcstate(c, S_WAIT);
    943 	register_bottom_half(check_queue, NULL);
    944 
    945 ret:
    946 	return;
    947 }
    948 
    949 void
    950 change_connection(struct status *oldstat, struct status *newstat, int newpri)
    951 {
    952 	struct connection *c;
    953 	const int oldpri = oldstat->pri;
    954 	if (oldstat->state < 0) {
    955 		if (newstat) {
    956 			struct cache_entry *ce = oldstat->ce;
    957 			if (ce)
    958 				ce->refcount++;
    959 			newstat->ce = oldstat->ce;
    960 			newstat->state = oldstat->state;
    961 			newstat->prev_error = oldstat->prev_error;
    962 			if (newstat->end)
    963 				newstat->end(newstat, newstat->data);
    964 			if (ce)
    965 				ce->refcount--;
    966 		}
    967 		return;
    968 	}
    969 	c = oldstat->c;
    970 	if (--c->pri[oldpri] < 0) {
    971 		internal("priority counter underflow");
    972 		c->pri[oldpri] = 0;
    973 	}
    974 	c->pri[newpri]++;
    975 	del_from_list(oldstat);
    976 	oldstat->state = S_INTERRUPTED;
    977 	if (newstat) {
    978 		newstat->prg = &c->prg;
    979 		add_to_list(c->statuss, newstat);
    980 		newstat->state = c->state;
    981 		newstat->prev_error = c->prev_error;
    982 		newstat->pri = newpri;
    983 		newstat->c = c;
    984 		newstat->ce = c->cache;
    985 	}
    986 	if (c->detached && !newstat) {
    987 		setcstate(c, S_INTERRUPTED);
    988 		abort_connection(c);
    989 	}
    990 	sort_queue();
    991 	register_bottom_half(check_queue, NULL);
    992 }
    993 
    994 void
    995 detach_connection(struct status *stat, off_t pos, int want_to_restart,
    996                   int dont_check_refcount)
    997 {
    998 	struct connection *c;
    999 	int i, n_users;
   1000 	off_t l;
   1001 	if (stat->state < 0)
   1002 		return;
   1003 	c = stat->c;
   1004 	if (c->no_compress && want_to_restart)
   1005 		return;
   1006 	if (!c->cache || (!dont_check_refcount && c->cache->refcount))
   1007 		return;
   1008 	want_to_restart |= pos > c->from && is_connection_seekable(c);
   1009 	if (c->detached)
   1010 		goto detach_done;
   1011 	if (c->est_length == -1)
   1012 		l = c->from;
   1013 	else
   1014 		l = c->est_length;
   1015 	if (!dont_check_refcount
   1016 	    && l < (long)memory_cache_size * MAX_CACHED_OBJECT
   1017 	    && !want_to_restart)
   1018 		return;
   1019 	n_users = 0;
   1020 	for (i = 0; i < PRI_CANCEL; i++)
   1021 		n_users += c->pri[i];
   1022 	if (!n_users)
   1023 		internal("detaching free connection");
   1024 	if (n_users != 1)
   1025 		return;
   1026 	shrink_memory(SH_CHECK_QUOTA);
   1027 	detach_cache_entry(c->cache);
   1028 	c->detached = 1;
   1029 detach_done:
   1030 	free_entry_to(c->cache, pos);
   1031 
   1032 	if (c->detached < 2 && want_to_restart) {
   1033 		int running = c->running;
   1034 		c->no_compress = 1;
   1035 		if (running)
   1036 			interrupt_connection(c);
   1037 		c->from = pos;
   1038 		if (running)
   1039 			run_connection(c);
   1040 		c->detached = 2;
   1041 	}
   1042 }
   1043 
   1044 static uttime
   1045 get_timeout_value(struct connection *c)
   1046 {
   1047 	uttime t;
   1048 	if (c->state == S_CONN || c->state == S_CONN_ANOTHER)
   1049 		t = timeout_multiple_addresses
   1050 		    * (c->tries < 1 ? 1 : c->tries + 1);
   1051 	else if (c->unrestartable)
   1052 		t = unrestartable_receive_timeout;
   1053 	else
   1054 		t = receive_timeout;
   1055 	t *= 500;
   1056 	return t;
   1057 }
   1058 
   1059 static void
   1060 connection_timeout(void *c_)
   1061 {
   1062 	struct connection *c = (struct connection *)c_;
   1063 	c->timer = NULL;
   1064 	if (c->state == S_CONN || c->state == S_CONN_ANOTHER) {
   1065 		retry_connect(c, get_error_from_errno(ETIMEDOUT), 0);
   1066 		return;
   1067 	}
   1068 	setcstate(c, S_TIMEOUT);
   1069 	retry_connection(c);
   1070 }
   1071 
   1072 static void
   1073 connection_timeout_1(void *c_)
   1074 {
   1075 	struct connection *c = (struct connection *)c_;
   1076 	c->timer = install_timer(get_timeout_value(c), connection_timeout, c);
   1077 }
   1078 
   1079 void
   1080 clear_connection_timeout(struct connection *c)
   1081 {
   1082 	if (c->timer) {
   1083 		kill_timer(c->timer);
   1084 		c->timer = NULL;
   1085 	}
   1086 }
   1087 
   1088 void
   1089 set_connection_timeout(struct connection *c)
   1090 {
   1091 	clear_connection_timeout(c);
   1092 	c->timer = install_timer(get_timeout_value(c), connection_timeout_1, c);
   1093 }
   1094 
   1095 void
   1096 set_connection_timeout_keepal(struct connection *c)
   1097 {
   1098 	if (c->keepalive && !c->unrestartable) {
   1099 		clear_connection_timeout(c);
   1100 		c->timer = install_timer(timeout_multiple_addresses * 1000,
   1101 		                         connection_timeout, c);
   1102 		return;
   1103 	}
   1104 	set_connection_timeout(c);
   1105 }
   1106 
   1107 void
   1108 abort_all_connections(void)
   1109 {
   1110 	while (!list_empty(queue)) {
   1111 		struct connection *c =
   1112 		    list_struct(queue.next, struct connection);
   1113 		setcstate(c, S_INTERRUPTED);
   1114 		abort_connection(c);
   1115 	}
   1116 	abort_all_keepalive_connections();
   1117 }
   1118 
   1119 int
   1120 abort_background_connections(void)
   1121 {
   1122 	int did_something = 0;
   1123 	struct connection *c = NULL;
   1124 	struct list_head *lc;
   1125 again:
   1126 	foreach (struct connection, c, lc, queue) {
   1127 		if (getpri(c) >= PRI_CANCEL) {
   1128 			setcstate(c, S_INTERRUPTED);
   1129 			abort_connection(c);
   1130 			did_something = 1;
   1131 			goto again;
   1132 		}
   1133 	}
   1134 	return did_something | abort_all_keepalive_connections();
   1135 }
   1136 
   1137 int
   1138 is_entry_used(struct cache_entry *e)
   1139 {
   1140 	struct connection *c = NULL;
   1141 	struct list_head *lc;
   1142 	foreach (struct connection, c, lc, queue)
   1143 		if (c->cache == e)
   1144 			return 1;
   1145 	return 0;
   1146 }
   1147 
   1148 struct blacklist_entry {
   1149 	list_entry_1st;
   1150 	int flags;
   1151 	unsigned char host[1];
   1152 };
   1153 
   1154 static struct list_head blacklist = { &blacklist, &blacklist };
   1155 
   1156 void
   1157 add_blacklist_entry(unsigned char *host, int flags)
   1158 {
   1159 	struct blacklist_entry *b = NULL;
   1160 	struct list_head *lb;
   1161 	size_t sl;
   1162 	foreach (struct blacklist_entry, b, lb, blacklist)
   1163 		if (!casestrcmp(host, b->host)) {
   1164 			b->flags |= flags;
   1165 			return;
   1166 		}
   1167 	sl = strlen((const char *)host);
   1168 	if (sl > INT_MAX - sizeof(struct blacklist_entry))
   1169 		overalloc();
   1170 	b = xmalloc(sizeof(struct blacklist_entry) + sl);
   1171 	b->flags = flags;
   1172 	strcpy((char *)b->host, (const char *)host);
   1173 	add_to_list(blacklist, b);
   1174 }
   1175 
   1176 void
   1177 del_blacklist_entry(unsigned char *host, int flags)
   1178 {
   1179 	struct blacklist_entry *b = NULL;
   1180 	struct list_head *lb;
   1181 	foreach (struct blacklist_entry, b, lb, blacklist)
   1182 		if (!casestrcmp(host, b->host)) {
   1183 			b->flags &= ~flags;
   1184 			if (!b->flags) {
   1185 				del_from_list(b);
   1186 				free(b);
   1187 			}
   1188 			return;
   1189 		}
   1190 }
   1191 
   1192 int
   1193 get_blacklist_flags(unsigned char *host)
   1194 {
   1195 	struct blacklist_entry *b = NULL;
   1196 	struct list_head *lb;
   1197 	foreach (struct blacklist_entry, b, lb, blacklist)
   1198 		if (!casestrcmp(host, b->host))
   1199 			return b->flags;
   1200 	return 0;
   1201 }
   1202 
   1203 void
   1204 free_blacklist(void)
   1205 {
   1206 	free_list(struct blacklist_entry, blacklist);
   1207 }