27 extern void acquireMulticastLock();
28 extern void releaseMulticastLock();
35 :
Thread (
"Discovery_broadcast"),
53void NetworkServiceDiscovery::Advertiser::run()
55 if (! socket.bindToPort (0))
61 while (! threadShouldExit())
64 wait ((
int) minInterval.inMilliseconds());
68void NetworkServiceDiscovery::Advertiser::sendBroadcast()
71 message.setAttribute (
"address", localAddress.toString());
73 auto data = message.toString (XmlElement::TextFormat().singleLine().withoutHeader());
74 socket.write (broadcastAddress.toString(), broadcastPort, data.toRawUTF8(), (
int) data.getNumBytesAsUTF8());
99void NetworkServiceDiscovery::AvailableServiceList::run()
101 while (! threadShouldExit())
103 if (socket.waitUntilReady (
true, 200) == 1)
106 auto bytesRead = socket.read (buffer,
sizeof (buffer) - 1,
false);
111 if (xml->hasTagName (serviceTypeUID))
112 handleMessage (*xml);
115 removeTimedOutServices();
126void NetworkServiceDiscovery::AvailableServiceList::handleAsyncUpdate()
128 if (onChange !=
nullptr)
132void NetworkServiceDiscovery::AvailableServiceList::handleMessage (
const XmlElement& xml)
137 if (
service.instanceID.trim().isNotEmpty())
148static void sortServiceList (std::vector<NetworkServiceDiscovery::Service>& services)
150 auto compareServices = [] (
const NetworkServiceDiscovery::Service& s1,
151 const NetworkServiceDiscovery::Service& s2)
153 return s1.instanceID < s2.instanceID;
156 std::sort (services.begin(), services.end(), compareServices);
159void NetworkServiceDiscovery::AvailableServiceList::handleMessage (
const Service& service)
161 const ScopedLock sl (listLock);
163 for (
auto& s : services)
165 if (s.instanceID == service.instanceID)
167 if (s.description != service.description
168 || s.address != service.address
169 || s.port != service.port)
172 triggerAsyncUpdate();
175 s.lastSeen = service.lastSeen;
180 services.push_back (service);
181 sortServiceList (services);
182 triggerAsyncUpdate();
185void NetworkServiceDiscovery::AvailableServiceList::removeTimedOutServices()
187 const double timeoutSeconds = 5.0;
190 const ScopedLock sl (listLock);
192 auto oldEnd = std::end (services);
193 auto newEnd = std::remove_if (std::begin (services), oldEnd,
194 [=] (
const Service& s) {
return s.lastSeen < oldestAllowedTime; });
196 if (newEnd != oldEnd)
198 services.erase (newEnd, oldEnd);
199 triggerAsyncUpdate();
bool bindToPort(int localPortNumber)
static IPAddress getLocalAddress(bool includeIPv6=false)
static IPAddress getInterfaceBroadcastAddress(const IPAddress &interfaceAddress)
static RelativeTime seconds(double seconds) noexcept
static Time JUCE_CALLTYPE getCurrentTime() noexcept
int getIntAttribute(StringRef attributeName, int defaultReturnValue=0) const
const String & getStringAttribute(StringRef attributeName) const noexcept
void setAttribute(const Identifier &attributeName, const String &newValue)
Advertiser(const String &serviceTypeUID, const String &serviceDescription, int broadcastPort, int connectionPort, RelativeTime minTimeBetweenBroadcasts=RelativeTime::seconds(1.5))
AvailableServiceList(const String &serviceTypeUID, int broadcastPort)
~AvailableServiceList() override
std::vector< Service > getServices() const