libbluray | branch: master | hpi1 <[email protected]> | Wed Oct 29 14:51:15 2014 +0200| [6bfd1d1141a5a53339ec26705ae63eaeb7ff4d8f] | committer: hpi1
Close Xlet sockets when it is terminated > http://git.videolan.org/gitweb.cgi/libbluray.git/?a=commit;h=6bfd1d1141a5a53339ec26705ae63eaeb7ff4d8f --- .../bdj/java/org/videolan/BDJAppProxy.java | 1 + .../bdj/java/org/videolan/BDJSocketFactory.java | 79 +++++++++++++++++ .../bdj/java/org/videolan/BDJSockets.java | 89 ++++++++++++++++++++ .../bdj/java/org/videolan/BDJXletContext.java | 14 +++ src/libbluray/bdj/java/org/videolan/Libbluray.java | 2 + 5 files changed, 185 insertions(+) diff --git a/src/libbluray/bdj/java/org/videolan/BDJAppProxy.java b/src/libbluray/bdj/java/org/videolan/BDJAppProxy.java index 5da21b6..ccefb8a 100644 --- a/src/libbluray/bdj/java/org/videolan/BDJAppProxy.java +++ b/src/libbluray/bdj/java/org/videolan/BDJAppProxy.java @@ -238,6 +238,7 @@ public class BDJAppProxy implements DVBJProxy, Runnable { try { xlet.destroyXlet(force); + context.closeSockets(); context.getThreadGroup().waitForShutdown(1000, 1 + context.numEventQueueThreads()); String persistent = System.getProperty("dvb.persistent.root") + File.separator + diff --git a/src/libbluray/bdj/java/org/videolan/BDJSocketFactory.java b/src/libbluray/bdj/java/org/videolan/BDJSocketFactory.java new file mode 100644 index 0000000..876a9d9 --- /dev/null +++ b/src/libbluray/bdj/java/org/videolan/BDJSocketFactory.java @@ -0,0 +1,79 @@ +/* + * This file is part of libbluray + * Copyright (C) 2014 Petri Hintukainen <[email protected]> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +package org.videolan; + +import java.io.IOException; + +import java.lang.reflect.Constructor; + +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketImpl; +import java.net.SocketImplFactory; + +class BDJSocketFactory implements SocketImplFactory { + + protected static void init() { + try { + Socket.setSocketImplFactory(new BDJSocketFactory(false)); + ServerSocket.setSocketFactory(new BDJSocketFactory(true)); + } catch (IOException e) { + logger.error("Failed to hook SocketFactory: " + e); + } + } + + private BDJSocketFactory(boolean server) { + this.server = server; + } + + private SocketImpl newSocket() { + try { + Class defaultSocketImpl = Class.forName("java.net.SocksSocketImpl"); + Constructor constructor = defaultSocketImpl.getDeclaredConstructor/*s*/(new Class[0])/*[0]*/; + constructor.setAccessible(true); + return (SocketImpl) constructor.newInstance(new Object[0]); + } catch (Exception e) { + logger.error("Failed to create socket: " + e + " at " + logger.dumpStack()); + throw new RuntimeException(e); + } + } + + public SocketImpl createSocketImpl() { + + if (server) { + logger.error("Xlet tried to create server socket"); + throw new RuntimeException("server sockets disabled"); + } + + SocketImpl socket = newSocket(); + BDJXletContext ctx = BDJXletContext.getCurrentContext(); + if (ctx != null) { + logger.info("Xlet " + ctx + " created new socket"); + ctx.addSocket(socket); + } else { + logger.error("New socket created outside of Xlet context: " + logger.dumpStack()); + } + return socket; + } + + private boolean server = false; + + private static final Logger logger = Logger.getLogger(BDJSocketFactory.class.getName()); +} diff --git a/src/libbluray/bdj/java/org/videolan/BDJSockets.java b/src/libbluray/bdj/java/org/videolan/BDJSockets.java new file mode 100644 index 0000000..0395399 --- /dev/null +++ b/src/libbluray/bdj/java/org/videolan/BDJSockets.java @@ -0,0 +1,89 @@ +/* + * This file is part of libbluray + * Copyright (C) 2014 Petri Hintukainen <[email protected]> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +package org.videolan; + +import java.lang.reflect.Method; + +import java.util.Iterator; +import java.util.LinkedList; + +import java.net.Socket; +import java.net.SocketImpl; + +class BDJSockets { + + protected BDJSockets() { + } + + protected synchronized void add(Object obj) { + if (!(obj instanceof SocketImpl)) { + throw new Error("expected SocketImpl"); + } + + if (closed) { + logger.error("Terminated Xlet tried to create socket at " + logger.dumpStack()); + throw new Error("Terminated Xlet can not create sockets"); + } + + /* drop closed sockets */ + for (Iterator it = sockets.iterator(); it.hasNext(); ) { + SocketImpl socketImpl = (SocketImpl)it.next(); + Socket socket = getSocket(socketImpl); + if (socket != null && socket.isClosed()) { + it.remove(); + } + } + + sockets.addLast(obj); + } + + protected synchronized void closeAll() { + closed = true; + + while (!sockets.isEmpty()) { + SocketImpl socketImpl = (SocketImpl)sockets.removeFirst(); + Socket socket = getSocket(socketImpl); + if (socket != null && !socket.isClosed()) { + logger.warning("Closing " + socket); + try { + socket.close(); + } catch (Exception e) { + logger.error("Failed to close socket: " + e); + } + } + } + } + + private Socket getSocket(SocketImpl socketImpl) { + try { + Method getSocket = SocketImpl.class.getDeclaredMethod("getSocket", new Class[0]); + getSocket.setAccessible(true); + return (Socket) getSocket.invoke(socketImpl, new Object[0]); + } catch (Exception e) { + logger.error("Failed to get Socket: " + e + " at " + logger.dumpStack()); + return null; + } + } + + private LinkedList sockets = new LinkedList(); + private boolean closed = false; + + private static final Logger logger = Logger.getLogger(BDJSockets.class.getName()); +} diff --git a/src/libbluray/bdj/java/org/videolan/BDJXletContext.java b/src/libbluray/bdj/java/org/videolan/BDJXletContext.java index d1208f6..65a6281 100644 --- a/src/libbluray/bdj/java/org/videolan/BDJXletContext.java +++ b/src/libbluray/bdj/java/org/videolan/BDJXletContext.java @@ -263,6 +263,18 @@ public class BDJXletContext implements javax.tv.xlet.XletContext, javax.microedi } /* + * sockets + */ + + protected void addSocket(Object socket) { + sockets.add(socket); + } + + protected void closeSockets() { + sockets.closeAll(); + } + + /* * Ixc */ @@ -383,6 +395,7 @@ public class BDJXletContext implements javax.tv.xlet.XletContext, javax.microedi protected void release() { + closeSockets(); removeAllFAA(); stopIxcThreads(); defaultLooks.clear(); @@ -424,6 +437,7 @@ public class BDJXletContext implements javax.tv.xlet.XletContext, javax.microedi private BDJThreadGroup threadGroup = null; private LinkedList ixcThreads = new LinkedList(); private LinkedList faaList = new LinkedList(); + private BDJSockets sockets = new BDJSockets(); private HashMap defaultLooks = new HashMap(); private BDJActionQueue callbackQueue; private static final Logger logger = Logger.getLogger(BDJXletContext.class.getName()); diff --git a/src/libbluray/bdj/java/org/videolan/Libbluray.java b/src/libbluray/bdj/java/org/videolan/Libbluray.java index 2f1488a..2bb2fa8 100644 --- a/src/libbluray/bdj/java/org/videolan/Libbluray.java +++ b/src/libbluray/bdj/java/org/videolan/Libbluray.java @@ -130,6 +130,8 @@ public class Libbluray { System.setProperty("bluray.memory.font_cache", "4096"); System.setProperty("bluray.network.connected", "YES"); + + BDJSocketFactory.init(); } public static void shutdown() { _______________________________________________ libbluray-devel mailing list [email protected] https://mailman.videolan.org/listinfo/libbluray-devel
