/** Report connection classes to a client. * @param[in] sptr Client requesting statistics. * @param[in] sd Stats descriptor for request (ignored). * @param[in] param Extra parameter from user (ignored). */ void report_classes(struct Client *sptr, const struct StatDesc *sd, char *param) { struct ConnectionClass *cltmp; for (cltmp = connClassList; cltmp; cltmp = cltmp->next) send_reply(sptr, RPL_STATSYLINE, (cltmp->valid ? 'Y' : 'y'), ConClass(cltmp), PingFreq(cltmp), ConFreq(cltmp), MaxLinks(cltmp), MaxSendq(cltmp), Links(cltmp) - 1); }
/** Unlink (and dereference) invalid connection classes. * This is used in combination with class_mark_delete() during rehash * to get rid of connection classes that are no longer in the * configuration. */ void class_delete_marked(void) { struct ConnectionClass* cl; struct ConnectionClass* prev; Debug((DEBUG_DEBUG, "Class check:")); for (prev = cl = connClassList; cl; cl = prev->next) { Debug((DEBUG_DEBUG, "Class %s : CF: %d PF: %d ML: %d LI: %d SQ: %d", ConClass(cl), ConFreq(cl), PingFreq(cl), MaxLinks(cl), Links(cl), MaxSendq(cl))); /* * unlink marked classes, delete unreferenced ones */ if (cl->valid || Links(cl) > 1) prev = cl; else { prev->next = cl->next; free_class(cl); } } }
/** Initialize the connection class list. * A connection class named "default" is created, with ping frequency, * connection frequency, maximum links and max SendQ values from the * corresponding configuration features. */ void init_class(void) { if (!connClassList) { connClassList = (struct ConnectionClass*) make_class(); connClassList->next = 0; } /* We had better not try and free this... */ ConClass(connClassList) = "default"; PingFreq(connClassList) = feature_int(FEAT_PINGFREQUENCY); ConFreq(connClassList) = feature_int(FEAT_CONNECTFREQUENCY); MaxLinks(connClassList) = feature_int(FEAT_MAXIMUM_LINKS); MaxSendq(connClassList) = feature_uint(FEAT_DEFAULTMAXSENDQLENGTH); connClassList->valid = 1; Links(connClassList) = 1; }
void UEdGraphSchema_BehaviorTreeDecorator::GetBreakLinkToSubMenuActions( class FMenuBuilder& MenuBuilder, UEdGraphPin* InGraphPin ) { // Make sure we have a unique name for every entry in the list TMap< FString, uint32 > LinkTitleCount; // Add all the links we could break from for(TArray<class UEdGraphPin*>::TConstIterator Links(InGraphPin->LinkedTo); Links; ++Links) { UEdGraphPin* Pin = *Links; FString TitleString = Pin->GetOwningNode()->GetNodeTitle(ENodeTitleType::ListView).ToString(); FText Title = FText::FromString( TitleString ); if ( Pin->PinName != TEXT("") ) { TitleString = FString::Printf(TEXT("%s (%s)"), *TitleString, *Pin->PinName); // Add name of connection if possible FFormatNamedArguments Args; Args.Add( TEXT("NodeTitle"), Title ); Args.Add( TEXT("PinName"), Pin->GetDisplayName() ); Title = FText::Format( LOCTEXT("BreakDescPin", "{NodeTitle} ({PinName})"), Args ); } uint32 &Count = LinkTitleCount.FindOrAdd( TitleString ); FText Description; FFormatNamedArguments Args; Args.Add( TEXT("NodeTitle"), Title ); Args.Add( TEXT("NumberOfNodes"), Count ); if ( Count == 0 ) { Description = FText::Format( LOCTEXT("BreakDesc", "Break link to {NodeTitle}"), Args ); } else { Description = FText::Format( LOCTEXT("BreakDescMulti", "Break link to {NodeTitle} ({NumberOfNodes})"), Args ); } ++Count; MenuBuilder.AddMenuEntry( Description, Description, FSlateIcon(), FUIAction( FExecuteAction::CreateUObject((USoundClassGraphSchema*const)this, &USoundClassGraphSchema::BreakSinglePinLink, const_cast< UEdGraphPin* >(InGraphPin), *Links) ) ); } }
/* ** 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); }
static void do_trace(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) { int i; struct Client *acptr; struct Client *acptr2; const struct ConnectionClass* cl; char* tname; int doall; int *link_s; int *link_u; int cnt = 0; int wilds; int dow; if (parc < 2 || BadPtr(parv[1])) { /* just "TRACE" without parameters. Must be from local client */ parc = 1; acptr = &me; tname = cli_name(&me); i = HUNTED_ISME; } else if (parc < 3 || BadPtr(parv[2])) { /* No target specified. Make one before propagating. */ parc = 2; tname = parv[1]; if ((acptr = find_match_server(parv[1])) || ((acptr = FindClient(parv[1])) && !MyUser(acptr))) { if (IsUser(acptr)) parv[2] = cli_name(cli_user(acptr)->server); else parv[2] = cli_name(acptr); parc = 3; parv[3] = 0; if ((i = hunt_server_cmd(sptr, CMD_TRACE, cptr, IsServer(acptr), "%s :%C", 2, parc, parv)) == HUNTED_NOSUCH) return; } else i = HUNTED_ISME; } else { /* Got "TRACE <tname> :<target>" */ parc = 3; if (MyUser(sptr) || Protocol(cptr) < 10) acptr = find_match_server(parv[2]); else acptr = FindNServer(parv[2]); if ((i = hunt_server_cmd(sptr, CMD_TRACE, cptr, 0, "%s :%C", 2, parc, parv)) == HUNTED_NOSUCH) return; tname = parv[1]; } if (i == HUNTED_PASS) { if (!acptr) acptr = next_client(GlobalClientList, tname); else acptr = cli_from(acptr); send_reply(sptr, RPL_TRACELINK, version, debugmode, tname, acptr ? cli_name(cli_from(acptr)) : "<No_match>"); return; } doall = (parv[1] && (parc > 1)) ? !match(tname, cli_name(&me)) : 1; wilds = !parv[1] || strchr(tname, '*') || strchr(tname, '?'); dow = wilds || doall; /* Don't give (long) remote listings to lusers */ if (dow && !MyConnect(sptr) && !IsAnOper(sptr)) { send_reply(sptr, RPL_TRACEEND); return; } link_s = MyCalloc(2 * maxconnections, sizeof(link_s[0])); link_u = link_s + maxconnections; if (doall) { for (acptr = GlobalClientList; acptr; acptr = cli_next(acptr)) { if (IsUser(acptr)) link_u[cli_fd(cli_from(acptr))]++; else if (IsServer(acptr)) link_s[cli_fd(cli_from(acptr))]++; } } /* report all direct connections */ for (i = 0; i <= HighestFd; i++) { const char *conClass; if (!(acptr = LocalClientArray[i])) /* Local Connection? */ continue; if (IsInvisible(acptr) && dow && !(MyConnect(sptr) && IsOper(sptr)) && !IsAnOper(acptr) && (acptr != sptr)) continue; if (!doall && wilds && match(tname, cli_name(acptr))) continue; if (!dow && 0 != ircd_strcmp(tname, cli_name(acptr))) continue; conClass = get_client_class(acptr); switch (cli_status(acptr)) { case STAT_CONNECTING: send_reply(sptr, RPL_TRACECONNECTING, conClass, cli_name(acptr)); cnt++; break; case STAT_HANDSHAKE: send_reply(sptr, RPL_TRACEHANDSHAKE, conClass, cli_name(acptr)); cnt++; break; case STAT_ME: break; case STAT_UNKNOWN: case STAT_UNKNOWN_USER: send_reply(sptr, RPL_TRACEUNKNOWN, conClass, get_client_name(acptr, HIDE_IP)); cnt++; break; case STAT_UNKNOWN_SERVER: send_reply(sptr, RPL_TRACEUNKNOWN, conClass, "Unknown Server"); cnt++; break; case STAT_USER: /* Only opers see users if there is a wildcard but anyone can see all the opers. */ if ((IsAnOper(sptr) && (MyUser(sptr) || !(dow && IsInvisible(acptr)))) || !dow || IsAnOper(acptr)) { if (IsAnOper(acptr)) send_reply(sptr, RPL_TRACEOPERATOR, conClass, get_client_name(acptr, SHOW_IP), CurrentTime - cli_lasttime(acptr)); else send_reply(sptr, RPL_TRACEUSER, conClass, get_client_name(acptr, SHOW_IP), CurrentTime - cli_lasttime(acptr)); cnt++; } break; /* * Connection is a server * * Serv <class> <nS> <nC> <name> <ConnBy> <last> <age> * * class Class the server is in * nS Number of servers reached via this link * nC Number of clients reached via this link * name Name of the server linked * ConnBy Who established this link * last Seconds since we got something from this link * age Seconds this link has been alive * * Additional comments etc...... -Cym-<*****@*****.**> */ case STAT_SERVER: if (cli_serv(acptr)->user) { if (!cli_serv(acptr)->by[0] || !(acptr2 = findNUser(cli_serv(acptr)->by)) || (cli_user(acptr2) != cli_serv(acptr)->user)) acptr2 = NULL; send_reply(sptr, RPL_TRACESERVER, conClass, link_s[i], link_u[i], cli_name(acptr), acptr2 ? cli_name(acptr2) : "*", cli_serv(acptr)->user->username, cli_serv(acptr)->user->host, CurrentTime - cli_lasttime(acptr), CurrentTime - cli_serv(acptr)->timestamp); } else send_reply(sptr, RPL_TRACESERVER, conClass, link_s[i], link_u[i], cli_name(acptr), (*(cli_serv(acptr))->by) ? cli_serv(acptr)->by : "*", "*", cli_name(&me), CurrentTime - cli_lasttime(acptr), CurrentTime - cli_serv(acptr)->timestamp); cnt++; break; default: /* We actually shouldn't come here, -msa */ send_reply(sptr, RPL_TRACENEWTYPE, get_client_name(acptr, HIDE_IP)); cnt++; break; } } /* * Add these lines to summarize the above which can get rather long * and messy when done remotely - Avalon */ if (IsAnOper(sptr) && doall) { for (cl = get_class_list(); cl; cl = cl->next) { if (Links(cl) > 1) send_reply(sptr, RPL_TRACECLASS, ConClass(cl), Links(cl) - 1); } } send_reply(sptr, RPL_TRACEEND); MyFree(link_s); }
/* * 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); }