Kore WOL feature works only partially
#1
Hi,

There seems to be a problem with WOL.
If I go and write manually port 9 in settings while Kodi is running and connected, and then shut down the PC and try WOL - it works fine.
If I force close the app and try again (in my case, went to sleep and tried again in the morning) - doesn't work anymore.

Writing 9 at port (I assume it doesn't really change anything, as it's the same default port) seems to be triggering something that makes a difference.
Just to make sure it's not my PC or Android, when I try the same with Wake On LAN app, it starts the PC every time.
MAC address is showing correctly in the server settings, defined in Wake On LAN app as well.

I'm pretty familiar with PCs. Not to the point where I would install WireShark and start sniffing the net for the "Magic packet", but if it'll be required and no way around it - I might try.


In addition, since I've already registered - another small thing which I'm just not sure about, might be a bug and might not.
When starting a picture slideshow, the first photo that started it is the one showing on the remote, it doesn't change. If I rotate the phone - it does change to the currently showing photo. Is that intentional behavior?


If any testing will be required - I can join Beta program, shouldn't be a problem.

Thanks.
Reply
#2
OK, I got a bit deeper. Downloaded packet sniffer for Android and Wireshark, recorded network traffic and found the differences. There were only 2 of them:

1. WOL packet from Kore came out on port 39269, from Wake On LAN app - on ports 40838 and 41035.
2. There was only one WOL packet from Kore towards the destination IP (192.168.1.xxx), but Wake On LAN app has sent 2 packets - one to the same destination IP (192.168.1.xxx) and one to 192.168.1.255.

Otherwise the packets looked the same, excluding checksum (correctness of which I couldn't verify, but it would obviously change with changed source ports).

I guess that the extra packet to 192.168.1.255 makes a difference. The question is - why, and why is it needed at all.
Reply
#3
OK, some more conclusions from my testing (and I have taken quite a few Wireshark logs for that):

I've made 2 recordings:
a. 3 repeated failing attempts of WOL by Kore, followed by 1 working attempt by Wake On LAN app.
b. A single successful attempt of WOL by Kore by the method I've described (manually setting destination port to 9 while Kodi is running and Kore is connected, shutting down Kodi PC through the remote, and calling WOL from the remote - all without exiting Kore).

The first time I got 4 packets (no extra packets this time) - 3 packets (from Kore) with source ports 36986, 36448, 36423 and 1 packet (from WOL app) with source port 56543.
The second time I got 1 packet only - with source port 56266 (from Kore).


So, I thought the conclusion is - UDP source port number above 40000 works, below 40000 doesn't.

But then I've ran Wireshark on the working target PC and captured everything that went its way, and I saw that there were mixed packets from Kodi - above and below source port 40000. Then I turned off the PC and Kodi again couldn't wake it up at all - and I tried 30-40 times. So the previous conclusion was dropped.

And then I understood the reason for 2nd packet by Wake On LAN app. It's a subnet broadcast packet. And this is probably why it always worked.


I guess the best way to actually nail this would be to get the code from Git, compile it here and test the modifications to see what works. Oh well, might be a good reason to update my Android Studio, didn't touch it for a while.

I'll update with the results.
Reply
#4
Alright, additional broadcast-IP WOL packet following the original directed WOL packet worked like charm.

Here's the updated function in NetUtils.java (I don't have a GIT account - hopefully you'll save me the trouble).
Basically it finds every possible broadcast IP and sends WOL packet there, which makes sense - it will only wake up by MAC, so everywhere else it'll just pass and be gone.

Code:
public static boolean sendWolMagicPacket(String macAddress, String hostAddress, int port) {
        if (macAddress == null) {
            return false;
        }

        // Get MAC adress bytes
        byte[] macAddressBytes = new byte[6];
        String[] hex = macAddress.split("(\\:|\\-)");
        if (hex.length != 6) {
            LogUtils.LOGD(TAG, "Send magic packet: got an invalid MAC address: " + macAddress);
            return false;
        }

        try {
            for (int i = 0; i < 6; i++) {
                macAddressBytes[i] = (byte)Integer.parseInt(hex[i], 16);
            }
        }
        catch (NumberFormatException e) {
            LogUtils.LOGD(TAG, "Send magic packet: got an invalid MAC address: " + macAddress);
            return false;
        }

        byte[] bytes = new byte[6 + 16 * macAddressBytes.length];
        for (int i = 0; i < 6; i++) {
            bytes[i] = (byte)0xff;
        }
        for (int i = 6; i < bytes.length; i += macAddressBytes.length) {
            System.arraycopy(macAddressBytes, 0, bytes, i, macAddressBytes.length);
        }

        try {
            InetAddress address = InetAddress.getByName(hostAddress);
            DatagramPacket packet = new DatagramPacket(bytes, bytes.length, address, port);
            DatagramSocket socket = new DatagramSocket();
            socket.send(packet);

            // Piece of code apprehended from here:  http://stackoverflow.com/a/29017289
            // Check all the existing interfaces that can be broadcasted to
            Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
            while (interfaces.hasMoreElements()) {
                NetworkInterface networkInterface = interfaces.nextElement();

                if (networkInterface.isLoopback())
                    continue; // Don't want to broadcast to the loopback interface

                for (InterfaceAddress interfaceAddress : networkInterface.getInterfaceAddresses()) {
                    InetAddress broadcast = interfaceAddress.getBroadcast();
                    // Android seems smart enough to set to null broadcast to
                    //  the external mobile network. It makes sense since Android
                    //  silently drop UDP broadcasts involving external mobile network.
                    // Seems to automatically skip IPv6 as it has broadcast IP null

                    if (broadcast != null) {
                        // Broadcasts WOL Magic Packet to every possible broadcast address
                        packet = new DatagramPacket(bytes, bytes.length, broadcast, port);
                        socket.send(packet);
                    }
                }
            }
            socket.close();
        } catch (IOException e) {
            LogUtils.LOGD(TAG, "Exception while sending magic packet.", e);
            return false;
        }
        return true;
    }



On this happy note, what about this small one?
(2015-03-30, 12:12)Jack_R1 Wrote: When starting a picture slideshow, the first photo that started it is the one showing on the remote, it doesn't change. If I rotate the phone - it does change to the currently showing photo. Is that intentional behavior?
Reply
#5
This is a little more complicated Smile

You need to send to broadcast when on local network but still send targeted UDP for WAN WOL.

Correct code would be to check if the XBMC ip is in the same range as the phone then send to broadcast, if not sent to target IP as it's this router ip that will re broadcast the magic packet.
Reply
#6
But Kodi remote doesn't work on WAN (well, technically if you forward the port and have dynamic DNS service, I suppose you could connect to it from WAN, but I don't really see the point of doing so) Smile

However, this solution (can't really call it mine, as I copied it from Wake On LAN app behavior) isn't limited to the local network only - the code above is sending both a targeted packet (that might work on LAN and might not, probably depending on the router, but should allow working on WAN) and a broadcast packet (that should always work on LAN and never on WAN, won't even be broadcasted). For cases from WAN to LAN need translation of directed packet to broadcast packet - needs to be configured in the router in addition to port forwarding. So, at the cost of having redundant WOL packet(s), it should cover both cases. I suppose I could add a check to see if target IP is in the same subnet and remove the redundancy, but it'll potentially introduce many complications and false detections, and I'm not sure reduced redundancy is worth it.


P.S. I guess the reason original code worked when I changed network settings with a working Kodi PC and then shut it down was also in the router - some of the packets sent when testing the interface might have left "trace" in the routing table, so a directed packet following them would also be routed the same way for some time, until this "trace" faded.
Reply
#7
@Jack_R1,

Nice work, thank you very much. In retrospect, sending it to 255 makes sense. I also agree that the redundancy in this case isn't problematic.

I'll just review the code with a little more attention, test it (though it always worked for me, so there's no reason for it not to work now) and update github.

Thanks!

Regarding the picture slideshow, it's not intentional, but it is what it is Smile. I guess Kodi doesn't send an event when it changes the picture, so the remote isn't notified and doesn't change it. When you rotate the device Kore explicitly asks for what's currently playing and gets the new picture. There's a third scenario: Go into the server's settings and set the TCP port to something that doesn't make sense, forcing all communications through HTTP. The picture should now change with the slideshow as the remote is now actively polling Kodi.
Reply
#8
Works like a charm. I actually had one system where WoL wasn't working and i just assumed that i hadn't enabled it on the interface, but it's working now Smile (i know, assumptions are the mother of all ...)

Oce again, thanks
Reply
#9
Hi,

There seems to be a problem with WOL again.

Quote:If I go and write manually port 9 in settings while Kodi is running and connected, and then shut down the PC and try WOL - it works fine.
If I force close the app and try again (in my case, went to sleep and tried again in the morning) - doesn't work anymore.
- Jack_R1

It doesn't work for me in the first and the second case.

According to tcpdump capture, the WOL magic packets are all well-received from the Kodi server platform.
The UDP source port number is above 40000 for all packets after sampling a lot.
The UDP destination port number is well the default port 9.

I would like to know your expertise about the issue.

Any lead ? (problem with WOL support, bad platform, bad configuration, false alert ?)

Configuration:

Platform: Raspberry-Pi 3
OS: Arch-ARM v7
Kernel: 4.4.32-3
Network: local
Kodi version: 16.1
Kore version: 2.1.0
Default port (WOL): 9
Reply

Logout Mark Read Team Forum Stats Members Help
Kore WOL feature works only partially0