"Fossies" - the Fresh Open Source Software Archive

Member "links-1.03/sched.c" (16 Nov 2011, 20688 Bytes) of archive /linux/www/links-1.03.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "sched.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.8_vs_1.03.

    1 #include "links.h"
    2 
    3 tcount connection_count = 0;
    4 
    5 int active_connections = 0;
    6 
    7 struct list_head queue = {&queue, &queue};
    8 
    9 struct h_conn {
   10     struct h_conn *next;
   11     struct h_conn *prev;
   12     unsigned char *host;
   13     int conn;
   14 };
   15 
   16 struct list_head h_conns = {&h_conns, &h_conns};
   17 
   18 struct list_head keepalive_connections = {&keepalive_connections, &keepalive_connections};
   19 
   20 long connect_info(int type)
   21 {
   22     int i = 0;
   23     struct connection *ce;
   24     struct k_conn *cee;
   25     switch (type) {
   26         case CI_FILES:
   27             foreach(ce, queue) i++;
   28             return i;
   29         case CI_CONNECTING:
   30             foreach(ce, queue) i += ce->state > S_WAIT && ce->state < S_TRANS;
   31             return i;
   32         case CI_TRANSFER:
   33             foreach(ce, queue) i += ce->state == S_TRANS;
   34             return i;
   35         case CI_KEEP:
   36             foreach(cee, keepalive_connections) i++;
   37             return i;
   38         case CI_LIST:
   39             return (long) &queue;
   40         default:
   41             internal("cache_info: bad request");
   42     }
   43     return 0;
   44 }
   45 
   46 int connection_disappeared(struct connection *c, tcount count)
   47 {
   48     struct connection *d;
   49     foreach(d, queue) if (c == d && count == d->count) return 0;
   50     return 1;
   51 }
   52 
   53 struct h_conn *is_host_on_list(struct connection *c)
   54 {
   55     unsigned char *ho;
   56     struct h_conn *h;
   57     if (!(ho = get_host_name(c->url))) return NULL;
   58     foreach(h, h_conns) if (!strcmp(h->host, ho)) {
   59         mem_free(ho);
   60         return h;
   61     }
   62     mem_free(ho);
   63     return NULL;
   64 }
   65 
   66 int st_r = 0;
   67 
   68 void stat_timer(struct connection *c)
   69 {
   70     ttime a;
   71     struct remaining_info *r = &c->prg;
   72     if (getpri(c) == PRI_CANCEL && (c->est_length > (longlong)memory_cache_size * MAX_CACHED_OBJECT || c->from > (longlong)memory_cache_size * MAX_CACHED_OBJECT)) register_bottom_half(check_queue, NULL);
   73     r->loaded = c->received;
   74     if ((r->size = c->est_length) < (r->pos = c->from) && r->size != -1)
   75         r->size = c->from;
   76     r->dis_b += a = get_time() - r->last_time;
   77     while (r->dis_b >= SPD_DISP_TIME * CURRENT_SPD_SEC) {
   78         r->cur_loaded -= r->data_in_secs[0];
   79         memmove(r->data_in_secs, r->data_in_secs + 1, sizeof(int) * (CURRENT_SPD_SEC - 1));
   80         r->data_in_secs[CURRENT_SPD_SEC - 1] = 0;
   81         r->dis_b -= SPD_DISP_TIME;
   82     }
   83     r->data_in_secs[CURRENT_SPD_SEC - 1] += r->loaded - r->last_loaded;
   84     r->cur_loaded += r->loaded - r->last_loaded;
   85     r->last_loaded = r->loaded;
   86     r->last_time += a;
   87     r->elapsed += a;
   88     r->timer = install_timer(SPD_DISP_TIME, (void (*)(void *))stat_timer, c);
   89     if (!st_r) send_connection_info(c);
   90 }
   91 
   92 void setcstate(struct connection *c, int state)
   93 {
   94     struct status *stat;
   95     if (c->state < 0 && state >= 0) c->prev_error = c->state;
   96     if ((c->state = state) == S_TRANS) {
   97         struct remaining_info *r = &c->prg;
   98         if (r->timer == -1) {
   99             tcount count = c->count;
  100             if (!r->valid) {
  101                 memset(r, 0, sizeof(struct remaining_info));
  102                 r->valid = 1;
  103             }
  104             r->last_time = get_time();
  105             r->last_loaded = r->loaded;
  106             st_r = 1;
  107             stat_timer(c);
  108             st_r = 0;
  109             if (connection_disappeared(c, count)) return;
  110         }
  111     } else {
  112         struct remaining_info *r = &c->prg;
  113         if (r->timer != -1) kill_timer(r->timer), r->timer = -1;
  114     }
  115     foreach(stat, c->statuss) {
  116         stat->state = state;
  117         stat->prev_error = c->prev_error;
  118     }
  119     if (state >= 0) send_connection_info(c);
  120 }
  121 
  122 struct k_conn *is_host_on_keepalive_list(struct connection *c)
  123 {
  124     unsigned char *ho;
  125     int po;
  126     void (*ph)(struct connection *);
  127     struct k_conn *h;
  128     if ((po = get_port(c->url)) == -1) return NULL;
  129     if (!(ph = get_protocol_handle(c->url))) return NULL;
  130     if (!(ho = get_host_and_pass(c->url))) return NULL;
  131     foreach(h, keepalive_connections)
  132         if (h->protocol == ph && h->port == po && !strcmp(h->host, ho)) {
  133             mem_free(ho);
  134             return h;
  135         }
  136     mem_free(ho);
  137     return NULL;
  138 }
  139 
  140 int get_keepalive_socket(struct connection *c)
  141 {
  142     struct k_conn *k;
  143     int cc;
  144     if (!(k = is_host_on_keepalive_list(c))) return -1;
  145     cc = k->conn;
  146     del_from_list(k);
  147     mem_free(k->host);
  148     mem_free(k);
  149     c->sock1 = cc;
  150     return 0;
  151 }
  152 
  153 void check_keepalive_connections();
  154 
  155 void abort_all_keepalive_connections()
  156 {
  157     struct k_conn *k;
  158     foreach(k, keepalive_connections) mem_free(k->host), close(k->conn);
  159     free_list(keepalive_connections);
  160     check_keepalive_connections();
  161 }
  162 
  163 void free_connection_data(struct connection *c)
  164 {
  165     struct h_conn *h;
  166     if (c->sock1 != -1) set_handlers(c->sock1, NULL, NULL, NULL, NULL);
  167     if (c->sock2 != -1) set_handlers(c->sock2, NULL, NULL, NULL, NULL);
  168     close_socket(&c->sock2);
  169     if (c->pid) {
  170         kill(c->pid, SIGINT);
  171         kill(c->pid, SIGTERM);
  172         kill(c->pid, SIGKILL);
  173         c->pid = 0;
  174     }
  175     if (!c->running) {
  176         internal("connection already suspended");
  177     }
  178     c->running = 0;
  179     if (c->dnsquery) kill_dns_request(&c->dnsquery);
  180     if (c->buffer) {
  181         mem_free(c->buffer);
  182         c->buffer = NULL;
  183     }
  184     if (c->newconn) {
  185         mem_free(c->newconn);
  186         c->newconn = NULL;
  187     }
  188     if (c->info) {
  189         mem_free(c->info);
  190         c->info = NULL;
  191     }
  192     if (c->timer != -1) kill_timer(c->timer), c->timer = -1;
  193     if (--active_connections < 0) {
  194         internal("active connections underflow");
  195         active_connections = 0;
  196     }
  197     if (c->state != S_WAIT) {
  198         if ((h = is_host_on_list(c))) {
  199             if (!--h->conn) {
  200                 del_from_list(h);
  201                 mem_free(h->host);
  202                 mem_free(h);
  203             }
  204         } else internal("suspending connection that is not on the list (state %d)", c->state);
  205     }
  206 }
  207 
  208 void send_connection_info(struct connection *c)
  209 {
  210     int st = c->state;
  211     tcount count = c->count;
  212     struct status *stat = c->statuss.next;
  213     while ((void *)stat != &c->statuss) {
  214         stat->ce = c->cache;
  215         stat = stat->next;
  216         if (stat->prev->end) stat->prev->end(stat->prev, stat->prev->data);
  217         if (st >= 0 && connection_disappeared(c, count)) return;
  218     }
  219 }
  220 
  221 void del_connection(struct connection *c)
  222 {
  223     del_from_list(c);
  224     send_connection_info(c);
  225     mem_free(c->url);
  226     mem_free(c);
  227 }
  228 
  229 #ifdef DEBUG
  230 void check_queue_bugs();
  231 #endif
  232 
  233 void add_keepalive_socket(struct connection *c, ttime timeout)
  234 {
  235     struct k_conn *k;
  236     free_connection_data(c);
  237     if (c->sock1 == -1) {
  238         internal("keepalive connection not connected");
  239         goto del;
  240     }
  241     k = mem_alloc(sizeof(struct k_conn));
  242     if ((k->port = get_port(c->url)) == -1 || !(k->protocol = get_protocol_handle(c->url)) || !(k->host = get_host_and_pass(c->url))) {
  243         mem_free(k);
  244         del_connection(c);
  245         goto close;
  246     }
  247     k->conn = c->sock1;
  248     k->timeout = timeout;
  249     k->add_time = get_time();
  250     add_to_list(keepalive_connections, k);
  251     del:
  252     del_connection(c);
  253 #ifdef DEBUG
  254     check_queue_bugs();
  255 #endif
  256     register_bottom_half(check_queue, NULL);
  257     return;
  258     close:
  259     close(c->sock1);
  260 #ifdef DEBUG
  261     check_queue_bugs();
  262 #endif
  263     register_bottom_half(check_queue, NULL);
  264 }
  265 
  266 void del_keepalive_socket(struct k_conn *kc)
  267 {
  268     del_from_list(kc);
  269     close(kc->conn);
  270     mem_free(kc->host);
  271     mem_free(kc);
  272 }
  273 
  274 int keepalive_timeout = -1;
  275 
  276 void check_keepalive_connections();
  277 
  278 void keepalive_timer(void *x)
  279 {
  280     keepalive_timeout = -1;
  281     check_keepalive_connections();
  282 }
  283 
  284 void check_keepalive_connections()
  285 {
  286     struct k_conn *kc;
  287     ttime ct = get_time();
  288     int p = 0;
  289     if (keepalive_timeout != -1) kill_timer(keepalive_timeout), keepalive_timeout = -1;
  290     foreach(kc, keepalive_connections) if (can_read(kc->conn) || ct - kc->add_time > kc->timeout) {
  291         kc = kc->prev;
  292         del_keepalive_socket(kc->next);
  293     } else p++;
  294     for (; p > MAX_KEEPALIVE_CONNECTIONS; p--)
  295         if (!list_empty(keepalive_connections))
  296             del_keepalive_socket(keepalive_connections.prev);
  297         else internal("keepalive list empty");
  298     if (!list_empty(keepalive_connections)) keepalive_timeout = install_timer(KEEPALIVE_CHECK_TIME, keepalive_timer, NULL);
  299 }
  300 
  301 void add_to_queue(struct connection *c)
  302 {
  303     struct connection *cc;
  304     int pri = getpri(c);
  305     foreach(cc, queue) if (getpri(cc) > pri) break;
  306     add_at_pos(cc->prev, c);
  307 }
  308 
  309 void sort_queue()
  310 {
  311     struct connection *c, *n;
  312     int swp;
  313     do {
  314         swp = 0;
  315         foreach(c, queue) if ((void *)c->next != &queue) {
  316             if (getpri(c->next) < getpri(c)) {
  317                 n = c->next;
  318                 del_from_list(c);
  319                 add_at_pos(n, c);
  320                 swp = 1;
  321             }
  322         }
  323     } while (swp);
  324 }
  325 
  326 void interrupt_connection(struct connection *c)
  327 {
  328 #ifdef HAVE_SSL
  329     if (c->ssl == (void *)-1) c->ssl = 0;
  330     if(c->ssl) {
  331         SSL_free(c->ssl);
  332         c->ssl=NULL;
  333     }
  334 #endif
  335     close_socket(&c->sock1);
  336     free_connection_data(c);
  337 }
  338 
  339 void suspend_connection(struct connection *c)
  340 {
  341     interrupt_connection(c);
  342     setcstate(c, S_WAIT);
  343 }
  344 
  345 int try_to_suspend_connection(struct connection *c, unsigned char *ho)
  346 {
  347     int pri = getpri(c);
  348     struct connection *d;
  349     foreachback(d, queue) {
  350         if (getpri(d) <= pri) return -1;
  351         if (d->state == S_WAIT) continue;
  352         if (d->unrestartable == 2 && getpri(d) < PRI_CANCEL) continue;
  353         if (ho) {
  354             unsigned char *h;
  355             if (!(h = get_host_name(d->url))) continue;
  356             if (strcmp(h, ho)) {
  357                 mem_free(h);
  358                 continue;
  359             }
  360             mem_free(h);
  361         }
  362         suspend_connection(d);
  363         return 0;
  364     }
  365     return -1;
  366 }
  367 
  368 void run_connection(struct connection *c)
  369 {
  370     struct h_conn *hc;
  371     void (*func)(struct connection *);
  372     if (c->running) {
  373         internal("connection already running");
  374         return;
  375     }
  376     if (!(func = get_protocol_handle(c->url))) {
  377         setcstate(c, S_BAD_URL);
  378         del_connection(c);
  379         return;
  380     }
  381     if (!(hc = is_host_on_list(c))) {
  382         if (!(hc = mem_alloc(sizeof(struct h_conn)))) {
  383             setcstate(c, S_OUT_OF_MEM);
  384             del_connection(c);
  385             return;
  386         }
  387         if (!(hc->host = get_host_name(c->url))) {
  388             setcstate(c, S_BAD_URL);
  389             del_connection(c);
  390             mem_free(hc);
  391             return;
  392         }
  393         hc->conn = 0;
  394         add_to_list(h_conns, hc);
  395     }
  396     hc->conn++;
  397     active_connections++;
  398     c->running = 1;
  399     func(c);
  400 }
  401 
  402 int is_connection_restartable(struct connection *c)
  403 {
  404     return !(c->unrestartable >= 2 || (c->tries + 1 >= (max_tries ? max_tries : 1000)));
  405 }
  406 
  407 void retry_connection(struct connection *c)
  408 {
  409     interrupt_connection(c);
  410     if (!is_connection_restartable(c)) {
  411         /*send_connection_info(c);*/
  412         del_connection(c);
  413 #ifdef DEBUG
  414         check_queue_bugs();
  415 #endif
  416         register_bottom_half(check_queue, NULL);
  417     } else {
  418         c->tries++;
  419         c->prev_error = c->state;
  420         run_connection(c);
  421     }
  422 }
  423 
  424 void abort_connection(struct connection *c)
  425 {
  426     if (c->running) interrupt_connection(c);
  427     /*send_connection_info(c);*/
  428     del_connection(c);
  429 #ifdef DEBUG
  430     check_queue_bugs();
  431 #endif
  432     register_bottom_half(check_queue, NULL);
  433 }
  434 
  435 int try_connection(struct connection *c)
  436 {
  437     struct h_conn *hc = NULL;
  438     if ((hc = is_host_on_list(c))) {
  439         if (hc->conn >= max_connections_to_host) {
  440             if (try_to_suspend_connection(c, hc->host)) return 0;
  441             else return -1;
  442         }
  443     }
  444     if (active_connections >= max_connections) {
  445         if (try_to_suspend_connection(c, NULL)) return 0;
  446         else return -1;
  447     }
  448     run_connection(c);
  449     return 1;
  450 }
  451 
  452 #ifdef DEBUG
  453 void check_queue_bugs()
  454 {
  455     struct connection *d;
  456     int p = 0, ps = 0;
  457     int cc;
  458     again:
  459     cc = 0;
  460     foreach(d, queue) {
  461         int q = getpri(d);
  462         cc += d->running;
  463         if (q < p) if (!ps) {
  464             internal("queue is not sorted");
  465             sort_queue();
  466             ps = 1;
  467             goto again;
  468         } else {
  469             internal("queue is not sorted even after sort_queue!");
  470             break;
  471         } else p = q;
  472         if (d->state < 0) {
  473             internal("interrupted connection on queue (conn %s, state %d)", d->url, d->state);
  474             d = d->prev;
  475             abort_connection(d->next);
  476         }
  477     }
  478     if (cc != active_connections) {
  479         internal("bad number of active connections (counted %d, stored %d)", cc, active_connections);
  480         active_connections = cc;
  481     }
  482 }
  483 #endif
  484 
  485 void check_queue(void *dummy)
  486 {
  487     struct connection *c;
  488     again:
  489     c = queue.next;
  490 #ifdef DEBUG
  491     check_queue_bugs();
  492 #endif
  493     check_keepalive_connections();
  494     while (c != (struct connection *)&queue) {
  495         struct connection *d;
  496         int cp = getpri(c);
  497         for (d = c; d != (struct connection *)&queue && getpri(d) == cp;) {
  498             struct connection *dd = d; d = d->next;
  499             if (!dd->state) if (is_host_on_keepalive_list(dd)) {
  500                 if (try_connection(dd)) goto again;
  501             }
  502         }
  503         for (d = c; d != (struct connection *)&queue && getpri(d) == cp;) {
  504             struct connection *dd = d; d = d->next;
  505             if (!dd->state) {
  506                 if (try_connection(dd)) goto again;
  507             }
  508         }
  509         c = d;
  510     }
  511     again2:
  512     foreachback(c, queue) {
  513         if (getpri(c) < PRI_CANCEL) break;
  514         if (c->state == S_WAIT) {
  515             setcstate(c, S_INTERRUPTED);
  516             del_connection(c);
  517             goto again2;
  518         } else if (c->est_length > (longlong)memory_cache_size * MAX_CACHED_OBJECT || c->from > (longlong)memory_cache_size * MAX_CACHED_OBJECT) {
  519             setcstate(c, S_INTERRUPTED);
  520             abort_connection(c);
  521             goto again2;
  522         }
  523     }
  524 #ifdef DEBUG
  525     check_queue_bugs();
  526 #endif
  527 }
  528 
  529 unsigned char *get_proxy(unsigned char *url)
  530 {
  531     size_t l = strlen(url);
  532     unsigned char *proxy = NULL;
  533     unsigned char *u;
  534     if (*http_proxy && l >= 7 && !casecmp(url, "http://", 7)) proxy = http_proxy;
  535     if (*ftp_proxy && l >= 6 && !casecmp(url, "ftp://", 6)) proxy = ftp_proxy;
  536     u = mem_alloc(l + 1 + (proxy ? strlen(proxy) + 9 : 0));
  537     if (proxy) strcpy(u, "proxy://"), strcat(u, proxy), strcat(u, "/");
  538     else *u = 0;
  539     strcat(u, url);
  540     return u;
  541 }
  542 
  543 int load_url(unsigned char *url, struct status *stat, int pri, int no_cache)
  544 {
  545     struct cache_entry *e = NULL;
  546     struct connection *c;
  547     unsigned char *u;
  548     if (stat) stat->c = NULL, stat->ce = NULL, stat->pri = pri;
  549 #ifdef DEBUG
  550     foreach(c, queue) {
  551         struct status *st;
  552         foreach (st, c->statuss) {
  553             if (st == stat) {
  554                 internal("status already assigned to '%s'", c->url);
  555                 stat->state = S_INTERNAL;
  556                 if (stat->end) stat->end(stat, stat->data);
  557                 return 0;
  558             }
  559         }
  560     }
  561 #endif
  562     if (stat) stat->state = S_OUT_OF_MEM, stat->prev_error = 0;
  563     if (no_cache <= NC_CACHE && !find_in_cache(url, &e)) {
  564         if (e->incomplete) {
  565             e->refcount--;
  566             goto skip_cache;
  567         }
  568         if (stat) {
  569             stat->ce = e;
  570             stat->state = S_OK;
  571             if (stat->end) stat->end(stat, stat->data);
  572         }
  573         e->refcount--;
  574         return 0;
  575     }
  576     skip_cache:
  577     if (!casecmp(url, "proxy://", 8)) {
  578         if (stat) {
  579             stat->state = S_BAD_URL;
  580             if (stat->end) stat->end(stat, stat->data);
  581         }
  582         return 0;
  583     }
  584     if (!(u = get_proxy(url))) {
  585         if (stat) stat->end(stat, stat->data);
  586         return -1;
  587     }
  588     foreach(c, queue) if (!c->detached && !strcmp(c->url, u)) {
  589         mem_free(u);
  590         if (getpri(c) > pri) {
  591             del_from_list(c);
  592             c->pri[pri]++;
  593             add_to_queue(c);
  594             register_bottom_half(check_queue, NULL);
  595         } else c->pri[pri]++;
  596         if (stat) {
  597             stat->prg = &c->prg;
  598             stat->c = c;
  599             stat->ce = c->cache;
  600             add_to_list(c->statuss, stat);
  601             setcstate(c, c->state);
  602         }
  603 #ifdef DEBUG
  604         check_queue_bugs();
  605 #endif
  606         return 0;
  607     }
  608     c = mem_alloc(sizeof(struct connection));
  609     memset(c, 0, sizeof(struct connection));
  610     c->count = connection_count++;
  611     c->url = u;
  612     c->running = 0;
  613     c->prev_error = 0;
  614     c->from = no_cache >= NC_IF_MOD || !e || e->frag.next == &e->frag || ((struct fragment *)e->frag.next)->offset ? 0 : ((struct fragment *)e->frag.next)->length;
  615     memset(c->pri, 0, sizeof c->pri);
  616     c->pri[pri] = 1;
  617     c->no_cache = no_cache;
  618     c->sock1 = c->sock2 = -1;
  619     c->dnsquery = NULL;
  620     c->info = NULL;
  621     c->buffer = NULL;
  622     c->newconn = NULL;
  623     c->cache = NULL;
  624     c->tries = 0;
  625     init_list(c->statuss);
  626     c->est_length = -1;
  627     c->unrestartable = 0;
  628     c->prg.timer = -1;
  629     c->timer = -1;
  630     if (stat) {
  631         stat->prg = &c->prg;
  632         stat->c = c;
  633         stat->ce = NULL;
  634         add_to_list(c->statuss, stat);
  635     }
  636     add_to_queue(c);
  637     setcstate(c, S_WAIT);
  638 #ifdef DEBUG
  639     check_queue_bugs();
  640 #endif
  641     register_bottom_half(check_queue, NULL);
  642     return 0;
  643 }
  644 
  645 void change_connection(struct status *oldstat, struct status *newstat, int newpri)
  646 {       /* !!! FIXME: one object in more connections */
  647     struct connection *c;
  648     int oldpri;
  649     if (!oldstat) {
  650         internal("change_connection: oldstat == NULL");
  651         return;
  652     }
  653     oldpri = oldstat->pri;
  654     if (oldstat->state < 0) {
  655         if (newstat) {
  656             newstat->ce = oldstat->ce;
  657             newstat->state = oldstat->state;
  658             newstat->prev_error = oldstat->prev_error;
  659             if (newstat->end) newstat->end(newstat, newstat->data);
  660         }
  661         return;
  662     }
  663 #ifdef DEBUG
  664     check_queue_bugs();
  665 #endif
  666     c = oldstat->c;
  667     if (--c->pri[oldpri] < 0) {
  668         internal("priority counter underflow");
  669         c->pri[oldpri] = 0;
  670     }
  671     c->pri[newpri]++;
  672     del_from_list(oldstat);
  673     oldstat->state = S_INTERRUPTED;
  674     if (newstat) {
  675         newstat->prg = &c->prg;
  676         add_to_list(c->statuss, newstat);
  677         newstat->state = c->state;
  678         newstat->prev_error = c->prev_error;
  679         newstat->pri = newpri;
  680         newstat->c = c;
  681         newstat->ce = c->cache;
  682     }
  683     if (c->detached && !newstat) {
  684         setcstate(c, S_INTERRUPTED);
  685         abort_connection(c);
  686     }
  687     sort_queue();
  688 #ifdef DEBUG
  689     check_queue_bugs();
  690 #endif
  691     register_bottom_half(check_queue, NULL);
  692 }
  693 
  694 void detach_connection(struct status *stat, off_t pos)
  695 {
  696     struct connection *c;
  697     int i;
  698     off_t l;
  699     if (stat->state < 0) return;
  700     c = stat->c;
  701     if (c->detached) goto detach_done;
  702     if (!c->cache) return;
  703     if (c->est_length == -1) l = c->from;
  704     else l = c->est_length;
  705     if (l < (longlong)memory_cache_size * MAX_CACHED_OBJECT) return;
  706     l = 0;
  707     for (i = 0; i < PRI_CANCEL; i++) l += c->pri[i];
  708     if (!l) internal("detaching free connection");
  709     delete_unused_format_cache_entries();
  710     if (l != 1 || c->cache->refcount) return;
  711     c->cache->url[0] = 0;
  712     c->detached = 1;
  713     detach_done:
  714     free_entry_to(c->cache, pos);
  715 }
  716 
  717 void connection_timeout(struct connection *c)
  718 {
  719     c->timer = -1;
  720     setcstate(c, S_TIMEOUT);
  721     if (c->dnsquery) abort_connection(c);
  722     else retry_connection(c);
  723 }
  724 
  725 void connection_timeout_1(struct connection *c)
  726 {
  727     c->timer = install_timer((c->unrestartable ? unrestartable_receive_timeout : receive_timeout) * 500, (void (*)(void *))connection_timeout, c);
  728 }
  729 
  730 void set_timeout(struct connection *c)
  731 {
  732     if (c->timer != -1) kill_timer(c->timer);
  733     c->timer = install_timer((c->unrestartable ? unrestartable_receive_timeout : receive_timeout) * 500, (void (*)(void *))connection_timeout_1, c);
  734 }
  735 
  736 void reset_timeout(struct connection *c)
  737 {
  738     if (c->timer != -1) kill_timer(c->timer), c->timer = -1;
  739 }
  740 
  741 void abort_all_connections()
  742 {
  743     while(queue.next != &queue) {
  744         setcstate(queue.next, S_INTERRUPTED);
  745         abort_connection(queue.next);
  746     }
  747     abort_all_keepalive_connections();
  748 }
  749 
  750 void abort_background_connections()
  751 {
  752     int i = 0;
  753     while (1) {
  754         int j;
  755         struct connection *c = (void *)&queue;
  756         for (j = 0; j <= i; j++) if ((c = c->next) == (void *)&queue) goto brk;
  757         if (getpri(c) >= PRI_CANCEL) {
  758             setcstate(c, S_INTERRUPTED);
  759             abort_connection(c);
  760         } else i++;
  761     }
  762     brk:
  763     abort_all_keepalive_connections();
  764 }
  765 
  766 int is_entry_used(struct cache_entry *e)
  767 {
  768     struct connection *c;
  769     foreach(c, queue) if (c->cache == e) return 1;
  770     return 0;
  771 }
  772 
  773 struct blacklist_entry {
  774     struct blacklist_entry *next;
  775     struct blacklist_entry *prev;
  776     int flags;
  777     unsigned char host[1];
  778 };
  779 
  780 struct list_head blacklist = { &blacklist, &blacklist };
  781 
  782 void add_blacklist_entry(unsigned char *host, int flags)
  783 {
  784     struct blacklist_entry *b;
  785     foreach(b, blacklist) if (!strcasecmp(host, b->host)) {
  786         b->flags |= flags;
  787         return;
  788     }
  789     b = mem_alloc(sizeof(struct blacklist_entry) + strlen(host) + 1);
  790     b->flags = flags;
  791     strcpy(b->host, host);
  792     add_to_list(blacklist, b);
  793 }
  794 
  795 void del_blacklist_entry(unsigned char *host, int flags)
  796 {
  797     struct blacklist_entry *b;
  798     foreach(b, blacklist) if (!strcasecmp(host, b->host)) {
  799         b->flags &= ~flags;
  800         if (!b->flags) {
  801             del_from_list(b);
  802             mem_free(b);
  803         }
  804         return;
  805     }
  806 }
  807 
  808 int get_blacklist_flags(unsigned char *host)
  809 {
  810     struct blacklist_entry *b;
  811     foreach(b, blacklist) if (!strcasecmp(host, b->host)) return b->flags;
  812     return 0;
  813 }
  814 
  815 void free_blacklist()
  816 {
  817     free_list(blacklist);
  818 }
  819 
  820 struct s_msg_dsc msg_dsc[] = {
  821     { S_WAIT,       TEXT_(T_WAITING_IN_QUEUE) },
  822     { S_DNS,        TEXT_(T_LOOKING_UP_HOST) },
  823     { S_CONN,       TEXT_(T_MAKING_CONNECTION) },
  824     { S_SSL_NEG,        TEXT_(T_SSL_NEGOTIATION) },
  825     { S_SENT,       TEXT_(T_REQUEST_SENT) },
  826     { S_LOGIN,      TEXT_(T_LOGGING_IN) },
  827     { S_GETH,       TEXT_(T_GETTING_HEADERS) },
  828     { S_PROC,       TEXT_(T_SERVER_IS_PROCESSING_REQUEST) },
  829     { S_TRANS,      TEXT_(T_TRANSFERRING) },
  830 
  831     { S_OK,         TEXT_(T_OK) },
  832     { S_INTERRUPTED,    TEXT_(T_INTERRUPTED) },
  833     { S_EXCEPT,     TEXT_(T_SOCKET_EXCEPTION) },
  834     { S_INTERNAL,       TEXT_(T_INTERNAL_ERROR) },
  835     { S_OUT_OF_MEM,     TEXT_(T_OUT_OF_MEMORY) },
  836     { S_NO_DNS,     TEXT_(T_HOST_NOT_FOUND) },
  837     { S_CANT_WRITE,     TEXT_(T_ERROR_WRITING_TO_SOCKET) },
  838     { S_CANT_READ,      TEXT_(T_ERROR_READING_FROM_SOCKET) },
  839     { S_MODIFIED,       TEXT_(T_DATA_MODIFIED) },
  840     { S_BAD_URL,        TEXT_(T_BAD_URL_SYNTAX) },
  841     { S_TIMEOUT,        TEXT_(T_RECEIVE_TIMEOUT) },
  842     { S_RESTART,        TEXT_(T_REQUEST_MUST_BE_RESTARTED) },
  843     { S_STATE,      TEXT_(T_CANT_GET_SOCKET_STATE) },
  844     { S_LARGE_FILE,     TEXT_(T_TOO_LARGE_FILE)},
  845 
  846     { S_HTTP_ERROR,     TEXT_(T_BAD_HTTP_RESPONSE) },
  847     { S_HTTP_100,       TEXT_(T_HTTP_100) },
  848     { S_HTTP_204,       TEXT_(T_NO_CONTENT) },
  849 
  850     { S_FILE_TYPE,      TEXT_(T_UNKNOWN_FILE_TYPE) },
  851     { S_FILE_ERROR,     TEXT_(T_ERROR_OPENING_FILE) },
  852 
  853     { S_FTP_ERROR,      TEXT_(T_BAD_FTP_RESPONSE) },
  854     { S_FTP_UNAVAIL,    TEXT_(T_FTP_SERVICE_UNAVAILABLE) },
  855     { S_FTP_LOGIN,      TEXT_(T_BAD_FTP_LOGIN) },
  856     { S_FTP_PORT,       TEXT_(T_FTP_PORT_COMMAND_FAILED) },
  857     { S_FTP_NO_FILE,    TEXT_(T_FILE_NOT_FOUND) },
  858     { S_FTP_FILE_ERROR, TEXT_(T_FTP_FILE_ERROR) },
  859 
  860     { S_SSL_ERROR,      TEXT_(T_SSL_ERROR) },
  861     { S_NO_SSL,     TEXT_(T_NO_SSL) },
  862 
  863     { S_NO_SMB_CLIENT,  TEXT_(T_NO_SMB_CLIENT) },
  864 
  865     { S_WAIT_REDIR,     TEXT_(T_WAITING_FOR_REDIRECT_CONFIRMATION) },
  866     { 0,            NULL },
  867 };