bug 771: Remember whether navigation was requested by user
[elinks/kon.git] / src / network / connection.c
blob61614ee80401f15ddb1155d3a25f7e360f920b9a
1 /* Connections management */
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
7 #include <stdlib.h>
8 #include <string.h>
9 #ifdef HAVE_UNISTD_H
10 #include <unistd.h>
11 #endif
13 #include "elinks.h"
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"
38 struct keepalive_connection {
39 LIST_HEAD(struct keepalive_connection);
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;
46 /* Function called when the keepalive has timed out or is deleted */
47 void (*done)(struct connection *);
49 timeval_T timeout;
50 timeval_T creation_time;
52 unsigned int protocol_family:1; /* see network/socket.h, EL_PF_INET, EL_PF_INET6 */
53 int socket;
57 static unsigned int connection_id = 0;
58 static int active_connections = 0;
59 static timer_id_T keepalive_timeout = TIMER_ID_UNDEF;
61 static INIT_LIST_OF(struct connection, connection_queue);
62 static INIT_LIST_OF(struct host_connection, host_connections);
63 static INIT_LIST_OF(struct keepalive_connection, keepalive_connections);
65 /* Prototypes */
66 static void notify_connection_callbacks(struct connection *conn);
67 static void check_keepalive_connections(void);
70 static /* inline */ enum connection_priority
71 get_priority(struct connection *conn)
73 enum connection_priority priority;
75 for (priority = 0; priority < PRIORITIES; priority++)
76 if (conn->pri[priority])
77 break;
79 assertm(priority != PRIORITIES, "Connection has no owner");
80 /* Recovery path ;-). (XXX?) */
82 return priority;
85 int
86 get_connections_count(void)
88 return list_size(&connection_queue);
91 int
92 get_keepalive_connections_count(void)
94 return list_size(&keepalive_connections);
97 int
98 get_connections_connecting_count(void)
100 struct connection *conn;
101 int i = 0;
103 foreach (conn, connection_queue)
104 i += is_in_connecting_state(conn->state);
106 return i;
110 get_connections_transfering_count(void)
112 struct connection *conn;
113 int i = 0;
115 foreach (conn, connection_queue)
116 i += is_in_transfering_state(conn->state);
118 return i;
121 /** Check whether the pointer @a conn still points to a connection
122 * with the given @a id. If the struct connection has already been
123 * freed, this returns 0. By comparing connection.id, this function
124 * can usually detect even the case where a different connection has
125 * been created at the same address. For that to work, the caller
126 * must save the connection.id before the connection can be deleted. */
127 static inline int
128 connection_disappeared(struct connection *conn, unsigned int id)
130 struct connection *c;
132 foreach (c, connection_queue)
133 if (conn == c && id == c->id)
134 return 0;
136 return 1;
139 /* Host connection management: */
140 /* Used to keep track on the number of connections to any given host. When
141 * trying to setup a new connection the list is searched to see if the maximum
142 * number of connection has been reached. If that is the case we try to suspend
143 * an already established connection. */
144 /* Some connections (like file://) that do not involve hosts are not maintained
145 * in the list. */
147 struct host_connection {
148 OBJECT_HEAD(struct host_connection);
150 /* XXX: This is just the URI of the connection that registered the
151 * host connection so only rely on the host part. */
152 struct uri *uri;
155 static struct host_connection *
156 get_host_connection(struct connection *conn)
158 struct host_connection *host_conn;
160 if (!conn->uri->host) return NULL;
162 foreach (host_conn, host_connections)
163 if (compare_uri(host_conn->uri, conn->uri, URI_HOST))
164 return host_conn;
166 return NULL;
169 /* Returns if the connection was successfully added. */
170 /* Don't add hostnameless host connections but they're valid. */
171 static int
172 add_host_connection(struct connection *conn)
174 struct host_connection *host_conn = get_host_connection(conn);
176 if (!host_conn && conn->uri->host) {
177 host_conn = mem_calloc(1, sizeof(*host_conn));
178 if (!host_conn) return 0;
180 host_conn->uri = get_uri_reference(conn->uri);
181 object_nolock(host_conn, "host_connection");
182 add_to_list(host_connections, host_conn);
184 if (host_conn) object_lock(host_conn);
186 return 1;
189 /* Decrements and free()s the host connection if it is the last 'refcount'. */
190 static void
191 done_host_connection(struct connection *conn)
193 struct host_connection *host_conn = get_host_connection(conn);
195 if (!host_conn) return;
197 object_unlock(host_conn);
198 if (is_object_used(host_conn)) return;
200 del_from_list(host_conn);
201 done_uri(host_conn->uri);
202 mem_free(host_conn);
206 static void sort_queue();
208 #ifdef CONFIG_DEBUG
209 static void
210 check_queue_bugs(void)
212 struct connection *conn;
213 enum connection_priority prev_priority = 0;
214 int cc = 0;
216 foreach (conn, connection_queue) {
217 enum connection_priority priority = get_priority(conn);
219 cc += conn->running;
221 assertm(priority >= prev_priority, "queue is not sorted");
222 assertm(is_in_progress_state(conn->state),
223 "interrupted connection on queue (conn %s, state %d)",
224 struri(conn->uri), conn->state);
225 prev_priority = priority;
228 assertm(cc == active_connections,
229 "bad number of active connections (counted %d, stored %d)",
230 cc, active_connections);
232 #else
233 #define check_queue_bugs()
234 #endif
236 static void
237 set_connection_socket_state(struct socket *socket, struct connection_state state)
239 assert(socket);
240 set_connection_state(socket->conn, state);
243 static void
244 set_connection_socket_timeout(struct socket *socket, struct connection_state state)
246 assert(socket);
247 set_connection_timeout(socket->conn);
250 static void
251 retry_connection_socket(struct socket *socket, struct connection_state state)
253 assert(socket);
254 retry_connection(socket->conn, state);
257 static void
258 done_connection_socket(struct socket *socket, struct connection_state state)
260 assert(socket);
261 abort_connection(socket->conn, state);
264 static struct connection *
265 init_connection(struct uri *uri, struct uri *proxied_uri, struct uri *referrer,
266 off_t start, enum cache_mode cache_mode,
267 enum connection_priority priority)
269 static struct socket_operations connection_socket_operations = {
270 set_connection_socket_state,
271 set_connection_socket_timeout,
272 retry_connection_socket,
273 done_connection_socket,
275 struct connection *conn = mem_calloc(1, sizeof(*conn));
277 if (!conn) return NULL;
279 assert(proxied_uri->protocol != PROTOCOL_PROXY);
281 conn->socket = init_socket(conn, &connection_socket_operations);
282 if (!conn->socket) {
283 mem_free(conn);
284 return NULL;
287 conn->data_socket = init_socket(conn, &connection_socket_operations);
288 if (!conn->data_socket) {
289 mem_free(conn->socket);
290 mem_free(conn);
291 return NULL;
294 conn->progress = init_progress(start);
295 if (!conn->progress) {
296 mem_free(conn->data_socket);
297 mem_free(conn->socket);
298 mem_free(conn);
299 return NULL;
302 /* load_uri() gets the URI from get_proxy() which grabs a reference for
303 * us. */
304 conn->uri = uri;
305 conn->proxied_uri = proxied_uri;
306 conn->id = connection_id++;
307 conn->pri[priority] = 1;
308 conn->cache_mode = cache_mode;
310 conn->content_encoding = ENCODING_NONE;
311 conn->stream_pipes[0] = conn->stream_pipes[1] = -1;
312 init_list(conn->downloads);
313 conn->est_length = -1;
314 conn->timer = TIMER_ID_UNDEF;
316 if (referrer) {
317 /* Don't set referrer when it is the file protocol and the URI
318 * being loaded is not. This means CGI scripts will have it
319 * available while preventing information about the local
320 * system from being leaked to external servers. */
321 if (referrer->protocol != PROTOCOL_FILE
322 || uri->protocol == PROTOCOL_FILE)
323 conn->referrer = get_uri_reference(referrer);
326 return conn;
329 static void
330 update_connection_progress(struct connection *conn)
332 update_progress(conn->progress, conn->received, conn->est_length, conn->from);
335 /* Progress timer callback for @conn->progress. As explained in
336 * @start_update_progress, this function must erase the expired timer
337 * ID from @conn->progress->timer. */
338 static void
339 stat_timer(struct connection *conn)
341 update_connection_progress(conn);
342 /* The expired timer ID has now been erased. */
343 notify_connection_callbacks(conn);
346 void
347 set_connection_state(struct connection *conn, struct connection_state state)
349 struct download *download;
350 struct progress *progress = conn->progress;
352 if (is_in_result_state(conn->state) && is_in_progress_state(state))
353 conn->prev_error = conn->state;
355 conn->state = state;
356 if (is_in_state(conn->state, S_TRANS)) {
357 if (progress->timer == TIMER_ID_UNDEF) {
358 const unsigned int id = conn->id;
360 start_update_progress(progress, (void (*)(void *)) stat_timer, conn);
361 update_connection_progress(conn);
362 if (connection_disappeared(conn, id))
363 return;
366 } else {
367 kill_timer(&progress->timer);
370 foreach (download, conn->downloads) {
371 download->state = state;
372 download->prev_error = conn->prev_error;
375 if (is_in_progress_state(state)) notify_connection_callbacks(conn);
378 void
379 shutdown_connection_stream(struct connection *conn)
381 if (conn->stream) {
382 close_encoded(conn->stream);
383 conn->stream = NULL;
384 } else if (conn->stream_pipes[0] >= 0) {
385 /* close_encoded() usually closes this end of the pipe,
386 * but open_encoded() apparently failed this time. */
387 close(conn->stream_pipes[0]);
389 if (conn->stream_pipes[1] >= 0)
390 close(conn->stream_pipes[1]);
391 conn->stream_pipes[0] = conn->stream_pipes[1] = -1;
394 static void
395 free_connection_data(struct connection *conn)
397 assertm(conn->running, "connection already suspended");
398 /* XXX: Recovery path? Originally, there was none. I think we'll get
399 * at least active_connections underflows along the way. --pasky */
400 conn->running = 0;
402 active_connections--;
403 assertm(active_connections >= 0, "active connections underflow");
404 if_assert_failed active_connections = 0;
406 #ifdef CONFIG_SSL
407 if (conn->socket->ssl && conn->cached)
408 mem_free_set(&conn->cached->ssl_info, get_ssl_connection_cipher(conn->socket));
409 #endif
411 if (conn->done)
412 conn->done(conn);
414 done_socket(conn->socket);
415 done_socket(conn->data_socket);
417 shutdown_connection_stream(conn);
419 mem_free_set(&conn->info, NULL);
421 kill_timer(&conn->timer);
423 if (!is_in_state(conn->state, S_WAIT))
424 done_host_connection(conn);
427 void
428 notify_connection_callbacks(struct connection *conn)
430 struct connection_state state = conn->state;
431 unsigned int id = conn->id;
432 struct download *download, *next;
434 foreachsafe (download, next, conn->downloads) {
435 download->cached = conn->cached;
436 if (download->callback)
437 download->callback(download, download->data);
438 if (is_in_progress_state(state)
439 && connection_disappeared(conn, id))
440 return;
444 static void
445 done_connection(struct connection *conn)
447 /* When removing the connection callbacks should always be aware of it
448 * so they can unregister themselves. We do this by enforcing that the
449 * connection is in a result state. If it is not already it is an
450 * internal bug. This should never happen but it does. ;) --jonas */
451 if (!is_in_result_state(conn->state))
452 set_connection_state(conn, connection_state(S_INTERNAL));
454 del_from_list(conn);
455 notify_connection_callbacks(conn);
456 if (conn->referrer) done_uri(conn->referrer);
457 done_uri(conn->uri);
458 done_uri(conn->proxied_uri);
459 mem_free(conn->socket);
460 mem_free(conn->data_socket);
461 done_progress(conn->progress);
462 mem_free(conn);
463 check_queue_bugs();
466 static inline void
467 add_to_queue(struct connection *conn)
469 struct connection *c;
470 enum connection_priority priority = get_priority(conn);
472 foreach (c, connection_queue)
473 if (get_priority(c) > priority)
474 break;
476 add_at_pos(c->prev, conn);
480 /* Returns zero if no callback was done and the keepalive connection should be
481 * deleted or non-zero if the keepalive connection should not be deleted. */
482 static int
483 do_keepalive_connection_callback(struct keepalive_connection *keep_conn)
485 struct uri *proxied_uri = get_proxied_uri(keep_conn->uri);
486 struct uri *proxy_uri = get_proxy_uri(keep_conn->uri, NULL);
488 if (proxied_uri && proxy_uri) {
489 struct connection *conn;
491 conn = init_connection(proxy_uri, proxied_uri, NULL, 0,
492 CACHE_MODE_NEVER, PRI_CANCEL);
494 if (conn) {
495 void (*done)(struct connection *) = keep_conn->done;
497 add_to_queue(conn);
499 /* Get the keepalive info and let it clean up */
500 if (!has_keepalive_connection(conn)
501 || !add_host_connection(conn)) {
502 free_connection_data(conn);
503 done_connection(conn);
504 return 0;
507 active_connections++;
508 conn->running = 1;
509 done(conn);
510 return 1;
514 if (proxied_uri) done_uri(proxied_uri);
515 if (proxy_uri) done_uri(proxy_uri);
517 return 0;
520 static inline void
521 done_keepalive_connection(struct keepalive_connection *keep_conn)
523 if (keep_conn->done && do_keepalive_connection_callback(keep_conn))
524 return;
526 del_from_list(keep_conn);
527 if (keep_conn->socket != -1) close(keep_conn->socket);
528 done_uri(keep_conn->uri);
529 mem_free(keep_conn);
532 static struct keepalive_connection *
533 init_keepalive_connection(struct connection *conn, long timeout_in_seconds,
534 void (*done)(struct connection *))
536 struct keepalive_connection *keep_conn;
537 struct uri *uri = conn->uri;
539 assert(uri->host);
540 if_assert_failed return NULL;
542 keep_conn = mem_calloc(1, sizeof(*keep_conn));
543 if (!keep_conn) return NULL;
545 keep_conn->uri = get_uri_reference(uri);
546 keep_conn->done = done;
547 keep_conn->protocol_family = conn->socket->protocol_family;
548 keep_conn->socket = conn->socket->fd;
549 timeval_from_seconds(&keep_conn->timeout, timeout_in_seconds);
550 timeval_now(&keep_conn->creation_time);
552 return keep_conn;
555 static struct keepalive_connection *
556 get_keepalive_connection(struct connection *conn)
558 struct keepalive_connection *keep_conn;
560 if (!conn->uri->host) return NULL;
562 foreach (keep_conn, keepalive_connections)
563 if (compare_uri(keep_conn->uri, conn->uri, URI_KEEPALIVE))
564 return keep_conn;
566 return NULL;
570 has_keepalive_connection(struct connection *conn)
572 struct keepalive_connection *keep_conn = get_keepalive_connection(conn);
574 if (!keep_conn) return 0;
576 conn->socket->fd = keep_conn->socket;
577 conn->socket->protocol_family = keep_conn->protocol_family;
579 /* Mark that the socket should not be closed and the callback should be
580 * ignored. */
581 keep_conn->socket = -1;
582 keep_conn->done = NULL;
583 done_keepalive_connection(keep_conn);
585 return 1;
588 void
589 add_keepalive_connection(struct connection *conn, long timeout_in_seconds,
590 void (*done)(struct connection *))
592 struct keepalive_connection *keep_conn;
594 assertm(conn->socket->fd != -1, "keepalive connection not connected");
595 if_assert_failed goto done;
597 keep_conn = init_keepalive_connection(conn, timeout_in_seconds, done);
598 if (keep_conn) {
599 /* Make sure that the socket descriptor will not periodically be
600 * checked or closed by free_connection_data(). */
601 clear_handlers(conn->socket->fd);
602 conn->socket->fd = -1;
603 add_to_list(keepalive_connections, keep_conn);
605 } else if (done) {
606 /* It will take just a little more time */
607 done(conn);
608 return;
611 done:
612 free_connection_data(conn);
613 done_connection(conn);
614 register_check_queue();
617 /* Timer callback for @keepalive_timeout. As explained in @install_timer,
618 * this function must erase the expired timer ID from all variables. */
619 static void
620 keepalive_timer(void *x)
622 keepalive_timeout = TIMER_ID_UNDEF;
623 /* The expired timer ID has now been erased. */
624 check_keepalive_connections();
627 void
628 check_keepalive_connections(void)
630 struct keepalive_connection *keep_conn, *next;
631 timeval_T now;
632 int p = 0;
634 timeval_now(&now);
636 kill_timer(&keepalive_timeout);
638 foreachsafe (keep_conn, next, keepalive_connections) {
639 timeval_T age;
641 if (can_read(keep_conn->socket)) {
642 done_keepalive_connection(keep_conn);
643 continue;
646 timeval_sub(&age, &keep_conn->creation_time, &now);
647 if (timeval_cmp(&age, &keep_conn->timeout) > 0) {
648 done_keepalive_connection(keep_conn);
649 continue;
652 p++;
655 for (; p > MAX_KEEPALIVE_CONNECTIONS; p--) {
656 assertm(!list_empty(keepalive_connections), "keepalive list empty");
657 if_assert_failed return;
658 done_keepalive_connection(keepalive_connections.prev);
661 if (!list_empty(keepalive_connections))
662 install_timer(&keepalive_timeout, KEEPALIVE_CHECK_TIME,
663 keepalive_timer, NULL);
666 static inline void
667 abort_all_keepalive_connections(void)
669 while (!list_empty(keepalive_connections))
670 done_keepalive_connection(keepalive_connections.next);
672 check_keepalive_connections();
676 static void
677 sort_queue(void)
679 while (1) {
680 struct connection *conn;
681 int swp = 0;
683 foreach (conn, connection_queue) {
684 if (!list_has_next(connection_queue, conn)) break;
686 if (get_priority(conn->next) < get_priority(conn)) {
687 struct connection *c = conn->next;
689 del_from_list(conn);
690 add_at_pos(c, conn);
691 swp = 1;
695 if (!swp) break;
699 static void
700 interrupt_connection(struct connection *conn)
702 free_connection_data(conn);
705 static inline void
706 suspend_connection(struct connection *conn)
708 interrupt_connection(conn);
709 set_connection_state(conn, connection_state(S_WAIT));
712 static void
713 run_connection(struct connection *conn)
715 protocol_handler_T *func = get_protocol_handler(conn->uri->protocol);
717 assert(func);
719 assertm(!conn->running, "connection already running");
720 if_assert_failed return;
722 if (!add_host_connection(conn)) {
723 set_connection_state(conn, connection_state(S_OUT_OF_MEM));
724 done_connection(conn);
725 return;
728 active_connections++;
729 conn->running = 1;
731 func(conn);
734 /* Set certain state on a connection and then abort the connection. */
735 void
736 abort_connection(struct connection *conn, struct connection_state state)
738 assertm(is_in_result_state(state),
739 "connection didn't end in result state (%d)", state);
741 if (is_in_state(state, S_OK) && conn->cached)
742 normalize_cache_entry(conn->cached, conn->from);
744 set_connection_state(conn, state);
746 if (conn->running) interrupt_connection(conn);
747 done_connection(conn);
748 register_check_queue();
751 /* Set certain state on a connection and then retry the connection. */
752 void
753 retry_connection(struct connection *conn, struct connection_state state)
755 int max_tries = get_opt_int("connection.retries");
757 assertm(is_in_result_state(state),
758 "connection didn't end in result state (%d)", state);
760 set_connection_state(conn, state);
762 interrupt_connection(conn);
763 if (conn->uri->post || (max_tries && ++conn->tries >= max_tries)) {
764 done_connection(conn);
765 register_check_queue();
766 } else {
767 conn->prev_error = conn->state;
768 run_connection(conn);
772 static int
773 try_to_suspend_connection(struct connection *conn, struct uri *uri)
775 enum connection_priority priority = get_priority(conn);
776 struct connection *c;
778 foreachback (c, connection_queue) {
779 if (get_priority(c) <= priority) return -1;
780 if (is_in_state(c->state, S_WAIT)) continue;
781 if (c->uri->post && get_priority(c) < PRI_CANCEL) continue;
782 if (uri && !compare_uri(uri, c->uri, URI_HOST)) continue;
783 suspend_connection(c);
784 return 0;
787 return -1;
790 static inline int
791 try_connection(struct connection *conn, int max_conns_to_host, int max_conns)
793 struct host_connection *host_conn = get_host_connection(conn);
795 if (host_conn && get_object_refcount(host_conn) >= max_conns_to_host)
796 return try_to_suspend_connection(conn, host_conn->uri) ? 0 : -1;
798 if (active_connections >= max_conns)
799 return try_to_suspend_connection(conn, NULL) ? 0 : -1;
801 run_connection(conn);
802 return 1;
805 static void
806 check_queue(void)
808 struct connection *conn;
809 int max_conns_to_host = get_opt_int("connection.max_connections_to_host");
810 int max_conns = get_opt_int("connection.max_connections");
812 again:
813 conn = connection_queue.next;
814 check_queue_bugs();
815 check_keepalive_connections();
817 while (conn != (struct connection *) &connection_queue) {
818 struct connection *c;
819 enum connection_priority pri = get_priority(conn);
821 for (c = conn; c != (struct connection *) &connection_queue && get_priority(c) == pri;) {
822 struct connection *cc = c;
824 c = c->next;
825 if (is_in_state(cc->state, S_WAIT)
826 && get_keepalive_connection(cc)
827 && try_connection(cc, max_conns_to_host, max_conns))
828 goto again;
831 for (c = conn; c != (struct connection *) &connection_queue && get_priority(c) == pri;) {
832 struct connection *cc = c;
834 c = c->next;
835 if (is_in_state(cc->state, S_WAIT)
836 && try_connection(cc, max_conns_to_host, max_conns))
837 goto again;
839 conn = c;
842 again2:
843 foreachback (conn, connection_queue) {
844 if (get_priority(conn) < PRI_CANCEL) break;
845 if (is_in_state(conn->state, S_WAIT)) {
846 set_connection_state(conn, connection_state(S_INTERRUPTED));
847 done_connection(conn);
848 goto again2;
852 check_queue_bugs();
856 register_check_queue(void)
858 return register_bottom_half(check_queue, NULL);
862 load_uri(struct uri *uri, struct uri *referrer, struct download *download,
863 enum connection_priority pri, enum cache_mode cache_mode, off_t start)
865 struct cache_entry *cached;
866 struct connection *conn;
867 struct uri *proxy_uri, *proxied_uri;
868 struct connection_state error_state = connection_state(S_OK);
870 if (download) {
871 download->conn = NULL;
872 download->cached = NULL;
873 download->pri = pri;
874 download->state = connection_state(S_OUT_OF_MEM);
875 download->prev_error = connection_state(0);
878 #ifdef CONFIG_DEBUG
879 foreach (conn, connection_queue) {
880 struct download *assigned;
882 foreach (assigned, conn->downloads) {
883 assertm(assigned != download, "Download assigned to '%s'", struri(conn->uri));
884 if_assert_failed {
885 download->state = connection_state(S_INTERNAL);
886 if (download->callback)
887 download->callback(download, download->data);
888 return 0;
890 /* No recovery path should be necessary. */
893 #endif
895 cached = get_validated_cache_entry(uri, cache_mode);
896 if (cached) {
897 if (download) {
898 download->cached = cached;
899 download->state = connection_state(S_OK);
900 /* XXX:
901 * This doesn't work since sometimes |download->progress|
902 * is undefined and contains random memory locations.
903 * It's not supposed to point on anything here since
904 * |download| has no connection attached.
905 * Downloads resuming will probably break in some
906 * cases without this, though.
907 * FIXME: Needs more investigation. --pasky */
908 /* if (download->progress) download->progress->start = start; */
909 if (download->callback)
910 download->callback(download, download->data);
912 return 0;
915 proxied_uri = get_proxied_uri(uri);
916 proxy_uri = get_proxy_uri(uri, &error_state);
918 if (!proxy_uri
919 || !proxied_uri
920 || (get_protocol_need_slash_after_host(proxy_uri->protocol)
921 && !proxy_uri->hostlen)) {
923 if (download) {
924 if (is_in_state(error_state, S_OK)) {
925 error_state = proxy_uri && proxied_uri
926 ? connection_state(S_BAD_URL)
927 : connection_state(S_OUT_OF_MEM);
930 download->state = error_state;
931 download->callback(download, download->data);
933 if (proxy_uri) done_uri(proxy_uri);
934 if (proxied_uri) done_uri(proxied_uri);
935 return -1;
938 foreach (conn, connection_queue) {
939 if (conn->detached
940 || !compare_uri(conn->uri, proxy_uri, 0))
941 continue;
943 done_uri(proxy_uri);
944 done_uri(proxied_uri);
946 if (get_priority(conn) > pri) {
947 del_from_list(conn);
948 conn->pri[pri]++;
949 add_to_queue(conn);
950 register_check_queue();
951 } else {
952 conn->pri[pri]++;
955 if (download) {
956 download->progress = conn->progress;
957 download->conn = conn;
958 download->cached = conn->cached;
959 add_to_list(conn->downloads, download);
960 /* This is likely to call download->callback() now! */
961 set_connection_state(conn, conn->state);
963 check_queue_bugs();
964 return 0;
967 conn = init_connection(proxy_uri, proxied_uri, referrer, start, cache_mode, pri);
968 if (!conn) {
969 if (download) {
970 download->state = connection_state(S_OUT_OF_MEM);
971 download->callback(download, download->data);
973 if (proxy_uri) done_uri(proxy_uri);
974 if (proxied_uri) done_uri(proxied_uri);
975 return -1;
978 if (cache_mode < CACHE_MODE_FORCE_RELOAD && cached && !list_empty(cached->frag)
979 && !((struct fragment *) cached->frag.next)->offset)
980 conn->from = ((struct fragment *) cached->frag.next)->length;
982 if (download) {
983 download->progress = conn->progress;
984 download->conn = conn;
985 download->cached = NULL;
986 download->state = connection_state(S_OK);
987 add_to_list(conn->downloads, download);
990 add_to_queue(conn);
991 set_connection_state(conn, connection_state(S_WAIT));
993 check_queue_bugs();
995 register_check_queue();
996 return 0;
1000 /* FIXME: one object in more connections */
1001 void
1002 cancel_download(struct download *download, int interrupt)
1004 struct connection *conn;
1006 assert(download);
1007 if_assert_failed return;
1009 /* Did the connection already end? */
1010 if (is_in_result_state(download->state))
1011 return;
1013 assertm(download->conn != NULL, "last state is %d", download->state);
1015 check_queue_bugs();
1017 download->state = connection_state(S_INTERRUPTED);
1018 del_from_list(download);
1020 conn = download->conn;
1022 conn->pri[download->pri]--;
1023 assertm(conn->pri[download->pri] >= 0, "priority counter underflow");
1024 if_assert_failed conn->pri[download->pri] = 0;
1026 if (list_empty(conn->downloads)) {
1027 /* Necessary because of assertion in get_priority(). */
1028 conn->pri[PRI_CANCEL]++;
1030 if (conn->detached || interrupt)
1031 abort_connection(conn, connection_state(S_INTERRUPTED));
1034 sort_queue();
1035 check_queue_bugs();
1037 register_check_queue();
1040 void
1041 move_download(struct download *old, struct download *new,
1042 enum connection_priority newpri)
1044 struct connection *conn;
1046 assert(old);
1048 /* The download doesn't necessarily have a connection attached, for
1049 * example the file protocol loads it's object immediately. This is
1050 * catched by the result state check below. */
1052 conn = old->conn;
1054 new->conn = conn;
1055 new->cached = old->cached;
1056 new->prev_error = old->prev_error;
1057 new->progress = old->progress;
1058 new->state = old->state;
1059 new->pri = newpri;
1061 if (is_in_result_state(old->state)) {
1062 /* Ensure that new->conn is always "valid", that is NULL if the
1063 * connection has been detached and non-NULL otherwise. */
1064 if (new->callback) {
1065 new->conn = NULL;
1066 new->progress = NULL;
1067 new->callback(new, new->data);
1069 return;
1072 assertm(old->conn != NULL, "last state is %d", old->state);
1074 conn->pri[new->pri]++;
1075 add_to_list(conn->downloads, new);
1076 /* In principle, we need to sort_queue() only if conn->pri[new->pri]
1077 * just changed from 0 to 1. But the risk of bugs is smaller if we
1078 * sort every time. */
1079 sort_queue();
1081 cancel_download(old, 0);
1085 /* This will remove 'pos' bytes from the start of the cache for the specified
1086 * connection, if the cached object is already too big. */
1087 void
1088 detach_connection(struct download *download, off_t pos)
1090 struct connection *conn = download->conn;
1092 if (is_in_result_state(download->state)) return;
1094 if (!conn->detached) {
1095 off_t total_len;
1096 off_t i, total_pri = 0;
1098 if (!conn->cached)
1099 return;
1101 total_len = (conn->est_length == -1) ? conn->from
1102 : conn->est_length;
1104 if (total_len < (get_opt_long("document.cache.memory.size")
1105 * MAX_CACHED_OBJECT_PERCENT / 100)) {
1106 /* This whole thing will fit to the memory anyway, so
1107 * there's no problem in detaching the connection. */
1108 return;
1111 for (i = 0; i < PRI_CANCEL; i++)
1112 total_pri += conn->pri[i];
1113 assertm(total_pri, "detaching free connection");
1114 /* No recovery path should be necessary...? */
1116 /* Pre-clean cache. */
1117 shrink_format_cache(0);
1119 if (total_pri != 1 || is_object_used(conn->cached)) {
1120 /* We're too important, or someone uses our cache
1121 * entry. */
1122 return;
1125 /* DBG("detached"); */
1127 /* We aren't valid cache entry anymore. */
1128 conn->cached->valid = 0;
1129 conn->detached = 1;
1132 /* Strip the entry. */
1133 free_entry_to(conn->cached, pos);
1136 /* Timer callback for @conn->timer. As explained in @install_timer,
1137 * this function must erase the expired timer ID from all variables. */
1138 static void
1139 connection_timeout(struct connection *conn)
1141 conn->timer = TIMER_ID_UNDEF;
1142 /* The expired timer ID has now been erased. */
1143 timeout_socket(conn->socket);
1146 /* Timer callback for @conn->timer. As explained in @install_timer,
1147 * this function must erase the expired timer ID from all variables.
1149 * Huh, using two timers? Is this to account for changes of c->unrestartable
1150 * or can it be reduced? --jonas */
1151 static void
1152 connection_timeout_1(struct connection *conn)
1154 install_timer(&conn->timer, (milliseconds_T)
1155 ((conn->unrestartable
1156 ? get_opt_int("connection.unrestartable_receive_timeout")
1157 : get_opt_int("connection.receive_timeout"))
1158 * 500), (void (*)(void *)) connection_timeout, conn);
1159 /* The expired timer ID has now been erased. */
1162 void
1163 set_connection_timeout(struct connection *conn)
1165 kill_timer(&conn->timer);
1167 install_timer(&conn->timer, (milliseconds_T)
1168 ((conn->unrestartable
1169 ? get_opt_int("connection.unrestartable_receive_timeout")
1170 : get_opt_int("connection.receive_timeout"))
1171 * 500), (void (*)(void *)) connection_timeout_1, conn);
1175 void
1176 abort_all_connections(void)
1178 while (!list_empty(connection_queue)) {
1179 abort_connection(connection_queue.next,
1180 connection_state(S_INTERRUPTED));
1183 abort_all_keepalive_connections();
1186 void
1187 abort_background_connections(void)
1189 struct connection *conn, *next;
1191 foreachsafe (conn, next, connection_queue) {
1192 if (get_priority(conn) >= PRI_CANCEL)
1193 abort_connection(conn, connection_state(S_INTERRUPTED));
1198 is_entry_used(struct cache_entry *cached)
1200 struct connection *conn;
1202 foreach (conn, connection_queue)
1203 if (conn->cached == cached)
1204 return 1;
1206 return 0;