OpenShot Audio Library | OpenShotAudio: juce_NetworkServiceDiscovery.cpp Source File

OpenShot Audio Library | OpenShotAudio 0.4.0

Loading...
Searching...
No Matches
juce_NetworkServiceDiscovery.cpp
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
31NetworkServiceDiscovery::Advertiser::Advertiser (const String& serviceTypeUID,
32 const String& serviceDescription,
33 int broadcastPortToUse, int connectionPort,
34 RelativeTime minTimeBetweenBroadcasts)
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
47NetworkServiceDiscovery::Advertiser::~Advertiser()
48{
49 stopThread (2000);
50 socket.shutdown();
51}
52
53void NetworkServiceDiscovery::Advertiser::run()
54{
55 if (! socket.bindToPort (0))
56 {
57 jassertfalse;
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//==============================================================================
87NetworkServiceDiscovery::AvailableServiceList::AvailableServiceList (const String& serviceType, int broadcastPort)
88 : Thread ("Discovery_listen"), serviceTypeUID (serviceType)
89{
90 #if JUCE_ANDROID
91 acquireMulticastLock();
92 #endif
93
94 socket.bindToPort (broadcastPort);
95 startThread (Priority::background);
96}
97
98NetworkServiceDiscovery::AvailableServiceList::~AvailableServiceList()
99{
100 socket.shutdown();
101 stopThread (2000);
102
103 #if JUCE_ANDROID
104 releaseMulticastLock();
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
128std::vector<NetworkServiceDiscovery::Service> NetworkServiceDiscovery::AvailableServiceList::getServices() const
129{
130 const ScopedLock sl (listLock);
131 auto listCopy = services;
132 return listCopy;
133}
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;
196 auto oldestAllowedTime = Time::getCurrentTime() - RelativeTime::seconds (timeoutSeconds);
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
juce::CharPointer_UTF8
Definition juce_CharPointer_UTF8.h:35
juce::DatagramSocket::bindToPort
bool bindToPort(int localPortNumber)
Definition juce_Socket.cpp:697
juce::GenericScopedLock
Definition juce_ScopedLock.h:55
juce::IPAddress
Definition juce_IPAddress.h:33
juce::IPAddress::getAllAddresses
static Array< IPAddress > getAllAddresses(bool includeIPv6=false)
Definition juce_IPAddress.cpp:368
juce::IPAddress::local
static IPAddress local(bool IPv6=false) noexcept
Definition juce_IPAddress.cpp:243
juce::IPAddress::getInterfaceBroadcastAddress
static IPAddress getInterfaceBroadcastAddress(const IPAddress &interfaceAddress)
juce::RelativeTime
Definition juce_RelativeTime.h:37
juce::RelativeTime::seconds
static RelativeTime seconds(double seconds) noexcept
Definition juce_RelativeTime.cpp:33
juce::String
Definition juce_String.h:53
juce::Thread
Definition juce_Thread.h:43
juce::Thread::startThread
bool startThread()
Definition juce_Thread.cpp:145
juce::Time::getCurrentTime
static Time JUCE_CALLTYPE getCurrentTime() noexcept
Definition juce_Time.cpp:233
juce::Uuid
Definition juce_Uuid.h:39
juce::XmlElement
Definition juce_XmlElement.h:83
juce::XmlElement::getIntAttribute
int getIntAttribute(StringRef attributeName, int defaultReturnValue=0) const
Definition juce_XmlElement.cpp:571
juce::XmlElement::getStringAttribute
const String & getStringAttribute(StringRef attributeName) const noexcept
Definition juce_XmlElement.cpp:555
juce::XmlElement::setAttribute
void setAttribute(const Identifier &attributeName, const String &newValue)
Definition juce_XmlElement.cpp:615
juce::NetworkServiceDiscovery::Advertiser::Advertiser
Advertiser(const String &serviceTypeUID, const String &serviceDescription, int broadcastPort, int connectionPort, RelativeTime minTimeBetweenBroadcasts=RelativeTime::seconds(1.5))
Definition juce_NetworkServiceDiscovery.cpp:31
juce::NetworkServiceDiscovery::Advertiser::~Advertiser
~Advertiser() override
Definition juce_NetworkServiceDiscovery.cpp:47
juce::NetworkServiceDiscovery::AvailableServiceList::AvailableServiceList
AvailableServiceList(const String &serviceTypeUID, int broadcastPort)
Definition juce_NetworkServiceDiscovery.cpp:87
juce::NetworkServiceDiscovery::AvailableServiceList::~AvailableServiceList
~AvailableServiceList() override
Definition juce_NetworkServiceDiscovery.cpp:98
juce::NetworkServiceDiscovery::AvailableServiceList::getServices
std::vector< Service > getServices() const
Definition juce_NetworkServiceDiscovery.cpp:128