content encoding: New function accept_encoding_header.
[elinks.git] / src / network / connection.c
blob879bd84d0805c0bf58515b2e0861742eab067eb6
1 /* Connections management */
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #ifdef HAVE_UNISTD_H
11 #include <unistd.h>
12 #endif
14 #include "elinks.h"
16 #include "cache/cache.h"
17 #include "config/options.h"
18 #include "document/document.h"
19 #include "encoding/encoding.h"
20 #include "intl/gettext/libintl.h"
21 #include "main/object.h"
22 #include "main/select.h"
23 #include "main/timer.h"
24 #include "network/connection.h"
25 #include "network/dns.h"
26 #include "network/progress.h"
27 #include "network/socket.h"
28 #include "network/ssl/ssl.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 notify_connection_callbacks(struct connection *conn);
68 static void check_keepalive_connections(void);
71 static /* inline */ enum connection_priority
72 get_priority(struct connection *conn)
74 enum connection_priority priority;
76 for (priority = 0; priority < PRIORITIES; priority++)
77 if (conn->pri[priority])
78 break;
80 assertm(priority != PRIORITIES, "Connection has no owner");
81 /* Recovery path ;-). (XXX?) */
83 return priority;
86 int
87 get_connections_count(void)
89 return list_size(&connection_queue);
92 int
93 get_keepalive_connections_count(void)
95 return list_size(&keepalive_connections);
98 int
99 get_connections_connecting_count(void)
101 struct connection *conn;
102 int i = 0;
104 foreach (conn, connection_queue)
105 i += is_in_connecting_state(conn->state);
107 return i;
111 get_connections_transfering_count(void)
113 struct connection *conn;
114 int i = 0;
116 foreach (conn, connection_queue)
117 i += is_in_transfering_state(conn->state);
119 return i;
122 static inline int
123 connection_disappeared(struct connection *conn)
125 struct connection *c;
127 foreach (c, connection_queue)
128 if (conn == c && conn->id == c->id)
129 return 0;
131 return 1;
134 /* Host connection management: */
135 /* Used to keep track on the number of connections to any given host. When
136 * trying to setup a new connection the list is searched to see if the maximum
137 * number of connection has been reached. If that is the case we try to suspend
138 * an already established connection. */
139 /* Some connections (like file://) that do not involve hosts are not maintained
140 * in the list. */
142 struct host_connection {
143 OBJECT_HEAD(struct host_connection);
145 /* XXX: This is just the URI of the connection that registered the
146 * host connection so only rely on the host part. */
147 struct uri *uri;
150 static struct host_connection *
151 get_host_connection(struct connection *conn)
153 struct host_connection *host_conn;
155 if (!conn->uri->host) return NULL;
157 foreach (host_conn, host_connections)
158 if (compare_uri(host_conn->uri, conn->uri, URI_HOST))
159 return host_conn;
161 return NULL;
164 /* Returns if the connection was successfully added. */
165 /* Don't add hostnameless host connections but they're valid. */
166 static int
167 add_host_connection(struct connection *conn)
169 struct host_connection *host_conn = get_host_connection(conn);
171 if (!host_conn && conn->uri->host) {
172 host_conn = mem_calloc(1, sizeof(*host_conn));
173 if (!host_conn) return 0;
175 host_conn->uri = get_uri_reference(conn->uri);
176 object_nolock(host_conn, "host_connection");
177 add_to_list(host_connections, host_conn);
179 if (host_conn) object_lock(host_conn);
181 return 1;
184 /* Decrements and free()s the host connection if it is the last 'refcount'. */
185 static void
186 done_host_connection(struct connection *conn)
188 struct host_connection *host_conn = get_host_connection(conn);
190 if (!host_conn) return;
192 object_unlock(host_conn);
193 if (is_object_used(host_conn)) return;
195 del_from_list(host_conn);
196 done_uri(host_conn->uri);
197 mem_free(host_conn);
201 static void sort_queue();
203 #ifdef CONFIG_DEBUG
204 static void
205 check_queue_bugs(void)
207 struct connection *conn;
208 enum connection_priority prev_priority = 0;
209 int cc = 0;
211 foreach (conn, connection_queue) {
212 enum connection_priority priority = get_priority(conn);
214 cc += conn->running;
216 assertm(priority >= prev_priority, "queue is not sorted");
217 assertm(is_in_progress_state(conn->state),
218 "interrupted connection on queue (conn %s, state %d)",
219 struri(conn->uri), conn->state);
220 prev_priority = priority;
223 assertm(cc == active_connections,
224 "bad number of active connections (counted %d, stored %d)",
225 cc, active_connections);
227 #else
228 #define check_queue_bugs()
229 #endif
231 static void
232 set_connection_socket_state(struct socket *socket, enum connection_state state)
234 assert(socket);
235 set_connection_state(socket->conn, state);
238 static void
239 set_connection_socket_timeout(struct socket *socket, enum connection_state state)
241 assert(socket);
242 set_connection_timeout(socket->conn);
245 static void
246 retry_connection_socket(struct socket *socket, enum connection_state state)
248 assert(socket);
249 retry_connection(socket->conn, state);
252 static void
253 done_connection_socket(struct socket *socket, enum connection_state state)
255 assert(socket);
256 abort_connection(socket->conn, state);
259 static struct connection *
260 init_connection(struct uri *uri, struct uri *proxied_uri, struct uri *referrer,
261 off_t start, enum cache_mode cache_mode,
262 enum connection_priority priority)
264 static struct socket_operations connection_socket_operations = {
265 set_connection_socket_state,
266 set_connection_socket_timeout,
267 retry_connection_socket,
268 done_connection_socket,
270 struct connection *conn = mem_calloc(1, sizeof(*conn));
272 if (!conn) return NULL;
274 assert(proxied_uri->protocol != PROTOCOL_PROXY);
276 conn->socket = init_socket(conn, &connection_socket_operations);
277 if (!conn->socket) {
278 mem_free(conn);
279 return NULL;
282 conn->data_socket = init_socket(conn, &connection_socket_operations);
283 if (!conn->data_socket) {
284 mem_free(conn->socket);
285 mem_free(conn);
286 return NULL;
289 conn->progress = init_progress(start);
290 if (!conn->progress) {
291 mem_free(conn->data_socket);
292 mem_free(conn->socket);
293 mem_free(conn);
294 return NULL;
297 /* load_uri() gets the URI from get_proxy() which grabs a reference for
298 * us. */
299 conn->uri = uri;
300 conn->proxied_uri = proxied_uri;
301 conn->id = connection_id++;
302 conn->pri[priority] = 1;
303 conn->cache_mode = cache_mode;
305 conn->content_encoding = ENCODING_NONE;
306 conn->stream_pipes[0] = conn->stream_pipes[1] = -1;
307 init_list(conn->downloads);
308 conn->est_length = -1;
309 conn->timer = TIMER_ID_UNDEF;
311 if (referrer) {
312 /* Don't set referrer when it is the file protocol and the URI
313 * being loaded is not. This means CGI scripts will have it
314 * available while preventing information about the local
315 * system from being leaked to external servers. */
316 if (referrer->protocol != PROTOCOL_FILE
317 || uri->protocol == PROTOCOL_FILE)
318 conn->referrer = get_uri_reference(referrer);
321 return conn;
324 static void
325 update_connection_progress(struct connection *conn)
327 update_progress(conn->progress, conn->received, conn->est_length, conn->from);
330 /* Progress timer callback for @conn->progress. As explained in
331 * @start_update_progress, this function must erase the expired timer
332 * ID from @conn->progress->timer. */
333 static void
334 stat_timer(struct connection *conn)
336 update_connection_progress(conn);
337 /* The expired timer ID has now been erased. */
338 notify_connection_callbacks(conn);
341 void
342 set_connection_state(struct connection *conn, enum connection_state state)
344 struct download *download;
345 struct progress *progress = conn->progress;
347 if (is_in_result_state(conn->state) && is_in_progress_state(state))
348 conn->prev_error = conn->state;
350 conn->state = state;
351 if (conn->state == S_TRANS) {
352 if (progress->timer == TIMER_ID_UNDEF) {
353 start_update_progress(progress, (void (*)(void *)) stat_timer, conn);
354 update_connection_progress(conn);
355 if (connection_disappeared(conn))
356 return;
359 } else {
360 kill_timer(&progress->timer);
363 foreach (download, conn->downloads) {
364 download->state = state;
365 download->prev_error = conn->prev_error;
368 if (is_in_progress_state(state)) notify_connection_callbacks(conn);
371 void
372 shutdown_connection_stream(struct connection *conn)
374 if (conn->stream) {
375 close_encoded(conn->stream);
376 conn->stream = NULL;
377 } else if (conn->stream_pipes[0] >= 0) {
378 /* close_encoded() usually closes this end of the pipe,
379 * but open_encoded() apparently failed this time. */
380 close(conn->stream_pipes[0]);
382 if (conn->stream_pipes[1] >= 0)
383 close(conn->stream_pipes[1]);
384 conn->stream_pipes[0] = conn->stream_pipes[1] = -1;
387 static void
388 close_popen(int fd)
390 struct popen_data *pop;
392 foreach (pop, copiousoutput_data) {
393 if (pop->fd == fd) {
394 del_from_list(pop);
395 fclose(pop->stream);
396 if (pop->filename) {
397 unlink(pop->filename);
398 mem_free(pop->filename);
400 mem_free(pop);
401 break;
406 static void
407 free_connection_data(struct connection *conn)
409 assertm(conn->running, "connection already suspended");
410 /* XXX: Recovery path? Originally, there was none. I think we'll get
411 * at least active_connections underflows along the way. --pasky */
412 conn->running = 0;
414 active_connections--;
415 assertm(active_connections >= 0, "active connections underflow");
416 if_assert_failed active_connections = 0;
418 #ifdef CONFIG_SSL
419 if (conn->socket->ssl && conn->cached)
420 mem_free_set(&conn->cached->ssl_info, get_ssl_connection_cipher(conn->socket));
421 #endif
423 if (conn->done)
424 conn->done(conn);
426 if (conn->popen) close_popen(conn->socket->fd);
427 done_socket(conn->socket);
428 done_socket(conn->data_socket);
430 shutdown_connection_stream(conn);
432 mem_free_set(&conn->info, NULL);
434 kill_timer(&conn->timer);
436 if (conn->state != S_WAIT)
437 done_host_connection(conn);
440 void
441 notify_connection_callbacks(struct connection *conn)
443 enum connection_state state = conn->state;
444 struct download *download, *next;
446 foreachsafe (download, next, conn->downloads) {
447 download->cached = conn->cached;
448 if (download->callback)
449 download->callback(download, download->data);
450 if (is_in_progress_state(state) && connection_disappeared(conn))
451 return;
455 static void
456 done_connection(struct connection *conn)
458 /* When removing the connection callbacks should always be aware of it
459 * so they can unregister themselves. We do this by enforcing that the
460 * connection is in a result state. If it is not already it is an
461 * internal bug. This should never happen but it does. ;) --jonas */
462 if (!is_in_result_state(conn->state))
463 set_connection_state(conn, S_INTERNAL);
465 del_from_list(conn);
466 notify_connection_callbacks(conn);
467 if (conn->referrer) done_uri(conn->referrer);
468 done_uri(conn->uri);
469 done_uri(conn->proxied_uri);
470 mem_free(conn->socket);
471 mem_free(conn->data_socket);
472 done_progress(conn->progress);
473 mem_free(conn);
474 check_queue_bugs();
477 static inline void
478 add_to_queue(struct connection *conn)
480 struct connection *c;
481 enum connection_priority priority = get_priority(conn);
483 foreach (c, connection_queue)
484 if (get_priority(c) > priority)
485 break;
487 add_at_pos(c->prev, conn);
491 /* Returns zero if no callback was done and the keepalive connection should be
492 * deleted or non-zero if the keepalive connection should not be deleted. */
493 static int
494 do_keepalive_connection_callback(struct keepalive_connection *keep_conn)
496 struct uri *proxied_uri = get_proxied_uri(keep_conn->uri);
497 struct uri *proxy_uri = get_proxy_uri(keep_conn->uri, NULL);
499 if (proxied_uri && proxy_uri) {
500 struct connection *conn;
502 conn = init_connection(proxy_uri, proxied_uri, NULL, 0,
503 CACHE_MODE_NEVER, PRI_CANCEL);
505 if (conn) {
506 void (*done)(struct connection *) = keep_conn->done;
508 add_to_queue(conn);
510 /* Get the keepalive info and let it clean up */
511 if (!has_keepalive_connection(conn)
512 || !add_host_connection(conn)) {
513 free_connection_data(conn);
514 done_connection(conn);
515 return 0;
518 active_connections++;
519 conn->running = 1;
520 done(conn);
521 return 1;
525 if (proxied_uri) done_uri(proxied_uri);
526 if (proxy_uri) done_uri(proxy_uri);
528 return 0;
531 static inline void
532 done_keepalive_connection(struct keepalive_connection *keep_conn)
534 if (keep_conn->done && do_keepalive_connection_callback(keep_conn))
535 return;
537 del_from_list(keep_conn);
538 if (keep_conn->socket != -1) close(keep_conn->socket);
539 done_uri(keep_conn->uri);
540 mem_free(keep_conn);
543 static struct keepalive_connection *
544 init_keepalive_connection(struct connection *conn, long timeout_in_seconds,
545 void (*done)(struct connection *))
547 struct keepalive_connection *keep_conn;
548 struct uri *uri = conn->uri;
550 assert(uri->host);
551 if_assert_failed return NULL;
553 keep_conn = mem_calloc(1, sizeof(*keep_conn));
554 if (!keep_conn) return NULL;
556 keep_conn->uri = get_uri_reference(uri);
557 keep_conn->done = done;
558 keep_conn->protocol_family = conn->socket->protocol_family;
559 keep_conn->socket = conn->socket->fd;
560 timeval_from_seconds(&keep_conn->timeout, timeout_in_seconds);
561 timeval_now(&keep_conn->creation_time);
563 return keep_conn;
566 static struct keepalive_connection *
567 get_keepalive_connection(struct connection *conn)
569 struct keepalive_connection *keep_conn;
571 if (!conn->uri->host) return NULL;
573 foreach (keep_conn, keepalive_connections)
574 if (compare_uri(keep_conn->uri, conn->uri, URI_KEEPALIVE))
575 return keep_conn;
577 return NULL;
581 has_keepalive_connection(struct connection *conn)
583 struct keepalive_connection *keep_conn = get_keepalive_connection(conn);
585 if (!keep_conn) return 0;
587 conn->socket->fd = keep_conn->socket;
588 conn->socket->protocol_family = keep_conn->protocol_family;
590 /* Mark that the socket should not be closed and the callback should be
591 * ignored. */
592 keep_conn->socket = -1;
593 keep_conn->done = NULL;
594 done_keepalive_connection(keep_conn);
596 return 1;
599 void
600 add_keepalive_connection(struct connection *conn, long timeout_in_seconds,
601 void (*done)(struct connection *))
603 struct keepalive_connection *keep_conn;
605 assertm(conn->socket->fd != -1, "keepalive connection not connected");
606 if_assert_failed goto done;
608 keep_conn = init_keepalive_connection(conn, timeout_in_seconds, done);
609 if (keep_conn) {
610 /* Make sure that the socket descriptor will not periodically be
611 * checked or closed by free_connection_data(). */
612 clear_handlers(conn->socket->fd);
613 conn->socket->fd = -1;
614 add_to_list(keepalive_connections, keep_conn);
616 } else if (done) {
617 /* It will take just a little more time */
618 done(conn);
619 return;
622 done:
623 free_connection_data(conn);
624 done_connection(conn);
625 register_check_queue();
628 /* Timer callback for @keepalive_timeout. As explained in @install_timer,
629 * this function must erase the expired timer ID from all variables. */
630 static void
631 keepalive_timer(void *x)
633 keepalive_timeout = TIMER_ID_UNDEF;
634 /* The expired timer ID has now been erased. */
635 check_keepalive_connections();
638 void
639 check_keepalive_connections(void)
641 struct keepalive_connection *keep_conn, *next;
642 timeval_T now;
643 int p = 0;
645 timeval_now(&now);
647 kill_timer(&keepalive_timeout);
649 foreachsafe (keep_conn, next, keepalive_connections) {
650 timeval_T age;
652 if (can_read(keep_conn->socket)) {
653 done_keepalive_connection(keep_conn);
654 continue;
657 timeval_sub(&age, &keep_conn->creation_time, &now);
658 if (timeval_cmp(&age, &keep_conn->timeout) > 0) {
659 done_keepalive_connection(keep_conn);
660 continue;
663 p++;
666 for (; p > MAX_KEEPALIVE_CONNECTIONS; p--) {
667 assertm(!list_empty(keepalive_connections), "keepalive list empty");
668 if_assert_failed return;
669 done_keepalive_connection(keepalive_connections.prev);
672 if (!list_empty(keepalive_connections))
673 install_timer(&keepalive_timeout, KEEPALIVE_CHECK_TIME,
674 keepalive_timer, NULL);
677 static inline void
678 abort_all_keepalive_connections(void)
680 while (!list_empty(keepalive_connections))
681 done_keepalive_connection(keepalive_connections.next);
683 check_keepalive_connections();
687 static void
688 sort_queue(void)
690 while (1) {
691 struct connection *conn;
692 int swp = 0;
694 foreach (conn, connection_queue) {
695 if (!list_has_next(connection_queue, conn)) break;
697 if (get_priority(conn->next) < get_priority(conn)) {
698 struct connection *c = conn->next;
700 del_from_list(conn);
701 add_at_pos(c, conn);
702 swp = 1;
706 if (!swp) break;
710 static void
711 interrupt_connection(struct connection *conn)
713 free_connection_data(conn);
716 static inline void
717 suspend_connection(struct connection *conn)
719 interrupt_connection(conn);
720 set_connection_state(conn, S_WAIT);
723 static void
724 run_connection(struct connection *conn)
726 protocol_handler_T *func = get_protocol_handler(conn->uri->protocol);
728 assert(func);
730 assertm(!conn->running, "connection already running");
731 if_assert_failed return;
733 if (!add_host_connection(conn)) {
734 set_connection_state(conn, S_OUT_OF_MEM);
735 done_connection(conn);
736 return;
739 active_connections++;
740 conn->running = 1;
742 func(conn);
745 /* Set certain state on a connection and then abort the connection. */
746 void
747 abort_connection(struct connection *conn, enum connection_state state)
749 assertm(is_in_result_state(state),
750 "connection didn't end in result state (%d)", state);
752 if (state == S_OK && conn->cached)
753 normalize_cache_entry(conn->cached, conn->from);
755 set_connection_state(conn, state);
757 if (conn->running) interrupt_connection(conn);
758 done_connection(conn);
759 register_check_queue();
762 /* Set certain state on a connection and then retry the connection. */
763 void
764 retry_connection(struct connection *conn, enum connection_state state)
766 int max_tries = get_opt_int("connection.retries");
768 assertm(is_in_result_state(state),
769 "connection didn't end in result state (%d)", state);
771 set_connection_state(conn, state);
773 interrupt_connection(conn);
774 if (conn->uri->post || (max_tries && ++conn->tries >= max_tries)) {
775 done_connection(conn);
776 register_check_queue();
777 } else {
778 conn->prev_error = conn->state;
779 run_connection(conn);
783 static int
784 try_to_suspend_connection(struct connection *conn, struct uri *uri)
786 enum connection_priority priority = get_priority(conn);
787 struct connection *c;
789 foreachback (c, connection_queue) {
790 if (get_priority(c) <= priority) return -1;
791 if (c->state == S_WAIT) continue;
792 if (c->uri->post && get_priority(c) < PRI_CANCEL) continue;
793 if (uri && !compare_uri(uri, c->uri, URI_HOST)) continue;
794 suspend_connection(c);
795 return 0;
798 return -1;
801 static inline int
802 try_connection(struct connection *conn, int max_conns_to_host, int max_conns)
804 struct host_connection *host_conn = get_host_connection(conn);
806 if (host_conn && get_object_refcount(host_conn) >= max_conns_to_host)
807 return try_to_suspend_connection(conn, host_conn->uri) ? 0 : -1;
809 if (active_connections >= max_conns)
810 return try_to_suspend_connection(conn, NULL) ? 0 : -1;
812 run_connection(conn);
813 return 1;
816 static void
817 check_queue(void)
819 struct connection *conn;
820 int max_conns_to_host = get_opt_int("connection.max_connections_to_host");
821 int max_conns = get_opt_int("connection.max_connections");
823 again:
824 conn = connection_queue.next;
825 check_queue_bugs();
826 check_keepalive_connections();
828 while (conn != (struct connection *) &connection_queue) {
829 struct connection *c;
830 enum connection_priority pri = get_priority(conn);
832 for (c = conn; c != (struct connection *) &connection_queue && get_priority(c) == pri;) {
833 struct connection *cc = c;
835 c = c->next;
836 if (cc->state == S_WAIT && get_keepalive_connection(cc)
837 && try_connection(cc, max_conns_to_host, max_conns))
838 goto again;
841 for (c = conn; c != (struct connection *) &connection_queue && get_priority(c) == pri;) {
842 struct connection *cc = c;
844 c = c->next;
845 if (cc->state == S_WAIT
846 && try_connection(cc, max_conns_to_host, max_conns))
847 goto again;
849 conn = c;
852 again2:
853 foreachback (conn, connection_queue) {
854 if (get_priority(conn) < PRI_CANCEL) break;
855 if (conn->state == S_WAIT) {
856 set_connection_state(conn, S_INTERRUPTED);
857 done_connection(conn);
858 goto again2;
862 check_queue_bugs();
866 register_check_queue(void)
868 return register_bottom_half(check_queue, NULL);
872 load_uri(struct uri *uri, struct uri *referrer, struct download *download,
873 enum connection_priority pri, enum cache_mode cache_mode, off_t start)
875 struct cache_entry *cached;
876 struct connection *conn;
877 struct uri *proxy_uri, *proxied_uri;
878 enum connection_state connection_state = S_OK;
880 if (download) {
881 download->conn = NULL;
882 download->cached = NULL;
883 download->pri = pri;
884 download->state = S_OUT_OF_MEM;
885 download->prev_error = 0;
888 #ifdef CONFIG_DEBUG
889 foreach (conn, connection_queue) {
890 struct download *assigned;
892 foreach (assigned, conn->downloads) {
893 assertm(assigned != download, "Download assigned to '%s'", struri(conn->uri));
894 if_assert_failed {
895 download->state = S_INTERNAL;
896 if (download->callback)
897 download->callback(download, download->data);
898 return 0;
900 /* No recovery path should be necessary. */
903 #endif
905 cached = get_validated_cache_entry(uri, cache_mode);
906 if (cached) {
907 if (download) {
908 download->cached = cached;
909 download->state = S_OK;
910 /* XXX:
911 * This doesn't work since sometimes |download->progress|
912 * is undefined and contains random memory locations.
913 * It's not supposed to point on anything here since
914 * |download| has no connection attached.
915 * Downloads resuming will probably break in some
916 * cases without this, though.
917 * FIXME: Needs more investigation. --pasky */
918 /* if (download->progress) download->progress->start = start; */
919 if (download->callback)
920 download->callback(download, download->data);
922 return 0;
925 proxied_uri = get_proxied_uri(uri);
926 proxy_uri = get_proxy_uri(uri, &connection_state);
928 if (!proxy_uri
929 || !proxied_uri
930 || (get_protocol_need_slash_after_host(proxy_uri->protocol)
931 && !proxy_uri->hostlen)) {
933 if (download) {
934 if (connection_state == S_OK) {
935 connection_state = proxy_uri && proxied_uri
936 ? S_BAD_URL : S_OUT_OF_MEM;
939 download->state = connection_state;
940 download->callback(download, download->data);
942 if (proxy_uri) done_uri(proxy_uri);
943 if (proxied_uri) done_uri(proxied_uri);
944 return -1;
947 foreach (conn, connection_queue) {
948 if (conn->detached
949 || !compare_uri(conn->uri, proxy_uri, 0))
950 continue;
952 done_uri(proxy_uri);
953 done_uri(proxied_uri);
955 if (get_priority(conn) > pri) {
956 del_from_list(conn);
957 conn->pri[pri]++;
958 add_to_queue(conn);
959 register_check_queue();
960 } else {
961 conn->pri[pri]++;
964 if (download) {
965 download->progress = conn->progress;
966 download->conn = conn;
967 download->cached = conn->cached;
968 add_to_list(conn->downloads, download);
969 /* This is likely to call download->callback() now! */
970 set_connection_state(conn, conn->state);
972 check_queue_bugs();
973 return 0;
976 conn = init_connection(proxy_uri, proxied_uri, referrer, start, cache_mode, pri);
977 if (!conn) {
978 if (download) {
979 download->state = S_OUT_OF_MEM;
980 download->callback(download, download->data);
982 if (proxy_uri) done_uri(proxy_uri);
983 if (proxied_uri) done_uri(proxied_uri);
984 return -1;
987 if (cache_mode < CACHE_MODE_FORCE_RELOAD && cached && !list_empty(cached->frag)
988 && !((struct fragment *) cached->frag.next)->offset)
989 conn->from = ((struct fragment *) cached->frag.next)->length;
991 if (download) {
992 download->progress = conn->progress;
993 download->conn = conn;
994 download->cached = NULL;
995 download->state = S_OK;
996 add_to_list(conn->downloads, download);
999 add_to_queue(conn);
1000 set_connection_state(conn, S_WAIT);
1002 check_queue_bugs();
1004 register_check_queue();
1005 return 0;
1009 /* FIXME: one object in more connections */
1010 void
1011 cancel_download(struct download *download, int interrupt)
1013 struct connection *conn;
1015 assert(download);
1016 if_assert_failed return;
1018 /* Did the connection already end? */
1019 if (is_in_result_state(download->state))
1020 return;
1022 assertm(download->conn != NULL, "last state is %d", download->state);
1024 check_queue_bugs();
1026 download->state = S_INTERRUPTED;
1027 del_from_list(download);
1029 conn = download->conn;
1031 conn->pri[download->pri]--;
1032 assertm(conn->pri[download->pri] >= 0, "priority counter underflow");
1033 if_assert_failed conn->pri[download->pri] = 0;
1035 if (list_empty(conn->downloads)) {
1036 /* Necessary because of assertion in get_priority(). */
1037 conn->pri[PRI_CANCEL]++;
1039 if (conn->detached || interrupt)
1040 abort_connection(conn, S_INTERRUPTED);
1043 sort_queue();
1044 check_queue_bugs();
1046 register_check_queue();
1049 void
1050 move_download(struct download *old, struct download *new,
1051 enum connection_priority newpri)
1053 struct connection *conn;
1055 assert(old);
1057 /* The download doesn't necessarily have a connection attached, for
1058 * example the file protocol loads it's object immediately. This is
1059 * catched by the result state check below. */
1061 conn = old->conn;
1063 new->conn = conn;
1064 new->cached = old->cached;
1065 new->prev_error = old->prev_error;
1066 new->progress = old->progress;
1067 new->state = old->state;
1068 new->pri = newpri;
1070 if (is_in_result_state(old->state)) {
1071 /* Ensure that new->conn is always "valid", that is NULL if the
1072 * connection has been detached and non-NULL otherwise. */
1073 if (new->callback) {
1074 new->conn = NULL;
1075 new->progress = NULL;
1076 new->callback(new, new->data);
1078 return;
1081 assertm(old->conn != NULL, "last state is %d", old->state);
1083 conn->pri[new->pri]++;
1084 add_to_list(conn->downloads, new);
1085 /* In principle, we need to sort_queue() only if conn->pri[new->pri]
1086 * just changed from 0 to 1. But the risk of bugs is smaller if we
1087 * sort every time. */
1088 sort_queue();
1090 cancel_download(old, 0);
1094 /* This will remove 'pos' bytes from the start of the cache for the specified
1095 * connection, if the cached object is already too big. */
1096 void
1097 detach_connection(struct download *download, off_t pos)
1099 struct connection *conn = download->conn;
1101 if (is_in_result_state(download->state)) return;
1103 if (!conn->detached) {
1104 off_t total_len;
1105 off_t i, total_pri = 0;
1107 if (!conn->cached)
1108 return;
1110 total_len = (conn->est_length == -1) ? conn->from
1111 : conn->est_length;
1113 if (total_len < (get_opt_long("document.cache.memory.size")
1114 * MAX_CACHED_OBJECT_PERCENT / 100)) {
1115 /* This whole thing will fit to the memory anyway, so
1116 * there's no problem in detaching the connection. */
1117 return;
1120 for (i = 0; i < PRI_CANCEL; i++)
1121 total_pri += conn->pri[i];
1122 assertm(total_pri, "detaching free connection");
1123 /* No recovery path should be necessary...? */
1125 /* Pre-clean cache. */
1126 shrink_format_cache(0);
1128 if (total_pri != 1 || is_object_used(conn->cached)) {
1129 /* We're too important, or someone uses our cache
1130 * entry. */
1131 return;
1134 /* DBG("detached"); */
1136 /* We aren't valid cache entry anymore. */
1137 conn->cached->valid = 0;
1138 conn->detached = 1;
1141 /* Strip the entry. */
1142 free_entry_to(conn->cached, pos);
1145 /* Timer callback for @conn->timer. As explained in @install_timer,
1146 * this function must erase the expired timer ID from all variables. */
1147 static void
1148 connection_timeout(struct connection *conn)
1150 conn->timer = TIMER_ID_UNDEF;
1151 /* The expired timer ID has now been erased. */
1152 timeout_socket(conn->socket);
1155 /* Timer callback for @conn->timer. As explained in @install_timer,
1156 * this function must erase the expired timer ID from all variables.
1158 * Huh, using two timers? Is this to account for changes of c->unrestartable
1159 * or can it be reduced? --jonas */
1160 static void
1161 connection_timeout_1(struct connection *conn)
1163 install_timer(&conn->timer, (milliseconds_T)
1164 ((conn->unrestartable
1165 ? get_opt_int("connection.unrestartable_receive_timeout")
1166 : get_opt_int("connection.receive_timeout"))
1167 * 500), (void (*)(void *)) connection_timeout, conn);
1168 /* The expired timer ID has now been erased. */
1171 void
1172 set_connection_timeout(struct connection *conn)
1174 kill_timer(&conn->timer);
1176 install_timer(&conn->timer, (milliseconds_T)
1177 ((conn->unrestartable
1178 ? get_opt_int("connection.unrestartable_receive_timeout")
1179 : get_opt_int("connection.receive_timeout"))
1180 * 500), (void (*)(void *)) connection_timeout_1, conn);
1184 void
1185 abort_all_connections(void)
1187 while (!list_empty(connection_queue)) {
1188 abort_connection(connection_queue.next, S_INTERRUPTED);
1191 abort_all_keepalive_connections();
1194 void
1195 abort_background_connections(void)
1197 struct connection *conn, *next;
1199 foreachsafe (conn, next, connection_queue) {
1200 if (get_priority(conn) >= PRI_CANCEL)
1201 abort_connection(conn, S_INTERRUPTED);
1206 is_entry_used(struct cache_entry *cached)
1208 struct connection *conn;
1210 foreach (conn, connection_queue)
1211 if (conn->cached == cached)
1212 return 1;
1214 return 0;