JUCE-7.0.12-0-g4f43011b96 JUCE-7.0.12-0-g4f43011b96
JUCE — C++ application framework with suport for VST, VST3, LV2 audio plug-ins

« « « Anklang Documentation
Loading...
Searching...
No Matches
juce_NetworkServiceDiscovery.cpp
Go to the documentation of this file.
1 /*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 The code included in this file is provided under the terms of the ISC license
11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12 To use, copy, modify, and/or distribute this software for any purpose with or
13 without fee is hereby granted provided that the above copyright notice and
14 this permission notice appear in all copies.
15
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18 DISCLAIMED.
19
20 ==============================================================================
21*/
22
23namespace juce
24{
25
26#if JUCE_ANDROID
27 extern void acquireMulticastLock();
28 extern void releaseMulticastLock();
29#endif
30
35 : Thread ("Discovery_broadcast"),
36 message (serviceTypeUID), broadcastPort (broadcastPortToUse),
37 minInterval (minTimeBetweenBroadcasts)
38{
39 message.setAttribute ("id", Uuid().toString());
40 message.setAttribute ("name", serviceDescription);
41 message.setAttribute ("address", String());
42 message.setAttribute ("port", connectionPort);
43
44 startThread (Priority::background);
45}
46
48{
49 stopThread (2000);
50 socket.shutdown();
51}
52
53void NetworkServiceDiscovery::Advertiser::run()
54{
55 if (! socket.bindToPort (0))
56 {
58 return;
59 }
60
61 while (! threadShouldExit())
62 {
63 sendBroadcast();
64 wait ((int) minInterval.inMilliseconds());
65 }
66}
67
68void NetworkServiceDiscovery::Advertiser::sendBroadcast()
69{
70 static IPAddress local = IPAddress::local();
71
72 for (auto& address : IPAddress::getAllAddresses())
73 {
74 if (address == local)
75 continue;
76
77 message.setAttribute ("address", address.toString());
78
79 auto broadcastAddress = IPAddress::getInterfaceBroadcastAddress (address);
80 auto data = message.toString (XmlElement::TextFormat().singleLine().withoutHeader());
81
82 socket.write (broadcastAddress.toString(), broadcastPort, data.toRawUTF8(), (int) data.getNumBytesAsUTF8());
83 }
84}
85
86//==============================================================================
88 : Thread ("Discovery_listen"), serviceTypeUID (serviceType)
89{
90 #if JUCE_ANDROID
92 #endif
93
94 socket.bindToPort (broadcastPort);
95 startThread (Priority::background);
96}
97
99{
100 socket.shutdown();
101 stopThread (2000);
102
103 #if JUCE_ANDROID
105 #endif
106}
107
108void NetworkServiceDiscovery::AvailableServiceList::run()
109{
110 while (! threadShouldExit())
111 {
112 if (socket.waitUntilReady (true, 200) == 1)
113 {
114 char buffer[1024];
115 auto bytesRead = socket.read (buffer, sizeof (buffer) - 1, false);
116
117 if (bytesRead > 10)
118 if (auto xml = parseXML (String (CharPointer_UTF8 (buffer),
119 CharPointer_UTF8 (buffer + bytesRead))))
120 if (xml->hasTagName (serviceTypeUID))
121 handleMessage (*xml);
122 }
123
124 removeTimedOutServices();
125 }
126}
127
134
135void NetworkServiceDiscovery::AvailableServiceList::handleAsyncUpdate()
136{
137 NullCheckedInvocation::invoke (onChange);
138}
139
140void NetworkServiceDiscovery::AvailableServiceList::handleMessage (const XmlElement& xml)
141{
142 Service service;
143 service.instanceID = xml.getStringAttribute ("id");
144
145 if (service.instanceID.trim().isNotEmpty())
146 {
147 service.description = xml.getStringAttribute ("name");
148 service.address = IPAddress (xml.getStringAttribute ("address"));
149 service.port = xml.getIntAttribute ("port");
150 service.lastSeen = Time::getCurrentTime();
151
152 handleMessage (service);
153 }
154}
155
156static void sortServiceList (std::vector<NetworkServiceDiscovery::Service>& services)
157{
158 auto compareServices = [] (const NetworkServiceDiscovery::Service& s1,
159 const NetworkServiceDiscovery::Service& s2)
160 {
161 return s1.instanceID < s2.instanceID;
162 };
163
164 std::sort (services.begin(), services.end(), compareServices);
165}
166
167void NetworkServiceDiscovery::AvailableServiceList::handleMessage (const Service& service)
168{
169 const ScopedLock sl (listLock);
170
171 for (auto& s : services)
172 {
173 if (s.instanceID == service.instanceID)
174 {
175 if (s.description != service.description
176 || s.address != service.address
177 || s.port != service.port)
178 {
179 s = service;
180 triggerAsyncUpdate();
181 }
182
183 s.lastSeen = service.lastSeen;
184 return;
185 }
186 }
187
188 services.push_back (service);
189 sortServiceList (services);
190 triggerAsyncUpdate();
191}
192
193void NetworkServiceDiscovery::AvailableServiceList::removeTimedOutServices()
194{
195 const double timeoutSeconds = 5.0;
197
198 const ScopedLock sl (listLock);
199
200 auto oldEnd = std::end (services);
201 auto newEnd = std::remove_if (std::begin (services), oldEnd,
202 [=] (const Service& s) { return s.lastSeen < oldestAllowedTime; });
203
204 if (newEnd != oldEnd)
205 {
206 services.erase (newEnd, oldEnd);
207 triggerAsyncUpdate();
208 }
209}
210
211} // namespace juce
T begin(T... args)
Wraps a pointer to a null-terminated UTF-8 character string, and provides various methods to operate ...
bool bindToPort(int localPortNumber)
Binds the socket to the specified local port.
Automatically locks and unlocks a mutex object.
Represents an IP address.
static IPAddress local(bool IPv6=false) noexcept
Returns an IPv4 or IPv6 address meaning "localhost", equivalent to 127.0.0.1 (IPv4) or ::1 (IPv6)
static IPAddress getInterfaceBroadcastAddress(const IPAddress &interfaceAddress)
If the IPAdress is the address of an interface on the machine, returns the associated broadcast addre...
A relative measure of time.
static RelativeTime seconds(double seconds) noexcept
Creates a new RelativeTime object representing a number of seconds.
The JUCE String class!
Definition juce_String.h:53
Encapsulates a thread.
Definition juce_Thread.h:43
bool startThread()
Attempts to start a new thread with default ('Priority::normal') priority.
static Time JUCE_CALLTYPE getCurrentTime() noexcept
Returns a Time object that is set to the current system time.
A universally unique 128-bit identifier.
Definition juce_Uuid.h:39
Used to build a tree of elements representing an XML document.
int getIntAttribute(StringRef attributeName, int defaultReturnValue=0) const
Returns the value of a named attribute as an integer.
const String & getStringAttribute(StringRef attributeName) const noexcept
Returns the value of a named attribute.
void setAttribute(const Identifier &attributeName, const String &newValue)
Adds a named attribute to the element.
T data(T... args)
T end(T... args)
#define jassertfalse
This will always cause an assertion failure.
JUCE Namespace.
CriticalSection::ScopedLockType ScopedLock
Automatically locks and unlocks a CriticalSection object.
std::unique_ptr< XmlElement > parseXML(const String &textToParse)
Attempts to parse some XML text, returning a new XmlElement if it was valid.
Type unalignedPointerCast(void *ptr) noexcept
Casts a pointer to another type via void*, which suppresses the cast-align warning which sometimes ar...
Definition juce_Memory.h:88
T remove_if(T... args)
socket
T sort(T... args)
Advertiser(const String &serviceTypeUID, const String &serviceDescription, int broadcastPort, int connectionPort, RelativeTime minTimeBetweenBroadcasts=RelativeTime::seconds(1.5))
Creates and starts an Advertiser thread, broadcasting with the given properties.
AvailableServiceList(const String &serviceTypeUID, int broadcastPort)
Creates an AvailableServiceList that will bind to the given port number and watch the network for Adv...
std::vector< Service > getServices() const
Returns a list of the currently known services.
wait