OpenShot Audio Library | OpenShotAudio: juce_IPAddress.cpp Source File

OpenShot Audio Library | OpenShotAudio 0.4.0

Loading...
Searching...
No Matches
juce_IPAddress.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
27 union IPAddressByteUnion
28{
29 uint16 combined;
30 uint8 split[2];
31};
32
33static void zeroUnusedBytes (uint8* address) noexcept
34{
35 for (int i = 4; i < 16; ++i)
36 address[i] = 0;
37}
38
39IPAddress::IPAddress() noexcept
40{
41 for (int i = 0; i < 16; ++i)
42 address[i] = 0;
43}
44
45 IPAddress::IPAddress (const uint8 bytes[], bool IPv6) noexcept : isIPv6 (IPv6)
46{
47 for (int i = 0; i < (isIPv6 ? 16 : 4); ++i)
48 address[i] = bytes[i];
49
50 if (! isIPv6)
51 zeroUnusedBytes (address);
52}
53
54 IPAddress::IPAddress (const uint16 bytes[8]) noexcept : isIPv6 (true)
55{
56 IPAddressByteUnion temp;
57
58 for (int i = 0; i < 8; ++i)
59 {
60 temp.combined = bytes[i];
61
62 address[i * 2] = temp.split[0];
63 address[i * 2 + 1] = temp.split[1];
64 }
65}
66
67 IPAddress::IPAddress (uint8 a0, uint8 a1, uint8 a2, uint8 a3) noexcept : isIPv6 (false)
68{
69 address[0] = a0; address[1] = a1;
70 address[2] = a2; address[3] = a3;
71
72 zeroUnusedBytes (address);
73}
74
75 IPAddress::IPAddress (uint16 a1, uint16 a2, uint16 a3, uint16 a4,
76 uint16 a5, uint16 a6, uint16 a7, uint16 a8) noexcept : isIPv6 (true)
77
78{
79 uint16 array[8] = { a1, a2, a3, a4, a5, a6, a7, a8 };
80
81 IPAddressByteUnion temp;
82
83 for (int i = 0; i < 8; ++i)
84 {
85 temp.combined = array[i];
86 address[i * 2] = temp.split[0];
87 address[i * 2 + 1] = temp.split[1];
88 }
89}
90
91 IPAddress::IPAddress (uint32 n) noexcept : isIPv6 (false)
92{
93 address[0] = static_cast<uint8> (n >> 24);
94 address[1] = static_cast<uint8> ((n >> 16) & 255);
95 address[2] = static_cast<uint8> ((n >> 8) & 255);
96 address[3] = static_cast<uint8> ((n & 255));
97
98 zeroUnusedBytes (address);
99}
100
101 bool IPAddress::isNull() const
102{
103 for (int i = 0; i < 16; ++i)
104 if (address[i] != 0)
105 return false;
106
107 return true;
108}
109
110static String removePort (const String& adr)
111{
112 if (adr.containsAnyOf ("[]"))
113 return adr.fromFirstOccurrenceOf ("[", false, true).upToLastOccurrenceOf ("]", false, true);
114
115 if (adr.indexOf (":") == adr.lastIndexOf (":"))
116 return adr.upToLastOccurrenceOf (":", false, true);
117
118 return adr;
119}
120
121 IPAddress::IPAddress (const String& adr)
122{
123 auto ipAddress = removePort (adr);
124
125 isIPv6 = ipAddress.contains (":");
126
127 if (! isIPv6)
128 {
129 auto tokens = StringArray::fromTokens (ipAddress, ".", {});
130
131 for (int i = 0; i < 4; ++i)
132 address[i] = (uint8) tokens[i].getIntValue();
133
134 zeroUnusedBytes (address);
135 }
136 else
137 {
138 auto tokens = StringArray::fromTokens (ipAddress, ":", {});
139
140 if (tokens.contains ({})) // if :: shorthand has been used
141 {
142 auto idx = tokens.indexOf ({});
143 tokens.set (idx, "0");
144 tokens.removeEmptyStrings();
145
146 // mapped IPv4 address will be treated as a single token, so pad the end of the StringArray
147 if (tokens[tokens.size() - 1].containsChar ('.'))
148 tokens.add ({});
149
150 while (tokens.size() < 8)
151 tokens.insert (idx, "0");
152 }
153
154 for (int i = 0; i < 8; ++i)
155 {
156 if (i == 6 && isIPv4MappedAddress (IPAddress (address, true)))
157 {
158 IPAddress v4Address (tokens[i]);
159
160 address[12] = v4Address.address[0];
161 address[13] = v4Address.address[1];
162 address[14] = v4Address.address[2];
163 address[15] = v4Address.address[3];
164
165 break;
166 }
167
168 IPAddressByteUnion temp;
169 temp.combined = CharacterFunctions::HexParser<uint16>::parse (tokens[i].getCharPointer());
170
171 address[i * 2] = temp.split[0];
172 address[i * 2 + 1] = temp.split[1];
173 }
174 }
175}
176
177 String IPAddress::toString() const
178{
179 if (! isIPv6)
180 {
181 String s ((int) address[0]);
182
183 for (int i = 1; i < 4; ++i)
184 s << '.' << (int) address[i];
185
186 return s;
187 }
188
189 IPAddressByteUnion temp;
190
191 temp.split[0] = address[0];
192 temp.split[1] = address[1];
193
194 auto addressString = String::toHexString (temp.combined);
195
196 for (int i = 1; i < 8; ++i)
197 {
198 temp.split[0] = address[i * 2];
199 temp.split[1] = address[i * 2 + 1];
200
201 addressString << ':' << String::toHexString (temp.combined);
202 }
203
204 return getFormattedAddress (addressString);
205}
206
207bool IPAddress::operator== (const IPAddress& other) const noexcept { return compare (other) == 0; }
208bool IPAddress::operator!= (const IPAddress& other) const noexcept { return compare (other) != 0; }
209bool IPAddress::operator< (const IPAddress& other) const noexcept { return compare (other) < 0; }
210bool IPAddress::operator<= (const IPAddress& other) const noexcept { return compare (other) <= 0; }
211bool IPAddress::operator> (const IPAddress& other) const noexcept { return compare (other) > 0; }
212bool IPAddress::operator>= (const IPAddress& other) const noexcept { return compare (other) >= 0; }
213
214 int IPAddress::compare (const IPAddress& other) const noexcept
215{
216 if (isIPv6 != other.isIPv6)
217 {
218 if (isIPv6)
219 {
220 if (isIPv4MappedAddress (*this))
221 return convertIPv4MappedAddressToIPv4 (*this).compare (other);
222
223 return 1;
224 }
225
226 if (isIPv4MappedAddress (other))
227 return compare (convertIPv4MappedAddressToIPv4 (other));
228
229 return -1;
230 }
231
232 for (int i = 0; i < (isIPv6 ? 16 : 4); ++i)
233 {
234 if (address[i] > other.address[i]) return 1;
235 if (address[i] < other.address[i]) return -1;
236 }
237
238 return 0;
239}
240
241 IPAddress IPAddress::any() noexcept { return IPAddress(); }
242 IPAddress IPAddress::broadcast() noexcept { return IPAddress (255, 255, 255, 255); }
243 IPAddress IPAddress::local (bool IPv6) noexcept { return IPv6 ? IPAddress (0, 0, 0, 0, 0, 0, 0, 1)
244 : IPAddress (127, 0, 0, 1); }
245
246 String IPAddress::getFormattedAddress (const String& unformattedAddress)
247{
248 jassert (unformattedAddress.contains (":") && ! unformattedAddress.contains ("::")); // needs to be an unformatted IPv6 address!
249
250 auto portString = unformattedAddress.fromFirstOccurrenceOf ("]", false, true);
251 auto addressString = unformattedAddress.dropLastCharacters (portString.length()).removeCharacters ("[]");
252
253 auto tokens = StringArray::fromTokens (addressString, ":", {});
254
255 int numZeros = 0;
256 int numZerosTemp = 0;
257 bool isFirst = false;
258 bool isLast = false;
259
260 for (int i = 0; i < tokens.size(); ++i)
261 {
262 auto& t = tokens.getReference (i);
263
264 if (t.getHexValue32() == 0x0000)
265 {
266 ++numZeros;
267
268 if (i == 0)
269 isFirst = true;
270 else if (i == tokens.size() - 1 && numZeros > numZerosTemp)
271 isLast = true;
272
273 if (t.length() > 1)
274 addressString = addressString.replace (String::repeatedString ("0", t.length()), "0");
275
276 if (isFirst && numZerosTemp != 0 && numZeros > numZerosTemp)
277 isFirst = false;
278 }
279 else
280 {
281 addressString = addressString.replace (t, t.trimCharactersAtStart ("0").toLowerCase());
282
283 if (numZeros > 0)
284 {
285 if (numZeros > numZerosTemp)
286 numZerosTemp = numZeros;
287
288 numZeros = 0;
289 }
290 }
291 }
292
293 if (numZerosTemp > numZeros)
294 numZeros = numZerosTemp;
295
296 if (numZeros > 1)
297 {
298 if (numZeros == tokens.size())
299 {
300 addressString = "::,";
301 }
302 else
303 {
304 auto zeroString = isFirst ? "0" + String::repeatedString (":0", numZeros - 1)
305 : String::repeatedString (":0", numZeros);
306
307 addressString = addressString.replaceFirstOccurrenceOf (zeroString, ":");
308
309 if (isLast)
310 addressString << ':';
311 }
312 }
313
314 if (portString.isNotEmpty())
315 addressString = "[" + addressString + "]" + portString;
316
317 return addressString;
318}
319
320 bool IPAddress::isIPv4MappedAddress (const IPAddress& mappedAddress)
321{
322 if (! mappedAddress.isIPv6)
323 return false;
324
325 for (int i = 0; i < 10; ++i)
326 if (mappedAddress.address[i] != 0)
327 return false;
328
329 if (mappedAddress.address[10] != 255 || mappedAddress.address[11] != 255)
330 return false;
331
332 return true;
333}
334
335 IPAddress IPAddress::convertIPv4MappedAddressToIPv4 (const IPAddress& mappedAddress)
336{
337 // The address that you're converting needs to be IPv6!
338 jassert (mappedAddress.isIPv6);
339
340 if (isIPv4MappedAddress (mappedAddress))
341 return { mappedAddress.address[12], mappedAddress.address[13],
342 mappedAddress.address[14], mappedAddress.address[15] };
343
344 return {};
345}
346
347 IPAddress IPAddress::convertIPv4AddressToIPv4Mapped (const IPAddress& addressToMap)
348{
349 // The address that you're converting needs to be IPv4!
350 jassert (! addressToMap.isIPv6);
351
352 return { 0x0, 0x0, 0x0, 0x0, 0x0, 0xffff,
353 static_cast<uint16> ((addressToMap.address[0] << 8) | addressToMap.address[1]),
354 static_cast<uint16> ((addressToMap.address[2] << 8) | addressToMap.address[3]) };
355}
356
357 IPAddress IPAddress::getLocalAddress (bool includeIPv6)
358{
359 auto addresses = getAllAddresses (includeIPv6);
360
361 for (auto& a : addresses)
362 if (a != local())
363 return a;
364
365 return local();
366}
367
368 Array<IPAddress> IPAddress::getAllAddresses (bool includeIPv6)
369{
370 Array<IPAddress> addresses;
371 findAllAddresses (addresses, includeIPv6);
372 return addresses;
373}
374
375
376//==============================================================================
377//==============================================================================
378#if JUCE_UNIT_TESTS
379
380struct IPAddressTests final : public UnitTest
381{
382 IPAddressTests()
383 : UnitTest ("IPAddress", UnitTestCategories::networking)
384 {}
385
386 void runTest() override
387 {
388 testConstructors();
389 testFindAllAddresses();
390 testFindBroadcastAddress();
391 }
392
393 void testConstructors()
394 {
395 beginTest ("constructors");
396
397 // Default IPAdress should be null
398 IPAddress defaultConstructed;
399 expect (defaultConstructed.isNull());
400
401 auto local = IPAddress::local();
402 expect (! local.isNull());
403
404 IPAddress ipv4{1, 2, 3, 4};
405 expect (! ipv4.isNull());
406 expect (! ipv4.isIPv6);
407 expect (ipv4.toString() == "1.2.3.4");
408 }
409
410 void testFindAllAddresses()
411 {
412 beginTest ("find all addresses");
413
414 Array<IPAddress> ipv4Addresses;
415 Array<IPAddress> allAddresses;
416
417 IPAddress::findAllAddresses (ipv4Addresses, false);
418 IPAddress::findAllAddresses (allAddresses, true);
419
420 expect (allAddresses.size() >= ipv4Addresses.size());
421
422 for (auto& a : ipv4Addresses)
423 {
424 expect (! a.isNull());
425 expect (! a.isIPv6);
426 }
427
428 for (auto& a : allAddresses)
429 {
430 expect (! a.isNull());
431 }
432 }
433
434 void testFindBroadcastAddress()
435 {
436 beginTest ("broadcast addresses");
437
438 Array<IPAddress> addresses;
439
440 // Only IPv4 interfaces have broadcast
441 IPAddress::findAllAddresses (addresses, false);
442
443 for (auto& a : addresses)
444 {
445 expect (! a.isNull());
446
447 auto broadcastAddress = IPAddress::getInterfaceBroadcastAddress (a);
448
449 // If we retrieve an address, it should be an IPv4 address
450 if (! broadcastAddress.isNull())
451 {
452 expect (! a.isIPv6);
453 }
454 }
455
456 // Expect to fail to find a broadcast for this address
457 IPAddress address{1, 2, 3, 4};
458 expect (IPAddress::getInterfaceBroadcastAddress (address).isNull());
459 }
460};
461
462static IPAddressTests iPAddressTests;
463
464#endif
465
466} // namespace juce
juce::Array
Definition juce_Array.h:56
juce::IPAddress
Definition juce_IPAddress.h:33
juce::IPAddress::getAllAddresses
static Array< IPAddress > getAllAddresses(bool includeIPv6=false)
Definition juce_IPAddress.cpp:368
juce::IPAddress::getLocalAddress
static IPAddress getLocalAddress(bool includeIPv6=false)
Definition juce_IPAddress.cpp:357
juce::IPAddress::isNull
bool isNull() const
Definition juce_IPAddress.cpp:101
juce::IPAddress::local
static IPAddress local(bool IPv6=false) noexcept
Definition juce_IPAddress.cpp:243
juce::IPAddress::isIPv4MappedAddress
static bool isIPv4MappedAddress(const IPAddress &mappedAddress)
Definition juce_IPAddress.cpp:320
juce::IPAddress::any
static IPAddress any() noexcept
Definition juce_IPAddress.cpp:241
juce::IPAddress::getFormattedAddress
static String getFormattedAddress(const String &unformattedAddress)
Definition juce_IPAddress.cpp:246
juce::IPAddress::compare
int compare(const IPAddress &) const noexcept
Definition juce_IPAddress.cpp:214
juce::IPAddress::toString
String toString() const
Definition juce_IPAddress.cpp:177
juce::IPAddress::broadcast
static IPAddress broadcast() noexcept
Definition juce_IPAddress.cpp:242
juce::IPAddress::findAllAddresses
static void findAllAddresses(Array< IPAddress > &results, bool includeIPv6=false)
juce::IPAddress::address
uint8 address[16]
Definition juce_IPAddress.h:113
juce::IPAddress::convertIPv4AddressToIPv4Mapped
static IPAddress convertIPv4AddressToIPv4Mapped(const IPAddress &addressToMap)
Definition juce_IPAddress.cpp:347
juce::IPAddress::convertIPv4MappedAddressToIPv4
static IPAddress convertIPv4MappedAddressToIPv4(const IPAddress &mappedAddress)
Definition juce_IPAddress.cpp:335
juce::IPAddress::IPAddress
IPAddress() noexcept
Definition juce_IPAddress.cpp:39
juce::StringArray::fromTokens
static StringArray fromTokens(StringRef stringToTokenise, bool preserveQuotedStrings)
Definition juce_StringArray.cpp:387
juce::String
Definition juce_String.h:53
juce::String::repeatedString
static String repeatedString(StringRef stringToRepeat, int numberOfTimesToRepeat)
Definition juce_String.cpp:1147
juce::String::removeCharacters
String removeCharacters(StringRef charactersToRemove) const
Definition juce_String.cpp:1757
juce::String::indexOf
int indexOf(StringRef textToLookFor) const noexcept
Definition juce_String.cpp:931
juce::String::lastIndexOf
int lastIndexOf(StringRef textToLookFor) const noexcept
Definition juce_String.cpp:979
juce::String::dropLastCharacters
String dropLastCharacters(int numberToDrop) const
Definition juce_String.cpp:1555
juce::String::contains
bool contains(StringRef text) const noexcept
Definition juce_String.cpp:1035
juce::String::toHexString
static String toHexString(IntegerType number)
Definition juce_String.h:1097
juce::String::upToLastOccurrenceOf
String upToLastOccurrenceOf(StringRef substringToFind, bool includeSubStringInResult, bool ignoreCase) const
Definition juce_String.cpp:1595
juce::String::containsAnyOf
bool containsAnyOf(StringRef charactersItMightContain) const noexcept
Definition juce_String.cpp:1805
juce::String::fromFirstOccurrenceOf
String fromFirstOccurrenceOf(StringRef substringToStartFrom, bool includeSubStringInResult, bool ignoreCase) const
Definition juce_String.cpp:1565
juce::UnitTest
Definition juce_UnitTest.h:70
juce::CharacterFunctions::HexParser
Definition juce_CharacterFunctions.h:492
juce::IPAddressByteUnion
Definition juce_IPAddress.cpp:28