Пример #1
0
/*
 * 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;
}
Пример #2
0
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)) {