BOOST_FOREACH(const Zone::Ptr& zone, ConfigType::GetObjectsByType<Zone>()) { /* don't connect to global zones */ if (zone->GetGlobal()) continue; /* only connect to endpoints in a) the same zone b) our parent zone c) immediate child zones */ if (my_zone != zone && my_zone != zone->GetParent() && zone != my_zone->GetParent()) { Log(LogDebug, "ApiListener") << "Not connecting to Zone '" << zone->GetName() << "' because it's not in the same zone, a parent or a child zone."; continue; } BOOST_FOREACH(const Endpoint::Ptr& endpoint, zone->GetEndpoints()) { /* don't connect to ourselves */ if (endpoint == GetLocalEndpoint()) { Log(LogDebug, "ApiListener") << "Not connecting to Endpoint '" << endpoint->GetName() << "' because that's us."; continue; } /* don't try to connect to endpoints which don't have a host and port */ if (endpoint->GetHost().IsEmpty() || endpoint->GetPort().IsEmpty()) { Log(LogDebug, "ApiListener") << "Not connecting to Endpoint '" << endpoint->GetName() << "' because the host/port attributes are missing."; continue; } /* don't try to connect if there's already a connection attempt */ if (endpoint->GetConnecting()) { Log(LogDebug, "ApiListener") << "Not connecting to Endpoint '" << endpoint->GetName() << "' because we're already trying to connect to it."; continue; } /* don't try to connect if we're already connected */ if (endpoint->GetConnected()) { Log(LogDebug, "ApiListener") << "Not connecting to Endpoint '" << endpoint->GetName() << "' because we're already connected to it."; continue; } boost::thread thread(boost::bind(&ApiListener::AddConnection, this, endpoint)); thread.detach(); } }
bool ApiListener::RelayMessageOne(const Zone::Ptr& targetZone, const MessageOrigin::Ptr& origin, const Dictionary::Ptr& message, const Endpoint::Ptr& currentMaster) { ASSERT(targetZone); Zone::Ptr myZone = Zone::GetLocalZone(); /* only relay the message to a) the same zone, b) the parent zone and c) direct child zones. Exception is a global zone. */ if (!targetZone->GetGlobal() && targetZone != myZone && targetZone != myZone->GetParent() && targetZone->GetParent() != myZone) { return true; } Endpoint::Ptr myEndpoint = GetLocalEndpoint(); std::vector<Endpoint::Ptr> skippedEndpoints; bool relayed = false, log_needed = false, log_done = false; std::set<Endpoint::Ptr> targetEndpoints; if (targetZone->GetGlobal()) { targetEndpoints = myZone->GetEndpoints(); for (const Zone::Ptr& zone : ConfigType::GetObjectsByType<Zone>()) { /* Fetch immediate child zone members */ if (zone->GetParent() == myZone) { std::set<Endpoint::Ptr> endpoints = zone->GetEndpoints(); targetEndpoints.insert(endpoints.begin(), endpoints.end()); } } } else { targetEndpoints = targetZone->GetEndpoints(); } for (const Endpoint::Ptr& endpoint : targetEndpoints) { /* don't relay messages to ourselves */ if (endpoint == GetLocalEndpoint()) continue; log_needed = true; /* don't relay messages to disconnected endpoints */ if (!endpoint->GetConnected()) { if (targetZone == myZone) log_done = false; continue; } log_done = true; /* don't relay the message to the zone through more than one endpoint unless this is our own zone */ if (relayed && targetZone != myZone) { skippedEndpoints.push_back(endpoint); continue; } /* don't relay messages back to the endpoint which we got the message from */ if (origin && origin->FromClient && endpoint == origin->FromClient->GetEndpoint()) { skippedEndpoints.push_back(endpoint); continue; } /* don't relay messages back to the zone which we got the message from */ if (origin && origin->FromZone && targetZone == origin->FromZone) { skippedEndpoints.push_back(endpoint); continue; } /* only relay message to the master if we're not currently the master */ if (currentMaster != myEndpoint && currentMaster != endpoint) { skippedEndpoints.push_back(endpoint); continue; } relayed = true; SyncSendMessage(endpoint, message); } if (!skippedEndpoints.empty()) { double ts = message->Get("ts"); for (const Endpoint::Ptr& endpoint : skippedEndpoints) endpoint->SetLocalLogPosition(ts); } return !log_needed || log_done; }