Browse Source

Do not multicast to self.

Adam Ierymenko 10 years ago
parent
commit
3f7e7e8a88
3 changed files with 22 additions and 13 deletions
  1. 2 2
      node/IncomingPacket.cpp
  2. 18 10
      node/Multicaster.cpp
  3. 2 1
      node/Multicaster.hpp

+ 2 - 2
node/IncomingPacket.cpp

@@ -925,7 +925,7 @@ bool IncomingPacket::_doMULTICAST_GATHER(const RuntimeEnvironment *RR,const Shar
 			outp.append(nwid);
 			mg.mac().appendTo(outp);
 			outp.append((uint32_t)mg.adi());
-			if (RR->mc->gather(RR,nwid,mg,outp,gatherLimit)) {
+			if (RR->mc->gather(RR,peer->address(),nwid,mg,outp,gatherLimit)) {
 				outp.armor(peer->key(),true);
 				_fromSock->send(_remoteAddress,outp.data(),outp.size());
 			}
@@ -1003,7 +1003,7 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,const Share
 					to.mac().appendTo(outp);
 					outp.append((uint32_t)to.adi());
 					outp.append((unsigned char)0x01); // flag 0x01 = contains gather results
-					if (RR->mc->gather(RR,nwid,to,outp,gatherLimit)) {
+					if (RR->mc->gather(RR,peer->address(),nwid,to,outp,gatherLimit)) {
 						outp.armor(peer->key(),true);
 						_fromSock->send(_remoteAddress,outp.data(),outp.size());
 					}

+ 18 - 10
node/Multicaster.cpp

@@ -49,10 +49,10 @@ Multicaster::~Multicaster()
 {
 }
 
-unsigned int Multicaster::gather(const RuntimeEnvironment *RR,uint64_t nwid,MulticastGroup &mg,Packet &appendTo,unsigned int limit) const
+unsigned int Multicaster::gather(const RuntimeEnvironment *RR,const Address &queryingPeer,uint64_t nwid,MulticastGroup &mg,Packet &appendTo,unsigned int limit) const
 {
 	unsigned char *p;
-	unsigned int n = 0,i,rptr;
+	unsigned int n = 0,i,rptr,skipped = 0;
 	uint64_t a,done[(ZT_PROTO_MAX_PACKET_LENGTH / 5) + 1];
 
 	Mutex::Lock _l(_groups_m);
@@ -90,16 +90,20 @@ restart_member_scan:
 		// Log that we've picked this one
 		done[n++] = a;
 
-		// Append to packet
-		p = (unsigned char *)appendTo.appendField(ZT_ADDRESS_LENGTH);
-		*(p++) = (unsigned char)((a >> 32) & 0xff);
-		*(p++) = (unsigned char)((a >> 24) & 0xff);
-		*(p++) = (unsigned char)((a >> 16) & 0xff);
-		*(p++) = (unsigned char)((a >> 8) & 0xff);
-		*p = (unsigned char)(a & 0xff);
+		if (queryingPeer.toInt() == a) {
+			++skipped;
+		} else {
+			// Append to packet
+			p = (unsigned char *)appendTo.appendField(ZT_ADDRESS_LENGTH);
+			*(p++) = (unsigned char)((a >> 32) & 0xff);
+			*(p++) = (unsigned char)((a >> 24) & 0xff);
+			*(p++) = (unsigned char)((a >> 16) & 0xff);
+			*(p++) = (unsigned char)((a >> 8) & 0xff);
+			*p = (unsigned char)(a & 0xff);
+		}
 	}
 
-	appendTo.setAt(nAt,(uint16_t)n);
+	appendTo.setAt(nAt,(uint16_t)(n - skipped));
 
 	return n;
 }
@@ -249,6 +253,10 @@ void Multicaster::_add(uint64_t now,uint64_t nwid,MulticastGroupStatus &gs,const
 {
 	// assumes _groups_m is locked
 
+	// Do not add self -- even if someone else returns it
+	if (member == RR->identity.address())
+		return;
+
 	// Update timestamp and learnedFrom if existing
 	for(std::vector<MulticastGroupMember>::iterator m(gs.members.begin());m!=gs.members.end();++m) {
 		if (m->address == member) {

+ 2 - 1
node/Multicaster.hpp

@@ -109,6 +109,7 @@ public:
 	 * If zero is returned, the first two fields will still have been appended.
 	 *
 	 * @param RR Runtime environment
+	 * @param queryingPeer Peer asking for gather (to skip in results)
 	 * @param nwid Network ID
 	 * @param mg Multicast group
 	 * @param appendTo Packet to append to
@@ -116,7 +117,7 @@ public:
 	 * @return Number of addresses appended
 	 * @throws std::out_of_range Buffer overflow writing to packet
 	 */
-	unsigned int gather(const RuntimeEnvironment *RR,uint64_t nwid,MulticastGroup &mg,Packet &appendTo,unsigned int limit) const;
+	unsigned int gather(const RuntimeEnvironment *RR,const Address &queryingPeer,uint64_t nwid,MulticastGroup &mg,Packet &appendTo,unsigned int limit) const;
 
 	/**
 	 * Send a multicast