1 /* Connections management */
2 
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
6 
7 #include <stdlib.h>
8 #include <string.h>
9 #ifdef HAVE_UNISTD_H
10 #include <unistd.h>
11 #endif
12 
13 #include "elinks.h"
14 
15 #include "cache/cache.h"
16 #include "config/options.h"
17 #include "document/document.h"
18 #include "encoding/encoding.h"
19 #include "intl/gettext/libintl.h"
20 #include "main/object.h"
21 #include "main/select.h"
22 #include "main/timer.h"
23 #include "network/connection.h"
24 #include "network/dns.h"
25 #include "network/progress.h"
26 #include "network/socket.h"
27 #include "network/ssl/ssl.h"
28 #include "protocol/protocol.h"
29 #include "protocol/proxy.h"
30 #include "protocol/uri.h"
31 #include "session/session.h"
32 #include "util/error.h"
33 #include "util/memory.h"
34 #include "util/string.h"
35 #include "util/time.h"
36 
37 
38 struct keepalive_connection {
39 	LIST_HEAD(struct keepalive_connection);
40 
41 	/* XXX: This is just the URI of the connection that registered the
42 	 * keepalive connection so only rely on the protocol, user, password,
43 	 * host and port part. */
44 	struct uri *uri;
45 
46 	/* Function called when the keepalive has timed out or is deleted */
47 	void (*done)(struct connection *);
48 
49 	timeval_T timeout;
50 	timeval_T creation_time;
51 
52 	unsigned int protocol_family:1; /* see network/socket.h, EL_PF_INET, EL_PF_INET6 */
53 	int socket;
54 };
55 
56 
57 static unsigned int connection_id = 0;
58 static int active_connections = 0;
59 static timer_id_T keepalive_timeout = TIMER_ID_UNDEF;
60 
61 static INIT_LIST_HEAD(connection_queue);
62 static INIT_LIST_HEAD(host_connections);
63 static INIT_LIST_HEAD(keepalive_connections);
64 
65 /* Prototypes */
66 static void notify_connection_callbacks(struct connection *conn);
67 static void check_keepalive_connections(void);
68 
69 
70 static /* inline */ enum connection_priority
get_priority(struct connection * conn)71 get_priority(struct connection *conn)
72 {
73 	enum connection_priority priority;
74 
75 	for (priority = 0; priority < PRIORITIES; priority++)
76 		if (conn->pri[priority])
77 			break;
78 
79 	assertm(priority != PRIORITIES, "Connection has no owner");
80 	/* Recovery path ;-). (XXX?) */
81 
82 	return priority;
83 }
84 
85 int
get_connections_count(void)86 get_connections_count(void)
87 {
88 	return list_size(&connection_queue);
89 }
90 
91 int
get_keepalive_connections_count(void)92 get_keepalive_connections_count(void)
93 {
94 	return list_size(&keepalive_connections);
95 }
96 
97 int
get_connections_connecting_count(void)98 get_connections_connecting_count(void)
99 {
100 	struct connection *conn;
101 	int i = 0;
102 
103 	foreach (conn, connection_queue)
104 		i += is_in_connecting_state(conn->state);
105 
106 	return i;
107 }
108 
109 int
get_connections_transfering_count(void)110 get_connections_transfering_count(void)
111 {
112 	struct connection *conn;
113 	int i = 0;
114 
115 	foreach (conn, connection_queue)
116 		i += is_in_transfering_state(conn->state);
117 
118 	return i;
119 }
120 
121 static inline int
connection_disappeared(struct connection * conn)122 connection_disappeared(struct connection *conn)
123 {
124 	struct connection *c;
125 
126 	foreach (c, connection_queue)
127 		if (conn == c && conn->id == c->id)
128 			return 0;
129 
130 	return 1;
131 }
132 
133 /* Host connection management: */
134 /* Used to keep track on the number of connections to any given host. When
135  * trying to setup a new connection the list is searched to see if the maximum
136  * number of connection has been reached. If that is the case we try to suspend
137  * an already established connection. */
138 /* Some connections (like file://) that do not involve hosts are not maintained
139  * in the list. */
140 
141 struct host_connection {
142 	OBJECT_HEAD(struct host_connection);
143 
144 	/* XXX: This is just the URI of the connection that registered the
145 	 * host connection so only rely on the host part. */
146 	struct uri *uri;
147 };
148 
149 static struct host_connection *
get_host_connection(struct connection * conn)150 get_host_connection(struct connection *conn)
151 {
152 	struct host_connection *host_conn;
153 
154 	if (!conn->uri->host) return NULL;
155 
156 	foreach (host_conn, host_connections)
157 		if (compare_uri(host_conn->uri, conn->uri, URI_HOST))
158 			return host_conn;
159 
160 	return NULL;
161 }
162 
163 /* Returns if the connection was successfully added. */
164 /* Don't add hostnameless host connections but they're valid. */
165 static int
add_host_connection(struct connection * conn)166 add_host_connection(struct connection *conn)
167 {
168 	struct host_connection *host_conn = get_host_connection(conn);
169 
170 	if (!host_conn && conn->uri->host) {
171 		host_conn = mem_calloc(1, sizeof(*host_conn));
172 		if (!host_conn) return 0;
173 
174 		host_conn->uri = get_uri_reference(conn->uri);
175 		object_nolock(host_conn, "host_connection");
176 		add_to_list(host_connections, host_conn);
177 	}
178 	if (host_conn) object_lock(host_conn);
179 
180 	return 1;
181 }
182 
183 /* Decrements and free()s the host connection if it is the last 'refcount'. */
184 static void
done_host_connection(struct connection * conn)185 done_host_connection(struct connection *conn)
186 {
187 	struct host_connection *host_conn = get_host_connection(conn);
188 
189 	if (!host_conn) return;
190 
191 	object_unlock(host_conn);
192 	if (is_object_used(host_conn)) return;
193 
194 	del_from_list(host_conn);
195 	done_uri(host_conn->uri);
196 	mem_free(host_conn);
197 }
198 
199 
200 static void sort_queue();
201 
202 #ifdef CONFIG_DEBUG
203 static void
check_queue_bugs(void)204 check_queue_bugs(void)
205 {
206 	struct connection *conn;
207 	enum connection_priority prev_priority = 0;
208 	int cc = 0;
209 
210 	foreach (conn, connection_queue) {
211 		enum connection_priority priority = get_priority(conn);
212 
213 		cc += conn->running;
214 
215 		assertm(priority >= prev_priority, "queue is not sorted");
216 		assertm(is_in_progress_state(conn->state),
217 			"interrupted connection on queue (conn %s, state %d)",
218 			struri(conn->uri), conn->state);
219 		prev_priority = priority;
220 	}
221 
222 	assertm(cc == active_connections,
223 		"bad number of active connections (counted %d, stored %d)",
224 		cc, active_connections);
225 }
226 #else
227 #define check_queue_bugs()
228 #endif
229 
230 static void
set_connection_socket_state(struct socket * socket,enum connection_state state)231 set_connection_socket_state(struct socket *socket, enum connection_state state)
232 {
233 	assert(socket);
234 	set_connection_state(socket->conn, state);
235 }
236 
237 static void
set_connection_socket_timeout(struct socket * socket,enum connection_state state)238 set_connection_socket_timeout(struct socket *socket, enum connection_state state)
239 {
240 	assert(socket);
241 	set_connection_timeout(socket->conn);
242 }
243 
244 static void
retry_connection_socket(struct socket * socket,enum connection_state state)245 retry_connection_socket(struct socket *socket, enum connection_state state)
246 {
247 	assert(socket);
248 	retry_connection(socket->conn, state);
249 }
250 
251 static void
done_connection_socket(struct socket * socket,enum connection_state state)252 done_connection_socket(struct socket *socket, enum connection_state state)
253 {
254 	assert(socket);
255 	abort_connection(socket->conn, state);
256 }
257 
258 static struct connection *
init_connection(struct uri * uri,struct uri * proxied_uri,struct uri * referrer,off_t start,enum cache_mode cache_mode,enum connection_priority priority)259 init_connection(struct uri *uri, struct uri *proxied_uri, struct uri *referrer,
260 		off_t start, enum cache_mode cache_mode,
261 		enum connection_priority priority)
262 {
263 	static struct socket_operations connection_socket_operations = {
264 		set_connection_socket_state,
265 		set_connection_socket_timeout,
266 		retry_connection_socket,
267 		done_connection_socket,
268 	};
269 	struct connection *conn = mem_calloc(1, sizeof(*conn));
270 
271 	if (!conn) return NULL;
272 
273 	assert(proxied_uri->protocol != PROTOCOL_PROXY);
274 
275 	conn->socket = init_socket(conn, &connection_socket_operations);
276 	if (!conn->socket) {
277 		mem_free(conn);
278 		return NULL;
279 	}
280 
281 	conn->data_socket = init_socket(conn, &connection_socket_operations);
282 	if (!conn->data_socket) {
283 		mem_free(conn->socket);
284 		mem_free(conn);
285 		return NULL;
286 	}
287 
288 	conn->progress = init_progress(start);
289 	if (!conn->progress) {
290 		mem_free(conn->data_socket);
291 		mem_free(conn->socket);
292 		mem_free(conn);
293 		return NULL;
294 	}
295 
296 	/* load_uri() gets the URI from get_proxy() which grabs a reference for
297 	 * us. */
298 	conn->uri = uri;
299 	conn->proxied_uri = proxied_uri;
300 	conn->id = connection_id++;
301 	conn->pri[priority] = 1;
302 	conn->cache_mode = cache_mode;
303 
304 	conn->content_encoding = ENCODING_NONE;
305 	conn->stream_pipes[0] = conn->stream_pipes[1] = -1;
306 	conn->cgi_pipes[0] = conn->cgi_pipes[1] = -1;
307 	init_list(conn->downloads);
308 	conn->est_length = -1;
309 	conn->timer = TIMER_ID_UNDEF;
310 
311 	if (referrer) {
312 		/* Don't set referrer when it is the file protocol and the URI
313 		 * being loaded is not. This means CGI scripts will have it
314 		 * available while preventing information about the local
315 		 * system from being leaked to external servers. */
316 		if (referrer->protocol != PROTOCOL_FILE
317 		    || uri->protocol == PROTOCOL_FILE)
318 			conn->referrer = get_uri_reference(referrer);
319 	}
320 
321 	return conn;
322 }
323 
324 static void
update_connection_progress(struct connection * conn)325 update_connection_progress(struct connection *conn)
326 {
327 	update_progress(conn->progress, conn->received, conn->est_length, conn->from);
328 }
329 
330 static void
stat_timer(struct connection * conn)331 stat_timer(struct connection *conn)
332 {
333 	update_connection_progress(conn);
334 	notify_connection_callbacks(conn);
335 }
336 
337 void
set_connection_state(struct connection * conn,enum connection_state state)338 set_connection_state(struct connection *conn, enum connection_state state)
339 {
340 	struct download *download;
341 	struct progress *progress = conn->progress;
342 
343 	if (is_in_result_state(conn->state) && is_in_progress_state(state))
344 		conn->prev_error = conn->state;
345 
346 	conn->state = state;
347 	if (conn->state == S_TRANS) {
348 		if (progress->timer == TIMER_ID_UNDEF) {
349 			start_update_progress(progress, (void (*)(void *)) stat_timer, conn);
350 			update_connection_progress(conn);
351 			if (connection_disappeared(conn))
352 				return;
353 		}
354 
355 	} else {
356 		kill_timer(&progress->timer);
357 	}
358 
359 	foreach (download, conn->downloads) {
360 		download->state = state;
361 		download->prev_error = conn->prev_error;
362 	}
363 
364 	if (is_in_progress_state(state)) notify_connection_callbacks(conn);
365 }
366 
367 void
shutdown_connection_stream(struct connection * conn)368 shutdown_connection_stream(struct connection *conn)
369 {
370 	if (conn->stream) {
371 		close_encoded(conn->stream);
372 		conn->stream = NULL;
373 	}
374 	if (conn->stream_pipes[1] >= 0)
375 		close(conn->stream_pipes[1]);
376 	conn->stream_pipes[0] = conn->stream_pipes[1] = -1;
377 }
378 
379 static void
free_connection_data(struct connection * conn)380 free_connection_data(struct connection *conn)
381 {
382 	assertm(conn->running, "connection already suspended");
383 	/* XXX: Recovery path? Originally, there was none. I think we'll get
384 	 * at least active_connections underflows along the way. --pasky */
385 	conn->running = 0;
386 
387 	active_connections--;
388 	assertm(active_connections >= 0, "active connections underflow");
389 	if_assert_failed active_connections = 0;
390 
391 #ifdef CONFIG_SSL
392 	if (conn->socket->ssl && conn->cached)
393 		mem_free_set(&conn->cached->ssl_info, get_ssl_connection_cipher(conn->socket));
394 #endif
395 
396 	if (conn->done)
397 		conn->done(conn);
398 
399 	done_socket(conn->socket);
400 	done_socket(conn->data_socket);
401 
402 	shutdown_connection_stream(conn);
403 
404 	if (conn->cgi_pipes[0] >= 0)
405 		close(conn->cgi_pipes[0]);
406 	if (conn->cgi_pipes[1] >= 0)
407 		close(conn->cgi_pipes[1]);
408 	conn->cgi_pipes[0] = conn->cgi_pipes[1] = -1;
409 
410 	mem_free_set(&conn->info, NULL);
411 
412 	kill_timer(&conn->timer);
413 
414 	if (conn->state != S_WAIT)
415 		done_host_connection(conn);
416 }
417 
418 void
notify_connection_callbacks(struct connection * conn)419 notify_connection_callbacks(struct connection *conn)
420 {
421 	enum connection_state state = conn->state;
422 	struct download *download, *next;
423 
424 	foreachsafe (download, next, conn->downloads) {
425 		download->cached = conn->cached;
426 		if (download->callback)
427 			download->callback(download, download->data);
428 		if (is_in_progress_state(state) && connection_disappeared(conn))
429 			return;
430 	}
431 }
432 
433 static void
done_connection(struct connection * conn)434 done_connection(struct connection *conn)
435 {
436 	/* When removing the connection callbacks should always be aware of it
437 	 * so they can unregister themselves. We do this by enforcing that the
438 	 * connection is in a result state. If it is not already it is an
439 	 * internal bug. This should never happen but it does. ;) --jonas */
440 	if (!is_in_result_state(conn->state))
441 		set_connection_state(conn, S_INTERNAL);
442 
443 	del_from_list(conn);
444 	notify_connection_callbacks(conn);
445 	if (conn->referrer) done_uri(conn->referrer);
446 	done_uri(conn->uri);
447 	done_uri(conn->proxied_uri);
448 	mem_free(conn->socket);
449 	mem_free(conn->data_socket);
450 	done_progress(conn->progress);
451 	mem_free(conn);
452 	check_queue_bugs();
453 }
454 
455 static inline void
add_to_queue(struct connection * conn)456 add_to_queue(struct connection *conn)
457 {
458 	struct connection *c;
459 	enum connection_priority priority = get_priority(conn);
460 
461 	foreach (c, connection_queue)
462 		if (get_priority(c) > priority)
463 			break;
464 
465 	add_at_pos(c->prev, conn);
466 }
467 
468 
469 /* Returns zero if no callback was done and the keepalive connection should be
470  * deleted or non-zero if the keepalive connection should not be deleted. */
471 static int
do_keepalive_connection_callback(struct keepalive_connection * keep_conn)472 do_keepalive_connection_callback(struct keepalive_connection *keep_conn)
473 {
474 	struct uri *proxied_uri = get_proxied_uri(keep_conn->uri);
475 	struct uri *proxy_uri   = get_proxy_uri(keep_conn->uri, NULL);
476 
477 	if (proxied_uri && proxy_uri) {
478 		struct connection *conn;
479 
480 		conn = init_connection(proxy_uri, proxied_uri, NULL, 0,
481 				       CACHE_MODE_NEVER, PRI_CANCEL);
482 
483 		if (conn) {
484 			void (*done)(struct connection *) = keep_conn->done;
485 
486 			add_to_queue(conn);
487 
488 			/* Get the keepalive info and let it clean up */
489 			if (!has_keepalive_connection(conn)
490 			    || !add_host_connection(conn)) {
491 				free_connection_data(conn);
492 				done_connection(conn);
493 				return 0;
494 			}
495 
496 			active_connections++;
497 			conn->running = 1;
498 			done(conn);
499 			return 1;
500 		}
501 	}
502 
503 	if (proxied_uri) done_uri(proxied_uri);
504 	if (proxy_uri) done_uri(proxy_uri);
505 
506 	return 0;
507 }
508 
509 static inline void
done_keepalive_connection(struct keepalive_connection * keep_conn)510 done_keepalive_connection(struct keepalive_connection *keep_conn)
511 {
512 	if (keep_conn->done && do_keepalive_connection_callback(keep_conn))
513 		return;
514 
515 	del_from_list(keep_conn);
516 	if (keep_conn->socket != -1) close(keep_conn->socket);
517 	done_uri(keep_conn->uri);
518 	mem_free(keep_conn);
519 }
520 
521 static struct keepalive_connection *
init_keepalive_connection(struct connection * conn,long timeout_in_seconds,void (* done)(struct connection *))522 init_keepalive_connection(struct connection *conn, long timeout_in_seconds,
523 			  void (*done)(struct connection *))
524 {
525 	struct keepalive_connection *keep_conn;
526 	struct uri *uri = conn->uri;
527 
528 	assert(uri->host);
529 	if_assert_failed return NULL;
530 
531 	keep_conn = mem_calloc(1, sizeof(*keep_conn));
532 	if (!keep_conn) return NULL;
533 
534 	keep_conn->uri = get_uri_reference(uri);
535 	keep_conn->done = done;
536 	keep_conn->protocol_family = conn->socket->protocol_family;
537 	keep_conn->socket = conn->socket->fd;
538 	timeval_from_seconds(&keep_conn->timeout, timeout_in_seconds);
539 	timeval_now(&keep_conn->creation_time);
540 
541 	return keep_conn;
542 }
543 
544 static struct keepalive_connection *
get_keepalive_connection(struct connection * conn)545 get_keepalive_connection(struct connection *conn)
546 {
547 	struct keepalive_connection *keep_conn;
548 
549 	if (!conn->uri->host) return NULL;
550 
551 	foreach (keep_conn, keepalive_connections)
552 		if (compare_uri(keep_conn->uri, conn->uri, URI_KEEPALIVE))
553 			return keep_conn;
554 
555 	return NULL;
556 }
557 
558 int
has_keepalive_connection(struct connection * conn)559 has_keepalive_connection(struct connection *conn)
560 {
561 	struct keepalive_connection *keep_conn = get_keepalive_connection(conn);
562 
563 	if (!keep_conn) return 0;
564 
565 	conn->socket->fd = keep_conn->socket;
566 	conn->socket->protocol_family = keep_conn->protocol_family;
567 
568 	/* Mark that the socket should not be closed and the callback should be
569 	 * ignored. */
570 	keep_conn->socket = -1;
571 	keep_conn->done = NULL;
572 	done_keepalive_connection(keep_conn);
573 
574 	return 1;
575 }
576 
577 void
add_keepalive_connection(struct connection * conn,long timeout_in_seconds,void (* done)(struct connection *))578 add_keepalive_connection(struct connection *conn, long timeout_in_seconds,
579 			 void (*done)(struct connection *))
580 {
581 	struct keepalive_connection *keep_conn;
582 
583 	assertm(conn->socket->fd != -1, "keepalive connection not connected");
584 	if_assert_failed goto done;
585 
586 	keep_conn = init_keepalive_connection(conn, timeout_in_seconds, done);
587 	if (keep_conn) {
588 		/* Make sure that the socket descriptor will not periodically be
589 		 * checked or closed by free_connection_data(). */
590 		clear_handlers(conn->socket->fd);
591 		conn->socket->fd = -1;
592 		add_to_list(keepalive_connections, keep_conn);
593 
594 	} else if (done) {
595 		/* It will take just a little more time */
596 		done(conn);
597 		return;
598 	}
599 
600 done:
601 	free_connection_data(conn);
602 	done_connection(conn);
603 	register_check_queue();
604 }
605 
606 static void
keepalive_timer(void * x)607 keepalive_timer(void *x)
608 {
609 	keepalive_timeout = TIMER_ID_UNDEF;
610 	check_keepalive_connections();
611 }
612 
613 void
check_keepalive_connections(void)614 check_keepalive_connections(void)
615 {
616 	struct keepalive_connection *keep_conn, *next;
617 	timeval_T now;
618 	int p = 0;
619 
620 	timeval_now(&now);
621 
622 	kill_timer(&keepalive_timeout);
623 
624 	foreachsafe (keep_conn, next, keepalive_connections) {
625 		timeval_T age;
626 
627 		if (can_read(keep_conn->socket)) {
628 			done_keepalive_connection(keep_conn);
629 			continue;
630 		}
631 
632 		timeval_sub(&age, &keep_conn->creation_time, &now);
633 		if (timeval_cmp(&age, &keep_conn->timeout) > 0) {
634 			done_keepalive_connection(keep_conn);
635 			continue;
636 		}
637 
638 		p++;
639 	}
640 
641 	for (; p > MAX_KEEPALIVE_CONNECTIONS; p--) {
642 		assertm(!list_empty(keepalive_connections), "keepalive list empty");
643 		if_assert_failed return;
644 		done_keepalive_connection(keepalive_connections.prev);
645 	}
646 
647 	if (!list_empty(keepalive_connections))
648 		install_timer(&keepalive_timeout, KEEPALIVE_CHECK_TIME,
649 			      keepalive_timer, NULL);
650 }
651 
652 static inline void
abort_all_keepalive_connections(void)653 abort_all_keepalive_connections(void)
654 {
655 	while (!list_empty(keepalive_connections))
656 		done_keepalive_connection(keepalive_connections.next);
657 
658 	check_keepalive_connections();
659 }
660 
661 
662 static void
sort_queue(void)663 sort_queue(void)
664 {
665 	while (1) {
666 		struct connection *conn;
667 		int swp = 0;
668 
669 		foreach (conn, connection_queue) {
670 			if (!list_has_next(connection_queue, conn)) break;
671 
672 			if (get_priority(conn->next) < get_priority(conn)) {
673 				struct connection *c = conn->next;
674 
675 				del_from_list(conn);
676 				add_at_pos(c, conn);
677 				swp = 1;
678 			}
679 		}
680 
681 		if (!swp) break;
682 	};
683 }
684 
685 static void
interrupt_connection(struct connection * conn)686 interrupt_connection(struct connection *conn)
687 {
688 	free_connection_data(conn);
689 }
690 
691 static inline void
suspend_connection(struct connection * conn)692 suspend_connection(struct connection *conn)
693 {
694 	interrupt_connection(conn);
695 	set_connection_state(conn, S_WAIT);
696 }
697 
698 static void
run_connection(struct connection * conn)699 run_connection(struct connection *conn)
700 {
701 	protocol_handler_T *func = get_protocol_handler(conn->uri->protocol);
702 
703 	assert(func);
704 
705 	assertm(!conn->running, "connection already running");
706 	if_assert_failed return;
707 
708 	if (!add_host_connection(conn)) {
709 		set_connection_state(conn, S_OUT_OF_MEM);
710 		done_connection(conn);
711 		return;
712 	}
713 
714 	active_connections++;
715 	conn->running = 1;
716 
717 	func(conn);
718 }
719 
720 /* Set certain state on a connection and then abort the connection. */
721 void
abort_connection(struct connection * conn,enum connection_state state)722 abort_connection(struct connection *conn, enum connection_state state)
723 {
724 	assertm(is_in_result_state(state),
725 		"connection didn't end in result state (%d)", state);
726 
727 	set_connection_state(conn, state);
728 
729 	if (conn->running) interrupt_connection(conn);
730 	done_connection(conn);
731 	register_check_queue();
732 }
733 
734 /* Set certain state on a connection and then retry the connection. */
735 void
retry_connection(struct connection * conn,enum connection_state state)736 retry_connection(struct connection *conn, enum connection_state state)
737 {
738 	int max_tries = get_opt_int("connection.retries");
739 
740 	assertm(is_in_result_state(state),
741 		"connection didn't end in result state (%d)", state);
742 
743 	set_connection_state(conn, state);
744 
745 	interrupt_connection(conn);
746 	if (conn->uri->post || !max_tries || ++conn->tries >= max_tries) {
747 		done_connection(conn);
748 		register_check_queue();
749 	} else {
750 		conn->prev_error = conn->state;
751 		run_connection(conn);
752 	}
753 }
754 
755 static int
try_to_suspend_connection(struct connection * conn,struct uri * uri)756 try_to_suspend_connection(struct connection *conn, struct uri *uri)
757 {
758 	enum connection_priority priority = get_priority(conn);
759 	struct connection *c;
760 
761 	foreachback (c, connection_queue) {
762 		if (get_priority(c) <= priority) return -1;
763 		if (c->state == S_WAIT) continue;
764 		if (c->uri->post && get_priority(c) < PRI_CANCEL) continue;
765 		if (uri && !compare_uri(uri, c->uri, URI_HOST)) continue;
766 		suspend_connection(c);
767 		return 0;
768 	}
769 
770 	return -1;
771 }
772 
773 static inline int
try_connection(struct connection * conn,int max_conns_to_host,int max_conns)774 try_connection(struct connection *conn, int max_conns_to_host, int max_conns)
775 {
776 	struct host_connection *host_conn = get_host_connection(conn);
777 
778 	if (host_conn && get_object_refcount(host_conn) >= max_conns_to_host)
779 		return try_to_suspend_connection(conn, host_conn->uri) ? 0 : -1;
780 
781 	if (active_connections >= max_conns)
782 		return try_to_suspend_connection(conn, NULL) ? 0 : -1;
783 
784 	run_connection(conn);
785 	return 1;
786 }
787 
788 static void
check_queue(void)789 check_queue(void)
790 {
791 	struct connection *conn;
792 	int max_conns_to_host = get_opt_int("connection.max_connections_to_host");
793 	int max_conns = get_opt_int("connection.max_connections");
794 
795 again:
796 	conn = connection_queue.next;
797 	check_queue_bugs();
798 	check_keepalive_connections();
799 
800 	while (conn != (struct connection *) &connection_queue) {
801 		struct connection *c;
802 		enum connection_priority pri = get_priority(conn);
803 
804 		for (c = conn; c != (struct connection *) &connection_queue && get_priority(c) == pri;) {
805 			struct connection *cc = c;
806 
807 			c = c->next;
808 			if (cc->state == S_WAIT && get_keepalive_connection(cc)
809 			    && try_connection(cc, max_conns_to_host, max_conns))
810 				goto again;
811 		}
812 
813 		for (c = conn; c != (struct connection *) &connection_queue && get_priority(c) == pri;) {
814 			struct connection *cc = c;
815 
816 			c = c->next;
817 			if (cc->state == S_WAIT
818 			    && try_connection(cc, max_conns_to_host, max_conns))
819 				goto again;
820 		}
821 		conn = c;
822 	}
823 
824 again2:
825 	foreachback (conn, connection_queue) {
826 		if (get_priority(conn) < PRI_CANCEL) break;
827 		if (conn->state == S_WAIT) {
828 			set_connection_state(conn, S_INTERRUPTED);
829 			done_connection(conn);
830 			goto again2;
831 		}
832 	}
833 
834 	check_queue_bugs();
835 }
836 
837 int
register_check_queue(void)838 register_check_queue(void)
839 {
840 	return register_bottom_half(check_queue, NULL);
841 }
842 
843 int
load_uri(struct uri * uri,struct uri * referrer,struct download * download,enum connection_priority pri,enum cache_mode cache_mode,off_t start)844 load_uri(struct uri *uri, struct uri *referrer, struct download *download,
845 	 enum connection_priority pri, enum cache_mode cache_mode, off_t start)
846 {
847 	struct cache_entry *cached;
848 	struct connection *conn;
849 	struct uri *proxy_uri, *proxied_uri;
850 	enum connection_state connection_state = S_OK;
851 
852 	if (download) {
853 		download->conn = NULL;
854 		download->cached = NULL;
855 		download->pri = pri;
856 		download->state = S_OUT_OF_MEM;
857 		download->prev_error = 0;
858 	}
859 
860 #ifdef CONFIG_DEBUG
861 	foreach (conn, connection_queue) {
862 		struct download *assigned;
863 
864 		foreach (assigned, conn->downloads) {
865 			assertm(assigned != download, "Download assigned to '%s'", struri(conn->uri));
866 			if_assert_failed {
867 				download->state = S_INTERNAL;
868 				if (download->callback)
869 					download->callback(download, download->data);
870 				return 0;
871 			}
872 			/* No recovery path should be necessary. */
873 		}
874 	}
875 #endif
876 
877 	cached = get_validated_cache_entry(uri, cache_mode);
878 	if (cached) {
879 		if (download) {
880 			download->cached = cached;
881 			download->state = S_OK;
882 			/* XXX:
883 			 * This doesn't work since sometimes |download->progress|
884 			 * is undefined and contains random memory locations.
885 			 * It's not supposed to point on anything here since
886 			 * |download| has no connection attached.
887 			 * Downloads resuming will probably break in some
888 			 * cases without this, though.
889 			 * FIXME: Needs more investigation. --pasky */
890 			/* if (download->progress) download->progress->start = start; */
891 			if (download->callback)
892 				download->callback(download, download->data);
893 		}
894 		return 0;
895 	}
896 
897 	proxied_uri = get_proxied_uri(uri);
898 	proxy_uri   = get_proxy_uri(uri, &connection_state);
899 
900 	if (!proxy_uri
901 	    || !proxied_uri
902 	    || (get_protocol_need_slash_after_host(proxy_uri->protocol)
903 		&& !proxy_uri->hostlen)) {
904 
905 		if (download) {
906 			if (connection_state == S_OK) {
907 				connection_state = proxy_uri && proxied_uri
908 						 ? S_BAD_URL : S_OUT_OF_MEM;
909 			}
910 
911 			download->state = connection_state;
912 			download->callback(download, download->data);
913 		}
914 		if (proxy_uri) done_uri(proxy_uri);
915 		if (proxied_uri) done_uri(proxied_uri);
916 		return -1;
917 	}
918 
919 	foreach (conn, connection_queue) {
920 		if (conn->detached
921 		    || !compare_uri(conn->uri, proxy_uri, 0))
922 			continue;
923 
924 		done_uri(proxy_uri);
925 		done_uri(proxied_uri);
926 
927 		if (get_priority(conn) > pri) {
928 			del_from_list(conn);
929 			conn->pri[pri]++;
930 			add_to_queue(conn);
931 			register_check_queue();
932 		} else {
933 			conn->pri[pri]++;
934 		}
935 
936 		if (download) {
937 			download->progress = conn->progress;
938 			download->conn = conn;
939 			download->cached = conn->cached;
940 			add_to_list(conn->downloads, download);
941 			/* This is likely to call download->callback() now! */
942 			set_connection_state(conn, conn->state);
943 		}
944 		check_queue_bugs();
945 		return 0;
946 	}
947 
948 	conn = init_connection(proxy_uri, proxied_uri, referrer, start, cache_mode, pri);
949 	if (!conn) {
950 		if (download) {
951 			download->state = S_OUT_OF_MEM;
952 			download->callback(download, download->data);
953 		}
954 		if (proxy_uri) done_uri(proxy_uri);
955 		if (proxied_uri) done_uri(proxied_uri);
956 		return -1;
957 	}
958 
959 	if (cache_mode < CACHE_MODE_FORCE_RELOAD && cached && !list_empty(cached->frag)
960 	    && !((struct fragment *) cached->frag.next)->offset)
961 		conn->from = ((struct fragment *) cached->frag.next)->length;
962 
963 	if (download) {
964 		download->progress = conn->progress;
965 		download->conn = conn;
966 		download->cached = NULL;
967 		add_to_list(conn->downloads, download);
968 	}
969 
970 	add_to_queue(conn);
971 	set_connection_state(conn, S_WAIT);
972 
973 	check_queue_bugs();
974 
975 	register_check_queue();
976 	return 0;
977 }
978 
979 
980 /* FIXME: one object in more connections */
981 void
change_connection(struct download * old,struct download * new,enum connection_priority newpri,int interrupt)982 change_connection(struct download *old, struct download *new,
983 		  enum connection_priority newpri, int interrupt)
984 {
985 	struct connection *conn;
986 
987 	assert(old);
988 	if_assert_failed return;
989 
990 	if (is_in_result_state(old->state)) {
991 		if (new) {
992 			new->cached = old->cached;
993 			new->state = old->state;
994 			new->prev_error = old->prev_error;
995 			if (new->callback)
996 				new->callback(new, new->data);
997 		}
998 		return;
999 	}
1000 
1001 	check_queue_bugs();
1002 
1003 	conn = old->conn;
1004 
1005 	conn->pri[old->pri]--;
1006 	assertm(conn->pri[old->pri] >= 0, "priority counter underflow");
1007 	if_assert_failed conn->pri[old->pri] = 0;
1008 
1009 	conn->pri[newpri]++;
1010 	del_from_list(old);
1011 	old->state = S_INTERRUPTED;
1012 
1013 	if (new) {
1014 		new->progress = conn->progress;
1015 		add_to_list(conn->downloads, new);
1016 		new->state = conn->state;
1017 		new->prev_error = conn->prev_error;
1018 		new->pri = newpri;
1019 		new->conn = conn;
1020 		new->cached = conn->cached;
1021 
1022 	} else if (conn->detached || interrupt) {
1023 		abort_connection(conn, S_INTERRUPTED);
1024 	}
1025 
1026 	sort_queue();
1027 	check_queue_bugs();
1028 
1029 	register_check_queue();
1030 }
1031 
1032 /* This will remove 'pos' bytes from the start of the cache for the specified
1033  * connection, if the cached object is already too big. */
1034 void
detach_connection(struct download * download,off_t pos)1035 detach_connection(struct download *download, off_t pos)
1036 {
1037 	struct connection *conn = download->conn;
1038 
1039 	if (is_in_result_state(download->state)) return;
1040 
1041 	if (!conn->detached) {
1042 		off_t total_len;
1043 		off_t i, total_pri = 0;
1044 
1045 		if (!conn->cached)
1046 			return;
1047 
1048 		total_len = (conn->est_length == -1) ? conn->from
1049 						     : conn->est_length;
1050 
1051 		if (total_len < (get_opt_long("document.cache.memory.size")
1052 				 * MAX_CACHED_OBJECT_PERCENT / 100)) {
1053 			/* This whole thing will fit to the memory anyway, so
1054 			 * there's no problem in detaching the connection. */
1055 			return;
1056 		}
1057 
1058 		for (i = 0; i < PRI_CANCEL; i++)
1059 			total_pri += conn->pri[i];
1060 		assertm(total_pri, "detaching free connection");
1061 		/* No recovery path should be necessary...? */
1062 
1063 		/* Pre-clean cache. */
1064 		shrink_format_cache(0);
1065 
1066 		if (total_pri != 1 || is_object_used(conn->cached)) {
1067 			/* We're too important, or someone uses our cache
1068 			 * entry. */
1069 			return;
1070 		}
1071 
1072 		/* DBG("detached"); */
1073 
1074 		/* We aren't valid cache entry anymore. */
1075 		conn->cached->valid = 0;
1076 		conn->detached = 1;
1077 	}
1078 
1079 	/* Strip the entry. */
1080 	free_entry_to(conn->cached, pos);
1081 }
1082 
1083 static void
connection_timeout(struct connection * conn)1084 connection_timeout(struct connection *conn)
1085 {
1086 	conn->timer = TIMER_ID_UNDEF;
1087 	timeout_socket(conn->socket);
1088 }
1089 
1090 /* Huh, using two timers? Is this to account for changes of c->unrestartable
1091  * or can it be reduced? --jonas */
1092 static void
connection_timeout_1(struct connection * conn)1093 connection_timeout_1(struct connection *conn)
1094 {
1095 	install_timer(&conn->timer, (milliseconds_T)
1096 			((conn->unrestartable
1097 			 ? get_opt_int("connection.unrestartable_receive_timeout")
1098 			 : get_opt_int("connection.receive_timeout"))
1099 			* 500), (void (*)(void *)) connection_timeout, conn);
1100 }
1101 
1102 void
set_connection_timeout(struct connection * conn)1103 set_connection_timeout(struct connection *conn)
1104 {
1105 	kill_timer(&conn->timer);
1106 
1107 	install_timer(&conn->timer, (milliseconds_T)
1108 			((conn->unrestartable
1109 			 ? get_opt_int("connection.unrestartable_receive_timeout")
1110 			 : get_opt_int("connection.receive_timeout"))
1111 			* 500), (void (*)(void *)) connection_timeout_1, conn);
1112 }
1113 
1114 
1115 void
abort_all_connections(void)1116 abort_all_connections(void)
1117 {
1118 	while (!list_empty(connection_queue)) {
1119 		abort_connection(connection_queue.next, S_INTERRUPTED);
1120 	}
1121 
1122 	abort_all_keepalive_connections();
1123 }
1124 
1125 void
abort_background_connections(void)1126 abort_background_connections(void)
1127 {
1128 	struct connection *conn, *next;
1129 
1130 	foreachsafe (conn, next, connection_queue) {
1131 		if (get_priority(conn) >= PRI_CANCEL)
1132 			abort_connection(conn, S_INTERRUPTED);
1133 	}
1134 }
1135 
1136 int
is_entry_used(struct cache_entry * cached)1137 is_entry_used(struct cache_entry *cached)
1138 {
1139 	struct connection *conn;
1140 
1141 	foreach (conn, connection_queue)
1142 		if (conn->cached == cached)
1143 			return 1;
1144 
1145 	return 0;
1146 }
1147