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_OF(struct connection
, connection_queue
);
63 static INIT_LIST_OF(struct host_connection
, host_connections
);
64 static INIT_LIST_OF(struct keepalive_connection
, 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
);
330 /* Progress timer callback for @conn->progress. As explained in
331 * @start_update_progress, this function must erase the expired timer
332 * ID from @conn->progress->timer. */
334 stat_timer(struct connection
*conn
)
336 update_connection_progress(conn
);
337 /* The expired timer ID has now been erased. */
338 notify_connection_callbacks(conn
);
342 set_connection_state(struct connection
*conn
, enum connection_state state
)
344 struct download
*download
;
345 struct progress
*progress
= conn
->progress
;
347 if (is_in_result_state(conn
->state
) && is_in_progress_state(state
))
348 conn
->prev_error
= conn
->state
;
351 if (conn
->state
== S_TRANS
) {
352 if (progress
->timer
== TIMER_ID_UNDEF
) {
353 start_update_progress(progress
, (void (*)(void *)) stat_timer
, conn
);
354 update_connection_progress(conn
);
355 if (connection_disappeared(conn
))
360 kill_timer(&progress
->timer
);
363 foreach (download
, conn
->downloads
) {
364 download
->state
= state
;
365 download
->prev_error
= conn
->prev_error
;
368 if (is_in_progress_state(state
)) notify_connection_callbacks(conn
);
372 shutdown_connection_stream(struct connection
*conn
)
375 close_encoded(conn
->stream
);
377 } else if (conn
->stream_pipes
[0] >= 0) {
378 /* close_encoded() usually closes this end of the pipe,
379 * but open_encoded() apparently failed this time. */
380 close(conn
->stream_pipes
[0]);
382 if (conn
->stream_pipes
[1] >= 0)
383 close(conn
->stream_pipes
[1]);
384 conn
->stream_pipes
[0] = conn
->stream_pipes
[1] = -1;
390 struct popen_data
*pop
;
392 foreach (pop
, copiousoutput_data
) {
397 unlink(pop
->filename
);
398 mem_free(pop
->filename
);
407 free_connection_data(struct connection
*conn
)
409 assertm(conn
->running
, "connection already suspended");
410 /* XXX: Recovery path? Originally, there was none. I think we'll get
411 * at least active_connections underflows along the way. --pasky */
414 active_connections
--;
415 assertm(active_connections
>= 0, "active connections underflow");
416 if_assert_failed active_connections
= 0;
419 if (conn
->socket
->ssl
&& conn
->cached
)
420 mem_free_set(&conn
->cached
->ssl_info
, get_ssl_connection_cipher(conn
->socket
));
426 if (conn
->popen
) close_popen(conn
->socket
->fd
);
427 done_socket(conn
->socket
);
428 done_socket(conn
->data_socket
);
430 shutdown_connection_stream(conn
);
432 mem_free_set(&conn
->info
, NULL
);
434 kill_timer(&conn
->timer
);
436 if (conn
->state
!= S_WAIT
)
437 done_host_connection(conn
);
441 notify_connection_callbacks(struct connection
*conn
)
443 enum connection_state state
= conn
->state
;
444 struct download
*download
, *next
;
446 foreachsafe (download
, next
, conn
->downloads
) {
447 download
->cached
= conn
->cached
;
448 if (download
->callback
)
449 download
->callback(download
, download
->data
);
450 if (is_in_progress_state(state
) && connection_disappeared(conn
))
456 done_connection(struct connection
*conn
)
458 /* When removing the connection callbacks should always be aware of it
459 * so they can unregister themselves. We do this by enforcing that the
460 * connection is in a result state. If it is not already it is an
461 * internal bug. This should never happen but it does. ;) --jonas */
462 if (!is_in_result_state(conn
->state
))
463 set_connection_state(conn
, S_INTERNAL
);
466 notify_connection_callbacks(conn
);
467 if (conn
->referrer
) done_uri(conn
->referrer
);
469 done_uri(conn
->proxied_uri
);
470 mem_free(conn
->socket
);
471 mem_free(conn
->data_socket
);
472 done_progress(conn
->progress
);
478 add_to_queue(struct connection
*conn
)
480 struct connection
*c
;
481 enum connection_priority priority
= get_priority(conn
);
483 foreach (c
, connection_queue
)
484 if (get_priority(c
) > priority
)
487 add_at_pos(c
->prev
, conn
);
491 /* Returns zero if no callback was done and the keepalive connection should be
492 * deleted or non-zero if the keepalive connection should not be deleted. */
494 do_keepalive_connection_callback(struct keepalive_connection
*keep_conn
)
496 struct uri
*proxied_uri
= get_proxied_uri(keep_conn
->uri
);
497 struct uri
*proxy_uri
= get_proxy_uri(keep_conn
->uri
, NULL
);
499 if (proxied_uri
&& proxy_uri
) {
500 struct connection
*conn
;
502 conn
= init_connection(proxy_uri
, proxied_uri
, NULL
, 0,
503 CACHE_MODE_NEVER
, PRI_CANCEL
);
506 void (*done
)(struct connection
*) = keep_conn
->done
;
510 /* Get the keepalive info and let it clean up */
511 if (!has_keepalive_connection(conn
)
512 || !add_host_connection(conn
)) {
513 free_connection_data(conn
);
514 done_connection(conn
);
518 active_connections
++;
525 if (proxied_uri
) done_uri(proxied_uri
);
526 if (proxy_uri
) done_uri(proxy_uri
);
532 done_keepalive_connection(struct keepalive_connection
*keep_conn
)
534 if (keep_conn
->done
&& do_keepalive_connection_callback(keep_conn
))
537 del_from_list(keep_conn
);
538 if (keep_conn
->socket
!= -1) close(keep_conn
->socket
);
539 done_uri(keep_conn
->uri
);
543 static struct keepalive_connection
*
544 init_keepalive_connection(struct connection
*conn
, long timeout_in_seconds
,
545 void (*done
)(struct connection
*))
547 struct keepalive_connection
*keep_conn
;
548 struct uri
*uri
= conn
->uri
;
551 if_assert_failed
return NULL
;
553 keep_conn
= mem_calloc(1, sizeof(*keep_conn
));
554 if (!keep_conn
) return NULL
;
556 keep_conn
->uri
= get_uri_reference(uri
);
557 keep_conn
->done
= done
;
558 keep_conn
->protocol_family
= conn
->socket
->protocol_family
;
559 keep_conn
->socket
= conn
->socket
->fd
;
560 timeval_from_seconds(&keep_conn
->timeout
, timeout_in_seconds
);
561 timeval_now(&keep_conn
->creation_time
);
566 static struct keepalive_connection
*
567 get_keepalive_connection(struct connection
*conn
)
569 struct keepalive_connection
*keep_conn
;
571 if (!conn
->uri
->host
) return NULL
;
573 foreach (keep_conn
, keepalive_connections
)
574 if (compare_uri(keep_conn
->uri
, conn
->uri
, URI_KEEPALIVE
))
581 has_keepalive_connection(struct connection
*conn
)
583 struct keepalive_connection
*keep_conn
= get_keepalive_connection(conn
);
585 if (!keep_conn
) return 0;
587 conn
->socket
->fd
= keep_conn
->socket
;
588 conn
->socket
->protocol_family
= keep_conn
->protocol_family
;
590 /* Mark that the socket should not be closed and the callback should be
592 keep_conn
->socket
= -1;
593 keep_conn
->done
= NULL
;
594 done_keepalive_connection(keep_conn
);
600 add_keepalive_connection(struct connection
*conn
, long timeout_in_seconds
,
601 void (*done
)(struct connection
*))
603 struct keepalive_connection
*keep_conn
;
605 assertm(conn
->socket
->fd
!= -1, "keepalive connection not connected");
606 if_assert_failed
goto done
;
608 keep_conn
= init_keepalive_connection(conn
, timeout_in_seconds
, done
);
610 /* Make sure that the socket descriptor will not periodically be
611 * checked or closed by free_connection_data(). */
612 clear_handlers(conn
->socket
->fd
);
613 conn
->socket
->fd
= -1;
614 add_to_list(keepalive_connections
, keep_conn
);
617 /* It will take just a little more time */
623 free_connection_data(conn
);
624 done_connection(conn
);
625 register_check_queue();
628 /* Timer callback for @keepalive_timeout. As explained in @install_timer,
629 * this function must erase the expired timer ID from all variables. */
631 keepalive_timer(void *x
)
633 keepalive_timeout
= TIMER_ID_UNDEF
;
634 /* The expired timer ID has now been erased. */
635 check_keepalive_connections();
639 check_keepalive_connections(void)
641 struct keepalive_connection
*keep_conn
, *next
;
647 kill_timer(&keepalive_timeout
);
649 foreachsafe (keep_conn
, next
, keepalive_connections
) {
652 if (can_read(keep_conn
->socket
)) {
653 done_keepalive_connection(keep_conn
);
657 timeval_sub(&age
, &keep_conn
->creation_time
, &now
);
658 if (timeval_cmp(&age
, &keep_conn
->timeout
) > 0) {
659 done_keepalive_connection(keep_conn
);
666 for (; p
> MAX_KEEPALIVE_CONNECTIONS
; p
--) {
667 assertm(!list_empty(keepalive_connections
), "keepalive list empty");
668 if_assert_failed
return;
669 done_keepalive_connection(keepalive_connections
.prev
);
672 if (!list_empty(keepalive_connections
))
673 install_timer(&keepalive_timeout
, KEEPALIVE_CHECK_TIME
,
674 keepalive_timer
, NULL
);
678 abort_all_keepalive_connections(void)
680 while (!list_empty(keepalive_connections
))
681 done_keepalive_connection(keepalive_connections
.next
);
683 check_keepalive_connections();
691 struct connection
*conn
;
694 foreach (conn
, connection_queue
) {
695 if (!list_has_next(connection_queue
, conn
)) break;
697 if (get_priority(conn
->next
) < get_priority(conn
)) {
698 struct connection
*c
= conn
->next
;
711 interrupt_connection(struct connection
*conn
)
713 free_connection_data(conn
);
717 suspend_connection(struct connection
*conn
)
719 interrupt_connection(conn
);
720 set_connection_state(conn
, S_WAIT
);
724 run_connection(struct connection
*conn
)
726 protocol_handler_T
*func
= get_protocol_handler(conn
->uri
->protocol
);
730 assertm(!conn
->running
, "connection already running");
731 if_assert_failed
return;
733 if (!add_host_connection(conn
)) {
734 set_connection_state(conn
, S_OUT_OF_MEM
);
735 done_connection(conn
);
739 active_connections
++;
745 /* Set certain state on a connection and then abort the connection. */
747 abort_connection(struct connection
*conn
, enum connection_state state
)
749 assertm(is_in_result_state(state
),
750 "connection didn't end in result state (%d)", state
);
752 if (state
== S_OK
&& conn
->cached
)
753 normalize_cache_entry(conn
->cached
, conn
->from
);
755 set_connection_state(conn
, state
);
757 if (conn
->running
) interrupt_connection(conn
);
758 done_connection(conn
);
759 register_check_queue();
762 /* Set certain state on a connection and then retry the connection. */
764 retry_connection(struct connection
*conn
, enum connection_state state
)
766 int max_tries
= get_opt_int("connection.retries");
768 assertm(is_in_result_state(state
),
769 "connection didn't end in result state (%d)", state
);
771 set_connection_state(conn
, state
);
773 interrupt_connection(conn
);
774 if (conn
->uri
->post
|| (max_tries
&& ++conn
->tries
>= max_tries
)) {
775 done_connection(conn
);
776 register_check_queue();
778 conn
->prev_error
= conn
->state
;
779 run_connection(conn
);
784 try_to_suspend_connection(struct connection
*conn
, struct uri
*uri
)
786 enum connection_priority priority
= get_priority(conn
);
787 struct connection
*c
;
789 foreachback (c
, connection_queue
) {
790 if (get_priority(c
) <= priority
) return -1;
791 if (c
->state
== S_WAIT
) continue;
792 if (c
->uri
->post
&& get_priority(c
) < PRI_CANCEL
) continue;
793 if (uri
&& !compare_uri(uri
, c
->uri
, URI_HOST
)) continue;
794 suspend_connection(c
);
802 try_connection(struct connection
*conn
, int max_conns_to_host
, int max_conns
)
804 struct host_connection
*host_conn
= get_host_connection(conn
);
806 if (host_conn
&& get_object_refcount(host_conn
) >= max_conns_to_host
)
807 return try_to_suspend_connection(conn
, host_conn
->uri
) ? 0 : -1;
809 if (active_connections
>= max_conns
)
810 return try_to_suspend_connection(conn
, NULL
) ? 0 : -1;
812 run_connection(conn
);
819 struct connection
*conn
;
820 int max_conns_to_host
= get_opt_int("connection.max_connections_to_host");
821 int max_conns
= get_opt_int("connection.max_connections");
824 conn
= connection_queue
.next
;
826 check_keepalive_connections();
828 while (conn
!= (struct connection
*) &connection_queue
) {
829 struct connection
*c
;
830 enum connection_priority pri
= get_priority(conn
);
832 for (c
= conn
; c
!= (struct connection
*) &connection_queue
&& get_priority(c
) == pri
;) {
833 struct connection
*cc
= c
;
836 if (cc
->state
== S_WAIT
&& get_keepalive_connection(cc
)
837 && try_connection(cc
, max_conns_to_host
, max_conns
))
841 for (c
= conn
; c
!= (struct connection
*) &connection_queue
&& get_priority(c
) == pri
;) {
842 struct connection
*cc
= c
;
845 if (cc
->state
== S_WAIT
846 && try_connection(cc
, max_conns_to_host
, max_conns
))
853 foreachback (conn
, connection_queue
) {
854 if (get_priority(conn
) < PRI_CANCEL
) break;
855 if (conn
->state
== S_WAIT
) {
856 set_connection_state(conn
, S_INTERRUPTED
);
857 done_connection(conn
);
866 register_check_queue(void)
868 return register_bottom_half(check_queue
, NULL
);
872 load_uri(struct uri
*uri
, struct uri
*referrer
, struct download
*download
,
873 enum connection_priority pri
, enum cache_mode cache_mode
, off_t start
)
875 struct cache_entry
*cached
;
876 struct connection
*conn
;
877 struct uri
*proxy_uri
, *proxied_uri
;
878 enum connection_state connection_state
= S_OK
;
881 download
->conn
= NULL
;
882 download
->cached
= NULL
;
884 download
->state
= S_OUT_OF_MEM
;
885 download
->prev_error
= 0;
889 foreach (conn
, connection_queue
) {
890 struct download
*assigned
;
892 foreach (assigned
, conn
->downloads
) {
893 assertm(assigned
!= download
, "Download assigned to '%s'", struri(conn
->uri
));
895 download
->state
= S_INTERNAL
;
896 if (download
->callback
)
897 download
->callback(download
, download
->data
);
900 /* No recovery path should be necessary. */
905 cached
= get_validated_cache_entry(uri
, cache_mode
);
908 download
->cached
= cached
;
909 download
->state
= S_OK
;
911 * This doesn't work since sometimes |download->progress|
912 * is undefined and contains random memory locations.
913 * It's not supposed to point on anything here since
914 * |download| has no connection attached.
915 * Downloads resuming will probably break in some
916 * cases without this, though.
917 * FIXME: Needs more investigation. --pasky */
918 /* if (download->progress) download->progress->start = start; */
919 if (download
->callback
)
920 download
->callback(download
, download
->data
);
925 proxied_uri
= get_proxied_uri(uri
);
926 proxy_uri
= get_proxy_uri(uri
, &connection_state
);
930 || (get_protocol_need_slash_after_host(proxy_uri
->protocol
)
931 && !proxy_uri
->hostlen
)) {
934 if (connection_state
== S_OK
) {
935 connection_state
= proxy_uri
&& proxied_uri
936 ? S_BAD_URL
: S_OUT_OF_MEM
;
939 download
->state
= connection_state
;
940 download
->callback(download
, download
->data
);
942 if (proxy_uri
) done_uri(proxy_uri
);
943 if (proxied_uri
) done_uri(proxied_uri
);
947 foreach (conn
, connection_queue
) {
949 || !compare_uri(conn
->uri
, proxy_uri
, 0))
953 done_uri(proxied_uri
);
955 if (get_priority(conn
) > pri
) {
959 register_check_queue();
965 download
->progress
= conn
->progress
;
966 download
->conn
= conn
;
967 download
->cached
= conn
->cached
;
968 add_to_list(conn
->downloads
, download
);
969 /* This is likely to call download->callback() now! */
970 set_connection_state(conn
, conn
->state
);
976 conn
= init_connection(proxy_uri
, proxied_uri
, referrer
, start
, cache_mode
, pri
);
979 download
->state
= S_OUT_OF_MEM
;
980 download
->callback(download
, download
->data
);
982 if (proxy_uri
) done_uri(proxy_uri
);
983 if (proxied_uri
) done_uri(proxied_uri
);
987 if (cache_mode
< CACHE_MODE_FORCE_RELOAD
&& cached
&& !list_empty(cached
->frag
)
988 && !((struct fragment
*) cached
->frag
.next
)->offset
)
989 conn
->from
= ((struct fragment
*) cached
->frag
.next
)->length
;
992 download
->progress
= conn
->progress
;
993 download
->conn
= conn
;
994 download
->cached
= NULL
;
995 download
->state
= S_OK
;
996 add_to_list(conn
->downloads
, download
);
1000 set_connection_state(conn
, S_WAIT
);
1004 register_check_queue();
1009 /* FIXME: one object in more connections */
1011 cancel_download(struct download
*download
, int interrupt
)
1013 struct connection
*conn
;
1016 if_assert_failed
return;
1018 /* Did the connection already end? */
1019 if (is_in_result_state(download
->state
))
1022 assertm(download
->conn
!= NULL
, "last state is %d", download
->state
);
1026 download
->state
= S_INTERRUPTED
;
1027 del_from_list(download
);
1029 conn
= download
->conn
;
1031 conn
->pri
[download
->pri
]--;
1032 assertm(conn
->pri
[download
->pri
] >= 0, "priority counter underflow");
1033 if_assert_failed conn
->pri
[download
->pri
] = 0;
1035 if (list_empty(conn
->downloads
)) {
1036 /* Necessary because of assertion in get_priority(). */
1037 conn
->pri
[PRI_CANCEL
]++;
1039 if (conn
->detached
|| interrupt
)
1040 abort_connection(conn
, S_INTERRUPTED
);
1046 register_check_queue();
1050 move_download(struct download
*old
, struct download
*new,
1051 enum connection_priority newpri
)
1053 struct connection
*conn
;
1057 /* The download doesn't necessarily have a connection attached, for
1058 * example the file protocol loads it's object immediately. This is
1059 * catched by the result state check below. */
1064 new->cached
= old
->cached
;
1065 new->prev_error
= old
->prev_error
;
1066 new->progress
= old
->progress
;
1067 new->state
= old
->state
;
1070 if (is_in_result_state(old
->state
)) {
1071 /* Ensure that new->conn is always "valid", that is NULL if the
1072 * connection has been detached and non-NULL otherwise. */
1073 if (new->callback
) {
1075 new->progress
= NULL
;
1076 new->callback(new, new->data
);
1081 assertm(old
->conn
!= NULL
, "last state is %d", old
->state
);
1083 conn
->pri
[new->pri
]++;
1084 add_to_list(conn
->downloads
, new);
1085 /* In principle, we need to sort_queue() only if conn->pri[new->pri]
1086 * just changed from 0 to 1. But the risk of bugs is smaller if we
1087 * sort every time. */
1090 cancel_download(old
, 0);
1094 /* This will remove 'pos' bytes from the start of the cache for the specified
1095 * connection, if the cached object is already too big. */
1097 detach_connection(struct download
*download
, off_t pos
)
1099 struct connection
*conn
= download
->conn
;
1101 if (is_in_result_state(download
->state
)) return;
1103 if (!conn
->detached
) {
1105 off_t i
, total_pri
= 0;
1110 total_len
= (conn
->est_length
== -1) ? conn
->from
1113 if (total_len
< (get_opt_long("document.cache.memory.size")
1114 * MAX_CACHED_OBJECT_PERCENT
/ 100)) {
1115 /* This whole thing will fit to the memory anyway, so
1116 * there's no problem in detaching the connection. */
1120 for (i
= 0; i
< PRI_CANCEL
; i
++)
1121 total_pri
+= conn
->pri
[i
];
1122 assertm(total_pri
, "detaching free connection");
1123 /* No recovery path should be necessary...? */
1125 /* Pre-clean cache. */
1126 shrink_format_cache(0);
1128 if (total_pri
!= 1 || is_object_used(conn
->cached
)) {
1129 /* We're too important, or someone uses our cache
1134 /* DBG("detached"); */
1136 /* We aren't valid cache entry anymore. */
1137 conn
->cached
->valid
= 0;
1141 /* Strip the entry. */
1142 free_entry_to(conn
->cached
, pos
);
1145 /* Timer callback for @conn->timer. As explained in @install_timer,
1146 * this function must erase the expired timer ID from all variables. */
1148 connection_timeout(struct connection
*conn
)
1150 conn
->timer
= TIMER_ID_UNDEF
;
1151 /* The expired timer ID has now been erased. */
1152 timeout_socket(conn
->socket
);
1155 /* Timer callback for @conn->timer. As explained in @install_timer,
1156 * this function must erase the expired timer ID from all variables.
1158 * Huh, using two timers? Is this to account for changes of c->unrestartable
1159 * or can it be reduced? --jonas */
1161 connection_timeout_1(struct connection
*conn
)
1163 install_timer(&conn
->timer
, (milliseconds_T
)
1164 ((conn
->unrestartable
1165 ? get_opt_int("connection.unrestartable_receive_timeout")
1166 : get_opt_int("connection.receive_timeout"))
1167 * 500), (void (*)(void *)) connection_timeout
, conn
);
1168 /* The expired timer ID has now been erased. */
1172 set_connection_timeout(struct connection
*conn
)
1174 kill_timer(&conn
->timer
);
1176 install_timer(&conn
->timer
, (milliseconds_T
)
1177 ((conn
->unrestartable
1178 ? get_opt_int("connection.unrestartable_receive_timeout")
1179 : get_opt_int("connection.receive_timeout"))
1180 * 500), (void (*)(void *)) connection_timeout_1
, conn
);
1185 abort_all_connections(void)
1187 while (!list_empty(connection_queue
)) {
1188 abort_connection(connection_queue
.next
, S_INTERRUPTED
);
1191 abort_all_keepalive_connections();
1195 abort_background_connections(void)
1197 struct connection
*conn
, *next
;
1199 foreachsafe (conn
, next
, connection_queue
) {
1200 if (get_priority(conn
) >= PRI_CANCEL
)
1201 abort_connection(conn
, S_INTERRUPTED
);
1206 is_entry_used(struct cache_entry
*cached
)
1208 struct connection
*conn
;
1210 foreach (conn
, connection_queue
)
1211 if (conn
->cached
== cached
)