/* ** try_connections ** ** Scan through configuration and try new connections. ** Returns the calendar time when the next call to this ** function should be made latest. (No harm done if this ** is called earlier or later...) */ static time_t try_connections(time_t currenttime) { Reg aConfItem *aconf; Reg aClient *cptr; aConfItem **pconf; int confrq; time_t next = 0; aClass *cltmp; aConfItem *con_conf = NULL; int allheld = 1; #ifdef DISABLE_DOUBLE_CONNECTS int i; #endif if ((bootopt & BOOT_STANDALONE)) return 0; Debug((DEBUG_NOTICE,"Connection check at : %s", myctime(currenttime))); for (aconf = conf; aconf; aconf = aconf->next ) { /* not a C-line */ if (!(aconf->status & (CONF_CONNECT_SERVER|CONF_ZCONNECT_SERVER))) continue; /* not a candidate for AC */ if (aconf->port <= 0) continue; cltmp = Class(aconf); /* not a candidate for AC */ if (MaxLinks(cltmp) == 0) continue; /* minimize next to lowest hold time of all AC-able C-lines */ if (next > aconf->hold || next == 0) next = aconf->hold; /* skip conf if the use of it is on hold until future. */ if (aconf->hold > currenttime) continue; /* at least one candidate not held for future, good */ allheld = 0; /* see if another link in this conf is allowed */ if (Links(cltmp) >= MaxLinks(cltmp)) continue; /* next possible check after connfreq secs for this C-line */ confrq = get_con_freq(cltmp); aconf->hold = currenttime + confrq; /* is this server already connected? */ cptr = find_name(aconf->name, (aClient *)NULL); if (!cptr) cptr = find_mask(aconf->name, (aClient *)NULL); /* matching client already exists, no AC to it */ if (cptr) continue; /* no such server, check D-lines */ if (find_denied(aconf->name, Class(cltmp))) continue; #ifdef DISABLE_DOUBLE_CONNECTS /* Much better would be traversing only unknown ** connections, but this requires another global ** variable, adding and removing from there in ** proper places etc. Some day. --B. */ for (i = highest_fd; i >= 0; i--) { if (!(cptr = local[i]) || cptr->status > STAT_UNKNOWN) { continue; } /* an unknown traveller we have */ if ( #ifndef INET6 cptr->ip.s_addr == aconf->ipnum.s_addr #else !memcmp(cptr->ip.s6_addr, aconf->ipnum.s6_addr, 16) #endif ) { /* IP the same. Coincidence? Maybe. ** Do not cause havoc with double connect. */ break; } cptr = NULL; } if (cptr) { sendto_flag(SCH_SERVER, "AC to %s postponed", aconf->name); continue; } #endif /* we have a candidate! */ /* choose the best. */ if (!con_conf || (con_conf->pref > aconf->pref && aconf->pref >= 0) || (con_conf->pref == -1 && Class(cltmp) > ConfClass(con_conf))) { con_conf = aconf; } /* above is my doubt: if we always choose best connection ** and it always fails connecting, we may never try another, ** even "worse"; what shall we do? --Beeth */ } if (con_conf) { if (con_conf->next) /* are we already last? */ { for (pconf = &conf; (aconf = *pconf); pconf = &(aconf->next)) /* put the current one at the end and * make sure we try all connections */ if (aconf == con_conf) *pconf = aconf->next; (*pconf = con_conf)->next = 0; } /* "Penalty" for being the best, so in next call of * try_connections() other servers have chance. --B. */ con_conf->hold += get_con_freq(Class(con_conf)); if (!iconf.aconnect) { sendto_flag(SCH_NOTICE, "Connection to %s deferred. Autoconnect " "administratively disabled", con_conf->name); } else if (connect_server(con_conf, (aClient *)NULL, (struct hostent *)NULL) == 0) { sendto_flag(SCH_NOTICE, "Connection to %s[%s] activated.", con_conf->name, con_conf->host); } } else if (allheld == 0) /* disable AC only when some C: got checked */ { /* No suitable conf for AC was found, so why bother checking ** again? If some server quits, it'd get reenabled --B. */ next = 0; } Debug((DEBUG_NOTICE,"Next connection check : %s", myctime(next))); return (next); }
/* * try_connections * * Scan through configuration and try new connections. * Returns the calendar time when the next call to this * function should be made latest. (No harm done if this * is called earlier or later...) */ static time_t try_connections(time_t currenttime) { aConfItem *aconf, **pconf, *con_conf = (aConfItem *) NULL; aClient *cptr; aClass *cltmp; int connecting, confrq, con_class = 0; time_t next = 0; connecting = FALSE; Debug((DEBUG_NOTICE, "Connection check at : %s", myctime(currenttime))); for (aconf = conf; aconf; aconf = aconf->next) { /* Also when already connecting! (update holdtimes) --SRB */ if (!(aconf->status & CONF_CONNECT_SERVER) || aconf->port <= 0) continue; cltmp = Class (aconf); /* * * Skip this entry if the use of it is still on hold until * future. Otherwise handle this entry (and set it on hold * until next time). Will reset only hold times, if already * made one successfull connection... [this algorithm is a bit * fuzzy... -- msa >;) ] */ if ((aconf->hold > currenttime)) { if ((next > aconf->hold) || (next == 0)) next = aconf->hold; continue; } confrq = get_con_freq(cltmp); aconf->hold = currenttime + confrq; /* Found a CONNECT config with port specified, scan clients * and see if this server is already connected? */ cptr = find_name(aconf->name, (aClient *) NULL); if (!cptr && (Links(cltmp) < MaxLinks(cltmp)) && (!connecting || (Class (cltmp) > con_class))) { con_class = Class (cltmp); con_conf = aconf; /* We connect only one at time... */ connecting = TRUE; } if ((next > aconf->hold) || (next == 0)) next = aconf->hold; } if (connecting) { if (con_conf->next) /* are we already last? */ { for (pconf = &conf; (aconf = *pconf); pconf = &(aconf->next)) /* * put the current one at the end and make sure we try all * connections */ if (aconf == con_conf) *pconf = aconf->next; (*pconf = con_conf)->next = 0; } if (connect_server(con_conf, (aClient *) NULL, (struct hostent *) NULL) == 0) sendto_gnotice("from %s: Connection to %s activated.", me.name, con_conf->name); } Debug((DEBUG_NOTICE, "Next connection check : %s", myctime(next))); return (next); }