📄 sched.c
字号:
c->prev_error = c->state; run_connection(c); }}void abort_connection(struct connection *c){ if (c->running) interrupt_connection(c); /*send_connection_info(c);*/ del_connection(c);#ifdef DEBUG check_queue_bugs();#endif register_bottom_half(check_queue, NULL);}int try_connection(struct connection *c){ struct h_conn *hc = NULL; if ((hc = is_host_on_list(c))) { if (hc->conn >= max_connections_to_host) { if (try_to_suspend_connection(c, hc->host)) return 0; else return -1; } } if (active_connections >= max_connections) { if (try_to_suspend_connection(c, NULL)) return 0; else return -1; } run_connection(c); return 1;}#ifdef DEBUGvoid check_queue_bugs(void){ struct connection *d; int p = 0, ps = 0; int cc; again: cc = 0; foreach(d, queue) { int q = getpri(d); cc += d->running; if (q < p) if (!ps) { internal("queue is not sorted"); sort_queue(); ps = 1; goto again; } else { internal("queue is not sorted even after sort_queue!"); break; } else p = q; if (d->state < 0) { internal("interrupted connection on queue (conn %s, state %d)", d->url, d->state); d = d->prev; abort_connection(d->next); } } if (cc != active_connections) { internal("bad number of active connections (counted %d, stored %d)", cc, active_connections); active_connections = cc; }}#endifvoid check_queue(void *dummy){ struct connection *c; again: c = queue.next;#ifdef DEBUG check_queue_bugs();#endif check_keepalive_connections(); while (c != (struct connection *)(void *)&queue) { struct connection *d; int cp = getpri(c); for (d = c; d != (struct connection *)(void *)&queue && getpri(d) == cp;) { struct connection *dd = d; d = d->next; if (!dd->state) if (is_host_on_keepalive_list(dd)) { if (try_connection(dd)) goto again; } } for (d = c; d != (struct connection *)(void *)&queue && getpri(d) == cp;) { struct connection *dd = d; d = d->next; if (!dd->state) { if (try_connection(dd)) goto again; } } c = d; } again2: foreachback(c, queue) { if (getpri(c) < PRI_CANCEL) break; if (c->state == S_WAIT) { setcstate(c, S_INTERRUPTED); del_connection(c); goto again2; } else if (c->est_length > memory_cache_size * MAX_CACHED_OBJECT || c->from > memory_cache_size * MAX_CACHED_OBJECT) { setcstate(c, S_INTERRUPTED); abort_connection(c); goto again2; } }#ifdef DEBUG check_queue_bugs();#endif}unsigned char *get_proxy(unsigned char *url){ size_t l = strlen(url); unsigned char *proxy = NULL; unsigned char *u; if (*proxies.http_proxy && l >= 7 && !casecmp(url, "http://", 7)) proxy = proxies.http_proxy; if (*proxies.ftp_proxy && l >= 6 && !casecmp(url, "ftp://", 6)) proxy = proxies.ftp_proxy; u = mem_alloc(l + 1 + (proxy ? strlen(proxy) + 9 : 0)); if (proxy) strcpy(u, "proxy://"), strcat(u, proxy), strcat(u, "/"); else *u = 0; strcat(u, url); return u;}/* prev_url is a pointer to previous url or NULL *//* prev_url will NOT be deallocated */int load_url(unsigned char *url, unsigned char * prev_url, struct status *stat, int pri, int no_cache){ struct cache_entry *e = NULL; struct connection *c; unsigned char *u; if (stat) stat->c = NULL, stat->ce = NULL, stat->pri = pri;#ifdef DEBUG foreach(c, queue) { struct status *st; foreach (st, c->statuss) { if (st == stat) { internal("status already assigned to '%s'", c->url); stat->state = S_INTERNAL; if (stat->end) stat->end(stat, stat->data); return 0; } } }#endif if (stat) stat->state = S_OUT_OF_MEM, stat->prev_error = 0; if (no_cache <= NC_CACHE && !find_in_cache(url, &e) && !e->incomplete) { if (!http_bugs.aggressive_cache && no_cache > NC_ALWAYS_CACHE) { if (e->expire_time && e->expire_time < time(NULL)) { if (no_cache < NC_IF_MOD) no_cache = NC_IF_MOD; goto skip_cache; } } if (stat) { stat->ce = e; stat->state = S_OK; if (stat->end) stat->end(stat, stat->data); } return 0; } skip_cache: if (!casecmp(url, "proxy://", 8)) { if (stat) { stat->state = S_BAD_URL; if (stat->end) stat->end(stat, stat->data); } return 0; } u = get_proxy(url); foreach(c, queue) if (!c->detached && !strcmp(c->url, u)) { mem_free(u); if (getpri(c) > pri) { del_from_list(c); c->pri[pri]++; add_to_queue(c); register_bottom_half(check_queue, NULL); } else c->pri[pri]++; if (stat) { stat->prg = &c->prg; stat->c = c; stat->ce = c->cache; add_to_list(c->statuss, stat); setcstate(c, c->state); }#ifdef DEBUG check_queue_bugs();#endif return 0; } c = mem_calloc(sizeof(struct connection)); c->count = connection_count++; c->url = u; c->prev_url = stracpy(prev_url); c->running = 0; c->prev_error = 0; 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; memset(c->pri, 0, sizeof c->pri); c->pri[pri] = 1; c->no_cache = no_cache; c->sock1 = c->sock2 = -1; c->dnsquery = NULL; c->info = NULL; c->buffer = NULL; c->newconn = NULL; c->cache = NULL; c->tries = 0; init_list(c->statuss); c->est_length = -1; c->unrestartable = 0; c->prg.timer = -1; c->timer = -1; if (stat) { stat->prg = &c->prg; stat->c = c; stat->ce = NULL; add_to_list(c->statuss, stat); } add_to_queue(c); setcstate(c, S_WAIT);#ifdef DEBUG check_queue_bugs();#endif register_bottom_half(check_queue, NULL); return 0;}void change_connection(struct status *oldstat, struct status *newstat, int newpri){ /* !!! FIXME: one object in more connections */ struct connection *c; int oldpri; if (!oldstat) { internal("change_connection: oldstat == NULL"); return; } oldpri = oldstat->pri; if (oldstat->state < 0) { if (newstat) { newstat->ce = oldstat->ce; newstat->state = oldstat->state; newstat->prev_error = oldstat->prev_error; if (newstat->end) newstat->end(newstat, newstat->data); } return; }#ifdef DEBUG check_queue_bugs();#endif c = oldstat->c; if (--c->pri[oldpri] < 0) { internal("priority counter underflow"); c->pri[oldpri] = 0; } c->pri[newpri]++; del_from_list(oldstat); oldstat->state = S_INTERRUPTED; if (newstat) { newstat->prg = &c->prg; add_to_list(c->statuss, newstat); newstat->state = c->state; newstat->prev_error = c->prev_error; newstat->pri = newpri; newstat->c = c; newstat->ce = c->cache; } if (c->detached && !newstat) { setcstate(c, S_INTERRUPTED); abort_connection(c); } sort_queue();#ifdef DEBUG check_queue_bugs();#endif register_bottom_half(check_queue, NULL);}void detach_connection(struct status *stat, off_t pos){ struct connection *c; int i; off_t l; if (stat->state < 0) return; c = stat->c; if (c->detached) goto detach_done; if (!c->cache) return; if (c->est_length == -1) l = c->from; else l = c->est_length; if (l < memory_cache_size * MAX_CACHED_OBJECT) return; l = 0; for (i = 0; i < PRI_CANCEL; i++) l += c->pri[i]; if (!l) internal("detaching free connection"); if (l != 1 || c->cache->refcount) return; shrink_memory(SH_CHECK_QUOTA); c->cache->url[0] = 0; c->detached = 1; detach_done: free_entry_to(c->cache, pos);}void connection_timeout(struct connection *c){ c->timer = -1; setcstate(c, S_TIMEOUT); if (c->dnsquery) abort_connection(c); else retry_connection(c);}void connection_timeout_1(struct connection *c){ c->timer = install_timer((c->unrestartable ? unrestartable_receive_timeout : receive_timeout) * 500, (void (*)(void *))connection_timeout, c);}void set_timeout(struct connection *c){ if (c->timer != -1) kill_timer(c->timer); c->timer = install_timer((c->unrestartable ? unrestartable_receive_timeout : receive_timeout) * 500, (void (*)(void *))connection_timeout_1, c);}void reset_timeout(struct connection *c){ if (c->timer != -1) kill_timer(c->timer), c->timer = -1;}void abort_all_connections(void){ while(queue.next != &queue) { setcstate(queue.next, S_INTERRUPTED); abort_connection(queue.next); } abort_all_keepalive_connections();}void abort_background_connections(void){ int i = 0; while (1) { int j; struct connection *c = (void *)&queue; for (j = 0; j <= i; j++) if ((c = c->next) == (void *)&queue) goto brk; if (getpri(c) >= PRI_CANCEL) { setcstate(c, S_INTERRUPTED); abort_connection(c); } else i++; } brk: abort_all_keepalive_connections();}int is_entry_used(struct cache_entry *e){ struct connection *c; foreach(c, queue) if (c->cache == e) return 1; return 0;}struct blacklist_entry { struct blacklist_entry *next; struct blacklist_entry *prev; int flags; unsigned char host[1];};struct list_head blacklist = { &blacklist, &blacklist };void add_blacklist_entry(unsigned char *host, int flags){ struct blacklist_entry *b; foreach(b, blacklist) if (!strcasecmp(host, b->host)) { b->flags |= flags; return; } b = mem_alloc(sizeof(struct blacklist_entry) + strlen(host) + 1); b->flags = flags; strcpy(b->host, host); add_to_list(blacklist, b);}void del_blacklist_entry(unsigned char *host, int flags){ struct blacklist_entry *b; foreach(b, blacklist) if (!strcasecmp(host, b->host)) { b->flags &= ~flags; if (!b->flags) { del_from_list(b); mem_free(b); } return; }}int get_blacklist_flags(unsigned char *host){ struct blacklist_entry *b; foreach(b, blacklist) if (!strcasecmp(host, b->host)) return b->flags; return 0;}void free_blacklist(void){ free_list(blacklist);}struct s_msg_dsc msg_dsc[] = { {S_WAIT, TEXT(T_WAITING_IN_QUEUE)}, {S_DNS, TEXT(T_LOOKING_UP_HOST)}, {S_CONN, TEXT(T_MAKING_CONNECTION)}, {S_SOCKS_NEG, TEXT(T_SOCKS_NEGOTIATION)}, {S_SSL_NEG, TEXT(T_SSL_NEGOTIATION)}, {S_SENT, TEXT(T_REQUEST_SENT)}, {S_LOGIN, TEXT(T_LOGGING_IN)}, {S_GETH, TEXT(T_GETTING_HEADERS)}, {S_PROC, TEXT(T_SERVER_IS_PROCESSING_REQUEST)}, {S_TRANS, TEXT(T_TRANSFERRING)}, {S_WAIT_REDIR, TEXT(T_WAITING_FOR_REDIRECT_CONFIRMATION)}, {S_OK, TEXT(T_OK)}, {S_INTERRUPTED, TEXT(T_INTERRUPTED)}, {S_EXCEPT, TEXT(T_SOCKET_EXCEPTION)}, {S_INTERNAL, TEXT(T_INTERNAL_ERROR)}, {S_OUT_OF_MEM, TEXT(T_OUT_OF_MEMORY)}, {S_NO_DNS, TEXT(T_HOST_NOT_FOUND)}, {S_CANT_WRITE, TEXT(T_ERROR_WRITING_TO_SOCKET)}, {S_CANT_READ, TEXT(T_ERROR_READING_FROM_SOCKET)}, {S_MODIFIED, TEXT(T_DATA_MODIFIED)}, {S_BAD_URL, TEXT(T_BAD_URL_SYNTAX)}, {S_TIMEOUT, TEXT(T_RECEIVE_TIMEOUT)}, {S_RESTART, TEXT(T_REQUEST_MUST_BE_RESTARTED)}, {S_STATE, TEXT(T_CANT_GET_SOCKET_STATE)}, {S_CYCLIC_REDIRECT, TEXT(T_CYCLIC_REDIRECT)}, {S_LARGE_FILE, TEXT(T_TOO_LARGE_FILE)}, {S_HTTP_ERROR, TEXT(T_BAD_HTTP_RESPONSE)}, {S_HTTP_100, TEXT(T_HTTP_100)}, {S_HTTP_204, TEXT(T_NO_CONTENT)}, {S_FILE_TYPE, TEXT(T_UNKNOWN_FILE_TYPE)}, {S_FILE_ERROR, TEXT(T_ERROR_OPENING_FILE)}, {S_FTP_ERROR, TEXT(T_BAD_FTP_RESPONSE)}, {S_FTP_UNAVAIL, TEXT(T_FTP_SERVICE_UNAVAILABLE)}, {S_FTP_LOGIN, TEXT(T_BAD_FTP_LOGIN)}, {S_FTP_PORT, TEXT(T_FTP_PORT_COMMAND_FAILED)}, {S_FTP_NO_FILE, TEXT(T_FILE_NOT_FOUND)}, {S_FTP_FILE_ERROR, TEXT(T_FTP_FILE_ERROR)}, {S_SSL_ERROR, TEXT(T_SSL_ERROR)}, {S_NO_SSL, TEXT(T_NO_SSL)}, {S_BAD_SOCKS_VERSION, TEXT(T_BAD_SOCKS_VERSION)}, {S_SOCKS_REJECTED, TEXT(T_SOCKS_REJECTED_OR_FAILED)}, {S_SOCKS_NO_IDENTD, TEXT(T_SOCKS_NO_IDENTD)}, {S_SOCKS_BAD_USERID, TEXT(T_SOCKS_BAD_USERID)}, {S_SOCKS_UNKNOWN_ERROR, TEXT(T_SOCKS_UNKNOWN_ERROR)}, {S_BLOCKED_URL, TEXT(T_BLOCKED_URL)}, {S_NO_PROXY, TEXT(T_NO_PROXY)}, {S_NO_SMB_CLIENT, TEXT(T_NO_SMB_CLIENT)}, {0, NULL}};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -