Let users retry connection in case of error. Especially SSL error.
[elinks.git] / src / network / connection.c
blob096ef40b07eeb12d32bea7084f178bf00a45a495
1 /* Connections management */
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
7 #include <stdlib.h>
8 #include <string.h>
9 #ifdef HAVE_UNISTD_H
10 #include <unistd.h>
11 #endif
13 #include "elinks.h"
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. */
45 struct uri *uri;
47 /* Function called when the keepalive has timed out or is deleted */
48 void (*done)(struct connection *);
50 timeval_T timeout;
51 timeval_T creation_time;
53 unsigned int protocol_family:1; /* see network/socket.h, EL_PF_INET, EL_PF_INET6 */
54 int socket;
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);
66 /* Prototypes */
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)
73 int priority;
75 for (priority = 0; priority < PRIORITIES; priority++)
76 if (conn->pri[priority])
77 break;
79 assertm(priority != PRIORITIES, "Connection has no owner");
80 /* Recovery path ;-). (XXX?) */
82 return priority;
85 int
86 get_connections_count(void)
88 return list_size(&connection_queue);
91 int
92 get_keepalive_connections_count(void)
94 return list_size(&keepalive_connections);
97 int
98 get_connections_connecting_count(void)
100 struct connection *conn;
101 int i = 0;
103 foreach (conn, connection_queue)
104 i += is_in_connecting_state(conn->state);
106 return i;
110 get_connections_transfering_count(void)
112 struct connection *conn;
113 int i = 0;
115 foreach (conn, connection_queue)
116 i += is_in_transfering_state(conn->state);
118 return i;
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. */
127 static inline int
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)
134 return 0;
136 return 1;
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
145 * in the list. */
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. */
152 struct uri *uri;
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))
164 return host_conn;
166 return NULL;
169 /* Returns if the connection was successfully added. */
170 /* Don't add hostnameless host connections but they're valid. */
171 static int
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);
186 return 1;
189 /* Decrements and free()s the host connection if it is the last 'refcount'. */
190 static void
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);
202 mem_free(host_conn);
206 static void sort_queue();
208 #ifdef CONFIG_DEBUG
209 static void
210 check_queue_bugs(void)
212 struct connection *conn;
213 enum connection_priority prev_priority = 0;
214 int cc = 0;
216 foreach (conn, connection_queue) {
217 enum connection_priority priority = get_priority(conn);
219 cc += conn->running;
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);
232 #else
233 #define check_queue_bugs()
234 #endif
236 static void
237 set_connection_socket_state(struct socket *socket, struct connection_state state)
239 assert(socket);
240 set_connection_state(socket->conn, state);
243 static void
244 set_connection_socket_timeout(struct socket *socket, struct connection_state state)
246 assert(socket);
247 set_connection_timeout(socket->conn);
250 static void
251 retry_connection_socket(struct socket *socket, struct connection_state state)
253 assert(socket);
254 retry_connection(socket->conn, state);
257 static void
258 done_connection_socket(struct socket *socket, struct connection_state state)
260 assert(socket);
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);
282 if (!conn->socket) {
283 mem_free(conn);
284 return NULL;
287 conn->data_socket = init_socket(conn, &connection_socket_operations);
288 if (!conn->data_socket) {
289 mem_free(conn->socket);
290 mem_free(conn);
291 return NULL;
294 conn->progress = init_progress(start);
295 if (!conn->progress) {
296 mem_free(conn->data_socket);
297 mem_free(conn->socket);
298 mem_free(conn);
299 return NULL;
302 /* load_uri() gets the URI from get_proxy() which grabs a reference for
303 * us. */
304 conn->uri = uri;
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;
315 if (referrer) {
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);
325 return conn;
328 static void
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. */
335 static void
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. */
343 static void
344 upload_stat_timer(struct connection *conn)
346 struct http_connection_info *http = conn->info;
348 assert(conn->http_upload_progress);
349 assert(http);
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);
357 void
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;
367 conn->state = 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))
376 return;
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))
382 return;
385 } else {
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);
398 void
399 shutdown_connection_stream(struct connection *conn)
401 if (conn->stream) {
402 close_encoded(conn->stream);
403 conn->stream = NULL;
407 static void
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 */
413 conn->running = 0;
415 active_connections--;
416 assertm(active_connections >= 0, "active connections underflow");
417 if_assert_failed active_connections = 0;
419 #ifdef CONFIG_SSL
420 if (conn->socket->ssl && conn->cached)
421 mem_free_set(&conn->cached->ssl_info, get_ssl_connection_cipher(conn->socket));
422 #endif
424 if (conn->done)
425 conn->done(conn);
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. */
441 conn->done = NULL;
443 kill_timer(&conn->timer);
445 if (!is_in_state(conn->state, S_WAIT))
446 done_host_connection(conn);
449 static void
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))
462 return;
466 static void
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));
476 del_from_list(conn);
477 notify_connection_callbacks(conn);
478 if (conn->referrer) done_uri(conn->referrer);
479 done_uri(conn->uri);
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);
486 mem_free(conn);
487 check_queue_bugs();
490 static inline void
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)
498 break;
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. */
506 static int
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);
518 if (conn) {
519 void (*done)(struct connection *) = keep_conn->done;
521 add_to_queue(conn);
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);
528 return 0;
531 active_connections++;
532 conn->running = 1;
533 done(conn);
534 return 1;
538 if (proxied_uri) done_uri(proxied_uri);
539 if (proxy_uri) done_uri(proxy_uri);
541 return 0;
544 static inline void
545 done_keepalive_connection(struct keepalive_connection *keep_conn)
547 if (keep_conn->done && do_keepalive_connection_callback(keep_conn))
548 return;
550 del_from_list(keep_conn);
551 if (keep_conn->socket != -1) close(keep_conn->socket);
552 done_uri(keep_conn->uri);
553 mem_free(keep_conn);
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;
563 assert(uri->host);
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);
576 return keep_conn;
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))
588 return keep_conn;
590 return NULL;
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
604 * ignored. */
605 keep_conn->socket = -1;
606 keep_conn->done = NULL;
607 done_keepalive_connection(keep_conn);
609 return 1;
612 void
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);
622 if (keep_conn) {
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);
629 } else if (done) {
630 /* It will take just a little more time */
631 done(conn);
632 return;
635 done:
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. */
643 static void
644 keepalive_timer(void *x)
646 keepalive_timeout = TIMER_ID_UNDEF;
647 /* The expired timer ID has now been erased. */
648 check_keepalive_connections();
651 void
652 check_keepalive_connections(void)
654 struct keepalive_connection *keep_conn, *next;
655 timeval_T now;
656 int p = 0;
658 timeval_now(&now);
660 kill_timer(&keepalive_timeout);
662 foreachsafe (keep_conn, next, keepalive_connections) {
663 timeval_T age;
665 if (can_read(keep_conn->socket)) {
666 done_keepalive_connection(keep_conn);
667 continue;
670 timeval_sub(&age, &keep_conn->creation_time, &now);
671 if (timeval_cmp(&age, &keep_conn->timeout) > 0) {
672 done_keepalive_connection(keep_conn);
673 continue;
676 p++;
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);
690 static inline void
691 abort_all_keepalive_connections(void)
693 while (!list_empty(keepalive_connections))
694 done_keepalive_connection(keepalive_connections.next);
696 check_keepalive_connections();
700 static void
701 sort_queue(void)
703 while (1) {
704 struct connection *conn;
705 int swp = 0;
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;
713 del_from_list(conn);
714 add_at_pos(c, conn);
715 swp = 1;
719 if (!swp) break;
723 static void
724 interrupt_connection(struct connection *conn)
726 free_connection_data(conn);
729 static inline void
730 suspend_connection(struct connection *conn)
732 interrupt_connection(conn);
733 set_connection_state(conn, connection_state(S_WAIT));
736 static void
737 run_connection(struct connection *conn)
739 protocol_handler_T *func = get_protocol_handler(conn->uri->protocol);
741 assert(func);
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);
749 return;
752 active_connections++;
753 conn->running = 1;
755 func(conn);
758 /* Set certain state on a connection and then abort the connection. */
759 void
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. */
776 void
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();
790 } else {
791 conn->prev_error = conn->state;
792 run_connection(conn);
796 static int
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);
808 return 0;
811 return -1;
814 static inline int
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);
826 return 1;
829 static void
830 check_queue(void)
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);
836 again:
837 conn = connection_queue.next;
838 check_queue_bugs();
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;
848 c = c->next;
849 if (is_in_state(cc->state, S_WAIT)
850 && get_keepalive_connection(cc)
851 && try_connection(cc, max_conns_to_host, max_conns))
852 goto again;
855 for (c = conn; c != (struct connection *) &connection_queue && get_priority(c) == pri;) {
856 struct connection *cc = c;
858 c = c->next;
859 if (is_in_state(cc->state, S_WAIT)
860 && try_connection(cc, max_conns_to_host, max_conns))
861 goto again;
863 conn = c;
866 again2:
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);
872 goto again2;
876 check_queue_bugs();
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);
894 if (download) {
895 download->conn = NULL;
896 download->cached = NULL;
897 download->pri = pri;
898 download->state = connection_state(S_OUT_OF_MEM);
899 download->prev_error = connection_state(0);
902 #ifdef CONFIG_DEBUG
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));
908 if_assert_failed {
909 download->state = connection_state(S_INTERNAL);
910 if (download->callback)
911 download->callback(download, download->data);
912 return 0;
914 /* No recovery path should be necessary. */
917 #endif
919 cached = get_validated_cache_entry(uri, cache_mode);
920 if (cached) {
921 if (download) {
922 download->cached = cached;
923 download->state = connection_state(S_OK);
924 /* XXX:
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);
936 return 0;
939 proxied_uri = get_proxied_uri(uri);
940 proxy_uri = get_proxy_uri(uri, &error_state);
942 if (!proxy_uri
943 || !proxied_uri
944 || (get_protocol_need_slash_after_host(proxy_uri->protocol)
945 && !proxy_uri->hostlen)) {
947 if (download) {
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);
959 return -1;
962 foreach (conn, connection_queue) {
963 if (conn->detached
964 || !compare_uri(conn->uri, proxy_uri, 0))
965 continue;
967 done_uri(proxy_uri);
968 done_uri(proxied_uri);
970 if (get_priority(conn) > pri) {
971 del_from_list(conn);
972 conn->pri[pri]++;
973 add_to_queue(conn);
974 register_check_queue();
975 } else {
976 conn->pri[pri]++;
979 if (download) {
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);
987 check_queue_bugs();
988 return 0;
991 if (download && cache_mode == CACHE_MODE_ALWAYS) {
992 cached = find_in_cache(uri);
993 if (cached) {
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);
1000 return 0;
1004 conn = init_connection(proxy_uri, proxied_uri, referrer, start, cache_mode, pri);
1005 if (!conn) {
1006 if (download) {
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);
1012 return -1;
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;
1019 if (download) {
1020 download->progress = conn->progress;
1021 download->conn = conn;
1022 conn->socket->verify = ((struct session *)download->data)->verify;
1023 download->cached = NULL;
1024 download->state = connection_state(S_OK);
1025 add_to_list(conn->downloads, download);
1028 add_to_queue(conn);
1029 set_connection_state(conn, connection_state(S_WAIT));
1031 check_queue_bugs();
1033 register_check_queue();
1034 return 0;
1038 /* FIXME: one object in more connections */
1039 void
1040 cancel_download(struct download *download, int interrupt)
1042 struct connection *conn;
1044 assert(download);
1045 if_assert_failed return;
1047 /* Did the connection already end? */
1048 if (is_in_result_state(download->state))
1049 return;
1051 assertm(download->conn != NULL, "last state is %d", download->state);
1053 check_queue_bugs();
1055 download->state = connection_state(S_INTERRUPTED);
1056 del_from_list(download);
1058 conn = download->conn;
1060 conn->pri[download->pri]--;
1061 assertm(conn->pri[download->pri] >= 0, "priority counter underflow");
1062 if_assert_failed conn->pri[download->pri] = 0;
1064 if (list_empty(conn->downloads)) {
1065 /* Necessary because of assertion in get_priority(). */
1066 conn->pri[PRI_CANCEL]++;
1068 if (conn->detached || interrupt)
1069 abort_connection(conn, connection_state(S_INTERRUPTED));
1072 sort_queue();
1073 check_queue_bugs();
1075 register_check_queue();
1078 void
1079 move_download(struct download *old, struct download *new_,
1080 enum connection_priority newpri)
1082 struct connection *conn;
1084 assert(old);
1086 /* The download doesn't necessarily have a connection attached, for
1087 * example the file protocol loads it's object immediately. This is
1088 * catched by the result state check below. */
1090 conn = old->conn;
1092 new_->conn = conn;
1093 new_->cached = old->cached;
1094 new_->prev_error = old->prev_error;
1095 new_->progress = old->progress;
1096 new_->state = old->state;
1097 new_->pri = newpri;
1099 if (is_in_result_state(old->state)) {
1100 /* Ensure that new_->conn is always "valid", that is NULL if the
1101 * connection has been detached and non-NULL otherwise. */
1102 if (new_->callback) {
1103 new_->conn = NULL;
1104 new_->progress = NULL;
1105 new_->callback(new_, new_->data);
1107 return;
1110 assertm(old->conn != NULL, "last state is %d", old->state);
1112 conn->pri[new_->pri]++;
1113 add_to_list(conn->downloads, new_);
1114 /* In principle, we need to sort_queue() only if conn->pri[new_->pri]
1115 * just changed from 0 to 1. But the risk of bugs is smaller if we
1116 * sort every time. */
1117 sort_queue();
1119 cancel_download(old, 0);
1123 /* This will remove 'pos' bytes from the start of the cache for the specified
1124 * connection, if the cached object is already too big. */
1125 void
1126 detach_connection(struct download *download, off_t pos)
1128 struct connection *conn = download->conn;
1130 if (is_in_result_state(download->state)) return;
1132 if (!conn->detached) {
1133 off_t total_len;
1134 off_t i, total_pri = 0;
1136 if (!conn->cached)
1137 return;
1139 total_len = (conn->est_length == -1) ? conn->from
1140 : conn->est_length;
1142 if (total_len < (get_opt_long("document.cache.memory.size",
1143 NULL)
1144 * MAX_CACHED_OBJECT_PERCENT / 100)) {
1145 /* This whole thing will fit to the memory anyway, so
1146 * there's no problem in detaching the connection. */
1147 return;
1150 for (i = 0; i < PRI_CANCEL; i++)
1151 total_pri += conn->pri[i];
1152 assertm(total_pri, "detaching free connection");
1153 /* No recovery path should be necessary...? */
1155 /* Pre-clean cache. */
1156 shrink_format_cache(0);
1158 if (total_pri != 1 || is_object_used(conn->cached)) {
1159 /* We're too important, or someone uses our cache
1160 * entry. */
1161 return;
1164 /* DBG("detached"); */
1166 /* We aren't valid cache entry anymore. */
1167 conn->cached->valid = 0;
1168 conn->detached = 1;
1171 /* Strip the entry. */
1172 free_entry_to(conn->cached, pos);
1175 /* Timer callback for @conn->timer. As explained in @install_timer,
1176 * this function must erase the expired timer ID from all variables. */
1177 static void
1178 connection_timeout(struct connection *conn)
1180 conn->timer = TIMER_ID_UNDEF;
1181 /* The expired timer ID has now been erased. */
1182 timeout_socket(conn->socket);
1185 /* Timer callback for @conn->timer. As explained in @install_timer,
1186 * this function must erase the expired timer ID from all variables.
1188 * Huh, using two timers? Is this to account for changes of c->unrestartable
1189 * or can it be reduced? --jonas */
1190 static void
1191 connection_timeout_1(struct connection *conn)
1193 install_timer(&conn->timer, (milliseconds_T)
1194 ((conn->unrestartable
1195 ? get_opt_int("connection.unrestartable_receive_timeout", NULL)
1196 : get_opt_int("connection.receive_timeout", NULL))
1197 * 500), (void (*)(void *)) connection_timeout, conn);
1198 /* The expired timer ID has now been erased. */
1201 void
1202 set_connection_timeout(struct connection *conn)
1204 kill_timer(&conn->timer);
1206 install_timer(&conn->timer, (milliseconds_T)
1207 ((conn->unrestartable
1208 ? get_opt_int("connection.unrestartable_receive_timeout", NULL)
1209 : get_opt_int("connection.receive_timeout", NULL))
1210 * 500), (void (*)(void *)) connection_timeout_1, conn);
1214 void
1215 abort_all_connections(void)
1217 while (!list_empty(connection_queue)) {
1218 abort_connection(connection_queue.next,
1219 connection_state(S_INTERRUPTED));
1222 abort_all_keepalive_connections();
1225 void
1226 abort_background_connections(void)
1228 struct connection *conn, *next;
1230 foreachsafe (conn, next, connection_queue) {
1231 if (get_priority(conn) >= PRI_CANCEL)
1232 abort_connection(conn, connection_state(S_INTERRUPTED));
1237 is_entry_used(struct cache_entry *cached)
1239 struct connection *conn;
1241 foreach (conn, connection_queue)
1242 if (conn->cached == cached)
1243 return 1;
1245 return 0;