resourcepool / ssdp-client

The most lightweight asynchronous Java SSDP (Simple Service Discovery Protocol) Client
Apache License 2.0
53 stars 21 forks source link

java.io.IOException: sendto failed: EPERM (Operation not permitted) #28

Closed chubecode closed 2 years ago

chubecode commented 2 years ago

Hey, Thankyou for create the beautiful library. But when I using it. Sometime the user complaint to me a lot about cannot scan the device. After check the logs I see that : libcore.io.IoBridge.maybeThrowAfterSendto(IoBridge.java:724), libcore.io.IoBridge.sendto(IoBridge.java:691), java.net.PlainDatagramSocketImpl.send(PlainDatagramSocketImpl.java:126), java.net.DatagramSocket.send(DatagramSocket.java:721), io.resourcepool.ssdp.client.impl.SsdpClientImpl.sendOnAllInterfaces(SsdpClientImpl.java:246), io.resourcepool.ssdp.client.impl.SsdpClientImpl.sendDiscoveryRequest(SsdpClientImpl.java:171), io.resourcepool.ssdp.client.impl.SsdpClientImpl.access$000(SsdpClientImpl.java:33), io.resourcepool.ssdp.client.impl.SsdpClientImpl$2.run(SsdpClientImpl.java:108), java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:462), java.util.concurrent.FutureTask.runAndReset(FutureTask.java:307), java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:302), java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167), java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641), java.lang.Thread.run(Thread.java:920)

Any suggestion about it? How to deal with it? I searched a lot on internet. They said me about reinstall the app. But I can't tell to user like that, they just give 1 star and leaving.. I want know the root cause, anybody can help me? I really appreciate that! Thanks

chubecode commented 2 years ago

Update: re-install doesn't solve this problem. Now my phone can't scan anything.

jeremiabitterfeld commented 2 years ago

Hi guys,

I'm facing exactly the same problem. It's weird that it happens on some devices only. On my Samsung with Android 11, ssdp scan works totally fine. Same with pre Android 10 devices.

But with my Pixel 3 on Android 12, I get a similar stacktrace as chubecode did.

Some of our customers complained that they could not scan with devices since Android 10.

I already set

    android:networkSecurityConfig="@xml/network_security_config"

in the Manifest and allowed cleartext connections in network_security_config.xml

<?xml version="1.0" encoding="utf-8"?>

But it is still failing...

2021-12-20 19:04:49.715 15183-15215/de.mp.ssdptester I/SSDPTester: Discovery failed. sendto failed: EPERM (Operation not permitted) 2021-12-20 19:04:49.716 15183-15215/de.mp.ssdptester E/SSDPTester: Root cause: java.io.IOException: sendto failed: EPERM (Operation not permitted) at libcore.io.IoBridge.maybeThrowAfterSendto(IoBridge.java:724) at libcore.io.IoBridge.sendto(IoBridge.java:691) at java.net.PlainDatagramSocketImpl.send(PlainDatagramSocketImpl.java:126) at java.net.DatagramSocket.send(DatagramSocket.java:721) at io.resourcepool.ssdp.client.impl.SsdpClientImpl.sendOnAllInterfaces(SsdpClientImpl.java:246) at io.resourcepool.ssdp.client.impl.SsdpClientImpl.sendDiscoveryRequest(SsdpClientImpl.java:171) at io.resourcepool.ssdp.client.impl.SsdpClientImpl.access$000(SsdpClientImpl.java:33) at io.resourcepool.ssdp.client.impl.SsdpClientImpl$2.run(SsdpClientImpl.java:108) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:462) at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:307) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:302) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) at java.lang.Thread.run(Thread.java:920) Caused by: android.system.ErrnoException: sendto failed: EPERM (Operation not permitted) at libcore.io.Linux.sendtoBytes(Native Method) at libcore.io.Linux.sendto(Linux.java:235)

chubecode commented 2 years ago

@jeremiabitterfeld I found problem You can take a look into sendOnAllInterfaces method. with a for loop , when one of all item throw exception it will kill the loop and ignore another item. Just add try/catch for each item it will be fine.

jeremiabitterfeld commented 2 years ago

@chubecode Thanx a lot for that hint! It helped me a lot. For Android 11 and above, it seems that the SDK is a little bit more restrictive concerning network use. It seems that a MulticastSocket is only allowed to use a NetworkInterface that supports multicast communication.

In my case, I had two NetworkInterface instances active on my device and both were in the viableInterfaces list. But only one (the wlan*) supports multicast, the other one failed when sending the request (as mentioned in your post).

My solution was to add three lines of code to the io.resourcepool.ssdp.client.util.Utils class, that guarantee that only NetworkInterfaces are used where supportsMulticast() is true. Pls see the snippet below...

  public static List<NetworkInterface> getMulticastInterfaces() throws SocketException {
    List<NetworkInterface> viableInterfaces = new ArrayList<NetworkInterface>();
    Enumeration e = NetworkInterface.getNetworkInterfaces();
    while (e.hasMoreElements()) {
      NetworkInterface n = (NetworkInterface) e.nextElement();
      if( !n.supportsMulticast() ) { // added due to Android security requirements
        continue;
      } // end of fix
      Enumeration ee = n.getInetAddresses();
      while (ee.hasMoreElements()) {
        InetAddress i = (InetAddress) ee.nextElement();
        if (i.isSiteLocalAddress() && !i.isAnyLocalAddress() && !i.isLinkLocalAddress()
            && !i.isLoopbackAddress() && !i.isMulticastAddress()) {
          viableInterfaces.add(NetworkInterface.getByName(n.getName()));
        }
      }
    }

Next week I'll do some intense testing with multiple devices and I hope the fix will be verified then.

Maybe someone could add this to the repo, so that we can continue using this awesome library even on latest Android devices.

chubecode commented 2 years ago

Nice solution! I hope it works too. My user complaint a lot about it.

loicortola commented 2 years ago

Hi everyone, thanks for jumping on this. I will explore after Christmas and release a fix hopefully Sunday.

loicortola commented 2 years ago

Thanks @jeremiabitterfeld, just implemented your code and 2.4.5 will ship with that and a couple other fixes. Let me know if everything works as expected.

jeremiabitterfeld commented 2 years ago

Thanx @loicortola for the really fast delivery! So I can make our customers happy again :-) Happy new year to all of you! and thanx again for that great lib!

chubecode commented 2 years ago

Yay! Happy new year!!