Ejemplo n.º 1
0
	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();
		}
	}
Ejemplo n.º 2
0
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;
}