Fixes to legacy peer support.

This commit is contained in:
Adam Ierymenko 2014-10-11 15:49:31 -07:00
parent a9c6913f12
commit c2aac69a9f
3 changed files with 45 additions and 46 deletions

View file

@ -604,26 +604,29 @@ bool IncomingPacket::_doP5_MULTICAST_FRAME(const RuntimeEnvironment *RR,const Sh
peer->receive(RR,_fromSock,_remoteAddress,hops(),packetId(),Packet::VERB_P5_MULTICAST_FRAME,0,Packet::VERB_NOP,Utils::now()); peer->receive(RR,_fromSock,_remoteAddress,hops(),packetId(),Packet::VERB_P5_MULTICAST_FRAME,0,Packet::VERB_NOP,Utils::now());
if (RR->topology->amSupernode()) { if (RR->topology->amSupernode()) {
std::vector<Address> legacyPeers(RR->mc->getLegacySubscribers(nwid,dest)); // To support legacy peers, old fashioned "P5" multicasts are propagated manually by supernodes.
// If the sending peer is >=1.0.0, they only go to legacy peers. Otherwise they go to all
// peers.
const unsigned int limit = 128; // use a fairly generous limit since we want legacy peers to always work until they go away
const bool senderIsLegacy = (peer->remoteVersionMajor() < 1);
std::vector<Address> members(RR->mc->getMembers(nwid,dest,limit));
setAt(ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_PROPAGATION_DEPTH,(uint16_t)0xffff); setAt(ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_PROPAGATION_DEPTH,(uint16_t)0xffff);
setSource(RR->identity.address()); setSource(RR->identity.address());
compress(); compress();
for(std::vector<Address>::iterator lp(members.begin());lp!=members.end();++lp) {
unsigned int count = 0; SharedPtr<Peer> lpp(RR->topology->getPeer(*lp));
for(std::vector<Address>::iterator lp(legacyPeers.begin());lp!=legacyPeers.end();++lp) { if ( (*lp != origin) && (*lp != peer->address()) && ((senderIsLegacy) || (!lpp) || (lpp->remoteVersionMajor() < 1)) ) {
if ((*lp != origin)&&(*lp != source())) {
newInitializationVector(); newInitializationVector();
setDestination(*lp); setDestination(*lp);
RR->sw->send(*this,true); RR->sw->send(*this,true);
if (++count >= 128) // harded-coded sanity limit for these legacy nodes }
break;
} }
} }
return true; SharedPtr<Network> network(RR->nc->network(nwid));
} else {
SharedPtr<Network> network(RR->nc->network(nwid)); // will be NULL if not a member
if (network) { if (network) {
if ((flags & ZT_PROTO_VERB_P5_MULTICAST_FRAME_FLAGS_HAS_MEMBERSHIP_CERTIFICATE)) { if ((flags & ZT_PROTO_VERB_P5_MULTICAST_FRAME_FLAGS_HAS_MEMBERSHIP_CERTIFICATE)) {
CertificateOfMembership com; CertificateOfMembership com;
@ -637,7 +640,7 @@ bool IncomingPacket::_doP5_MULTICAST_FRAME(const RuntimeEnvironment *RR,const Sh
return true; return true;
} }
if (frameLen) { if ((frameLen > 0)&&(frameLen <= 2800)) {
if (!dest.mac().isMulticast()) if (!dest.mac().isMulticast())
return true; return true;
if ((!sourceMac)||(sourceMac.isMulticast())||(sourceMac == network->mac())) if ((!sourceMac)||(sourceMac.isMulticast())||(sourceMac == network->mac()))
@ -651,7 +654,6 @@ bool IncomingPacket::_doP5_MULTICAST_FRAME(const RuntimeEnvironment *RR,const Sh
network->tapPut(sourceMac,dest.mac(),etherType,frame,frameLen); network->tapPut(sourceMac,dest.mac(),etherType,frame,frameLen);
} }
} }
}
} catch (std::exception &ex) { } catch (std::exception &ex) {
TRACE("dropped P5_MULTICAST_FRAME from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),ex.what()); TRACE("dropped P5_MULTICAST_FRAME from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),ex.what());
} catch ( ... ) { } catch ( ... ) {

View file

@ -118,21 +118,18 @@ restart_member_scan:
return added; return added;
} }
std::vector<Address> Multicaster::getLegacySubscribers(uint64_t nwid,const MulticastGroup &mg) const std::vector<Address> Multicaster::getMembers(uint64_t nwid,const MulticastGroup &mg,unsigned int limit) const
{ {
std::vector<Address> ls; std::vector<Address> ls;
Mutex::Lock _l(_groups_m); Mutex::Lock _l(_groups_m);
std::map< std::pair<uint64_t,MulticastGroup>,MulticastGroupStatus >::const_iterator gs(_groups.find(std::pair<uint64_t,MulticastGroup>(nwid,mg))); std::map< std::pair<uint64_t,MulticastGroup>,MulticastGroupStatus >::const_iterator gs(_groups.find(std::pair<uint64_t,MulticastGroup>(nwid,mg)));
if (gs == _groups.end()) if (gs == _groups.end())
return ls; return ls;
for(std::vector<MulticastGroupMember>::const_reverse_iterator m(gs->second.members.rbegin());m!=gs->second.members.rend();++m) {
for(std::vector<MulticastGroupMember>::const_iterator m(gs->second.members.begin());m!=gs->second.members.end();++m) {
SharedPtr<Peer> p(RR->topology->getPeer(m->address));
if ((p)&&(p->remoteVersionKnown())&&(p->remoteVersionMajor() < 1))
ls.push_back(m->address); ls.push_back(m->address);
if (ls.size() >= limit)
break;
} }
return ls; return ls;
} }
@ -281,7 +278,9 @@ void Multicaster::send(
outp.append((unsigned char)0); outp.append((unsigned char)0);
RR->identity.address().appendTo(outp); RR->identity.address().appendTo(outp);
outp.append((const void *)&rn,3); // random multicast ID outp.append((const void *)&rn,3); // random multicast ID
if (src)
src.appendTo(outp); src.appendTo(outp);
else MAC(RR->identity.address(),nwid).appendTo(outp);
mg.mac().appendTo(outp); mg.mac().appendTo(outp);
outp.append((uint32_t)mg.adi()); outp.append((uint32_t)mg.adi());
outp.append((uint16_t)etherType); outp.append((uint16_t)etherType);

View file

@ -120,14 +120,12 @@ public:
unsigned int gather(const Address &queryingPeer,uint64_t nwid,const MulticastGroup &mg,Packet &appendTo,unsigned int limit) const; unsigned int gather(const Address &queryingPeer,uint64_t nwid,const MulticastGroup &mg,Packet &appendTo,unsigned int limit) const;
/** /**
* Get known peers with versions <1.0.0 and that are not supernodes * Get subscribers to a multicast group
*
* This is legacy peer compatibility code and will be removed later.
* *
* @param nwid Network ID * @param nwid Network ID
* @param mg Multicast group * @param mg Multicast group
*/ */
std::vector<Address> getLegacySubscribers(uint64_t nwid,const MulticastGroup &mg) const; std::vector<Address> getMembers(uint64_t nwid,const MulticastGroup &mg,unsigned int limit) const;
/** /**
* Send a multicast * Send a multicast
@ -138,7 +136,7 @@ public:
* @param nwid Network ID * @param nwid Network ID
* @param alwaysSendTo Send to these peers first and even if not included in subscriber list * @param alwaysSendTo Send to these peers first and even if not included in subscriber list
* @param mg Multicast group * @param mg Multicast group
* @param src Source Ethernet MAC address * @param src Source Ethernet MAC address or NULL to skip in packet and compute from ZT address (non-bridged mode)
* @param etherType Ethernet frame type * @param etherType Ethernet frame type
* @param data Packet data * @param data Packet data
* @param len Length of packet data * @param len Length of packet data