コード例 #1
0
ファイル: Discover.cpp プロジェクト: dustyco/Drone
void Discover::announceRecords ()
{
	// Reset timer
	timer->start(announcePeriodMsec);

	if (not running) return;

	// Servers don't announce periodically or send departure messages
	if (mServerMode) return;

	// Start building a list of records to send in each scope
	QList<Record> recordsToSend;

	///////////////////////////////////////////////////////////////////////
	// Global scope first
	///////////////////////////////////////////////////////////////////////
	for (Record record : ownedRecords)
	if (record["Scope"] == "Global")
	{
		recordsToSend.push_back(record);
	}
	if (not recordsToSend.empty() or defaultScope=="Global")
	{
		// This is a discovery request which should be responded to
		QByteArray datagram("DSDR");
		if (departure) datagram = "DSDD";
		datagram += makeDatagram(recordsToSend, false);

		// Send to each Global server
		for (QPair<QHostAddress,quint16> globalServer : globalServers)
		{
			globalSocket->writeDatagram(datagram, globalServer.first, globalServer.second);
		}
	}

	///////////////////////////////////////////////////////////////////////
	// Local scope next
	///////////////////////////////////////////////////////////////////////
	for (Record record : ownedRecords)
	if (record["Scope"] == "Local")
	{
		recordsToSend.push_back(record);
	}
	if (not recordsToSend.empty() or defaultScope=="Global" or defaultScope=="Local")
	{
		QByteArray datagram("DSDA");
		if (announceNeedsResponse) datagram = "DSDR";
		if (departure)             datagram = "DSDD";
		datagram += makeDatagram(recordsToSend, true);

		// For each interface
		for (auto iface : QNetworkInterface::allInterfaces())
		{
			// For each IPv4 address on this interface
			for (auto entry : iface.addressEntries())
			{
				if (entry.ip().protocol() != QAbstractSocket::IPv4Protocol) continue;

				// Add it to addressEntryCache if necessary for local scope testing
				if (not addressEntryCache.contains(entry)) addressEntryCache.push_back(entry);

				// Multicast
				if (iface.flags().testFlag(QNetworkInterface::CanMulticast) and !entry.ip().isNull() and !entry.ip().isLoopback())
				{
					// Create the socket if it doesn't exit yet
					if (not multiSocket.contains(entry.ip().toString()))
					{
						logDebug(QString("New multicast socket: %1 %2").arg(entry.ip().toString(), entry.netmask().toString()));

						// Add it, create and bind the socket
						QUdpSocket* socket = new QUdpSocket(this);
						connect(socket, SIGNAL(readyRead()), this, SLOT(readDatagrams()));
						socket->setSocketOption(QAbstractSocket::MulticastTtlOption, 1);
						if (not socket->bind(QHostAddress::AnyIPv4, port, QAbstractSocket::ShareAddress | QAbstractSocket::ReuseAddressHint))
						{
							logWarning(QString("Error binding to iface %1: %2").arg(entry.ip().toString(), socket->errorString()));
						}
						socket->setMulticastInterface(iface);
						socket->joinMulticastGroup(groupAddress, iface);
						multiSocket.insert(entry.ip().toString(), socket);
					}

					// Send datagram
					multiSocket[entry.ip().toString()]->writeDatagram(datagram, groupAddress, port);
				}
			}
		}
	}

	///////////////////////////////////////////////////////////////////////
	// Loopback scope last
	///////////////////////////////////////////////////////////////////////
	for (Record record : ownedRecords)
	if (record["Scope"] == "Loopback")
	{
		recordsToSend.push_back(record);
	}
	if (not recordsToSend.empty() or true) // Any scope is above or equivalent to loopback
	{
		QByteArray datagram("DSDA");
		if (announceNeedsResponse) datagram = "DSDR";
		if (departure)             datagram = "DSDD";
		datagram += makeDatagram(recordsToSend, true);

		// Loopback
		//loopbackSocket->writeDatagram(datagram, QHostAddress::LocalHost, port);
	}

	// Reset
	announceNeedsResponse = false;
	departure = false;
}