1 /* Connections management */
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. */
46 /* Function called when the keepalive has timed out or is deleted */
47 void (*done
)(struct connection
*);
50 timeval_T creation_time
;
52 unsigned int protocol_family
:1; /* see network/socket.h, EL_PF_INET, EL_PF_INET6 */
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
);
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
])
79 assertm(priority
!= PRIORITIES
, "Connection has no owner");
80 /* Recovery path ;-). (XXX?) */
86 get_connections_count(void)
88 return list_size(&connection_queue
);
92 get_keepalive_connections_count(void)
94 return list_size(&keepalive_connections
);
98 get_connections_connecting_count(void)
100 struct connection
*conn
;
103 foreach (conn
, connection_queue
)
104 i
+= is_in_connecting_state(conn
->state
);
110 get_connections_transfering_count(void)
112 struct connection
*conn
;
115 foreach (conn
, connection_queue
)
116 i
+= is_in_transfering_state(conn
->state
);
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. */
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
)
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
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. */
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
))
169 /* Returns if the connection was successfully added. */
170 /* Don't add hostnameless host connections but they're valid. */
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
);
189 /* Decrements and free()s the host connection if it is the last 'refcount'. */
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
);
206 static void sort_queue();
210 check_queue_bugs(void)
212 struct connection
*conn
;
213 enum connection_priority prev_priority
= 0;
216 foreach (conn
, connection_queue
) {
217 enum connection_priority priority
= get_priority(conn
);
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
);
233 #define check_queue_bugs()
237 set_connection_socket_state(struct socket
*socket
, struct connection_state state
)
240 set_connection_state(socket
->conn
, state
);
244 set_connection_socket_timeout(struct socket
*socket
, struct connection_state state
)
247 set_connection_timeout(socket
->conn
);
251 retry_connection_socket(struct socket
*socket
, struct connection_state state
)
254 retry_connection(socket
->conn
, state
);
258 done_connection_socket(struct socket
*socket
, struct connection_state state
)
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
);
287 conn
->data_socket
= init_socket(conn
, &connection_socket_operations
);
288 if (!conn
->data_socket
) {
289 mem_free(conn
->socket
);
294 conn
->progress
= init_progress(start
);
295 if (!conn
->progress
) {
296 mem_free(conn
->data_socket
);
297 mem_free(conn
->socket
);
302 /* load_uri() gets the URI from get_proxy() which grabs a reference for
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
;
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
);
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. */
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
);
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
;
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
))
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
);
379 shutdown_connection_stream(struct connection
*conn
)
382 close_encoded(conn
->stream
);
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;
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 */
402 active_connections
--;
403 assertm(active_connections
>= 0, "active connections underflow");
404 if_assert_failed active_connections
= 0;
407 if (conn
->socket
->ssl
&& conn
->cached
)
408 mem_free_set(&conn
->cached
->ssl_info
, get_ssl_connection_cipher(conn
->socket
));
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
);
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
))
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
));
455 notify_connection_callbacks(conn
);
456 if (conn
->referrer
) done_uri(conn
->referrer
);
458 done_uri(conn
->proxied_uri
);
459 mem_free(conn
->socket
);
460 mem_free(conn
->data_socket
);
461 done_progress(conn
->progress
);
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
)
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. */
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
);
495 void (*done
)(struct connection
*) = keep_conn
->done
;
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
);
507 active_connections
++;
514 if (proxied_uri
) done_uri(proxied_uri
);
515 if (proxy_uri
) done_uri(proxy_uri
);
521 done_keepalive_connection(struct keepalive_connection
*keep_conn
)
523 if (keep_conn
->done
&& do_keepalive_connection_callback(keep_conn
))
526 del_from_list(keep_conn
);
527 if (keep_conn
->socket
!= -1) close(keep_conn
->socket
);
528 done_uri(keep_conn
->uri
);
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
;
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
);
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
))
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
581 keep_conn
->socket
= -1;
582 keep_conn
->done
= NULL
;
583 done_keepalive_connection(keep_conn
);
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
);
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
);
606 /* It will take just a little more time */
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. */
620 keepalive_timer(void *x
)
622 keepalive_timeout
= TIMER_ID_UNDEF
;
623 /* The expired timer ID has now been erased. */
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
, connection_state(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
, connection_state(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
, 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. */
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();
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 (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
);
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 (is_in_state(cc
->state
, S_WAIT
)
826 && get_keepalive_connection(cc
)
827 && try_connection(cc
, max_conns_to_host
, max_conns
))
831 for (c
= conn
; c
!= (struct connection
*) &connection_queue
&& get_priority(c
) == pri
;) {
832 struct connection
*cc
= c
;
835 if (is_in_state(cc
->state
, S_WAIT
)
836 && try_connection(cc
, max_conns_to_host
, max_conns
))
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
);
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
);
871 download
->conn
= NULL
;
872 download
->cached
= NULL
;
874 download
->state
= connection_state(S_OUT_OF_MEM
);
875 download
->prev_error
= connection_state(0);
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
));
885 download
->state
= connection_state(S_INTERNAL
);
886 if (download
->callback
)
887 download
->callback(download
, download
->data
);
890 /* No recovery path should be necessary. */
895 cached
= get_validated_cache_entry(uri
, cache_mode
);
898 download
->cached
= cached
;
899 download
->state
= connection_state(S_OK
);
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
);
915 proxied_uri
= get_proxied_uri(uri
);
916 proxy_uri
= get_proxy_uri(uri
, &error_state
);
920 || (get_protocol_need_slash_after_host(proxy_uri
->protocol
)
921 && !proxy_uri
->hostlen
)) {
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
);
938 foreach (conn
, connection_queue
) {
940 || !compare_uri(conn
->uri
, proxy_uri
, 0))
944 done_uri(proxied_uri
);
946 if (get_priority(conn
) > pri
) {
950 register_check_queue();
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
);
967 conn
= init_connection(proxy_uri
, proxied_uri
, referrer
, start
, cache_mode
, pri
);
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
);
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
;
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
);
991 set_connection_state(conn
, connection_state(S_WAIT
));
995 register_check_queue();
1000 /* FIXME: one object in more connections */
1002 cancel_download(struct download
*download
, int interrupt
)
1004 struct connection
*conn
;
1007 if_assert_failed
return;
1009 /* Did the connection already end? */
1010 if (is_in_result_state(download
->state
))
1013 assertm(download
->conn
!= NULL
, "last state is %d", download
->state
);
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
));
1037 register_check_queue();
1041 move_download(struct download
*old
, struct download
*new,
1042 enum connection_priority newpri
)
1044 struct connection
*conn
;
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. */
1055 new->cached
= old
->cached
;
1056 new->prev_error
= old
->prev_error
;
1057 new->progress
= old
->progress
;
1058 new->state
= old
->state
;
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
) {
1066 new->progress
= NULL
;
1067 new->callback(new, new->data
);
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. */
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. */
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
) {
1096 off_t i
, total_pri
= 0;
1101 total_len
= (conn
->est_length
== -1) ? conn
->from
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. */
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
1125 /* DBG("detached"); */
1127 /* We aren't valid cache entry anymore. */
1128 conn
->cached
->valid
= 0;
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. */
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 */
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. */
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
);
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();
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
)