/* * findpeer - find and return a peer match for a received datagram in * the peer_hash table. */ struct peer * findpeer( struct recvbuf *rbufp, int pkt_mode, int * action ) { struct peer * p; sockaddr_u * srcadr; u_int hash; struct pkt * pkt; l_fp pkt_org; findpeer_calls++; srcadr = &rbufp->recv_srcadr; hash = NTP_HASH_ADDR(srcadr); for (p = peer_hash[hash]; p != NULL; p = p->adr_link) { if (ADDR_PORT_EQ(srcadr, &p->srcadr)) { /* * if the association matching rules determine * that this is not a valid combination, then * look for the next valid peer association. */ *action = MATCH_ASSOC(p->hmode, pkt_mode); /* * A response to our manycastclient solicitation * might be misassociated with an ephemeral peer * already spun for the server. If the packet's * org timestamp doesn't match the peer's, check * if it matches the ACST prototype peer's. If * so it is a redundant solicitation response, * return AM_ERR to discard it. [Bug 1762] */ if (MODE_SERVER == pkt_mode && AM_PROCPKT == *action) { pkt = &rbufp->recv_pkt; NTOHL_FP(&pkt->org, &pkt_org); if (!L_ISEQU(&p->aorg, &pkt_org) && findmanycastpeer(rbufp)) *action = AM_ERR; } /* * if an error was returned, exit back right * here. */ if (*action == AM_ERR) return NULL; /* * if a match is found, we stop our search. */ if (*action != AM_NOMATCH) break; } } /* * If no matching association is found */ if (NULL == p) { *action = MATCH_ASSOC(NO_PEER, pkt_mode); } else if (p->dstadr != rbufp->dstadr) { set_peerdstadr(p, rbufp->dstadr); if (p->dstadr == rbufp->dstadr) { DPRINTF(1, ("Changed %s local address to match response\n", stoa(&p->srcadr))); return findpeer(rbufp, pkt_mode, action); } } return p; }
void Server::process(char *prefix, char *command, char *params[], int nparams, char *trailing) { if(!strcmp(command, "PRIVMSG") && prefix) { Source s; s.server = this; s.client = client; s.peer = findpeer(stripident(prefix)); int l = strlen(trailing); bool is_action = false; if(*trailing == 1 && trailing[l - 1] == 1 && !strncmp(trailing + 1, "ACTION", 6)) { trailing[l - 1] = 0; is_action = true; } if(is_chan(params[0])) { s.channel = findchan(params[0]); if(is_action) { if(client->channel_action_message_cb) client->channel_action_message_cb(&s, trailing + 8); } else if(client->channel_message_cb) client->channel_message_cb(&s, trailing); } else { s.channel = NULL; if(is_action) { if(client->private_action_message_cb) client->private_action_message_cb(&s, trailing + 8); } else if(client->channel_message_cb) client->private_message_cb(&s, trailing); } } else if(!strcmp(command, "NOTICE")) { if(client->notice_cb) client->notice_cb(this, prefix, trailing); } else if(!strcmp(command, "NICK")) { changenick(prefix, trailing); } else if(!strcmp(command, "PART")) { if(nparams >= 1) { Channel *c = findchan(params[0]); if(c) { Source s; s.server = this; s.client = client; s.peer = findpeer(stripident(prefix)); s.channel = c; c->peerpart(prefix); if(client->part_cb) client->part_cb(&s, trailing); } } } else if(!strcmp(command, "JOIN")) { Channel *c = findchan(trailing); if(!c && nparams >= 1) c = findchan(params[0]); if(c) { Source s; s.server = this; s.client = client; s.peer = findpeer(stripident(prefix)); s.channel = c; c->peerjoin(stripident(prefix)); if(client->join_cb) client->join_cb(&s); } } else if(!strcmp(command, "QUIT")) { for(unsigned int i = 0; i < peers.size(); i++) { if(!strcmp(peers[i]->nick, stripident(prefix))) { for(unsigned int j = 0; j < channels.size(); j++) { Channel *c = channels[j]; for(unsigned int k = 0; k < c->peers.size(); k++) { if(c->peers[k]->peer == peers[i]) { c->peers.erase(c->peers.begin() + k); break; } } } delete peers[i]; peers.erase(peers.begin() + i); break; } } } else if(!strcmp(command, "PING")) { if(trailing) DEBUGF(bufferevent_write_printf(buf, "PONG %s\r\n", trailing)) else DEBUGF(bufferevent_write_printf(buf, "PONG\r\n")); if(client->ping_cb) client->ping_cb(this, NULL, trailing); } else if(isdigit(*command)) {