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
);
122 connection_disappeared(struct connection
*conn
)
124 struct connection
*c
;
126 foreach (c
, connection_queue
)
127 if (conn
== c
&& conn
->id
== c
->id
)
133 /* Host connection management: */
134 /* Used to keep track on the number of connections to any given host. When
135 * trying to setup a new connection the list is searched to see if the maximum
136 * number of connection has been reached. If that is the case we try to suspend
137 * an already established connection. */
138 /* Some connections (like file://) that do not involve hosts are not maintained
141 struct host_connection
{
142 OBJECT_HEAD(struct host_connection
);
144 /* XXX: This is just the URI of the connection that registered the
145 * host connection so only rely on the host part. */
149 static struct host_connection
*
150 get_host_connection(struct connection
*conn
)
152 struct host_connection
*host_conn
;
154 if (!conn
->uri
->host
) return NULL
;
156 foreach (host_conn
, host_connections
)
157 if (compare_uri(host_conn
->uri
, conn
->uri
, URI_HOST
))
163 /* Returns if the connection was successfully added. */
164 /* Don't add hostnameless host connections but they're valid. */
166 add_host_connection(struct connection
*conn
)
168 struct host_connection
*host_conn
= get_host_connection(conn
);
170 if (!host_conn
&& conn
->uri
->host
) {
171 host_conn
= mem_calloc(1, sizeof(*host_conn
));
172 if (!host_conn
) return 0;
174 host_conn
->uri
= get_uri_reference(conn
->uri
);
175 object_nolock(host_conn
, "host_connection");
176 add_to_list(host_connections
, host_conn
);
178 if (host_conn
) object_lock(host_conn
);
183 /* Decrements and free()s the host connection if it is the last 'refcount'. */
185 done_host_connection(struct connection
*conn
)
187 struct host_connection
*host_conn
= get_host_connection(conn
);
189 if (!host_conn
) return;
191 object_unlock(host_conn
);
192 if (is_object_used(host_conn
)) return;
194 del_from_list(host_conn
);
195 done_uri(host_conn
->uri
);
200 static void sort_queue();
204 check_queue_bugs(void)
206 struct connection
*conn
;
207 enum connection_priority prev_priority
= 0;
210 foreach (conn
, connection_queue
) {
211 enum connection_priority priority
= get_priority(conn
);
215 assertm(priority
>= prev_priority
, "queue is not sorted");
216 assertm(is_in_progress_state(conn
->state
),
217 "interrupted connection on queue (conn %s, state %d)",
218 struri(conn
->uri
), conn
->state
);
219 prev_priority
= priority
;
222 assertm(cc
== active_connections
,
223 "bad number of active connections (counted %d, stored %d)",
224 cc
, active_connections
);
227 #define check_queue_bugs()
231 set_connection_socket_state(struct socket
*socket
, struct connection_state state
)
234 set_connection_state(socket
->conn
, state
);
238 set_connection_socket_timeout(struct socket
*socket
, struct connection_state state
)
241 set_connection_timeout(socket
->conn
);
245 retry_connection_socket(struct socket
*socket
, struct connection_state state
)
248 retry_connection(socket
->conn
, state
);
252 done_connection_socket(struct socket
*socket
, struct connection_state state
)
255 abort_connection(socket
->conn
, state
);
258 static struct connection
*
259 init_connection(struct uri
*uri
, struct uri
*proxied_uri
, struct uri
*referrer
,
260 off_t start
, enum cache_mode cache_mode
,
261 enum connection_priority priority
)
263 static struct socket_operations connection_socket_operations
= {
264 set_connection_socket_state
,
265 set_connection_socket_timeout
,
266 retry_connection_socket
,
267 done_connection_socket
,
269 struct connection
*conn
= mem_calloc(1, sizeof(*conn
));
271 if (!conn
) return NULL
;
273 assert(proxied_uri
->protocol
!= PROTOCOL_PROXY
);
275 conn
->socket
= init_socket(conn
, &connection_socket_operations
);
281 conn
->data_socket
= init_socket(conn
, &connection_socket_operations
);
282 if (!conn
->data_socket
) {
283 mem_free(conn
->socket
);
288 conn
->progress
= init_progress(start
);
289 if (!conn
->progress
) {
290 mem_free(conn
->data_socket
);
291 mem_free(conn
->socket
);
296 /* load_uri() gets the URI from get_proxy() which grabs a reference for
299 conn
->proxied_uri
= proxied_uri
;
300 conn
->id
= connection_id
++;
301 conn
->pri
[priority
] = 1;
302 conn
->cache_mode
= cache_mode
;
304 conn
->content_encoding
= ENCODING_NONE
;
305 conn
->stream_pipes
[0] = conn
->stream_pipes
[1] = -1;
306 init_list(conn
->downloads
);
307 conn
->est_length
= -1;
308 conn
->timer
= TIMER_ID_UNDEF
;
311 /* Don't set referrer when it is the file protocol and the URI
312 * being loaded is not. This means CGI scripts will have it
313 * available while preventing information about the local
314 * system from being leaked to external servers. */
315 if (referrer
->protocol
!= PROTOCOL_FILE
316 || uri
->protocol
== PROTOCOL_FILE
)
317 conn
->referrer
= get_uri_reference(referrer
);
324 update_connection_progress(struct connection
*conn
)
326 update_progress(conn
->progress
, conn
->received
, conn
->est_length
, conn
->from
);
329 /* Progress timer callback for @conn->progress. As explained in
330 * @start_update_progress, this function must erase the expired timer
331 * ID from @conn->progress->timer. */
333 stat_timer(struct connection
*conn
)
335 update_connection_progress(conn
);
336 /* The expired timer ID has now been erased. */
337 notify_connection_callbacks(conn
);
341 set_connection_state(struct connection
*conn
, struct connection_state state
)
343 struct download
*download
;
344 struct progress
*progress
= conn
->progress
;
346 if (is_in_result_state(conn
->state
) && is_in_progress_state(state
))
347 conn
->prev_error
= conn
->state
;
350 if (is_in_state(conn
->state
, S_TRANS
)) {
351 if (progress
->timer
== TIMER_ID_UNDEF
) {
352 start_update_progress(progress
, (void (*)(void *)) stat_timer
, conn
);
353 update_connection_progress(conn
);
354 if (connection_disappeared(conn
))
359 kill_timer(&progress
->timer
);
362 foreach (download
, conn
->downloads
) {
363 download
->state
= state
;
364 download
->prev_error
= conn
->prev_error
;
367 if (is_in_progress_state(state
)) notify_connection_callbacks(conn
);
371 shutdown_connection_stream(struct connection
*conn
)
374 close_encoded(conn
->stream
);
376 } else if (conn
->stream_pipes
[0] >= 0) {
377 /* close_encoded() usually closes this end of the pipe,
378 * but open_encoded() apparently failed this time. */
379 close(conn
->stream_pipes
[0]);
381 if (conn
->stream_pipes
[1] >= 0)
382 close(conn
->stream_pipes
[1]);
383 conn
->stream_pipes
[0] = conn
->stream_pipes
[1] = -1;
387 free_connection_data(struct connection
*conn
)
389 assertm(conn
->running
, "connection already suspended");
390 /* XXX: Recovery path? Originally, there was none. I think we'll get
391 * at least active_connections underflows along the way. --pasky */
394 active_connections
--;
395 assertm(active_connections
>= 0, "active connections underflow");
396 if_assert_failed active_connections
= 0;
399 if (conn
->socket
->ssl
&& conn
->cached
)
400 mem_free_set(&conn
->cached
->ssl_info
, get_ssl_connection_cipher(conn
->socket
));
406 done_socket(conn
->socket
);
407 done_socket(conn
->data_socket
);
409 shutdown_connection_stream(conn
);
411 mem_free_set(&conn
->info
, NULL
);
413 kill_timer(&conn
->timer
);
415 if (!is_in_state(conn
->state
, S_WAIT
))
416 done_host_connection(conn
);
420 notify_connection_callbacks(struct connection
*conn
)
422 struct connection_state state
= conn
->state
;
423 struct download
*download
, *next
;
425 foreachsafe (download
, next
, conn
->downloads
) {
426 download
->cached
= conn
->cached
;
427 if (download
->callback
)
428 download
->callback(download
, download
->data
);
429 if (is_in_progress_state(state
) && connection_disappeared(conn
))
435 done_connection(struct connection
*conn
)
437 /* When removing the connection callbacks should always be aware of it
438 * so they can unregister themselves. We do this by enforcing that the
439 * connection is in a result state. If it is not already it is an
440 * internal bug. This should never happen but it does. ;) --jonas */
441 if (!is_in_result_state(conn
->state
))
442 set_connection_state(conn
, connection_state(S_INTERNAL
));
445 notify_connection_callbacks(conn
);
446 if (conn
->referrer
) done_uri(conn
->referrer
);
448 done_uri(conn
->proxied_uri
);
449 mem_free(conn
->socket
);
450 mem_free(conn
->data_socket
);
451 done_progress(conn
->progress
);
457 add_to_queue(struct connection
*conn
)
459 struct connection
*c
;
460 enum connection_priority priority
= get_priority(conn
);
462 foreach (c
, connection_queue
)
463 if (get_priority(c
) > priority
)
466 add_at_pos(c
->prev
, conn
);
470 /* Returns zero if no callback was done and the keepalive connection should be
471 * deleted or non-zero if the keepalive connection should not be deleted. */
473 do_keepalive_connection_callback(struct keepalive_connection
*keep_conn
)
475 struct uri
*proxied_uri
= get_proxied_uri(keep_conn
->uri
);
476 struct uri
*proxy_uri
= get_proxy_uri(keep_conn
->uri
, NULL
);
478 if (proxied_uri
&& proxy_uri
) {
479 struct connection
*conn
;
481 conn
= init_connection(proxy_uri
, proxied_uri
, NULL
, 0,
482 CACHE_MODE_NEVER
, PRI_CANCEL
);
485 void (*done
)(struct connection
*) = keep_conn
->done
;
489 /* Get the keepalive info and let it clean up */
490 if (!has_keepalive_connection(conn
)
491 || !add_host_connection(conn
)) {
492 free_connection_data(conn
);
493 done_connection(conn
);
497 active_connections
++;
504 if (proxied_uri
) done_uri(proxied_uri
);
505 if (proxy_uri
) done_uri(proxy_uri
);
511 done_keepalive_connection(struct keepalive_connection
*keep_conn
)
513 if (keep_conn
->done
&& do_keepalive_connection_callback(keep_conn
))
516 del_from_list(keep_conn
);
517 if (keep_conn
->socket
!= -1) close(keep_conn
->socket
);
518 done_uri(keep_conn
->uri
);
522 static struct keepalive_connection
*
523 init_keepalive_connection(struct connection
*conn
, long timeout_in_seconds
,
524 void (*done
)(struct connection
*))
526 struct keepalive_connection
*keep_conn
;
527 struct uri
*uri
= conn
->uri
;
530 if_assert_failed
return NULL
;
532 keep_conn
= mem_calloc(1, sizeof(*keep_conn
));
533 if (!keep_conn
) return NULL
;
535 keep_conn
->uri
= get_uri_reference(uri
);
536 keep_conn
->done
= done
;
537 keep_conn
->protocol_family
= conn
->socket
->protocol_family
;
538 keep_conn
->socket
= conn
->socket
->fd
;
539 timeval_from_seconds(&keep_conn
->timeout
, timeout_in_seconds
);
540 timeval_now(&keep_conn
->creation_time
);
545 static struct keepalive_connection
*
546 get_keepalive_connection(struct connection
*conn
)
548 struct keepalive_connection
*keep_conn
;
550 if (!conn
->uri
->host
) return NULL
;
552 foreach (keep_conn
, keepalive_connections
)
553 if (compare_uri(keep_conn
->uri
, conn
->uri
, URI_KEEPALIVE
))
560 has_keepalive_connection(struct connection
*conn
)
562 struct keepalive_connection
*keep_conn
= get_keepalive_connection(conn
);
564 if (!keep_conn
) return 0;
566 conn
->socket
->fd
= keep_conn
->socket
;
567 conn
->socket
->protocol_family
= keep_conn
->protocol_family
;
569 /* Mark that the socket should not be closed and the callback should be
571 keep_conn
->socket
= -1;
572 keep_conn
->done
= NULL
;
573 done_keepalive_connection(keep_conn
);
579 add_keepalive_connection(struct connection
*conn
, long timeout_in_seconds
,
580 void (*done
)(struct connection
*))
582 struct keepalive_connection
*keep_conn
;
584 assertm(conn
->socket
->fd
!= -1, "keepalive connection not connected");
585 if_assert_failed
goto done
;
587 keep_conn
= init_keepalive_connection(conn
, timeout_in_seconds
, done
);
589 /* Make sure that the socket descriptor will not periodically be
590 * checked or closed by free_connection_data(). */
591 clear_handlers(conn
->socket
->fd
);
592 conn
->socket
->fd
= -1;
593 add_to_list(keepalive_connections
, keep_conn
);
596 /* It will take just a little more time */
602 free_connection_data(conn
);
603 done_connection(conn
);
604 register_check_queue();
607 /* Timer callback for @keepalive_timeout. As explained in @install_timer,
608 * this function must erase the expired timer ID from all variables. */
610 keepalive_timer(void *x
)
612 keepalive_timeout
= TIMER_ID_UNDEF
;
613 /* The expired timer ID has now been erased. */
614 check_keepalive_connections();
618 check_keepalive_connections(void)
620 struct keepalive_connection
*keep_conn
, *next
;
626 kill_timer(&keepalive_timeout
);
628 foreachsafe (keep_conn
, next
, keepalive_connections
) {
631 if (can_read(keep_conn
->socket
)) {
632 done_keepalive_connection(keep_conn
);
636 timeval_sub(&age
, &keep_conn
->creation_time
, &now
);
637 if (timeval_cmp(&age
, &keep_conn
->timeout
) > 0) {
638 done_keepalive_connection(keep_conn
);
645 for (; p
> MAX_KEEPALIVE_CONNECTIONS
; p
--) {
646 assertm(!list_empty(keepalive_connections
), "keepalive list empty");
647 if_assert_failed
return;
648 done_keepalive_connection(keepalive_connections
.prev
);
651 if (!list_empty(keepalive_connections
))
652 install_timer(&keepalive_timeout
, KEEPALIVE_CHECK_TIME
,
653 keepalive_timer
, NULL
);
657 abort_all_keepalive_connections(void)
659 while (!list_empty(keepalive_connections
))
660 done_keepalive_connection(keepalive_connections
.next
);
662 check_keepalive_connections();
670 struct connection
*conn
;
673 foreach (conn
, connection_queue
) {
674 if (!list_has_next(connection_queue
, conn
)) break;
676 if (get_priority(conn
->next
) < get_priority(conn
)) {
677 struct connection
*c
= conn
->next
;
690 interrupt_connection(struct connection
*conn
)
692 free_connection_data(conn
);
696 suspend_connection(struct connection
*conn
)
698 interrupt_connection(conn
);
699 set_connection_state(conn
, connection_state(S_WAIT
));
703 run_connection(struct connection
*conn
)
705 protocol_handler_T
*func
= get_protocol_handler(conn
->uri
->protocol
);
709 assertm(!conn
->running
, "connection already running");
710 if_assert_failed
return;
712 if (!add_host_connection(conn
)) {
713 set_connection_state(conn
, connection_state(S_OUT_OF_MEM
));
714 done_connection(conn
);
718 active_connections
++;
724 /* Set certain state on a connection and then abort the connection. */
726 abort_connection(struct connection
*conn
, struct connection_state state
)
728 assertm(is_in_result_state(state
),
729 "connection didn't end in result state (%d)", state
);
731 if (is_in_state(state
, S_OK
) && conn
->cached
)
732 normalize_cache_entry(conn
->cached
, conn
->from
);
734 set_connection_state(conn
, state
);
736 if (conn
->running
) interrupt_connection(conn
);
737 done_connection(conn
);
738 register_check_queue();
741 /* Set certain state on a connection and then retry the connection. */
743 retry_connection(struct connection
*conn
, struct connection_state state
)
745 int max_tries
= get_opt_int("connection.retries");
747 assertm(is_in_result_state(state
),
748 "connection didn't end in result state (%d)", state
);
750 set_connection_state(conn
, state
);
752 interrupt_connection(conn
);
753 if (conn
->uri
->post
|| (max_tries
&& ++conn
->tries
>= max_tries
)) {
754 done_connection(conn
);
755 register_check_queue();
757 conn
->prev_error
= conn
->state
;
758 run_connection(conn
);
763 try_to_suspend_connection(struct connection
*conn
, struct uri
*uri
)
765 enum connection_priority priority
= get_priority(conn
);
766 struct connection
*c
;
768 foreachback (c
, connection_queue
) {
769 if (get_priority(c
) <= priority
) return -1;
770 if (is_in_state(c
->state
, S_WAIT
)) continue;
771 if (c
->uri
->post
&& get_priority(c
) < PRI_CANCEL
) continue;
772 if (uri
&& !compare_uri(uri
, c
->uri
, URI_HOST
)) continue;
773 suspend_connection(c
);
781 try_connection(struct connection
*conn
, int max_conns_to_host
, int max_conns
)
783 struct host_connection
*host_conn
= get_host_connection(conn
);
785 if (host_conn
&& get_object_refcount(host_conn
) >= max_conns_to_host
)
786 return try_to_suspend_connection(conn
, host_conn
->uri
) ? 0 : -1;
788 if (active_connections
>= max_conns
)
789 return try_to_suspend_connection(conn
, NULL
) ? 0 : -1;
791 run_connection(conn
);
798 struct connection
*conn
;
799 int max_conns_to_host
= get_opt_int("connection.max_connections_to_host");
800 int max_conns
= get_opt_int("connection.max_connections");
803 conn
= connection_queue
.next
;
805 check_keepalive_connections();
807 while (conn
!= (struct connection
*) &connection_queue
) {
808 struct connection
*c
;
809 enum connection_priority pri
= get_priority(conn
);
811 for (c
= conn
; c
!= (struct connection
*) &connection_queue
&& get_priority(c
) == pri
;) {
812 struct connection
*cc
= c
;
815 if (is_in_state(cc
->state
, S_WAIT
)
816 && get_keepalive_connection(cc
)
817 && try_connection(cc
, max_conns_to_host
, max_conns
))
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 && try_connection(cc
, max_conns_to_host
, max_conns
))
833 foreachback (conn
, connection_queue
) {
834 if (get_priority(conn
) < PRI_CANCEL
) break;
835 if (is_in_state(conn
->state
, S_WAIT
)) {
836 set_connection_state(conn
, connection_state(S_INTERRUPTED
));
837 done_connection(conn
);
846 register_check_queue(void)
848 return register_bottom_half(check_queue
, NULL
);
852 load_uri(struct uri
*uri
, struct uri
*referrer
, struct download
*download
,
853 enum connection_priority pri
, enum cache_mode cache_mode
, off_t start
)
855 struct cache_entry
*cached
;
856 struct connection
*conn
;
857 struct uri
*proxy_uri
, *proxied_uri
;
858 struct connection_state error_state
= connection_state(S_OK
);
861 download
->conn
= NULL
;
862 download
->cached
= NULL
;
864 download
->state
= connection_state(S_OUT_OF_MEM
);
865 download
->prev_error
= connection_state(0);
869 foreach (conn
, connection_queue
) {
870 struct download
*assigned
;
872 foreach (assigned
, conn
->downloads
) {
873 assertm(assigned
!= download
, "Download assigned to '%s'", struri(conn
->uri
));
875 download
->state
= connection_state(S_INTERNAL
);
876 if (download
->callback
)
877 download
->callback(download
, download
->data
);
880 /* No recovery path should be necessary. */
885 cached
= get_validated_cache_entry(uri
, cache_mode
);
888 download
->cached
= cached
;
889 download
->state
= connection_state(S_OK
);
891 * This doesn't work since sometimes |download->progress|
892 * is undefined and contains random memory locations.
893 * It's not supposed to point on anything here since
894 * |download| has no connection attached.
895 * Downloads resuming will probably break in some
896 * cases without this, though.
897 * FIXME: Needs more investigation. --pasky */
898 /* if (download->progress) download->progress->start = start; */
899 if (download
->callback
)
900 download
->callback(download
, download
->data
);
905 proxied_uri
= get_proxied_uri(uri
);
906 proxy_uri
= get_proxy_uri(uri
, &error_state
);
910 || (get_protocol_need_slash_after_host(proxy_uri
->protocol
)
911 && !proxy_uri
->hostlen
)) {
914 if (is_in_state(error_state
, S_OK
)) {
915 error_state
= proxy_uri
&& proxied_uri
916 ? connection_state(S_BAD_URL
)
917 : connection_state(S_OUT_OF_MEM
);
920 download
->state
= error_state
;
921 download
->callback(download
, download
->data
);
923 if (proxy_uri
) done_uri(proxy_uri
);
924 if (proxied_uri
) done_uri(proxied_uri
);
928 foreach (conn
, connection_queue
) {
930 || !compare_uri(conn
->uri
, proxy_uri
, 0))
934 done_uri(proxied_uri
);
936 if (get_priority(conn
) > pri
) {
940 register_check_queue();
946 download
->progress
= conn
->progress
;
947 download
->conn
= conn
;
948 download
->cached
= conn
->cached
;
949 add_to_list(conn
->downloads
, download
);
950 /* This is likely to call download->callback() now! */
951 set_connection_state(conn
, conn
->state
);
957 conn
= init_connection(proxy_uri
, proxied_uri
, referrer
, start
, cache_mode
, pri
);
960 download
->state
= connection_state(S_OUT_OF_MEM
);
961 download
->callback(download
, download
->data
);
963 if (proxy_uri
) done_uri(proxy_uri
);
964 if (proxied_uri
) done_uri(proxied_uri
);
968 if (cache_mode
< CACHE_MODE_FORCE_RELOAD
&& cached
&& !list_empty(cached
->frag
)
969 && !((struct fragment
*) cached
->frag
.next
)->offset
)
970 conn
->from
= ((struct fragment
*) cached
->frag
.next
)->length
;
973 download
->progress
= conn
->progress
;
974 download
->conn
= conn
;
975 download
->cached
= NULL
;
976 download
->state
= connection_state(S_OK
);
977 add_to_list(conn
->downloads
, download
);
981 set_connection_state(conn
, connection_state(S_WAIT
));
985 register_check_queue();
990 /* FIXME: one object in more connections */
992 cancel_download(struct download
*download
, int interrupt
)
994 struct connection
*conn
;
997 if_assert_failed
return;
999 /* Did the connection already end? */
1000 if (is_in_result_state(download
->state
))
1003 assertm(download
->conn
!= NULL
, "last state is %d", download
->state
);
1007 download
->state
= connection_state(S_INTERRUPTED
);
1008 del_from_list(download
);
1010 conn
= download
->conn
;
1012 conn
->pri
[download
->pri
]--;
1013 assertm(conn
->pri
[download
->pri
] >= 0, "priority counter underflow");
1014 if_assert_failed conn
->pri
[download
->pri
] = 0;
1016 if (list_empty(conn
->downloads
)) {
1017 /* Necessary because of assertion in get_priority(). */
1018 conn
->pri
[PRI_CANCEL
]++;
1020 if (conn
->detached
|| interrupt
)
1021 abort_connection(conn
, connection_state(S_INTERRUPTED
));
1027 register_check_queue();
1031 move_download(struct download
*old
, struct download
*new,
1032 enum connection_priority newpri
)
1034 struct connection
*conn
;
1038 /* The download doesn't necessarily have a connection attached, for
1039 * example the file protocol loads it's object immediately. This is
1040 * catched by the result state check below. */
1045 new->cached
= old
->cached
;
1046 new->prev_error
= old
->prev_error
;
1047 new->progress
= old
->progress
;
1048 new->state
= old
->state
;
1051 if (is_in_result_state(old
->state
)) {
1052 /* Ensure that new->conn is always "valid", that is NULL if the
1053 * connection has been detached and non-NULL otherwise. */
1054 if (new->callback
) {
1056 new->progress
= NULL
;
1057 new->callback(new, new->data
);
1062 assertm(old
->conn
!= NULL
, "last state is %d", old
->state
);
1064 conn
->pri
[new->pri
]++;
1065 add_to_list(conn
->downloads
, new);
1066 /* In principle, we need to sort_queue() only if conn->pri[new->pri]
1067 * just changed from 0 to 1. But the risk of bugs is smaller if we
1068 * sort every time. */
1071 cancel_download(old
, 0);
1075 /* This will remove 'pos' bytes from the start of the cache for the specified
1076 * connection, if the cached object is already too big. */
1078 detach_connection(struct download
*download
, off_t pos
)
1080 struct connection
*conn
= download
->conn
;
1082 if (is_in_result_state(download
->state
)) return;
1084 if (!conn
->detached
) {
1086 off_t i
, total_pri
= 0;
1091 total_len
= (conn
->est_length
== -1) ? conn
->from
1094 if (total_len
< (get_opt_long("document.cache.memory.size")
1095 * MAX_CACHED_OBJECT_PERCENT
/ 100)) {
1096 /* This whole thing will fit to the memory anyway, so
1097 * there's no problem in detaching the connection. */
1101 for (i
= 0; i
< PRI_CANCEL
; i
++)
1102 total_pri
+= conn
->pri
[i
];
1103 assertm(total_pri
, "detaching free connection");
1104 /* No recovery path should be necessary...? */
1106 /* Pre-clean cache. */
1107 shrink_format_cache(0);
1109 if (total_pri
!= 1 || is_object_used(conn
->cached
)) {
1110 /* We're too important, or someone uses our cache
1115 /* DBG("detached"); */
1117 /* We aren't valid cache entry anymore. */
1118 conn
->cached
->valid
= 0;
1122 /* Strip the entry. */
1123 free_entry_to(conn
->cached
, pos
);
1126 /* Timer callback for @conn->timer. As explained in @install_timer,
1127 * this function must erase the expired timer ID from all variables. */
1129 connection_timeout(struct connection
*conn
)
1131 conn
->timer
= TIMER_ID_UNDEF
;
1132 /* The expired timer ID has now been erased. */
1133 timeout_socket(conn
->socket
);
1136 /* Timer callback for @conn->timer. As explained in @install_timer,
1137 * this function must erase the expired timer ID from all variables.
1139 * Huh, using two timers? Is this to account for changes of c->unrestartable
1140 * or can it be reduced? --jonas */
1142 connection_timeout_1(struct connection
*conn
)
1144 install_timer(&conn
->timer
, (milliseconds_T
)
1145 ((conn
->unrestartable
1146 ? get_opt_int("connection.unrestartable_receive_timeout")
1147 : get_opt_int("connection.receive_timeout"))
1148 * 500), (void (*)(void *)) connection_timeout
, conn
);
1149 /* The expired timer ID has now been erased. */
1153 set_connection_timeout(struct connection
*conn
)
1155 kill_timer(&conn
->timer
);
1157 install_timer(&conn
->timer
, (milliseconds_T
)
1158 ((conn
->unrestartable
1159 ? get_opt_int("connection.unrestartable_receive_timeout")
1160 : get_opt_int("connection.receive_timeout"))
1161 * 500), (void (*)(void *)) connection_timeout_1
, conn
);
1166 abort_all_connections(void)
1168 while (!list_empty(connection_queue
)) {
1169 abort_connection(connection_queue
.next
,
1170 connection_state(S_INTERRUPTED
));
1173 abort_all_keepalive_connections();
1177 abort_background_connections(void)
1179 struct connection
*conn
, *next
;
1181 foreachsafe (conn
, next
, connection_queue
) {
1182 if (get_priority(conn
) >= PRI_CANCEL
)
1183 abort_connection(conn
, connection_state(S_INTERRUPTED
));
1188 is_entry_used(struct cache_entry
*cached
)
1190 struct connection
*conn
;
1192 foreach (conn
, connection_queue
)
1193 if (conn
->cached
== cached
)