Bug 1013: Don't assume errno is between 0 and 100000
[elinks.git] / src / network / connection.c
blob2f4271bd084d2bfd27c18d4c268791adb2bcd268
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/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. */
44 struct uri *uri;
46 /* Function called when the keepalive has timed out or is deleted */
47 void (*done)(struct connection *);
49 timeval_T timeout;
50 timeval_T creation_time;
52 unsigned int protocol_family:1; /* see network/socket.h, EL_PF_INET, EL_PF_INET6 */
53 int socket;
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);
65 /* Prototypes */
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])
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 static inline int
122 connection_disappeared(struct connection *conn)
124 struct connection *c;
126 foreach (c, connection_queue)
127 if (conn == c && conn->id == c->id)
128 return 0;
130 return 1;
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
139 * in the list. */
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. */
146 struct uri *uri;
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))
158 return host_conn;
160 return NULL;
163 /* Returns if the connection was successfully added. */
164 /* Don't add hostnameless host connections but they're valid. */
165 static int
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);
180 return 1;
183 /* Decrements and free()s the host connection if it is the last 'refcount'. */
184 static void
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);
196 mem_free(host_conn);
200 static void sort_queue();
202 #ifdef CONFIG_DEBUG
203 static void
204 check_queue_bugs(void)
206 struct connection *conn;
207 enum connection_priority prev_priority = 0;
208 int cc = 0;
210 foreach (conn, connection_queue) {
211 enum connection_priority priority = get_priority(conn);
213 cc += conn->running;
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);
226 #else
227 #define check_queue_bugs()
228 #endif
230 static void
231 set_connection_socket_state(struct socket *socket, struct connection_state state)
233 assert(socket);
234 set_connection_state(socket->conn, state);
237 static void
238 set_connection_socket_timeout(struct socket *socket, struct connection_state state)
240 assert(socket);
241 set_connection_timeout(socket->conn);
244 static void
245 retry_connection_socket(struct socket *socket, struct connection_state state)
247 assert(socket);
248 retry_connection(socket->conn, state);
251 static void
252 done_connection_socket(struct socket *socket, struct connection_state state)
254 assert(socket);
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);
276 if (!conn->socket) {
277 mem_free(conn);
278 return NULL;
281 conn->data_socket = init_socket(conn, &connection_socket_operations);
282 if (!conn->data_socket) {
283 mem_free(conn->socket);
284 mem_free(conn);
285 return NULL;
288 conn->progress = init_progress(start);
289 if (!conn->progress) {
290 mem_free(conn->data_socket);
291 mem_free(conn->socket);
292 mem_free(conn);
293 return NULL;
296 /* load_uri() gets the URI from get_proxy() which grabs a reference for
297 * us. */
298 conn->uri = uri;
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;
310 if (referrer) {
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);
320 return conn;
323 static void
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. */
332 static void
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);
340 void
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;
349 conn->state = 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))
355 return;
358 } else {
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);
370 void
371 shutdown_connection_stream(struct connection *conn)
373 if (conn->stream) {
374 close_encoded(conn->stream);
375 conn->stream = NULL;
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;
386 static void
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 */
392 conn->running = 0;
394 active_connections--;
395 assertm(active_connections >= 0, "active connections underflow");
396 if_assert_failed active_connections = 0;
398 #ifdef CONFIG_SSL
399 if (conn->socket->ssl && conn->cached)
400 mem_free_set(&conn->cached->ssl_info, get_ssl_connection_cipher(conn->socket));
401 #endif
403 if (conn->done)
404 conn->done(conn);
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);
419 void
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))
430 return;
434 static void
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));
444 del_from_list(conn);
445 notify_connection_callbacks(conn);
446 if (conn->referrer) done_uri(conn->referrer);
447 done_uri(conn->uri);
448 done_uri(conn->proxied_uri);
449 mem_free(conn->socket);
450 mem_free(conn->data_socket);
451 done_progress(conn->progress);
452 mem_free(conn);
453 check_queue_bugs();
456 static inline void
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)
464 break;
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. */
472 static int
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);
484 if (conn) {
485 void (*done)(struct connection *) = keep_conn->done;
487 add_to_queue(conn);
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);
494 return 0;
497 active_connections++;
498 conn->running = 1;
499 done(conn);
500 return 1;
504 if (proxied_uri) done_uri(proxied_uri);
505 if (proxy_uri) done_uri(proxy_uri);
507 return 0;
510 static inline void
511 done_keepalive_connection(struct keepalive_connection *keep_conn)
513 if (keep_conn->done && do_keepalive_connection_callback(keep_conn))
514 return;
516 del_from_list(keep_conn);
517 if (keep_conn->socket != -1) close(keep_conn->socket);
518 done_uri(keep_conn->uri);
519 mem_free(keep_conn);
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;
529 assert(uri->host);
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);
542 return keep_conn;
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))
554 return keep_conn;
556 return NULL;
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
570 * ignored. */
571 keep_conn->socket = -1;
572 keep_conn->done = NULL;
573 done_keepalive_connection(keep_conn);
575 return 1;
578 void
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);
588 if (keep_conn) {
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);
595 } else if (done) {
596 /* It will take just a little more time */
597 done(conn);
598 return;
601 done:
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. */
609 static void
610 keepalive_timer(void *x)
612 keepalive_timeout = TIMER_ID_UNDEF;
613 /* The expired timer ID has now been erased. */
614 check_keepalive_connections();
617 void
618 check_keepalive_connections(void)
620 struct keepalive_connection *keep_conn, *next;
621 timeval_T now;
622 int p = 0;
624 timeval_now(&now);
626 kill_timer(&keepalive_timeout);
628 foreachsafe (keep_conn, next, keepalive_connections) {
629 timeval_T age;
631 if (can_read(keep_conn->socket)) {
632 done_keepalive_connection(keep_conn);
633 continue;
636 timeval_sub(&age, &keep_conn->creation_time, &now);
637 if (timeval_cmp(&age, &keep_conn->timeout) > 0) {
638 done_keepalive_connection(keep_conn);
639 continue;
642 p++;
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);
656 static inline void
657 abort_all_keepalive_connections(void)
659 while (!list_empty(keepalive_connections))
660 done_keepalive_connection(keepalive_connections.next);
662 check_keepalive_connections();
666 static void
667 sort_queue(void)
669 while (1) {
670 struct connection *conn;
671 int swp = 0;
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;
679 del_from_list(conn);
680 add_at_pos(c, conn);
681 swp = 1;
685 if (!swp) break;
689 static void
690 interrupt_connection(struct connection *conn)
692 free_connection_data(conn);
695 static inline void
696 suspend_connection(struct connection *conn)
698 interrupt_connection(conn);
699 set_connection_state(conn, connection_state(S_WAIT));
702 static void
703 run_connection(struct connection *conn)
705 protocol_handler_T *func = get_protocol_handler(conn->uri->protocol);
707 assert(func);
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);
715 return;
718 active_connections++;
719 conn->running = 1;
721 func(conn);
724 /* Set certain state on a connection and then abort the connection. */
725 void
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. */
742 void
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();
756 } else {
757 conn->prev_error = conn->state;
758 run_connection(conn);
762 static int
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);
774 return 0;
777 return -1;
780 static inline int
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);
792 return 1;
795 static void
796 check_queue(void)
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");
802 again:
803 conn = connection_queue.next;
804 check_queue_bugs();
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;
814 c = c->next;
815 if (is_in_state(cc->state, S_WAIT)
816 && get_keepalive_connection(cc)
817 && try_connection(cc, max_conns_to_host, max_conns))
818 goto again;
821 for (c = conn; c != (struct connection *) &connection_queue && get_priority(c) == pri;) {
822 struct connection *cc = c;
824 c = c->next;
825 if (is_in_state(cc->state, S_WAIT)
826 && try_connection(cc, max_conns_to_host, max_conns))
827 goto again;
829 conn = c;
832 again2:
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);
838 goto again2;
842 check_queue_bugs();
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);
860 if (download) {
861 download->conn = NULL;
862 download->cached = NULL;
863 download->pri = pri;
864 download->state = connection_state(S_OUT_OF_MEM);
865 download->prev_error = connection_state(0);
868 #ifdef CONFIG_DEBUG
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));
874 if_assert_failed {
875 download->state = connection_state(S_INTERNAL);
876 if (download->callback)
877 download->callback(download, download->data);
878 return 0;
880 /* No recovery path should be necessary. */
883 #endif
885 cached = get_validated_cache_entry(uri, cache_mode);
886 if (cached) {
887 if (download) {
888 download->cached = cached;
889 download->state = connection_state(S_OK);
890 /* XXX:
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);
902 return 0;
905 proxied_uri = get_proxied_uri(uri);
906 proxy_uri = get_proxy_uri(uri, &error_state);
908 if (!proxy_uri
909 || !proxied_uri
910 || (get_protocol_need_slash_after_host(proxy_uri->protocol)
911 && !proxy_uri->hostlen)) {
913 if (download) {
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);
925 return -1;
928 foreach (conn, connection_queue) {
929 if (conn->detached
930 || !compare_uri(conn->uri, proxy_uri, 0))
931 continue;
933 done_uri(proxy_uri);
934 done_uri(proxied_uri);
936 if (get_priority(conn) > pri) {
937 del_from_list(conn);
938 conn->pri[pri]++;
939 add_to_queue(conn);
940 register_check_queue();
941 } else {
942 conn->pri[pri]++;
945 if (download) {
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);
953 check_queue_bugs();
954 return 0;
957 conn = init_connection(proxy_uri, proxied_uri, referrer, start, cache_mode, pri);
958 if (!conn) {
959 if (download) {
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);
965 return -1;
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;
972 if (download) {
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);
980 add_to_queue(conn);
981 set_connection_state(conn, connection_state(S_WAIT));
983 check_queue_bugs();
985 register_check_queue();
986 return 0;
990 /* FIXME: one object in more connections */
991 void
992 cancel_download(struct download *download, int interrupt)
994 struct connection *conn;
996 assert(download);
997 if_assert_failed return;
999 /* Did the connection already end? */
1000 if (is_in_result_state(download->state))
1001 return;
1003 assertm(download->conn != NULL, "last state is %d", download->state);
1005 check_queue_bugs();
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));
1024 sort_queue();
1025 check_queue_bugs();
1027 register_check_queue();
1030 void
1031 move_download(struct download *old, struct download *new,
1032 enum connection_priority newpri)
1034 struct connection *conn;
1036 assert(old);
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. */
1042 conn = old->conn;
1044 new->conn = conn;
1045 new->cached = old->cached;
1046 new->prev_error = old->prev_error;
1047 new->progress = old->progress;
1048 new->state = old->state;
1049 new->pri = newpri;
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) {
1055 new->conn = NULL;
1056 new->progress = NULL;
1057 new->callback(new, new->data);
1059 return;
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. */
1069 sort_queue();
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. */
1077 void
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) {
1085 off_t total_len;
1086 off_t i, total_pri = 0;
1088 if (!conn->cached)
1089 return;
1091 total_len = (conn->est_length == -1) ? conn->from
1092 : conn->est_length;
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. */
1098 return;
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
1111 * entry. */
1112 return;
1115 /* DBG("detached"); */
1117 /* We aren't valid cache entry anymore. */
1118 conn->cached->valid = 0;
1119 conn->detached = 1;
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. */
1128 static void
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 */
1141 static void
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. */
1152 void
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);
1165 void
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();
1176 void
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)
1194 return 1;
1196 return 0;