IPAddress::getInterfaceBroadcastAddress() on Windows

Hi everyone.

I am making use of the IPAddress::getInterfaceBroadcastAddress(const IPAddress&) function in an app, which I initially built on MacOS. Now I started porting the thing to Windows and had to realise that where the implementation of that function should be, there’s only a comment saying TODO (see juce_win32_Network.cpp, line 593)

Does anyone have a solution on how to implement this for Windows? I don’t know very much about Windows platform specific implementations, so any help on how to get this working on Win would be appreciated.

Thanks

So, after banging my head against this for a couple of hours and after endless copy pasting from Windows documentation and stackoverflow I think I figured out a solution. I forked the Juce repo and created a pull request here:

I have no idea as for how good this is, if this is correct or can be done better (I assume so?)… But it’s working for me and delivers the same behaviour as on OSX and the broadcast addresses returned by this are correct, as far as I can tell.

I had to solve this problem some time ago too. Your solution is ok for Windows. I had to deal with oddities on some platforms (with non standard network interfaces), so came to a little dirty solution but working in the real world as far I can tell. Additionally there is a possibility to add a separate local IP address (passed as ip parameter in the Advertiser constructor) for platforms where one has to obtain local ip by other means. It will send broadcast to all computers working it the same subnet - my experience is some routers do not allow to send broadcast to other subnets (probably it’s a matter of router configuration). Maybe it will be helpful for somebody else.

void CustomNetworkServiceDiscovery::Advertiser::sendBroadcast()
{
    IPAddress address;
    IPAddress broadcastAddress;

    /*
    10.0.0.0 – 10.255.255.255 (Class A)
    172.16.0.0 – 172.31.255.255 (Class B)
    192.168.0.0 – 192.168.255.255 (Class C)
    */

    auto addresses = ip.isNull() ? IPAddress::getAllAddresses() : Array<IPAddress> { ip };

    for (auto& a: addresses)
    {
        if (a.isNull())
            continue;

        auto sa = StringArray::fromTokens (a.toString(), ".", {});

        if (sa.size() < 4)
            continue;

        // class A
        if (sa[0] == "10")
        {
            address = a;
            broadcastAddress = IPAddress ("10." + sa[1] + ".255.255");
            break;
        }

        // class B
        if (sa[0] == "172" && (sa[1].getIntValue() >= 16 && sa[1].getIntValue() <= 31))
        {
            address = a;
            broadcastAddress = IPAddress ("172." + sa[1] + ".255.255");
            break;
        }

        // class C
        if (sa[0] == "192" && sa[1] == "168")
        {
            address = a;
            broadcastAddress = IPAddress ("192.168." + sa[2] + ".255");
            break;
        }
    }

    if (address.isNull() || broadcastAddress.isNull())
        return;
        
    message.setAttribute ("address", address.toString());
    // auto data = message.createDocument ({}, true, false); /* JUCE 5.4.3 */
    auto data = message.toString (XmlElement::TextFormat().singleLine().withoutHeader());
    socket.write (broadcastAddress.toString(), broadcastPort, data.toRawUTF8(), (int) data.getNumBytesAsUTF8());
}

Yeah I’m using it similarly.

Very cool, I didn’t know about fromTokens(), gonna update that in my solution.