1 /* Connections management */
16 #include "cache/cache.h"
17 #include "config/options.h"
18 #include "document/document.h"
19 #include "encoding/encoding.h"
20 #include "intl/gettext/libintl.h"
21 #include "main/object.h"
22 #include "main/select.h"
23 #include "main/timer.h"
24 #include "network/connection.h"
25 #include "network/dns.h"
26 #include "network/progress.h"
27 #include "network/socket.h"
28 #include "network/ssl/ssl.h"
29 #include "protocol/protocol.h"
30 #include "protocol/proxy.h"
31 #include "protocol/uri.h"
32 #include "session/session.h"
33 #include "util/error.h"
34 #include "util/memory.h"
35 #include "util/string.h"
36 #include "util/time.h"
39 struct keepalive_connection
{
40 LIST_HEAD(struct keepalive_connection
);
42 /* XXX: This is just the URI of the connection that registered the
43 * keepalive connection so only rely on the protocol, user, password,
44 * host and port part. */
47 /* Function called when the keepalive has timed out or is deleted */
48 void (*done
)(struct connection
*);
51 timeval_T creation_time
;
53 unsigned int protocol_family
:1; /* see network/socket.h, EL_PF_INET, EL_PF_INET6 */
58 static unsigned int connection_id
= 0;
59 static int active_connections
= 0;
60 static timer_id_T keepalive_timeout
= TIMER_ID_UNDEF
;
62 static INIT_LIST_HEAD(connection_queue
);
63 static INIT_LIST_HEAD(host_connections
);
64 static INIT_LIST_HEAD(keepalive_connections
);
67 static void notify_connection_callbacks(struct connection
*conn
);
68 static void check_keepalive_connections(void);
71 static /* inline */ enum connection_priority
72 get_priority(struct connection
*conn
)
74 enum connection_priority priority
;
76 for (priority
= 0; priority
< PRIORITIES
; priority
++)
77 if (conn
->pri
[priority
])
80 assertm(priority
!= PRIORITIES
, "Connection has no owner");
81 /* Recovery path ;-). (XXX?) */
87 get_connections_count(void)
89 return list_size(&connection_queue
);
93 get_keepalive_connections_count(void)
95 return list_size(&keepalive_connections
);
99 get_connections_connecting_count(void)
101 struct connection
*conn
;
104 foreach (conn
, connection_queue
)
105 i
+= is_in_connecting_state(conn
->state
);
111 get_connections_transfering_count(void)
113 struct connection
*conn
;
116 foreach (conn
, connection_queue
)
117 i
+= is_in_transfering_state(conn
->state
);
123 connection_disappeared(struct connection
*conn
)
125 struct connection
*c
;
127 foreach (c
, connection_queue
)
128 if (conn
== c
&& conn
->id
== c
->id
)
134 /* Host connection management: */
135 /* Used to keep track on the number of connections to any given host. When
136 * trying to setup a new connection the list is searched to see if the maximum
137 * number of connection has been reached. If that is the case we try to suspend
138 * an already established connection. */
139 /* Some connections (like file://) that do not involve hosts are not maintained
142 struct host_connection
{
143 OBJECT_HEAD(struct host_connection
);
145 /* XXX: This is just the URI of the connection that registered the
146 * host connection so only rely on the host part. */
150 static struct host_connection
*
151 get_host_connection(struct connection
*conn
)
153 struct host_connection
*host_conn
;
155 if (!conn
->uri
->host
) return NULL
;
157 foreach (host_conn
, host_connections
)
158 if (compare_uri(host_conn
->uri
, conn
->uri
, URI_HOST
))
164 /* Returns if the connection was successfully added. */
165 /* Don't add hostnameless host connections but they're valid. */
167 add_host_connection(struct connection
*conn
)
169 struct host_connection
*host_conn
= get_host_connection(conn
);
171 if (!host_conn
&& conn
->uri
->host
) {
172 host_conn
= mem_calloc(1, sizeof(*host_conn
));
173 if (!host_conn
) return 0;
175 host_conn
->uri
= get_uri_reference(conn
->uri
);
176 object_nolock(host_conn
, "host_connection");
177 add_to_list(host_connections
, host_conn
);
179 if (host_conn
) object_lock(host_conn
);
184 /* Decrements and free()s the host connection if it is the last 'refcount'. */
186 done_host_connection(struct connection
*conn
)
188 struct host_connection
*host_conn
= get_host_connection(conn
);
190 if (!host_conn
) return;
192 object_unlock(host_conn
);
193 if (is_object_used(host_conn
)) return;
195 del_from_list(host_conn
);
196 done_uri(host_conn
->uri
);
201 static void sort_queue();
205 check_queue_bugs(void)
207 struct connection
*conn
;
208 enum connection_priority prev_priority
= 0;
211 foreach (conn
, connection_queue
) {
212 enum connection_priority priority
= get_priority(conn
);
216 assertm(priority
>= prev_priority
, "queue is not sorted");
217 assertm(is_in_progress_state(conn
->state
),
218 "interrupted connection on queue (conn %s, state %d)",
219 struri(conn
->uri
), conn
->state
);
220 prev_priority
= priority
;
223 assertm(cc
== active_connections
,
224 "bad number of active connections (counted %d, stored %d)",
225 cc
, active_connections
);
228 #define check_queue_bugs()
232 set_connection_socket_state(struct socket
*socket
, enum connection_state state
)
235 set_connection_state(socket
->conn
, state
);
239 set_connection_socket_timeout(struct socket
*socket
, enum connection_state state
)
242 set_connection_timeout(socket
->conn
);
246 retry_connection_socket(struct socket
*socket
, enum connection_state state
)
249 retry_connection(socket
->conn
, state
);
253 done_connection_socket(struct socket
*socket
, enum connection_state state
)
256 abort_connection(socket
->conn
, state
);
259 static struct connection
*
260 init_connection(struct uri
*uri
, struct uri
*proxied_uri
, struct uri
*referrer
,
261 off_t start
, enum cache_mode cache_mode
,
262 enum connection_priority priority
)
264 static struct socket_operations connection_socket_operations
= {
265 set_connection_socket_state
,
266 set_connection_socket_timeout
,
267 retry_connection_socket
,
268 done_connection_socket
,
270 struct connection
*conn
= mem_calloc(1, sizeof(*conn
));
272 if (!conn
) return NULL
;
274 assert(proxied_uri
->protocol
!= PROTOCOL_PROXY
);
276 conn
->socket
= init_socket(conn
, &connection_socket_operations
);
282 conn
->data_socket
= init_socket(conn
, &connection_socket_operations
);
283 if (!conn
->data_socket
) {
284 mem_free(conn
->socket
);
289 conn
->progress
= init_progress(start
);
290 if (!conn
->progress
) {
291 mem_free(conn
->data_socket
);
292 mem_free(conn
->socket
);
297 /* load_uri() gets the URI from get_proxy() which grabs a reference for
300 conn
->proxied_uri
= proxied_uri
;
301 conn
->id
= connection_id
++;
302 conn
->pri
[priority
] = 1;
303 conn
->cache_mode
= cache_mode
;
305 conn
->content_encoding
= ENCODING_NONE
;
306 conn
->stream_pipes
[0] = conn
->stream_pipes
[1] = -1;
307 init_list(conn
->downloads
);
308 conn
->est_length
= -1;
309 conn
->timer
= TIMER_ID_UNDEF
;
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
);
325 update_connection_progress(struct connection
*conn
)
327 update_progress(conn
->progress
, conn
->received
, conn
->est_length
, conn
->from
);
331 stat_timer(struct connection
*conn
)
333 update_connection_progress(conn
);
334 notify_connection_callbacks(conn
);
338 set_connection_state(struct connection
*conn
, enum connection_state state
)
340 struct download
*download
;
341 struct progress
*progress
= conn
->progress
;
343 if (is_in_result_state(conn
->state
) && is_in_progress_state(state
))
344 conn
->prev_error
= conn
->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
))
356 kill_timer(&progress
->timer
);
359 foreach (download
, conn
->downloads
) {
360 download
->state
= state
;
361 download
->prev_error
= conn
->prev_error
;
364 if (is_in_progress_state(state
)) notify_connection_callbacks(conn
);
368 shutdown_connection_stream(struct connection
*conn
)
371 close_encoded(conn
->stream
);
374 if (conn
->stream_pipes
[1] >= 0)
375 close(conn
->stream_pipes
[1]);
376 conn
->stream_pipes
[0] = conn
->stream_pipes
[1] = -1;
382 struct popen_data
*pop
;
384 foreach (pop
, copiousoutput_data
) {
389 unlink(pop
->filename
);
390 mem_free(pop
->filename
);
399 free_connection_data(struct connection
*conn
)
401 assertm(conn
->running
, "connection already suspended");
402 /* XXX: Recovery path? Originally, there was none. I think we'll get
403 * at least active_connections underflows along the way. --pasky */
406 active_connections
--;
407 assertm(active_connections
>= 0, "active connections underflow");
408 if_assert_failed active_connections
= 0;
411 if (conn
->socket
->ssl
&& conn
->cached
)
412 mem_free_set(&conn
->cached
->ssl_info
, get_ssl_connection_cipher(conn
->socket
));
418 if (conn
->popen
) close_popen(conn
->socket
->fd
);
419 done_socket(conn
->socket
);
420 done_socket(conn
->data_socket
);
422 shutdown_connection_stream(conn
);
424 mem_free_set(&conn
->info
, NULL
);
426 kill_timer(&conn
->timer
);
428 if (conn
->state
!= S_WAIT
)
429 done_host_connection(conn
);
433 notify_connection_callbacks(struct connection
*conn
)
435 enum connection_state state
= conn
->state
;
436 struct download
*download
, *next
;
438 foreachsafe (download
, next
, conn
->downloads
) {
439 download
->cached
= conn
->cached
;
440 if (download
->callback
)
441 download
->callback(download
, download
->data
);
442 if (is_in_progress_state(state
) && connection_disappeared(conn
))
448 done_connection(struct connection
*conn
)
450 /* When removing the connection callbacks should always be aware of it
451 * so they can unregister themselves. We do this by enforcing that the
452 * connection is in a result state. If it is not already it is an
453 * internal bug. This should never happen but it does. ;) --jonas */
454 if (!is_in_result_state(conn
->state
))
455 set_connection_state(conn
, S_INTERNAL
);
458 notify_connection_callbacks(conn
);
459 if (conn
->referrer
) done_uri(conn
->referrer
);
461 done_uri(conn
->proxied_uri
);
462 mem_free(conn
->socket
);
463 mem_free(conn
->data_socket
);
464 done_progress(conn
->progress
);
470 add_to_queue(struct connection
*conn
)
472 struct connection
*c
;
473 enum connection_priority priority
= get_priority(conn
);
475 foreach (c
, connection_queue
)
476 if (get_priority(c
) > priority
)
479 add_at_pos(c
->prev
, conn
);
483 /* Returns zero if no callback was done and the keepalive connection should be
484 * deleted or non-zero if the keepalive connection should not be deleted. */
486 do_keepalive_connection_callback(struct keepalive_connection
*keep_conn
)
488 struct uri
*proxied_uri
= get_proxied_uri(keep_conn
->uri
);
489 struct uri
*proxy_uri
= get_proxy_uri(keep_conn
->uri
, NULL
);
491 if (proxied_uri
&& proxy_uri
) {
492 struct connection
*conn
;
494 conn
= init_connection(proxy_uri
, proxied_uri
, NULL
, 0,
495 CACHE_MODE_NEVER
, PRI_CANCEL
);
498 void (*done
)(struct connection
*) = keep_conn
->done
;
502 /* Get the keepalive info and let it clean up */
503 if (!has_keepalive_connection(conn
)
504 || !add_host_connection(conn
)) {
505 free_connection_data(conn
);
506 done_connection(conn
);
510 active_connections
++;
517 if (proxied_uri
) done_uri(proxied_uri
);
518 if (proxy_uri
) done_uri(proxy_uri
);
524 done_keepalive_connection(struct keepalive_connection
*keep_conn
)
526 if (keep_conn
->done
&& do_keepalive_connection_callback(keep_conn
))
529 del_from_list(keep_conn
);
530 if (keep_conn
->socket
!= -1) close(keep_conn
->socket
);
531 done_uri(keep_conn
->uri
);
535 static struct keepalive_connection
*
536 init_keepalive_connection(struct connection
*conn
, long timeout_in_seconds
,
537 void (*done
)(struct connection
*))
539 struct keepalive_connection
*keep_conn
;
540 struct uri
*uri
= conn
->uri
;
543 if_assert_failed
return NULL
;
545 keep_conn
= mem_calloc(1, sizeof(*keep_conn
));
546 if (!keep_conn
) return NULL
;
548 keep_conn
->uri
= get_uri_reference(uri
);
549 keep_conn
->done
= done
;
550 keep_conn
->protocol_family
= conn
->socket
->protocol_family
;
551 keep_conn
->socket
= conn
->socket
->fd
;
552 timeval_from_seconds(&keep_conn
->timeout
, timeout_in_seconds
);
553 timeval_now(&keep_conn
->creation_time
);
558 static struct keepalive_connection
*
559 get_keepalive_connection(struct connection
*conn
)
561 struct keepalive_connection
*keep_conn
;
563 if (!conn
->uri
->host
) return NULL
;
565 foreach (keep_conn
, keepalive_connections
)
566 if (compare_uri(keep_conn
->uri
, conn
->uri
, URI_KEEPALIVE
))
573 has_keepalive_connection(struct connection
*conn
)
575 struct keepalive_connection
*keep_conn
= get_keepalive_connection(conn
);
577 if (!keep_conn
) return 0;
579 conn
->socket
->fd
= keep_conn
->socket
;
580 conn
->socket
->protocol_family
= keep_conn
->protocol_family
;
582 /* Mark that the socket should not be closed and the callback should be
584 keep_conn
->socket
= -1;
585 keep_conn
->done
= NULL
;
586 done_keepalive_connection(keep_conn
);
592 add_keepalive_connection(struct connection
*conn
, long timeout_in_seconds
,
593 void (*done
)(struct connection
*))
595 struct keepalive_connection
*keep_conn
;
597 assertm(conn
->socket
->fd
!= -1, "keepalive connection not connected");
598 if_assert_failed
goto done
;
600 keep_conn
= init_keepalive_connection(conn
, timeout_in_seconds
, done
);
602 /* Make sure that the socket descriptor will not periodically be
603 * checked or closed by free_connection_data(). */
604 clear_handlers(conn
->socket
->fd
);
605 conn
->socket
->fd
= -1;
606 add_to_list(keepalive_connections
, keep_conn
);
609 /* It will take just a little more time */
615 free_connection_data(conn
);
616 done_connection(conn
);
617 register_check_queue();
621 keepalive_timer(void *x
)
623 keepalive_timeout
= TIMER_ID_UNDEF
;
624 check_keepalive_connections();
628 check_keepalive_connections(void)
630 struct keepalive_connection
*keep_conn
, *next
;
636 kill_timer(&keepalive_timeout
);
638 foreachsafe (keep_conn
, next
, keepalive_connections
) {
641 if (can_read(keep_conn
->socket
)) {
642 done_keepalive_connection(keep_conn
);
646 timeval_sub(&age
, &keep_conn
->creation_time
, &now
);
647 if (timeval_cmp(&age
, &keep_conn
->timeout
) > 0) {
648 done_keepalive_connection(keep_conn
);
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
);
667 abort_all_keepalive_connections(void)
669 while (!list_empty(keepalive_connections
))
670 done_keepalive_connection(keepalive_connections
.next
);
672 check_keepalive_connections();
680 struct connection
*conn
;
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
;
700 interrupt_connection(struct connection
*conn
)
702 free_connection_data(conn
);
706 suspend_connection(struct connection
*conn
)
708 interrupt_connection(conn
);
709 set_connection_state(conn
, S_WAIT
);
713 run_connection(struct connection
*conn
)
715 protocol_handler_T
*func
= get_protocol_handler(conn
->uri
->protocol
);
719 assertm(!conn
->running
, "connection already running");
720 if_assert_failed
return;
722 if (!add_host_connection(conn
)) {
723 set_connection_state(conn
, S_OUT_OF_MEM
);
724 done_connection(conn
);
728 active_connections
++;
734 /* Set certain state on a connection and then abort the connection. */
736 abort_connection(struct connection
*conn
, enum connection_state state
)
738 assertm(is_in_result_state(state
),
739 "connection didn't end in result state (%d)", state
);
741 if (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. */
753 retry_connection(struct connection
*conn
, enum 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();
767 conn
->prev_error
= conn
->state
;
768 run_connection(conn
);
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 (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
);
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
);
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");
813 conn
= connection_queue
.next
;
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
;
825 if (cc
->state
== S_WAIT
&& get_keepalive_connection(cc
)
826 && try_connection(cc
, max_conns_to_host
, max_conns
))
830 for (c
= conn
; c
!= (struct connection
*) &connection_queue
&& get_priority(c
) == pri
;) {
831 struct connection
*cc
= c
;
834 if (cc
->state
== S_WAIT
835 && try_connection(cc
, max_conns_to_host
, max_conns
))
842 foreachback (conn
, connection_queue
) {
843 if (get_priority(conn
) < PRI_CANCEL
) break;
844 if (conn
->state
== S_WAIT
) {
845 set_connection_state(conn
, S_INTERRUPTED
);
846 done_connection(conn
);
855 register_check_queue(void)
857 return register_bottom_half(check_queue
, NULL
);
861 load_uri(struct uri
*uri
, struct uri
*referrer
, struct download
*download
,
862 enum connection_priority pri
, enum cache_mode cache_mode
, off_t start
)
864 struct cache_entry
*cached
;
865 struct connection
*conn
;
866 struct uri
*proxy_uri
, *proxied_uri
;
867 enum connection_state connection_state
= S_OK
;
870 download
->conn
= NULL
;
871 download
->cached
= NULL
;
873 download
->state
= S_OUT_OF_MEM
;
874 download
->prev_error
= 0;
878 foreach (conn
, connection_queue
) {
879 struct download
*assigned
;
881 foreach (assigned
, conn
->downloads
) {
882 assertm(assigned
!= download
, "Download assigned to '%s'", struri(conn
->uri
));
884 download
->state
= S_INTERNAL
;
885 if (download
->callback
)
886 download
->callback(download
, download
->data
);
889 /* No recovery path should be necessary. */
894 cached
= get_validated_cache_entry(uri
, cache_mode
);
897 download
->cached
= cached
;
898 download
->state
= S_OK
;
900 * This doesn't work since sometimes |download->progress|
901 * is undefined and contains random memory locations.
902 * It's not supposed to point on anything here since
903 * |download| has no connection attached.
904 * Downloads resuming will probably break in some
905 * cases without this, though.
906 * FIXME: Needs more investigation. --pasky */
907 /* if (download->progress) download->progress->start = start; */
908 if (download
->callback
)
909 download
->callback(download
, download
->data
);
914 proxied_uri
= get_proxied_uri(uri
);
915 proxy_uri
= get_proxy_uri(uri
, &connection_state
);
919 || (get_protocol_need_slash_after_host(proxy_uri
->protocol
)
920 && !proxy_uri
->hostlen
)) {
923 if (connection_state
== S_OK
) {
924 connection_state
= proxy_uri
&& proxied_uri
925 ? S_BAD_URL
: S_OUT_OF_MEM
;
928 download
->state
= connection_state
;
929 download
->callback(download
, download
->data
);
931 if (proxy_uri
) done_uri(proxy_uri
);
932 if (proxied_uri
) done_uri(proxied_uri
);
936 foreach (conn
, connection_queue
) {
938 || !compare_uri(conn
->uri
, proxy_uri
, 0))
942 done_uri(proxied_uri
);
944 if (get_priority(conn
) > pri
) {
948 register_check_queue();
954 download
->progress
= conn
->progress
;
955 download
->conn
= conn
;
956 download
->cached
= conn
->cached
;
957 add_to_list(conn
->downloads
, download
);
958 /* This is likely to call download->callback() now! */
959 set_connection_state(conn
, conn
->state
);
965 conn
= init_connection(proxy_uri
, proxied_uri
, referrer
, start
, cache_mode
, pri
);
968 download
->state
= S_OUT_OF_MEM
;
969 download
->callback(download
, download
->data
);
971 if (proxy_uri
) done_uri(proxy_uri
);
972 if (proxied_uri
) done_uri(proxied_uri
);
976 if (cache_mode
< CACHE_MODE_FORCE_RELOAD
&& cached
&& !list_empty(cached
->frag
)
977 && !((struct fragment
*) cached
->frag
.next
)->offset
)
978 conn
->from
= ((struct fragment
*) cached
->frag
.next
)->length
;
981 download
->progress
= conn
->progress
;
982 download
->conn
= conn
;
983 download
->cached
= NULL
;
984 add_to_list(conn
->downloads
, download
);
988 set_connection_state(conn
, S_WAIT
);
992 register_check_queue();
997 /* FIXME: one object in more connections */
999 cancel_download(struct download
*download
, int interrupt
)
1001 struct connection
*conn
;
1004 if_assert_failed
return;
1006 /* Did the connection already end? */
1007 if (is_in_result_state(download
->state
))
1010 assertm(download
->conn
, "last state is %d", download
->state
);
1014 download
->state
= S_INTERRUPTED
;
1015 del_from_list(download
);
1017 conn
= download
->conn
;
1019 conn
->pri
[download
->pri
]--;
1020 assertm(conn
->pri
[download
->pri
] >= 0, "priority counter underflow");
1021 if_assert_failed conn
->pri
[download
->pri
] = 0;
1023 if (list_empty(conn
->downloads
)) {
1024 /* Necessary because of assertion in get_priority(). */
1025 conn
->pri
[PRI_CANCEL
]++;
1027 if (conn
->detached
|| interrupt
)
1028 abort_connection(conn
, S_INTERRUPTED
);
1034 register_check_queue();
1038 move_download(struct download
*old
, struct download
*new,
1039 enum connection_priority newpri
)
1041 struct connection
*conn
;
1045 /* The download doesn't necessarily have a connection attached, for
1046 * example the file protocol loads it's object immediately. This is
1047 * catched by the result state check below. */
1052 new->cached
= old
->cached
;
1053 new->prev_error
= old
->prev_error
;
1054 new->progress
= old
->progress
;
1055 new->state
= old
->state
;
1058 if (is_in_result_state(old
->state
)) {
1059 /* Ensure that new->conn is always "valid", that is NULL if the
1060 * connection has been detached and non-NULL otherwise. */
1061 if (new->callback
) {
1063 new->progress
= NULL
;
1064 new->callback(new, new->data
);
1069 assertm(old
->conn
, "last state is %d", old
->state
);
1071 conn
->pri
[new->pri
]++;
1072 add_to_list(conn
->downloads
, new);
1074 cancel_download(old
, 0);
1078 /* This will remove 'pos' bytes from the start of the cache for the specified
1079 * connection, if the cached object is already too big. */
1081 detach_connection(struct download
*download
, off_t pos
)
1083 struct connection
*conn
= download
->conn
;
1085 if (is_in_result_state(download
->state
)) return;
1087 if (!conn
->detached
) {
1089 off_t i
, total_pri
= 0;
1094 total_len
= (conn
->est_length
== -1) ? conn
->from
1097 if (total_len
< (get_opt_long("document.cache.memory.size")
1098 * MAX_CACHED_OBJECT_PERCENT
/ 100)) {
1099 /* This whole thing will fit to the memory anyway, so
1100 * there's no problem in detaching the connection. */
1104 for (i
= 0; i
< PRI_CANCEL
; i
++)
1105 total_pri
+= conn
->pri
[i
];
1106 assertm(total_pri
, "detaching free connection");
1107 /* No recovery path should be necessary...? */
1109 /* Pre-clean cache. */
1110 shrink_format_cache(0);
1112 if (total_pri
!= 1 || is_object_used(conn
->cached
)) {
1113 /* We're too important, or someone uses our cache
1118 /* DBG("detached"); */
1120 /* We aren't valid cache entry anymore. */
1121 conn
->cached
->valid
= 0;
1125 /* Strip the entry. */
1126 free_entry_to(conn
->cached
, pos
);
1130 connection_timeout(struct connection
*conn
)
1132 conn
->timer
= TIMER_ID_UNDEF
;
1133 timeout_socket(conn
->socket
);
1136 /* Huh, using two timers? Is this to account for changes of c->unrestartable
1137 * or can it be reduced? --jonas */
1139 connection_timeout_1(struct connection
*conn
)
1141 install_timer(&conn
->timer
, (milliseconds_T
)
1142 ((conn
->unrestartable
1143 ? get_opt_int("connection.unrestartable_receive_timeout")
1144 : get_opt_int("connection.receive_timeout"))
1145 * 500), (void (*)(void *)) connection_timeout
, conn
);
1149 set_connection_timeout(struct connection
*conn
)
1151 kill_timer(&conn
->timer
);
1153 install_timer(&conn
->timer
, (milliseconds_T
)
1154 ((conn
->unrestartable
1155 ? get_opt_int("connection.unrestartable_receive_timeout")
1156 : get_opt_int("connection.receive_timeout"))
1157 * 500), (void (*)(void *)) connection_timeout_1
, conn
);
1162 abort_all_connections(void)
1164 while (!list_empty(connection_queue
)) {
1165 abort_connection(connection_queue
.next
, S_INTERRUPTED
);
1168 abort_all_keepalive_connections();
1172 abort_background_connections(void)
1174 struct connection
*conn
, *next
;
1176 foreachsafe (conn
, next
, connection_queue
) {
1177 if (get_priority(conn
) >= PRI_CANCEL
)
1178 abort_connection(conn
, S_INTERRUPTED
);
1183 is_entry_used(struct cache_entry
*cached
)
1185 struct connection
*conn
;
1187 foreach (conn
, connection_queue
)
1188 if (conn
->cached
== cached
)