/** Read the response from an outbound uping. * @param[in] pptr UPing to check. */ void uping_read(struct UPing* pptr) { struct irc_sockaddr sin; struct timeval tv; unsigned int len; unsigned int pingtime; char* s; char buf[BUFSIZE + 1]; IOResult ior; assert(0 != pptr); gettimeofday(&tv, NULL); ior = os_recvfrom_nonb(pptr->fd, buf, BUFSIZE, &len, &sin); if (IO_BLOCKED == ior) return; else if (IO_FAILURE == ior) { const char* msg = strerror(errno); if (!msg) msg = "Unknown error"; sendcmdto_one(&me, CMD_NOTICE, pptr->client, "%C :UPING: receive error: " "%s", pptr->client, msg); uping_end(pptr); return; } if (len < 19) return; /* Broken packet */ ++pptr->received; buf[len] = 0; pingtime = (tv.tv_sec - atol(&buf[1])) * 1000 + (tv.tv_usec - atol(buf + strlen(buf) + 1)) / 1000; pptr->ms_ave += pingtime; if (!pptr->ms_min || pptr->ms_min > pingtime) pptr->ms_min = pingtime; if (pingtime > pptr->ms_max) pptr->ms_max = pingtime; timer_chg(&pptr->killer, TT_RELATIVE, UPINGTIMEOUT); s = pptr->buf + strlen(pptr->buf); sprintf(s, " %u", pingtime); if (pptr->received == pptr->count) uping_end(pptr); return; }
/** Send a uping to another server. * @param[in] pptr Descriptor for uping. */ void uping_send(struct UPing* pptr) { struct timeval tv; char buf[BUFSIZE + 1]; assert(0 != pptr); if (pptr->sent == pptr->count) return; memset(buf, 0, sizeof(buf)); gettimeofday(&tv, NULL); sprintf(buf, " %10lu%c%6lu", (unsigned long)tv.tv_sec, '\0', (unsigned long)tv.tv_usec); Debug((DEBUG_SEND, "send_ping: sending [%s %s] to %s.%d on %d", buf, &buf[12], ircd_ntoa(&pptr->addr.addr), pptr->addr.port, pptr->fd)); if (os_sendto_nonb(pptr->fd, buf, BUFSIZE, NULL, 0, &pptr->addr) != IO_SUCCESS) { const char* msg = strerror(errno); if (!msg) msg = "Unknown error"; if (pptr->client) sendcmdto_one(&me, CMD_NOTICE, pptr->client, "%C :UPING: send failed: " "%s", pptr->client, msg); Debug((DEBUG_DEBUG, "UPING: send_ping: sendto failed on %d: %s", pptr->fd, msg)); uping_end(pptr); return; } ++pptr->sent; }
/** Send a uping to another server. * @param[in] pptr Descriptor for uping. */ void uping_send(struct UPing* pptr) { struct timeval tv; char buf[BUFSIZE + 1]; assert(0 != pptr); if (pptr->sent == pptr->count) return; memset(buf, 0, sizeof(buf)); gettimeofday(&tv, NULL); sprintf(buf, " %10lu%c%6lu", (long unsigned int)tv.tv_sec, '\0', tv.tv_usec); Debug((DEBUG_SEND, "send_ping: sending [%s %s] to %s.%d on %d", buf, &buf[12], ircd_ntoa((const char*) &pptr->sin.sin_addr), ntohs(pptr->sin.sin_port), pptr->fd)); if (sendto(pptr->fd, buf, BUFSIZE, 0, (struct sockaddr*) &pptr->sin, sizeof(struct sockaddr_in)) != BUFSIZE) { const char* msg = strerror(errno); if (!msg) msg = "Unknown error"; if (pptr->client) sendcmdto_one(&me, CMD_NOTICE, pptr->client, "%C :UPING: send failed: " "%s", pptr->client, msg); Debug((DEBUG_DEBUG, "UPING: send_ping: sendto failed on %d: %s", pptr->fd, msg)); uping_end(pptr); return; } ++pptr->sent; }
/** Change notifications for any upings by \a sptr. * @param[in] sptr Client to stop notifying. * @param[in] acptr New client to notify (or NULL). */ void uping_cancel(struct Client *sptr, struct Client* acptr) { struct UPing* ping; struct UPing* ping_next; Debug((DEBUG_DEBUG, "UPING: canceling uping for %s", cli_name(sptr))); for (ping = pingList; ping; ping = ping_next) { ping_next = ping->next; if (sptr == ping->client) { ping->client = acptr; uping_end(ping); } } ClearUPing(sptr); }
/** Timer callback to stop upings. * @param[in] ev Event for uping expiration. */ static void uping_killer_callback(struct Event* ev) { struct UPing *pptr; assert(0 != ev_timer(ev)); assert(0 != t_data(ev_timer(ev))); pptr = (struct UPing*) t_data(ev_timer(ev)); Debug((DEBUG_SEND, "uping_killer_callback called, %p (%d)", pptr, ev_type(ev))); if (ev_type(ev) == ET_DESTROY) { /* being destroyed */ pptr->freeable &= ~UPING_PENDING_KILLER; if (!pptr->freeable) MyFree(pptr); /* done with it, finally */ } else { assert(ev_type(ev) == ET_EXPIRE); uping_end(pptr); /* <FUDD>kill the uping, kill the uping!</FUDD> */ } }