/* * ms_ping - server message handler */ int ms_ping(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) { struct Client* acptr; char* origin; char* destination; assert(0 != cptr); assert(0 != sptr); assert(IsServer(cptr)); if (parc < 2 || EmptyString(parv[1])) { /* * don't bother sending the error back */ return 0; } origin = parv[1]; destination = parv[2]; /* Will get NULL or pointer (parc >= 2!!) */ if (parc > 3) { /* AsLL ping, send reply back */ int diff = atoi(militime_float(parv[3])); sendcmdto_one(&me, CMD_PONG, sptr, "%C %s %s %i %s", &me, origin, parv[3], diff, militime_float(NULL)); return 0; } if (!EmptyString(destination) && 0 != ircd_strcmp(destination, cli_name(&me))) { if ((acptr = FindServer(destination))) { /* * Servers can just forward the origin */ sendcmdto_one(sptr, CMD_PING, acptr, "%s :%s", origin, destination); } else { /* * this can happen if server split before the ping got here */ send_reply(sptr, ERR_NOSUCHSERVER, destination); } } else { /* * send pong back * NOTE: sptr is never local so if pong handles numerics everywhere we * could send a numeric here. */ sendcmdto_one(&me, CMD_PONG, sptr, "%C :%s", &me, origin); } return 0; }
/* PONG */ void nefarious_cmd_pong(char *servname, char *who) { char *t, *s; uint32 ts, tsnow, value; t = myStrGetToken(who, '!', 1); s = myStrGetToken(t, '.', 0); if (!s) { ts = 0; } else { ts = strtol(s, NULL, 10); } tsnow = time(NULL); value = tsnow - ts; if (denora->protocoldebug) { alog(LOG_PROTOCOL, "PONG: Server Name %s : Who %s", servname, who); } send_cmd(p10id, "Z %s %ld %ld %ld %s", p10id, (long int) ts, (long int) tsnow, (long int) value, militime_float(NULL)); if (s) { free(s); } if (t) { free(t); } }
/* * ms_pong - server message handler * * parv[0] = sender prefix * parv[1] = origin * parv[2] = destination */ int ms_pong(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) { char* origin; char* destination; assert(0 != cptr); assert(0 != sptr); assert(IsServer(cptr)); if (parc < 2 || EmptyString(parv[1])) { return protocol_violation(sptr,"No Origin on PONG"); } origin = parv[1]; destination = parv[2]; ClearPingSent(cptr); ClearPingSent(sptr); cli_lasttime(cptr) = CurrentTime; if (parc > 5) { /* AsLL pong */ cli_serv(cptr)->asll_rtt = atoi(militime_float(parv[3])); cli_serv(cptr)->asll_to = atoi(parv[4]); cli_serv(cptr)->asll_from = atoi(militime_float(parv[5])); cli_serv(cptr)->asll_last = CurrentTime; return 0; } if (EmptyString(destination)) return 0; if (*destination == '!') { /* AsLL ping reply from a non-AsLL server */ cli_serv(cptr)->asll_rtt = atoi(militime_float(destination + 1)); } else if (0 != ircd_strcmp(destination, cli_name(&me))) { struct Client* acptr; if ((acptr = FindClient(destination))) sendcmdto_one(sptr, CMD_PONG, acptr, "%s %s", origin, destination); } return 0; }
/* AB Z AB 1116103763 1116103763 0 1116103763.867010 */ void asuka_cmd_pong(char *servname, char *who) { char *t, *s; uint32 ts, tsnow, value; SET_SEGV_LOCATION(); t = myStrGetToken(who, '!', 1); s = myStrGetToken(t, '.', 0); if (!s) { ts = 0; alog(LOG_NORMAL, "This is an error, you should report this as a problem"); alog(LOG_NORMAL, "Server Name %s : Who %s", servname, who); } else { ts = strtol(s, NULL, 10); } tsnow = time(NULL); value = tsnow - ts; SET_SEGV_LOCATION(); if (denora->protocoldebug) { alog(LOG_PROTOCOL, "PONG: Server Name %s : Who %s", servname, who); } send_cmd(p10id, "Z %s %ld %ld %ld %s", p10id, (long int) ts, (long int) tsnow, (long int) value, militime_float(NULL)); SET_SEGV_LOCATION(); if (s) { free(s); } if (t) { free(t); } }
void asuka_cmd_ping(char *server) { /* AB G !1115872042.64217 denora.nomadirc.net 1115872042.64217 */ send_cmd(p10id, "G !%s %s %s", militime_float(NULL), server, militime_float(NULL)); }
/** Check for clients that have not sent a ping response recently. * Reschedules itself to run again at the appropriate time. * @param[in] ev Timer event (ignored). */ static void check_pings(struct Event* ev) { int expire = 0; int next_check = CurrentTime; int max_ping = 0; int i; assert(ET_EXPIRE == ev_type(ev)); assert(0 != ev_timer(ev)); next_check += feature_int(FEAT_PINGFREQUENCY); /* Scan through the client table */ for (i=0; i <= HighestFd; i++) { struct Client *cptr = LocalClientArray[i]; if (!cptr) continue; assert(&me != cptr); /* I should never be in the local client array! */ /* Remove dead clients. */ if (IsDead(cptr)) { exit_client(cptr, cptr, &me, cli_info(cptr)); continue; } max_ping = IsRegistered(cptr) ? client_get_ping(cptr) : feature_int(FEAT_CONNECTTIMEOUT); Debug((DEBUG_DEBUG, "check_pings(%s)=status:%s limit: %d current: %d", cli_name(cptr), IsPingSent(cptr) ? "[Ping Sent]" : "[]", max_ping, (int)(CurrentTime - cli_lasttime(cptr)))); /* If it's a server and we have not sent an AsLL lately, do so. */ if (IsServer(cptr)) { if (CurrentTime - cli_serv(cptr)->asll_last >= max_ping) { char *asll_ts; SetPingSent(cptr); cli_serv(cptr)->asll_last = CurrentTime; expire = cli_serv(cptr)->asll_last + max_ping; asll_ts = militime_float(NULL); sendcmdto_prio_one(&me, CMD_PING, cptr, "!%s %s %s", asll_ts, cli_name(cptr), asll_ts); } expire = cli_serv(cptr)->asll_last + max_ping; if (expire < next_check) next_check = expire; } /* Ok, the thing that will happen most frequently, is that someone will * have sent something recently. Cover this first for speed. * -- * If it's an unregistered client and hasn't managed to register within * max_ping then it's obviously having problems (broken client) or it's * just up to no good, so we won't skip it, even if its been sending * data to us. * -- hikari */ if ((CurrentTime-cli_lasttime(cptr) < max_ping) && IsRegistered(cptr)) { expire = cli_lasttime(cptr) + max_ping; if (expire < next_check) next_check = expire; continue; } /* Unregistered clients pingout after max_ping seconds, they don't * get given a second chance - if they were then people could not quite * finish registration and hold resources without being subject to k/g * lines */ if (!IsRegistered(cptr)) { assert(!IsServer(cptr)); /* If client authorization time has expired, ask auth whether they * should be checked again later. */ if ((CurrentTime-cli_firsttime(cptr) >= max_ping) && auth_ping_timeout(cptr)) continue; /* OK, they still have enough time left, so we'll just skip to the * next client. Set the next check to be when their time is up, if * that's before the currently scheduled next check -- hikari */ expire = cli_firsttime(cptr) + max_ping; if (expire < next_check) next_check = expire; continue; } /* Quit the client after max_ping*2 - they should have answered by now */ if (CurrentTime-cli_lasttime(cptr) >= (max_ping*2) ) { /* If it was a server, then tell ops about it. */ if (IsServer(cptr) || IsConnecting(cptr) || IsHandshake(cptr)) sendto_opmask_butone(0, SNO_OLDSNO, "No response from %s, closing link", cli_name(cptr)); exit_client_msg(cptr, cptr, &me, "Ping timeout"); continue; } if (!IsPingSent(cptr)) { /* If we haven't PINGed the connection and we haven't heard from it in a * while, PING it to make sure it is still alive. */ SetPingSent(cptr); /* If we're late in noticing don't hold it against them :) */ cli_lasttime(cptr) = CurrentTime - max_ping; if (IsUser(cptr)) sendrawto_one(cptr, MSG_PING " :%s", cli_name(&me)); else sendcmdto_prio_one(&me, CMD_PING, cptr, ":%s", cli_name(&me)); } expire = cli_lasttime(cptr) + max_ping * 2; if (expire < next_check) next_check=expire; } assert(next_check >= CurrentTime); Debug((DEBUG_DEBUG, "[%i] check_pings() again in %is", CurrentTime, next_check-CurrentTime)); timer_add(&ping_timer, check_pings, 0, TT_ABSOLUTE, next_check); }