upgrade to JUCE 5.4.3. Remove (probably) unused JUCE modules. Remove VST2 target (it's been end-of-life'd by Steinberg and by JUCE)

This commit is contained in:
Alex Birch
2019-06-22 20:41:38 +01:00
parent d22c2cd4fa
commit 9ee566b251
1140 changed files with 67534 additions and 105952 deletions

View File

@ -23,7 +23,20 @@
namespace juce
{
IPAddress::IPAddress (bool IPv6) noexcept : isIPv6 (IPv6)
/** Union used to split a 16-bit unsigned integer into 2 8-bit unsigned integers or vice-versa */
union IPAddressByteUnion
{
uint16 combined;
uint8 split[2];
};
static void zeroUnusedBytes (uint8* address) noexcept
{
for (int i = 4; i < 16; ++i)
address[i] = 0;
}
IPAddress::IPAddress() noexcept
{
for (int i = 0; i < 16; ++i)
address[i] = 0;
@ -35,12 +48,12 @@ IPAddress::IPAddress (const uint8 bytes[], bool IPv6) noexcept : isIPv6 (IPv6)
address[i] = bytes[i];
if (! isIPv6)
zeroUnusedBytes();
zeroUnusedBytes (address);
}
IPAddress::IPAddress (const uint16 bytes[8]) noexcept : isIPv6 (true)
{
ByteUnion temp;
IPAddressByteUnion temp;
for (int i = 0; i < 8; ++i)
{
@ -56,7 +69,7 @@ IPAddress::IPAddress (uint8 a0, uint8 a1, uint8 a2, uint8 a3) noexcept : isIPv6
address[0] = a0; address[1] = a1;
address[2] = a2; address[3] = a3;
zeroUnusedBytes();
zeroUnusedBytes (address);
}
IPAddress::IPAddress (uint16 a1, uint16 a2, uint16 a3, uint16 a4,
@ -65,7 +78,7 @@ IPAddress::IPAddress (uint16 a1, uint16 a2, uint16 a3, uint16 a4,
{
uint16 array[8] = { a1, a2, a3, a4, a5, a6, a7, a8 };
ByteUnion temp;
IPAddressByteUnion temp;
for (int i = 0; i < 8; ++i)
{
@ -82,30 +95,57 @@ IPAddress::IPAddress (uint32 n) noexcept : isIPv6 (false)
address[2] = (n >> 8) & 255;
address[3] = (n & 255);
zeroUnusedBytes();
zeroUnusedBytes (address);
}
bool IPAddress::isNull() const
{
for (int i = 0; i < 16; ++i)
if (address[i] != 0)
return false;
return true;
}
static String removePort (const String& adr)
{
if (adr.containsAnyOf ("[]"))
return adr.fromFirstOccurrenceOf ("[", false, true).upToLastOccurrenceOf ("]", false, true);
if (adr.indexOf (":") == adr.lastIndexOf (":"))
return adr.upToLastOccurrenceOf (":", false, true);
return adr;
}
IPAddress::IPAddress (const String& adr)
{
isIPv6 = adr.contains (":");
auto ipAddress = removePort (adr);
isIPv6 = ipAddress.contains (":");
if (! isIPv6)
{
StringArray tokens;
tokens.addTokens (adr, ".", String());
auto tokens = StringArray::fromTokens (ipAddress, ".", {});
for (int i = 0; i < 4; ++i)
address[i] = (uint8) tokens[i].getIntValue();
zeroUnusedBytes (address);
}
else
{
StringArray tokens;
tokens.addTokens (adr.removeCharacters ("[]"), ":", String());
auto tokens = StringArray::fromTokens (ipAddress, ":", {});
if (tokens.contains (StringRef())) // if :: shorthand has been used
if (tokens.contains ({})) // if :: shorthand has been used
{
int idx = tokens.indexOf (StringRef());
auto idx = tokens.indexOf ({});
tokens.set (idx, "0");
tokens.removeEmptyStrings();
// mapped IPv4 address will be treated as a single token, so pad the end of the StringArray
if (tokens[tokens.size() - 1].containsChar ('.'))
tokens.add ({});
while (tokens.size() < 8)
tokens.insert (idx, "0");
@ -113,7 +153,19 @@ IPAddress::IPAddress (const String& adr)
for (int i = 0; i < 8; ++i)
{
ByteUnion temp;
if (i == 6 && isIPv4MappedAddress (IPAddress (address, true)))
{
IPAddress v4Address (tokens[i]);
address[12] = v4Address.address[0];
address[13] = v4Address.address[1];
address[14] = v4Address.address[2];
address[15] = v4Address.address[3];
break;
}
IPAddressByteUnion temp;
temp.combined = (uint16) CharacterFunctions::HexParser<int>::parse (tokens[i].getCharPointer());
address[i * 2] = temp.split[0];
@ -134,29 +186,62 @@ String IPAddress::toString() const
return s;
}
String addressString;
ByteUnion temp;
IPAddressByteUnion temp;
temp.split[0] = address[0];
temp.split[1] = address[1];
addressString = String (String::toHexString (temp.combined));
auto addressString = String::toHexString (temp.combined);
for (int i = 1; i < 8; ++i)
{
temp.split[0] = address[i * 2];
temp.split[1] = address[i * 2 + 1];
addressString << ':' << String (String::toHexString (temp.combined));
addressString << ':' << String::toHexString (temp.combined);
}
return getFormattedAddress (addressString);
}
IPAddress IPAddress::any (bool IPv6) noexcept { return IPAddress (IPv6); }
IPAddress IPAddress::broadcast() noexcept { return IPAddress (255, 255, 255, 255); }
IPAddress IPAddress::local (bool IPv6) noexcept { return IPv6 ? IPAddress (0, 0, 0, 0, 0, 0, 0, 1)
: IPAddress (127, 0, 0, 1); }
bool IPAddress::operator== (const IPAddress& other) const noexcept { return compare (other) == 0; }
bool IPAddress::operator!= (const IPAddress& other) const noexcept { return compare (other) != 0; }
bool IPAddress::operator< (const IPAddress& other) const noexcept { return compare (other) < 0; }
bool IPAddress::operator<= (const IPAddress& other) const noexcept { return compare (other) <= 0; }
bool IPAddress::operator> (const IPAddress& other) const noexcept { return compare (other) > 0; }
bool IPAddress::operator>= (const IPAddress& other) const noexcept { return compare (other) >= 0; }
int IPAddress::compare (const IPAddress& other) const noexcept
{
if (isIPv6 != other.isIPv6)
{
if (isIPv6)
{
if (isIPv4MappedAddress (*this))
return convertIPv4MappedAddressToIPv4 (*this).compare (other);
return 1;
}
if (isIPv4MappedAddress (other))
return compare (convertIPv4MappedAddressToIPv4 (other));
return -1;
}
for (int i = 0; i < (isIPv6 ? 16 : 4); ++i)
{
if (address[i] > other.address[i]) return 1;
if (address[i] < other.address[i]) return -1;
}
return 0;
}
IPAddress IPAddress::any() noexcept { return IPAddress(); }
IPAddress IPAddress::broadcast() noexcept { return IPAddress (255, 255, 255, 255); }
IPAddress IPAddress::local (bool IPv6) noexcept { return IPv6 ? IPAddress (0, 0, 0, 0, 0, 0, 0, 1)
: IPAddress (127, 0, 0, 1); }
String IPAddress::getFormattedAddress (const String& unformattedAddress)
{
@ -174,7 +259,7 @@ String IPAddress::getFormattedAddress (const String& unformattedAddress)
for (int i = 0; i < tokens.size(); ++i)
{
const auto& t = tokens.getReference (i);
auto& t = tokens.getReference (i);
if (t.getHexValue32() == 0x0000)
{
@ -232,73 +317,149 @@ String IPAddress::getFormattedAddress (const String& unformattedAddress)
return addressString;
}
bool IPAddress::operator== (const IPAddress& other) const noexcept
bool IPAddress::isIPv4MappedAddress (const IPAddress& mappedAddress)
{
for (int i = 0; i < (isIPv6 ? 16 : 4); ++i)
if (address[i] != other.address[i])
if (! mappedAddress.isIPv6)
return false;
for (int i = 0; i < 10; ++i)
if (mappedAddress.address[i] != 0)
return false;
if (mappedAddress.address[10] != 255 || mappedAddress.address[11] != 255)
return false;
return true;
}
bool IPAddress::operator!= (const IPAddress& other) const noexcept
IPAddress IPAddress::convertIPv4MappedAddressToIPv4 (const IPAddress& mappedAddress)
{
return ! operator== (other);
// The address that you're converting needs to be IPv6!
jassert (mappedAddress.isIPv6);
if (isIPv4MappedAddress (mappedAddress))
return { mappedAddress.address[12], mappedAddress.address[13],
mappedAddress.address[14], mappedAddress.address[15] };
return {};
}
#if (! JUCE_WINDOWS) && (! JUCE_ANDROID)
static void addAddress (const sockaddr_in* addr_in, Array<IPAddress>& result)
IPAddress IPAddress::convertIPv4AddressToIPv4Mapped (const IPAddress& addressToMap)
{
auto addr = addr_in->sin_addr.s_addr;
// The address that you're converting needs to be IPv4!
jassert (! addressToMap.isIPv6);
if (addr != INADDR_NONE)
result.addIfNotAlreadyThere (IPAddress (ntohl (addr)));
return { 0x0, 0x0, 0x0, 0x0, 0x0, 0xffff,
static_cast<uint16> ((addressToMap.address[0] << 8) | addressToMap.address[1]),
static_cast<uint16> ((addressToMap.address[2] << 8) | addressToMap.address[3]) };
}
static void addAddress (const sockaddr_in6* addr_in, Array<IPAddress>& result)
IPAddress IPAddress::getLocalAddress (bool includeIPv6)
{
in6_addr addr = addr_in->sin6_addr;
auto addresses = getAllAddresses (includeIPv6);
typedef union
for (auto& a : addresses)
if (a != local())
return a;
return local();
}
Array<IPAddress> IPAddress::getAllAddresses (bool includeIPv6)
{
Array<IPAddress> addresses;
findAllAddresses (addresses, includeIPv6);
return addresses;
}
//==============================================================================
#if JUCE_UNIT_TESTS
struct IPAddressTests : public UnitTest
{
IPAddressTests()
: UnitTest ("IPAddress", "Networking")
{
uint16 combined;
uint8 split[2];
} ByteUnion;
ByteUnion temp;
uint16 arr[8];
for (int i = 0; i < 8; ++i) // Swap bytes from network to host order
{
temp.split[0] = addr.s6_addr[i * 2 + 1];
temp.split[1] = addr.s6_addr[i * 2];
arr[i] = temp.combined;
}
IPAddress ip (arr);
result.addIfNotAlreadyThere (ip);
}
void IPAddress::findAllAddresses (Array<IPAddress>& result, bool includeIPv6)
{
struct ifaddrs *ifaddr, *ifa;
if (getifaddrs (&ifaddr) == -1)
return;
for (ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next)
void runTest() override
{
if (ifa->ifa_addr == nullptr)
continue;
if (ifa->ifa_addr->sa_family == AF_INET) addAddress ((const sockaddr_in*) ifa->ifa_addr, result);
else if (ifa->ifa_addr->sa_family == AF_INET6 && includeIPv6) addAddress ((const sockaddr_in6*) ifa->ifa_addr, result);
testConstructors();
testFindAllAddresses();
testFindBroadcastAddress();
}
freeifaddrs (ifaddr);
}
void testConstructors()
{
beginTest ("constructors");
// Default IPAdress should be null
IPAddress defaultConstructed;
expect (defaultConstructed.isNull());
auto local = IPAddress::local();
expect (! local.isNull());
IPAddress ipv4{1, 2, 3, 4};
expect (! ipv4.isNull());
expect (! ipv4.isIPv6);
expect (ipv4.toString() == "1.2.3.4");
}
void testFindAllAddresses()
{
beginTest ("find all addresses");
Array<IPAddress> ipv4Addresses;
Array<IPAddress> allAddresses;
IPAddress::findAllAddresses (ipv4Addresses, false);
IPAddress::findAllAddresses (allAddresses, true);
expect (allAddresses.size() >= ipv4Addresses.size());
for (auto& a : ipv4Addresses)
{
expect (! a.isNull());
expect (! a.isIPv6);
}
for (auto& a : allAddresses)
{
expect (! a.isNull());
}
}
void testFindBroadcastAddress()
{
beginTest ("broadcast addresses");
Array<IPAddress> addresses;
// Only IPv4 interfaces have broadcast
IPAddress::findAllAddresses (addresses, false);
for (auto& a : addresses)
{
expect (! a.isNull());
auto broadcastAddress = IPAddress::getInterfaceBroadcastAddress (a);
// If we retrieve an address, it should be an IPv4 address
if (! broadcastAddress.isNull())
{
expect (! a.isIPv6);
}
}
// Expect to fail to find a broadcast for this address
IPAddress address{1, 2, 3, 4};
expect (IPAddress::getInterfaceBroadcastAddress (address).isNull());
}
};
static IPAddressTests iPAddressTests;
#endif
} // namespace juce

View File

@ -32,26 +32,45 @@ namespace juce
class JUCE_API IPAddress final
{
public:
//==============================================================================
/** Returns an IP address meaning "any", equivalent to 0.0.0.0 (IPv4) or ::, (IPv6) */
static IPAddress any() noexcept;
/** Returns an IPv4 address meaning "broadcast" (255.255.255.255) */
static IPAddress broadcast() noexcept;
/** Returns an IPv4 or IPv6 address meaning "localhost", equivalent to 127.0.0.1 (IPv4) or ::1 (IPv6) */
static IPAddress local (bool IPv6 = false) noexcept;
//==============================================================================
/** Populates a list of all the IP addresses that this machine is using. */
static void findAllAddresses (Array<IPAddress>& results, bool includeIPv6 = false);
//==============================================================================
/** Creates a null address - 0.0.0.0 (IPv4) or ::, (IPv6)
@param IPv6 if true indicates that this is an IPv6 address
/** Populates a list of all the IP addresses that this machine is using. */
static Array<IPAddress> getAllAddresses (bool includeIPv6 = false);
/** Returns the first 'real' address for the local machine.
Unlike local(), this will attempt to find the machine's actual assigned
address rather than "127.0.0.1". If there are multiple network cards, this
may return any of their addresses. If it doesn't find any, then it'll return
local() as a fallback.
*/
IPAddress (bool IPv6 = false) noexcept;
static IPAddress getLocalAddress (bool includeIPv6 = false);
//==============================================================================
/** Creates a null address - 0.0.0.0 (IPv4) or ::, (IPv6) */
IPAddress() noexcept;
/** Creates an IPv4 or IPv6 address by reading 4 or 16 bytes from an array.
@param bytes The array containing the bytes to read.
@param IPv6 if true indicates that 16 bytes should be read instead of 4.
*/
explicit IPAddress (const uint8 bytes[], bool IPv6 = false) noexcept;
explicit IPAddress (const uint8* bytes, bool IPv6 = false) noexcept;
/** Creates an IPv6 address from an array of 8 16-bit integers
@param bytes The array containing the bytes to read.
*/
explicit IPAddress (const uint16 bytes[8]) noexcept;
explicit IPAddress (const uint16* bytes) noexcept;
/** Creates an IPv4 address from 4 bytes. */
IPAddress (uint8 address1, uint8 address2, uint8 address3, uint8 address4) noexcept;
@ -68,47 +87,56 @@ public:
/** Parses a string IP address of the form "1.2.3.4" (IPv4) or "1:2:3:4:5:6:7:8" (IPv6). */
explicit IPAddress (const String& address);
/** Returns whether the address contains the null address (e.g. 0.0.0.0). */
bool isNull() const;
//==============================================================================
/** Returns a dot- or colon-separated string in the form "1.2.3.4" (IPv4) or "1:2:3:4:5:6:7:8" (IPv6). */
String toString() const;
/** Returns an IPv4 or IPv6 address meaning "any", equivalent to 0.0.0.0 (IPv4) or ::, (IPv6) */
static IPAddress any (bool IPv6 = false) noexcept;
/** Compares this IPAddress with another.
/** Returns an IPv4 address meaning "broadcast" (255.255.255.255) */
static IPAddress broadcast() noexcept;
/** Returns an IPv4 or IPv6 address meaning "localhost", equivalent to 127.0.0.1 (IPv4) or ::1 (IPv6) */
static IPAddress local (bool IPv6 = false) noexcept;
/** Returns a formatted version of the provided IPv6 address conforming to RFC 5952 with leading zeros suppressed,
lower case characters, and double-colon notation used to represent contiguous 16-bit fields of zeros.
@param unformattedAddress the IPv6 address to be formatted
@returns 0 if the two addresses are identical, negative if this address is smaller than
the other one, or positive if is greater.
*/
static String getFormattedAddress (const String& unformattedAddress);
int compare (const IPAddress&) const noexcept;
bool operator== (const IPAddress& other) const noexcept;
bool operator!= (const IPAddress& other) const noexcept;
bool operator== (const IPAddress&) const noexcept;
bool operator!= (const IPAddress&) const noexcept;
bool operator< (const IPAddress&) const noexcept;
bool operator> (const IPAddress&) const noexcept;
bool operator<= (const IPAddress&) const noexcept;
bool operator>= (const IPAddress&) const noexcept;
//==============================================================================
/** The elements of the IP address. */
uint8 address[16];
bool isIPv6;
bool isIPv6 = false;
private:
/** Union used to split a 16-bit unsigned integer into 2 8-bit unsigned integers or vice-versa */
typedef union
{
uint16 combined;
uint8 split[2];
} ByteUnion;
//==============================================================================
/** Returns a formatted version of the provided IPv6 address conforming to RFC 5952 with leading zeros suppressed,
lower case characters, and double-colon notation used to represent contiguous 16-bit fields of zeros.
/** Method used to zero the remaining bytes of the address array when creating IPv4 addresses */
void zeroUnusedBytes()
{
for (int i = 4; i < 16; ++i)
address[i] = 0;
}
@param unformattedAddress the IPv6 address to be formatted
*/
static String getFormattedAddress (const String& unformattedAddress);
/** Returns true if the given IP address is an IPv4-mapped IPv6 address. */
static bool isIPv4MappedAddress (const IPAddress& mappedAddress);
/** Converts an IPv4-mapped IPv6 address to an IPv4 address.
If the address is not IPv4-mapped, this will return a null address.
*/
static IPAddress convertIPv4MappedAddressToIPv4 (const IPAddress& mappedAddress);
/** Converts an IPv4 address to an IPv4-mapped IPv6 address. */
static IPAddress convertIPv4AddressToIPv4Mapped (const IPAddress& addressToMap);
/** If the IPAdress is the address of an interface on the machine, returns the associated broadcast address.
If the address is not an interface, it will return a null address.
*/
static IPAddress getInterfaceBroadcastAddress (const IPAddress& interfaceAddress);
};
} // namespace juce

View File

@ -85,6 +85,13 @@ int64 MACAddress::toInt64() const noexcept
return n;
}
Array<MACAddress> MACAddress::getAllAddresses()
{
Array<MACAddress> addresses;
findAllAddresses (addresses);
return addresses;
}
bool MACAddress::isNull() const noexcept { return toInt64() == 0; }
bool MACAddress::operator== (const MACAddress& other) const noexcept { return memcmp (address, other.address, sizeof (address)) == 0; }

View File

@ -33,6 +33,9 @@ class JUCE_API MACAddress final
{
public:
//==============================================================================
/** Returns a list of the MAC addresses of all the available network cards. */
static Array<MACAddress> getAllAddresses();
/** Populates a list of the MAC addresses of all the available network cards. */
static void findAllAddresses (Array<MACAddress>& results);

View File

@ -60,4 +60,198 @@ String NamedPipe::getName() const
// other methods for this class are implemented in the platform-specific files
//==============================================================================
#if JUCE_UNIT_TESTS
class NamedPipeTests : public UnitTest
{
public:
//==============================================================================
NamedPipeTests()
: UnitTest ("NamedPipe", "Networking")
{}
void runTest() override
{
const String pipeName ("TestPipe");
beginTest ("Pre test cleanup");
{
NamedPipe pipe;
expect (pipe.createNewPipe (pipeName, false));
}
beginTest ("Create pipe");
{
NamedPipe pipe;
expect (! pipe.isOpen());
expect (pipe.createNewPipe (pipeName, true));
expect (pipe.isOpen());
expect (pipe.createNewPipe (pipeName, false));
expect (pipe.isOpen());
NamedPipe otherPipe;
expect (! otherPipe.createNewPipe (pipeName, true));
expect (! otherPipe.isOpen());
}
beginTest ("Existing pipe");
{
NamedPipe pipe;
expect (! pipe.openExisting (pipeName));
expect (! pipe.isOpen());
expect (pipe.createNewPipe (pipeName, true));
NamedPipe otherPipe;
expect (otherPipe.openExisting (pipeName));
expect (otherPipe.isOpen());
}
int sendData = 4684682;
beginTest ("Receive message created pipe");
{
NamedPipe pipe;
expect (pipe.createNewPipe (pipeName, true));
WaitableEvent senderFinished;
SenderThread sender (pipeName, false, senderFinished, sendData);
sender.startThread();
int recvData = -1;
auto bytesRead = pipe.read (&recvData, sizeof (recvData), 2000);
expect (senderFinished.wait (4000));
expectEquals (bytesRead, (int) sizeof (recvData));
expectEquals (sender.result, (int) sizeof (sendData));
expectEquals (recvData, sendData);
}
beginTest ("Receive message existing pipe");
{
WaitableEvent senderFinished;
SenderThread sender (pipeName, true, senderFinished, sendData);
NamedPipe pipe;
expect (pipe.openExisting (pipeName));
sender.startThread();
int recvData = -1;
auto bytesRead = pipe.read (&recvData, sizeof (recvData), 2000);
expect (senderFinished.wait (4000));
expectEquals (bytesRead, (int) sizeof (recvData));
expectEquals (sender.result, (int) sizeof (sendData));
expectEquals (recvData, sendData);
}
beginTest ("Send message created pipe");
{
NamedPipe pipe;
expect (pipe.createNewPipe (pipeName, true));
WaitableEvent receiverFinished;
ReceiverThread receiver (pipeName, false, receiverFinished);
receiver.startThread();
auto bytesWritten = pipe.write (&sendData, sizeof (sendData), 2000);
expect (receiverFinished.wait (4000));
expectEquals (bytesWritten, (int) sizeof (sendData));
expectEquals (receiver.result, (int) sizeof (receiver.recvData));
expectEquals (receiver.recvData, sendData);
}
beginTest ("Send message existing pipe");
{
WaitableEvent receiverFinished;
ReceiverThread receiver (pipeName, true, receiverFinished);
NamedPipe pipe;
expect (pipe.openExisting (pipeName));
receiver.startThread();
auto bytesWritten = pipe.write (&sendData, sizeof (sendData), 2000);
expect (receiverFinished.wait (4000));
expectEquals (bytesWritten, (int) sizeof (sendData));
expectEquals (receiver.result, (int) sizeof (receiver.recvData));
expectEquals (receiver.recvData, sendData);
}
}
private:
//==============================================================================
struct NamedPipeThread : public Thread
{
NamedPipeThread (const String& threadName, const String& pName,
bool shouldCreatePipe, WaitableEvent& completed)
: Thread (threadName), pipeName (pName), workCompleted (completed)
{
if (shouldCreatePipe)
pipe.createNewPipe (pipeName);
else
pipe.openExisting (pipeName);
}
NamedPipe pipe;
const String& pipeName;
WaitableEvent& workCompleted;
int result = -2;
};
//==============================================================================
struct SenderThread : public NamedPipeThread
{
SenderThread (const String& pName, bool shouldCreatePipe,
WaitableEvent& completed, int sData)
: NamedPipeThread ("NamePipeSender", pName, shouldCreatePipe, completed),
sendData (sData)
{}
void run() override
{
result = pipe.write (&sendData, sizeof (sendData), 2000);
workCompleted.signal();
}
const int sendData;
};
//==============================================================================
struct ReceiverThread : public NamedPipeThread
{
ReceiverThread (const String& pName, bool shouldCreatePipe,
WaitableEvent& completed)
: NamedPipeThread ("NamePipeSender", pName, shouldCreatePipe, completed)
{}
void run() override
{
result = pipe.read (&recvData, sizeof (recvData), 2000);
workCompleted.signal();
}
int recvData = -2;
};
};
static NamedPipeTests namedPipeTests;
#endif
} // namespace juce

View File

@ -264,7 +264,7 @@ namespace SocketHelpers
}
else
{
timeoutp = 0;
timeoutp = nullptr;
}
fd_set rset, wset;
@ -282,7 +282,8 @@ namespace SocketHelpers
#else
{
int result;
while ((result = select (h + 1, prset, pwset, 0, timeoutp)) < 0
while ((result = select (h + 1, prset, pwset, nullptr, timeoutp)) < 0
&& errno == EINTR)
{
}
@ -590,11 +591,9 @@ bool StreamingSocket::isLocal() const noexcept
if (! isConnected())
return false;
Array<IPAddress> localAddresses;
IPAddress::findAllAddresses (localAddresses);
IPAddress currentIP (SocketHelpers::getConnectedAddress (handle));
for (auto& a : localAddresses)
for (auto& a : IPAddress::getAllAddresses())
if (a == currentIP)
return true;

View File

@ -68,7 +68,7 @@ public:
network address otherwise this function will fail.
@returns true on success; false may indicate that another socket is already bound
on the same port
@see bindToPort(int localPortNumber), IPAddress::findAllAddresses
@see bindToPort(int localPortNumber), IPAddress::getAllAddresses
*/
bool bindToPort (int localPortNumber, const String& localAddress);
@ -236,7 +236,7 @@ public:
network address otherwise this function will fail.
@returns true on success; false may indicate that another socket is already bound
on the same port
@see bindToPort(int localPortNumber), IPAddress::findAllAddresses
@see bindToPort(int localPortNumber), IPAddress::getAllAddresses
*/
bool bindToPort (int localPortNumber, const String& localAddress);

View File

@ -40,13 +40,14 @@ struct FallbackDownloadTask : public URL::DownloadTask,
jassert (fileStream != nullptr);
jassert (stream != nullptr);
contentLength = stream->getTotalLength();
httpCode = stream->getStatusCode();
targetLocation = fileStream->getFile();
contentLength = stream->getTotalLength();
httpCode = stream->getStatusCode();
startThread();
}
~FallbackDownloadTask()
~FallbackDownloadTask() override
{
signalThreadShouldExit();
stream->cancel();
@ -61,10 +62,10 @@ struct FallbackDownloadTask : public URL::DownloadTask,
if (listener != nullptr)
listener->progress (this, downloaded, contentLength);
const int max = jmin ((int) bufferSize, contentLength < 0 ? std::numeric_limits<int>::max()
: static_cast<int> (contentLength - downloaded));
auto max = jmin ((int) bufferSize, contentLength < 0 ? std::numeric_limits<int>::max()
: static_cast<int> (contentLength - downloaded));
const int actual = stream->read (buffer.get(), max);
auto actual = stream->read (buffer.get(), max);
if (actual < 0 || threadShouldExit() || stream->isError())
break;
@ -118,9 +119,7 @@ URL::DownloadTask* URL::DownloadTask::createFallbackDownloader (const URL& urlTo
const size_t bufferSize = 0x8000;
targetFileToUse.deleteFile();
std::unique_ptr<FileOutputStream> outputStream (targetFileToUse.createOutputStream (bufferSize));
if (outputStream != nullptr)
if (auto outputStream = std::unique_ptr<FileOutputStream> (targetFileToUse.createOutputStream (bufferSize)))
{
std::unique_ptr<WebInputStream> stream (new WebInputStream (urlToUse, usePostRequest));
stream->withExtraHeaders (extraHeadersToUse);
@ -186,8 +185,8 @@ void URL::init()
{
do
{
const int nextAmp = url.indexOfChar (i + 1, '&');
const int equalsPos = url.indexOfChar (i + 1, '=');
auto nextAmp = url.indexOfChar (i + 1, '&');
auto equalsPos = url.indexOfChar (i + 1, '=');
if (nextAmp < 0)
{
@ -211,26 +210,26 @@ void URL::init()
URL::URL (const String& u, int) : url (u) {}
URL::URL (URL&& other)
: url (static_cast<String&&> (other.url)),
postData (static_cast<MemoryBlock&&> (other.postData)),
parameterNames (static_cast<StringArray&&> (other.parameterNames)),
parameterValues (static_cast<StringArray&&> (other.parameterValues)),
filesToUpload (static_cast<ReferenceCountedArray<Upload>&&> (other.filesToUpload))
: url (std::move (other.url)),
postData (std::move (other.postData)),
parameterNames (std::move (other.parameterNames)),
parameterValues (std::move (other.parameterValues)),
filesToUpload (std::move (other.filesToUpload))
#if JUCE_IOS
, bookmark (static_cast<Bookmark::Ptr&&> (other.bookmark))
, bookmark (std::move (other.bookmark))
#endif
{
}
URL& URL::operator= (URL&& other)
{
url = static_cast<String&&> (other.url);
postData = static_cast<MemoryBlock&&> (other.postData);
parameterNames = static_cast<StringArray&&> (other.parameterNames);
parameterValues = static_cast<StringArray&&> (other.parameterValues);
filesToUpload = static_cast<ReferenceCountedArray<Upload>&&> (other.filesToUpload);
url = std::move (other.url);
postData = std::move (other.postData);
parameterNames = std::move (other.parameterNames);
parameterValues = std::move (other.parameterValues);
filesToUpload = std::move (other.filesToUpload);
#if JUCE_IOS
bookmark = static_cast<Bookmark::Ptr&&> (other.bookmark);
bookmark = std::move (other.bookmark);
#endif
return *this;
@ -324,7 +323,7 @@ void URL::addParameter (const String& name, const String& value)
parameterValues.add (value);
}
String URL::toString (const bool includeGetParameters) const
String URL::toString (bool includeGetParameters) const
{
if (includeGetParameters && parameterNames.size() > 0)
return url + "?" + URLHelpers::getMangledParameters (*this);
@ -345,14 +344,7 @@ bool URL::isWellFormed() const
String URL::getDomain() const
{
auto start = URLHelpers::findStartOfNetLocation (url);
auto end1 = url.indexOfChar (start, '/');
auto end2 = url.indexOfChar (start, ':');
auto end = (end1 < 0 && end2 < 0) ? std::numeric_limits<int>::max()
: ((end1 < 0 || end2 < 0) ? jmax (end1, end2)
: jmin (end1, end2));
return url.substring (start, end);
return getDomainInternal (false);
}
String URL::getSubPath() const
@ -393,7 +385,7 @@ File URL::fileFromFileSchemeURL (const URL& fileURL)
return {};
}
auto path = removeEscapeChars (fileURL.getDomain()).replace ("+", "%2B");
auto path = removeEscapeChars (fileURL.getDomainInternal (true)).replace ("+", "%2B");
#ifdef JUCE_WINDOWS
bool isUncPath = (! fileURL.url.startsWith ("file:///"));
@ -531,6 +523,18 @@ bool URL::isProbablyAnEmailAddress (const String& possibleEmailAddress)
&& ! possibleEmailAddress.endsWithChar ('.');
}
String URL::getDomainInternal (bool ignorePort) const
{
auto start = URLHelpers::findStartOfNetLocation (url);
auto end1 = url.indexOfChar (start, '/');
auto end2 = ignorePort ? -1 : url.indexOfChar (start, ':');
auto end = (end1 < 0 && end2 < 0) ? std::numeric_limits<int>::max()
: ((end1 < 0 || end2 < 0) ? jmax (end1, end2)
: jmin (end1, end2));
return url.substring (start, end);
}
#if JUCE_IOS
URL::Bookmark::Bookmark (void* bookmarkToUse)
: data (bookmarkToUse)
@ -576,11 +580,11 @@ public:
BOOL isBookmarkStale = false;
NSError* error = nil;
auto* nsURL = [NSURL URLByResolvingBookmarkData: bookmark
options: 0
relativeToURL: nil
bookmarkDataIsStale: &isBookmarkStale
error: &error];
auto nsURL = [NSURL URLByResolvingBookmarkData: bookmark
options: 0
relativeToURL: nil
bookmarkDataIsStale: &isBookmarkStale
error: &error];
if (error == nil)
{
@ -591,7 +595,7 @@ public:
}
else
{
auto* desc = [error localizedDescription];
auto desc = [error localizedDescription];
ignoreUnused (desc);
jassertfalse;
}
@ -609,10 +613,10 @@ private:
BOOL isBookmarkStale = false;
NSError* error = nil;
auto* nsURL = [NSURL URLByResolvingBookmarkData: bookmark
options: 0
relativeToURL: nil
bookmarkDataIsStale: &isBookmarkStale
auto nsURL = [NSURL URLByResolvingBookmarkData: bookmark
options: 0
relativeToURL: nil
bookmarkDataIsStale: &isBookmarkStale
error: &error];
if (error == nil)
@ -626,7 +630,7 @@ private:
}
else
{
auto* desc = [error localizedDescription];
auto desc = [error localizedDescription];
ignoreUnused (desc);
jassertfalse;
}
@ -653,14 +657,14 @@ private:
#endif
//==============================================================================
InputStream* URL::createInputStream (const bool usePostCommand,
OpenStreamProgressCallback* const progressCallback,
void* const progressCallbackContext,
InputStream* URL::createInputStream (bool usePostCommand,
OpenStreamProgressCallback* progressCallback,
void* progressCallbackContext,
String headers,
const int timeOutMs,
StringPairArray* const responseHeaders,
int timeOutMs,
StringPairArray* responseHeaders,
int* statusCode,
const int numRedirectsToFollow,
int numRedirectsToFollow,
String httpRequestCmd) const
{
if (isLocalFile())
@ -684,10 +688,10 @@ InputStream* URL::createInputStream (const bool usePostCommand,
bool postDataSendProgress (WebInputStream&, int bytesSent, int totalBytes) override
{
return callback(data, bytesSent, totalBytes);
return callback (data, bytesSent, totalBytes);
}
OpenStreamProgressCallback* const callback;
OpenStreamProgressCallback* callback;
void* const data;
// workaround a MSVC 2013 compiler warning
@ -858,8 +862,8 @@ String URL::removeEscapeChars (const String& s)
{
if (utf8.getUnchecked(i) == '%')
{
const int hexDigit1 = CharacterFunctions::getHexDigitValue ((juce_wchar) (uint8) utf8 [i + 1]);
const int hexDigit2 = CharacterFunctions::getHexDigitValue ((juce_wchar) (uint8) utf8 [i + 2]);
auto hexDigit1 = CharacterFunctions::getHexDigitValue ((juce_wchar) (uint8) utf8 [i + 1]);
auto hexDigit2 = CharacterFunctions::getHexDigitValue ((juce_wchar) (uint8) utf8 [i + 2]);
if (hexDigit1 >= 0 && hexDigit2 >= 0)
{

View File

@ -284,7 +284,7 @@ public:
It allows your app to receive progress updates during a lengthy POST operation. If you
want to continue the operation, this should return true, or false to abort.
*/
typedef bool (OpenStreamProgressCallback) (void* context, int bytesSent, int totalBytes);
using OpenStreamProgressCallback = bool (void* context, int bytesSent, int totalBytes);
/** Attempts to open a stream that can read from this URL.
@ -347,27 +347,26 @@ public:
//==============================================================================
/** Represents a download task.
Returned by downloadToFile to allow querying and controling the download task.
Returned by downloadToFile to allow querying and controlling the download task.
*/
class DownloadTask
class JUCE_API DownloadTask
{
public:
/** Used to receive callbacks for download progress */
struct Listener
struct JUCE_API Listener
{
virtual ~Listener();
/** Called when the download has finished. Be aware that this callback may
come on an arbitrary thread. */
virtual void finished (DownloadTask* task, bool success) = 0;
virtual void finished (URL::DownloadTask* task, bool success) = 0;
/** Called periodically by the OS to indicate download progress.
Beware that this callback may come on an arbitrary thread.
*/
virtual void progress (DownloadTask* task, int64 bytesDownloaded, int64 totalLength);
virtual void progress (URL::DownloadTask* task, int64 bytesDownloaded, int64 totalLength);
};
/** Releases the resources of the download task, unregisters the listener
and cancels the download if necessary. */
virtual ~DownloadTask();
@ -391,10 +390,14 @@ public:
/** Returns true if there was an error. */
inline bool hadError() const { return error; }
/** Returns the target file location that was provided in URL::downloadToFile. */
File getTargetLocation() const { return targetLocation; }
protected:
int64 contentLength = -1, downloaded = 0;
bool finished = false, error = false;
int httpCode = -1;
File targetLocation;
DownloadTask();
@ -464,7 +467,7 @@ public:
If it fails, or if the text that it reads can't be parsed as XML, this will
return nullptr.
When it returns a valid XmlElement object, the caller is responsibile for deleting
When it returns a valid XmlElement object, the caller is responsible for deleting
this object when no longer needed.
Note that on some platforms (Android, for example) it's not permitted to do any network
@ -526,6 +529,7 @@ private:
StringArray parameterNames, parameterValues;
static File fileFromFileSchemeURL (const URL&);
String getDomainInternal (bool) const;
struct Upload : public ReferenceCountedObject
{
@ -537,7 +541,6 @@ private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Upload)
};
friend struct ContainerDeletePolicy<Upload>;
ReferenceCountedArray<Upload> filesToUpload;
#if JUCE_IOS

View File

@ -36,7 +36,7 @@ class JUCE_API WebInputStream : public InputStream
class JUCE_API Listener
{
public:
virtual ~Listener() {}
virtual ~Listener() = default;
virtual bool postDataSendProgress (WebInputStream& /*request*/, int /*bytesSent*/, int /*totalBytes*/) { return true; }
};
@ -50,7 +50,7 @@ class JUCE_API WebInputStream : public InputStream
*/
WebInputStream (const URL& url, const bool usePost);
~WebInputStream();
~WebInputStream() override;
/** Add extra headers to http request
@ -101,7 +101,7 @@ class JUCE_API WebInputStream : public InputStream
If getResponseHeaders is called without an established connection, then
getResponseHeaders will call connect internally and block until connect
returns - either due to a succesful connection or a connection
returns - either due to a successful connection or a connection
error.
@see connect
@ -112,7 +112,7 @@ class JUCE_API WebInputStream : public InputStream
If getStatusCode is called without an established connection, then
getStatusCode will call connect internally and block until connect
returns - either due to a succesful connection or a connection
returns - either due to a successful connection or a connection
error.
@see connect
@ -153,7 +153,7 @@ class JUCE_API WebInputStream : public InputStream
If getTotalLength is called without an established connection, then
getTotalLength will call connect internally and block until connect
returns - either due to a succesful connection or a connection
returns - either due to a successful connection or a connection
error.
If the size of the stream isn't actually known, this will return -1.