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/http/http.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 check_keepalive_connections(void);
68 static void notify_connection_callbacks(struct connection
*conn
);
70 static /* inline */ enum connection_priority
71 get_priority(struct connection
*conn
)
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 init_list(conn
->downloads
);
312 conn
->est_length
= -1;
313 conn
->timer
= TIMER_ID_UNDEF
;
316 /* Don't set referrer when it is the file protocol and the URI
317 * being loaded is not. This means CGI scripts will have it
318 * available while preventing information about the local
319 * system from being leaked to external servers. */
320 if (referrer
->protocol
!= PROTOCOL_FILE
321 || uri
->protocol
== PROTOCOL_FILE
)
322 conn
->referrer
= get_uri_reference(referrer
);
329 update_connection_progress(struct connection
*conn
)
331 update_progress(conn
->progress
, conn
->received
, conn
->est_length
, conn
->from
);
334 /** Progress timer callback for @a conn->progress. */
336 stat_timer(struct connection
*conn
)
338 update_connection_progress(conn
);
339 notify_connection_callbacks(conn
);
342 /** Progress timer callback for @a conn->upload_progress. */
344 upload_stat_timer(struct connection
*conn
)
346 struct http_connection_info
*http
= conn
->info
;
348 assert(conn
->http_upload_progress
);
350 if_assert_failed
return;
352 update_progress(conn
->http_upload_progress
, http
->post
.uploaded
,
353 http
->post
.total_upload_length
, http
->post
.uploaded
);
354 notify_connection_callbacks(conn
);
358 set_connection_state(struct connection
*conn
, struct connection_state state
)
360 struct download
*download
;
361 struct progress
*progress
= conn
->progress
;
362 struct progress
*upload_progress
= conn
->http_upload_progress
;
364 if (is_in_result_state(conn
->state
) && is_in_progress_state(state
))
365 conn
->prev_error
= conn
->state
;
368 if (is_in_state(conn
->state
, S_TRANS
)) {
369 const unsigned int id
= conn
->id
;
371 if (upload_progress
&& upload_progress
->timer
== TIMER_ID_UNDEF
) {
372 start_update_progress(upload_progress
,
373 (void (*)(void *)) upload_stat_timer
, conn
);
374 upload_stat_timer(conn
);
375 if (connection_disappeared(conn
, id
))
378 if (progress
->timer
== TIMER_ID_UNDEF
) {
379 start_update_progress(progress
, (void (*)(void *)) stat_timer
, conn
);
380 update_connection_progress(conn
);
381 if (connection_disappeared(conn
, id
))
386 kill_timer(&progress
->timer
);
387 if (upload_progress
) kill_timer(&upload_progress
->timer
);
390 foreach (download
, conn
->downloads
) {
391 download
->state
= state
;
392 download
->prev_error
= conn
->prev_error
;
395 if (is_in_progress_state(state
)) notify_connection_callbacks(conn
);
399 shutdown_connection_stream(struct connection
*conn
)
402 close_encoded(conn
->stream
);
408 free_connection_data(struct connection
*conn
)
410 assertm(conn
->running
, "connection already suspended");
411 /* XXX: Recovery path? Originally, there was none. I think we'll get
412 * at least active_connections underflows along the way. --pasky */
415 active_connections
--;
416 assertm(active_connections
>= 0, "active connections underflow");
417 if_assert_failed active_connections
= 0;
420 if (conn
->socket
->ssl
&& conn
->cached
)
421 mem_free_set(&conn
->cached
->ssl_info
, get_ssl_connection_cipher(conn
->socket
));
427 done_socket(conn
->socket
);
428 done_socket(conn
->data_socket
);
430 shutdown_connection_stream(conn
);
432 mem_free_set(&conn
->info
, NULL
);
433 /* If conn->done is not NULL, it probably points to a function
434 * that expects conn->info to be a specific kind of structure.
435 * Such a function should not be called if a different pointer
436 * is later assigned to conn->info. Actually though, each
437 * free_connection_data() call seems to be soon followed by
438 * done_connection() so that conn->done would not be called
439 * again in any case. However, this assignment costs little
440 * and may make things a bit safer. */
443 kill_timer(&conn
->timer
);
445 if (!is_in_state(conn
->state
, S_WAIT
))
446 done_host_connection(conn
);
450 notify_connection_callbacks(struct connection
*conn
)
452 struct connection_state state
= conn
->state
;
453 unsigned int id
= conn
->id
;
454 struct download
*download
, *next
;
456 foreachsafe (download
, next
, conn
->downloads
) {
457 download
->cached
= conn
->cached
;
458 if (download
->callback
)
459 download
->callback(download
, download
->data
);
460 if (is_in_progress_state(state
)
461 && connection_disappeared(conn
, id
))
467 done_connection(struct connection
*conn
)
469 /* When removing the connection callbacks should always be aware of it
470 * so they can unregister themselves. We do this by enforcing that the
471 * connection is in a result state. If it is not already it is an
472 * internal bug. This should never happen but it does. ;) --jonas */
473 if (!is_in_result_state(conn
->state
))
474 set_connection_state(conn
, connection_state(S_INTERNAL
));
477 notify_connection_callbacks(conn
);
478 if (conn
->referrer
) done_uri(conn
->referrer
);
480 done_uri(conn
->proxied_uri
);
481 mem_free(conn
->socket
);
482 mem_free(conn
->data_socket
);
483 done_progress(conn
->progress
);
484 if (conn
->http_upload_progress
)
485 done_progress(conn
->http_upload_progress
);
491 add_to_queue(struct connection
*conn
)
493 struct connection
*c
;
494 enum connection_priority priority
= get_priority(conn
);
496 foreach (c
, connection_queue
)
497 if (get_priority(c
) > priority
)
500 add_at_pos(c
->prev
, conn
);
504 /* Returns zero if no callback was done and the keepalive connection should be
505 * deleted or non-zero if the keepalive connection should not be deleted. */
507 do_keepalive_connection_callback(struct keepalive_connection
*keep_conn
)
509 struct uri
*proxied_uri
= get_proxied_uri(keep_conn
->uri
);
510 struct uri
*proxy_uri
= get_proxy_uri(keep_conn
->uri
, NULL
);
512 if (proxied_uri
&& proxy_uri
) {
513 struct connection
*conn
;
515 conn
= init_connection(proxy_uri
, proxied_uri
, NULL
, 0,
516 CACHE_MODE_NEVER
, PRI_CANCEL
);
519 void (*done
)(struct connection
*) = keep_conn
->done
;
523 /* Get the keepalive info and let it clean up */
524 if (!has_keepalive_connection(conn
)
525 || !add_host_connection(conn
)) {
526 free_connection_data(conn
);
527 done_connection(conn
);
531 active_connections
++;
538 if (proxied_uri
) done_uri(proxied_uri
);
539 if (proxy_uri
) done_uri(proxy_uri
);
545 done_keepalive_connection(struct keepalive_connection
*keep_conn
)
547 if (keep_conn
->done
&& do_keepalive_connection_callback(keep_conn
))
550 del_from_list(keep_conn
);
551 if (keep_conn
->socket
!= -1) close(keep_conn
->socket
);
552 done_uri(keep_conn
->uri
);
556 static struct keepalive_connection
*
557 init_keepalive_connection(struct connection
*conn
, long timeout_in_seconds
,
558 void (*done
)(struct connection
*))
560 struct keepalive_connection
*keep_conn
;
561 struct uri
*uri
= conn
->uri
;
564 if_assert_failed
return NULL
;
566 keep_conn
= mem_calloc(1, sizeof(*keep_conn
));
567 if (!keep_conn
) return NULL
;
569 keep_conn
->uri
= get_uri_reference(uri
);
570 keep_conn
->done
= done
;
571 keep_conn
->protocol_family
= conn
->socket
->protocol_family
;
572 keep_conn
->socket
= conn
->socket
->fd
;
573 timeval_from_seconds(&keep_conn
->timeout
, timeout_in_seconds
);
574 timeval_now(&keep_conn
->creation_time
);
579 static struct keepalive_connection
*
580 get_keepalive_connection(struct connection
*conn
)
582 struct keepalive_connection
*keep_conn
;
584 if (!conn
->uri
->host
) return NULL
;
586 foreach (keep_conn
, keepalive_connections
)
587 if (compare_uri(keep_conn
->uri
, conn
->uri
, URI_KEEPALIVE
))
594 has_keepalive_connection(struct connection
*conn
)
596 struct keepalive_connection
*keep_conn
= get_keepalive_connection(conn
);
598 if (!keep_conn
) return 0;
600 conn
->socket
->fd
= keep_conn
->socket
;
601 conn
->socket
->protocol_family
= keep_conn
->protocol_family
;
603 /* Mark that the socket should not be closed and the callback should be
605 keep_conn
->socket
= -1;
606 keep_conn
->done
= NULL
;
607 done_keepalive_connection(keep_conn
);
613 add_keepalive_connection(struct connection
*conn
, long timeout_in_seconds
,
614 void (*done
)(struct connection
*))
616 struct keepalive_connection
*keep_conn
;
618 assertm(conn
->socket
->fd
!= -1, "keepalive connection not connected");
619 if_assert_failed
goto done
;
621 keep_conn
= init_keepalive_connection(conn
, timeout_in_seconds
, done
);
623 /* Make sure that the socket descriptor will not periodically be
624 * checked or closed by free_connection_data(). */
625 clear_handlers(conn
->socket
->fd
);
626 conn
->socket
->fd
= -1;
627 add_to_list(keepalive_connections
, keep_conn
);
630 /* It will take just a little more time */
636 free_connection_data(conn
);
637 done_connection(conn
);
638 register_check_queue();
641 /* Timer callback for @keepalive_timeout. As explained in @install_timer,
642 * this function must erase the expired timer ID from all variables. */
644 keepalive_timer(void *x
)
646 keepalive_timeout
= TIMER_ID_UNDEF
;
647 /* The expired timer ID has now been erased. */
648 check_keepalive_connections();
652 check_keepalive_connections(void)
654 struct keepalive_connection
*keep_conn
, *next
;
660 kill_timer(&keepalive_timeout
);
662 foreachsafe (keep_conn
, next
, keepalive_connections
) {
665 if (can_read(keep_conn
->socket
)) {
666 done_keepalive_connection(keep_conn
);
670 timeval_sub(&age
, &keep_conn
->creation_time
, &now
);
671 if (timeval_cmp(&age
, &keep_conn
->timeout
) > 0) {
672 done_keepalive_connection(keep_conn
);
679 for (; p
> MAX_KEEPALIVE_CONNECTIONS
; p
--) {
680 assertm(!list_empty(keepalive_connections
), "keepalive list empty");
681 if_assert_failed
return;
682 done_keepalive_connection(keepalive_connections
.prev
);
685 if (!list_empty(keepalive_connections
))
686 install_timer(&keepalive_timeout
, KEEPALIVE_CHECK_TIME
,
687 keepalive_timer
, NULL
);
691 abort_all_keepalive_connections(void)
693 while (!list_empty(keepalive_connections
))
694 done_keepalive_connection(keepalive_connections
.next
);
696 check_keepalive_connections();
704 struct connection
*conn
;
707 foreach (conn
, connection_queue
) {
708 if (!list_has_next(connection_queue
, conn
)) break;
710 if (get_priority(conn
->next
) < get_priority(conn
)) {
711 struct connection
*c
= conn
->next
;
724 interrupt_connection(struct connection
*conn
)
726 free_connection_data(conn
);
730 suspend_connection(struct connection
*conn
)
732 interrupt_connection(conn
);
733 set_connection_state(conn
, connection_state(S_WAIT
));
737 run_connection(struct connection
*conn
)
739 protocol_handler_T
*func
= get_protocol_handler(conn
->uri
->protocol
);
743 assertm(!conn
->running
, "connection already running");
744 if_assert_failed
return;
746 if (!add_host_connection(conn
)) {
747 set_connection_state(conn
, connection_state(S_OUT_OF_MEM
));
748 done_connection(conn
);
752 active_connections
++;
758 /* Set certain state on a connection and then abort the connection. */
760 abort_connection(struct connection
*conn
, struct connection_state state
)
762 assertm(is_in_result_state(state
),
763 "connection didn't end in result state (%d)", state
);
765 if (is_in_state(state
, S_OK
) && conn
->cached
)
766 normalize_cache_entry(conn
->cached
, conn
->from
);
768 set_connection_state(conn
, state
);
770 if (conn
->running
) interrupt_connection(conn
);
771 done_connection(conn
);
772 register_check_queue();
775 /* Set certain state on a connection and then retry the connection. */
777 retry_connection(struct connection
*conn
, struct connection_state state
)
779 int max_tries
= get_opt_int("connection.retries", NULL
);
781 assertm(is_in_result_state(state
),
782 "connection didn't end in result state (%d)", state
);
784 set_connection_state(conn
, state
);
786 interrupt_connection(conn
);
787 if (conn
->uri
->post
|| (max_tries
&& ++conn
->tries
>= max_tries
)) {
788 done_connection(conn
);
789 register_check_queue();
791 conn
->prev_error
= conn
->state
;
792 run_connection(conn
);
797 try_to_suspend_connection(struct connection
*conn
, struct uri
*uri
)
799 enum connection_priority priority
= get_priority(conn
);
800 struct connection
*c
;
802 foreachback (c
, connection_queue
) {
803 if (get_priority(c
) <= priority
) return -1;
804 if (is_in_state(c
->state
, S_WAIT
)) continue;
805 if (c
->uri
->post
&& get_priority(c
) < PRI_CANCEL
) continue;
806 if (uri
&& !compare_uri(uri
, c
->uri
, URI_HOST
)) continue;
807 suspend_connection(c
);
815 try_connection(struct connection
*conn
, int max_conns_to_host
, int max_conns
)
817 struct host_connection
*host_conn
= get_host_connection(conn
);
819 if (host_conn
&& get_object_refcount(host_conn
) >= max_conns_to_host
)
820 return try_to_suspend_connection(conn
, host_conn
->uri
) ? 0 : -1;
822 if (active_connections
>= max_conns
)
823 return try_to_suspend_connection(conn
, NULL
) ? 0 : -1;
825 run_connection(conn
);
832 struct connection
*conn
;
833 int max_conns_to_host
= get_opt_int("connection.max_connections_to_host", NULL
);
834 int max_conns
= get_opt_int("connection.max_connections", NULL
);
837 conn
= connection_queue
.next
;
839 check_keepalive_connections();
841 while (conn
!= (struct connection
*) &connection_queue
) {
842 struct connection
*c
;
843 enum connection_priority pri
= get_priority(conn
);
845 for (c
= conn
; c
!= (struct connection
*) &connection_queue
&& get_priority(c
) == pri
;) {
846 struct connection
*cc
= c
;
849 if (is_in_state(cc
->state
, S_WAIT
)
850 && get_keepalive_connection(cc
)
851 && try_connection(cc
, max_conns_to_host
, max_conns
))
855 for (c
= conn
; c
!= (struct connection
*) &connection_queue
&& get_priority(c
) == pri
;) {
856 struct connection
*cc
= c
;
859 if (is_in_state(cc
->state
, S_WAIT
)
860 && try_connection(cc
, max_conns_to_host
, max_conns
))
867 foreachback (conn
, connection_queue
) {
868 if (get_priority(conn
) < PRI_CANCEL
) break;
869 if (is_in_state(conn
->state
, S_WAIT
)) {
870 set_connection_state(conn
, connection_state(S_INTERRUPTED
));
871 done_connection(conn
);
880 register_check_queue(void)
882 return register_bottom_half(check_queue
, NULL
);
886 load_uri(struct uri
*uri
, struct uri
*referrer
, struct download
*download
,
887 enum connection_priority pri
, enum cache_mode cache_mode
, off_t start
)
889 struct cache_entry
*cached
;
890 struct connection
*conn
;
891 struct uri
*proxy_uri
, *proxied_uri
;
892 struct connection_state error_state
= connection_state(S_OK
);
895 download
->conn
= NULL
;
896 download
->cached
= NULL
;
898 download
->state
= connection_state(S_OUT_OF_MEM
);
899 download
->prev_error
= connection_state(0);
903 foreach (conn
, connection_queue
) {
904 struct download
*assigned
;
906 foreach (assigned
, conn
->downloads
) {
907 assertm(assigned
!= download
, "Download assigned to '%s'", struri(conn
->uri
));
909 download
->state
= connection_state(S_INTERNAL
);
910 if (download
->callback
)
911 download
->callback(download
, download
->data
);
914 /* No recovery path should be necessary. */
919 cached
= get_validated_cache_entry(uri
, cache_mode
);
922 download
->cached
= cached
;
923 download
->state
= connection_state(S_OK
);
925 * This doesn't work since sometimes |download->progress|
926 * is undefined and contains random memory locations.
927 * It's not supposed to point on anything here since
928 * |download| has no connection attached.
929 * Downloads resuming will probably break in some
930 * cases without this, though.
931 * FIXME: Needs more investigation. --pasky */
932 /* if (download->progress) download->progress->start = start; */
933 if (download
->callback
)
934 download
->callback(download
, download
->data
);
939 proxied_uri
= get_proxied_uri(uri
);
940 proxy_uri
= get_proxy_uri(uri
, &error_state
);
944 || (get_protocol_need_slash_after_host(proxy_uri
->protocol
)
945 && !proxy_uri
->hostlen
)) {
948 if (is_in_state(error_state
, S_OK
)) {
949 error_state
= proxy_uri
&& proxied_uri
950 ? connection_state(S_BAD_URL
)
951 : connection_state(S_OUT_OF_MEM
);
954 download
->state
= error_state
;
955 download
->callback(download
, download
->data
);
957 if (proxy_uri
) done_uri(proxy_uri
);
958 if (proxied_uri
) done_uri(proxied_uri
);
962 foreach (conn
, connection_queue
) {
964 || !compare_uri(conn
->uri
, proxy_uri
, 0))
968 done_uri(proxied_uri
);
970 if (get_priority(conn
) > pri
) {
974 register_check_queue();
980 download
->progress
= conn
->progress
;
981 download
->conn
= conn
;
982 download
->cached
= conn
->cached
;
983 add_to_list(conn
->downloads
, download
);
984 /* This is likely to call download->callback() now! */
985 set_connection_state(conn
, conn
->state
);
991 if (download
&& cache_mode
== CACHE_MODE_ALWAYS
) {
992 cached
= find_in_cache(uri
);
994 download
->cached
= cached
;
995 download
->state
= connection_state(S_OK
);
996 if (download
->callback
)
997 download
->callback(download
, download
->data
);
998 if (proxy_uri
) done_uri(proxy_uri
);
999 if (proxied_uri
) done_uri(proxied_uri
);
1004 conn
= init_connection(proxy_uri
, proxied_uri
, referrer
, start
, cache_mode
, pri
);
1007 download
->state
= connection_state(S_OUT_OF_MEM
);
1008 download
->callback(download
, download
->data
);
1010 if (proxy_uri
) done_uri(proxy_uri
);
1011 if (proxied_uri
) done_uri(proxied_uri
);
1015 if (cache_mode
< CACHE_MODE_FORCE_RELOAD
&& cached
&& !list_empty(cached
->frag
)
1016 && !((struct fragment
*) cached
->frag
.next
)->offset
)
1017 conn
->from
= ((struct fragment
*) cached
->frag
.next
)->length
;
1020 download
->progress
= conn
->progress
;
1021 download
->conn
= conn
;
1022 download
->cached
= NULL
;
1023 download
->state
= connection_state(S_OK
);
1024 add_to_list(conn
->downloads
, download
);
1028 set_connection_state(conn
, connection_state(S_WAIT
));
1032 register_check_queue();
1037 /* FIXME: one object in more connections */
1039 cancel_download(struct download
*download
, int interrupt
)
1041 struct connection
*conn
;
1044 if_assert_failed
return;
1046 /* Did the connection already end? */
1047 if (is_in_result_state(download
->state
))
1050 assertm(download
->conn
!= NULL
, "last state is %d", download
->state
);
1054 download
->state
= connection_state(S_INTERRUPTED
);
1055 del_from_list(download
);
1057 conn
= download
->conn
;
1059 conn
->pri
[download
->pri
]--;
1060 assertm(conn
->pri
[download
->pri
] >= 0, "priority counter underflow");
1061 if_assert_failed conn
->pri
[download
->pri
] = 0;
1063 if (list_empty(conn
->downloads
)) {
1064 /* Necessary because of assertion in get_priority(). */
1065 conn
->pri
[PRI_CANCEL
]++;
1067 if (conn
->detached
|| interrupt
)
1068 abort_connection(conn
, connection_state(S_INTERRUPTED
));
1074 register_check_queue();
1078 move_download(struct download
*old
, struct download
*new_
,
1079 enum connection_priority newpri
)
1081 struct connection
*conn
;
1085 /* The download doesn't necessarily have a connection attached, for
1086 * example the file protocol loads it's object immediately. This is
1087 * catched by the result state check below. */
1092 new_
->cached
= old
->cached
;
1093 new_
->prev_error
= old
->prev_error
;
1094 new_
->progress
= old
->progress
;
1095 new_
->state
= old
->state
;
1098 if (is_in_result_state(old
->state
)) {
1099 /* Ensure that new_->conn is always "valid", that is NULL if the
1100 * connection has been detached and non-NULL otherwise. */
1101 if (new_
->callback
) {
1103 new_
->progress
= NULL
;
1104 new_
->callback(new_
, new_
->data
);
1109 assertm(old
->conn
!= NULL
, "last state is %d", old
->state
);
1111 conn
->pri
[new_
->pri
]++;
1112 add_to_list(conn
->downloads
, new_
);
1113 /* In principle, we need to sort_queue() only if conn->pri[new_->pri]
1114 * just changed from 0 to 1. But the risk of bugs is smaller if we
1115 * sort every time. */
1118 cancel_download(old
, 0);
1122 /* This will remove 'pos' bytes from the start of the cache for the specified
1123 * connection, if the cached object is already too big. */
1125 detach_connection(struct download
*download
, off_t pos
)
1127 struct connection
*conn
= download
->conn
;
1129 if (is_in_result_state(download
->state
)) return;
1131 if (!conn
->detached
) {
1133 off_t i
, total_pri
= 0;
1138 total_len
= (conn
->est_length
== -1) ? conn
->from
1141 if (total_len
< (get_opt_long("document.cache.memory.size",
1143 * MAX_CACHED_OBJECT_PERCENT
/ 100)) {
1144 /* This whole thing will fit to the memory anyway, so
1145 * there's no problem in detaching the connection. */
1149 for (i
= 0; i
< PRI_CANCEL
; i
++)
1150 total_pri
+= conn
->pri
[i
];
1151 assertm(total_pri
, "detaching free connection");
1152 /* No recovery path should be necessary...? */
1154 /* Pre-clean cache. */
1155 shrink_format_cache(0);
1157 if (total_pri
!= 1 || is_object_used(conn
->cached
)) {
1158 /* We're too important, or someone uses our cache
1163 /* DBG("detached"); */
1165 /* We aren't valid cache entry anymore. */
1166 conn
->cached
->valid
= 0;
1170 /* Strip the entry. */
1171 free_entry_to(conn
->cached
, pos
);
1174 /* Timer callback for @conn->timer. As explained in @install_timer,
1175 * this function must erase the expired timer ID from all variables. */
1177 connection_timeout(struct connection
*conn
)
1179 conn
->timer
= TIMER_ID_UNDEF
;
1180 /* The expired timer ID has now been erased. */
1181 timeout_socket(conn
->socket
);
1184 /* Timer callback for @conn->timer. As explained in @install_timer,
1185 * this function must erase the expired timer ID from all variables.
1187 * Huh, using two timers? Is this to account for changes of c->unrestartable
1188 * or can it be reduced? --jonas */
1190 connection_timeout_1(struct connection
*conn
)
1192 install_timer(&conn
->timer
, (milliseconds_T
)
1193 ((conn
->unrestartable
1194 ? get_opt_int("connection.unrestartable_receive_timeout", NULL
)
1195 : get_opt_int("connection.receive_timeout", NULL
))
1196 * 500), (void (*)(void *)) connection_timeout
, conn
);
1197 /* The expired timer ID has now been erased. */
1201 set_connection_timeout(struct connection
*conn
)
1203 kill_timer(&conn
->timer
);
1205 install_timer(&conn
->timer
, (milliseconds_T
)
1206 ((conn
->unrestartable
1207 ? get_opt_int("connection.unrestartable_receive_timeout", NULL
)
1208 : get_opt_int("connection.receive_timeout", NULL
))
1209 * 500), (void (*)(void *)) connection_timeout_1
, conn
);
1214 abort_all_connections(void)
1216 while (!list_empty(connection_queue
)) {
1217 abort_connection(connection_queue
.next
,
1218 connection_state(S_INTERRUPTED
));
1221 abort_all_keepalive_connections();
1225 abort_background_connections(void)
1227 struct connection
*conn
, *next
;
1229 foreachsafe (conn
, next
, connection_queue
) {
1230 if (get_priority(conn
) >= PRI_CANCEL
)
1231 abort_connection(conn
, connection_state(S_INTERRUPTED
));
1236 is_entry_used(struct cache_entry
*cached
)
1238 struct connection
*conn
;
1240 foreach (conn
, connection_queue
)
1241 if (conn
->cached
== cached
)