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:
@ -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
|
||||
|
@ -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
|
||||
|
@ -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; }
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
Reference in New Issue
Block a user