Skip to content

Commit

Permalink
Disable all UPnP action calls based on HTTPS
Browse files Browse the repository at this point in the history
New setting etryAfterSeconds

New setting maxRequests to trigger an automatic restart of the router after a certain number of executed requests

Get the stack trace in DEBUG or TRACE level

Signed-off-by: Laurent Garnier <[email protected]>
  • Loading branch information
lolodomo committed Apr 23, 2020
1 parent ca13ee8 commit af85d80
Show file tree
Hide file tree
Showing 11 changed files with 260 additions and 152 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.jupnp.binding.xml.DeviceDescriptorBinder;
import org.jupnp.binding.xml.ServiceDescriptorBinder;
import org.jupnp.binding.xml.UDA10DeviceDescriptorBinderImpl;
Expand Down Expand Up @@ -53,6 +52,8 @@
import org.jupnp.transport.spi.StreamClient;
import org.jupnp.transport.spi.StreamServer;
import org.jupnp.util.Exceptions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Default configuration data of a typical UPnP stack.
Expand Down Expand Up @@ -88,7 +89,7 @@ public class DefaultUpnpServiceConfiguration implements UpnpServiceConfiguration

// set a fairly large core threadpool size, expecting that core timeout policy will
// allow the pool to reduce in size after inactivity. note that ThreadPoolExecutor
// only adds threads beyond its core size once the backlog is full, so a low value
// only adds threads beyond its core size once the backlog is full, so a low value
// core size is a poor choice when there are lots of long-running + idle jobs.
// a brief intro to the issue:
// http://www.bigsoft.co.uk/blog/2009/11/27/rules-of-a-threadpoolexecutor-pool-size
Expand Down Expand Up @@ -130,7 +131,8 @@ public DefaultUpnpServiceConfiguration(int streamListenPort, int multicastRespon
}

protected DefaultUpnpServiceConfiguration(boolean checkRuntime) {
this(NetworkAddressFactoryImpl.DEFAULT_TCP_HTTP_LISTEN_PORT, NetworkAddressFactoryImpl.DEFAULT_MULTICAST_RESPONSE_LISTEN_PORT, checkRuntime);
this(NetworkAddressFactoryImpl.DEFAULT_TCP_HTTP_LISTEN_PORT,
NetworkAddressFactoryImpl.DEFAULT_MULTICAST_RESPONSE_LISTEN_PORT, checkRuntime);
}

protected DefaultUpnpServiceConfiguration(int streamListenPort, int multicastResponsePort, boolean checkRuntime) {
Expand Down Expand Up @@ -173,7 +175,7 @@ public GENAEventProcessor getGenaEventProcessor() {
@Override
@SuppressWarnings("rawtypes")
public StreamClient createStreamClient() {
return transportConfiguration.createStreamClient(getSyncProtocolExecutorService());
return transportConfiguration.createStreamClient(getSyncProtocolExecutorService(), -1);
}

@Override
Expand All @@ -184,12 +186,8 @@ public StreamServer createStreamServer(NetworkAddressFactory networkAddressFacto

@Override
public MulticastReceiver createMulticastReceiver(NetworkAddressFactory networkAddressFactory) {
return new MulticastReceiverImpl(
new MulticastReceiverConfigurationImpl(
networkAddressFactory.getMulticastGroup(),
networkAddressFactory.getMulticastPort()
)
);
return new MulticastReceiverImpl(new MulticastReceiverConfigurationImpl(
networkAddressFactory.getMulticastGroup(), networkAddressFactory.getMulticastPort()));
}

@Override
Expand Down Expand Up @@ -296,6 +294,11 @@ public NetworkAddressFactory createNetworkAddressFactory() {
return createNetworkAddressFactory(streamListenPort, multicastResponsePort);
}

@Override
public int getMaxRequests() {
return -1;
}

@Override
public void shutdown() {
log.trace("Shutting down default executor service");
Expand Down Expand Up @@ -341,29 +344,22 @@ protected ExecutorService createDefaultExecutorService() {
public static class JUPnPExecutor extends ThreadPoolExecutor {

public JUPnPExecutor() {
this(new JUPnPThreadFactory(),
new ThreadPoolExecutor.DiscardPolicy() {
// The pool is bounded and rejections will happen during shutdown
@Override
public void rejectedExecution(Runnable runnable, ThreadPoolExecutor threadPoolExecutor) {
// Log and discard
LoggerFactory.getLogger(DefaultUpnpServiceConfiguration.class).warn("Thread pool rejected execution of " + runnable.getClass());
super.rejectedExecution(runnable, threadPoolExecutor);
}
}
);
this(new JUPnPThreadFactory(), new ThreadPoolExecutor.DiscardPolicy() {
// The pool is bounded and rejections will happen during shutdown
@Override
public void rejectedExecution(Runnable runnable, ThreadPoolExecutor threadPoolExecutor) {
// Log and discard
LoggerFactory.getLogger(DefaultUpnpServiceConfiguration.class)
.warn("Thread pool rejected execution of " + runnable.getClass());
super.rejectedExecution(runnable, threadPoolExecutor);
}
});
}

public JUPnPExecutor(ThreadFactory threadFactory, RejectedExecutionHandler rejectedHandler) {
// This is the same as Executors.newCachedThreadPool
super(CORE_THREAD_POOL_SIZE,
THREAD_POOL_SIZE,
10L,
TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(THREAD_QUEUE_SIZE),
threadFactory,
rejectedHandler
);
super(CORE_THREAD_POOL_SIZE, THREAD_POOL_SIZE, 10L, TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(THREAD_QUEUE_SIZE), threadFactory, rejectedHandler);
allowCoreThreadTimeOut(THREAD_POOL_CORE_TIMEOUT);
}

Expand All @@ -379,7 +375,8 @@ protected void afterExecute(Runnable runnable, Throwable throwable) {
return;
}
// Log only
LoggerFactory.getLogger(DefaultUpnpServiceConfiguration.class).warn("Thread terminated " + runnable + " abruptly with exception: " + throwable);
LoggerFactory.getLogger(DefaultUpnpServiceConfiguration.class)
.warn("Thread terminated " + runnable + " abruptly with exception: " + throwable);
LoggerFactory.getLogger(DefaultUpnpServiceConfiguration.class).warn("Root cause: " + cause);
}
}
Expand All @@ -399,15 +396,13 @@ public JUPnPThreadFactory() {

@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(
group, r,
namePrefix + threadNumber.getAndIncrement(),
0
);
if (t.isDaemon())
Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
if (t.isDaemon()) {
t.setDaemon(false);
if (t.getPriority() != Thread.NORM_PRIORITY)
}
if (t.getPriority() != Thread.NORM_PRIORITY) {
t.setPriority(Thread.NORM_PRIORITY);
}

return t;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ public class OSGiUpnpServiceConfiguration implements UpnpServiceConfiguration {
private int httpProxyPort = -1;
private int streamListenPort = 8080;
private Namespace callbackURI = new Namespace("http://localhost/upnpcallback");
private int retryAfterSeconds = -1;
private int maxRequests = -1;

private ExecutorService mainExecutorService;
private ExecutorService asyncExecutorService;
Expand Down Expand Up @@ -146,7 +148,6 @@ protected OSGiUpnpServiceConfiguration(int streamListenPort, int multicastRespon
}

protected void activate(BundleContext context, Map<String, Object> configProps) throws ConfigurationException {

this.context = context;

createConfiguration(configProps);
Expand Down Expand Up @@ -193,7 +194,7 @@ public GENAEventProcessor getGenaEventProcessor() {
@Override
@SuppressWarnings("rawtypes")
public StreamClient createStreamClient() {
return transportConfiguration.createStreamClient(getSyncProtocolExecutorService());
return transportConfiguration.createStreamClient(getSyncProtocolExecutorService(), retryAfterSeconds);
}

@Override
Expand Down Expand Up @@ -333,6 +334,11 @@ public NetworkAddressFactory createNetworkAddressFactory() {
return createNetworkAddressFactory(streamListenPort, multicastResponsePort);
}

@Override
public int getMaxRequests() {
return maxRequests;
}

@Override
public void shutdown() {
log.debug("Shutting down executor services");
Expand Down Expand Up @@ -472,6 +478,30 @@ private void createConfiguration(Map<String, Object> properties) throws Configur
} else if (prop instanceof Integer) {
httpProxyPort = (Integer) prop;
}

prop = properties.get("retryAfterSeconds");
if (prop instanceof String) {
try {
retryAfterSeconds = Integer.valueOf((String) prop);
} catch (NumberFormatException e) {
log.error("Invalid value '{}' for retryAfterSeconds - using default value", prop);
}
} else if (prop instanceof Integer) {
retryAfterSeconds = (Integer) prop;
}
log.info("OSGiUpnpServiceConfiguration createConfiguration retryAfterSeconds = {}", retryAfterSeconds);

prop = properties.get("maxRequests");
if (prop instanceof String) {
try {
maxRequests = Integer.valueOf((String) prop);
} catch (NumberFormatException e) {
log.error("Invalid value '{}' for maxRequests - using default value", prop);
}
} else if (prop instanceof Integer) {
maxRequests = (Integer) prop;
}
log.info("OSGiUpnpServiceConfiguration createConfiguration maxRequests = {}", maxRequests);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,14 @@ public interface UpnpServiceConfiguration {
public ExecutorService getStreamServerExecutorService();

/**
* @return The shared implementation of {@link org.jupnp.binding.xml.DeviceDescriptorBinder} for the UPnP 1.0 Device Architecture..
* @return The shared implementation of {@link org.jupnp.binding.xml.DeviceDescriptorBinder} for the UPnP 1.0 Device
* Architecture..
*/
public DeviceDescriptorBinder getDeviceDescriptorBinderUDA10();

/**
* @return The shared implementation of {@link org.jupnp.binding.xml.ServiceDescriptorBinder} for the UPnP 1.0 Device Architecture..
* @return The shared implementation of {@link org.jupnp.binding.xml.ServiceDescriptorBinder} for the UPnP 1.0
* Device Architecture..
*/
public ServiceDescriptorBinder getServiceDescriptorBinderUDA10();

Expand Down Expand Up @@ -142,7 +144,7 @@ public interface UpnpServiceConfiguration {
* @return The time in milliseconds to wait between each registry maintenance operation.
*/
public int getRegistryMaintenanceIntervalMillis();

/**
* Optional setting for flooding alive NOTIFY messages for local devices.
* <p>
Expand Down Expand Up @@ -228,7 +230,8 @@ public interface UpnpServiceConfiguration {
public Executor getAsyncProtocolExecutor();

/**
* @return The executor service which runs the processing of synchronous aspects of the UPnP stack (description, control, GENA).
* @return The executor service which runs the processing of synchronous aspects of the UPnP stack (description,
* control, GENA).
*/
public ExecutorService getSyncProtocolExecutorService();

Expand All @@ -247,6 +250,8 @@ public interface UpnpServiceConfiguration {
*/
public Executor getRegistryListenerExecutor();

public int getMaxRequests();

/**
* Called by the {@link org.jupnp.UpnpService} on shutdown, useful to e.g. shutdown thread pools.
*/
Expand Down
Loading

0 comments on commit af85d80

Please sign in to comment.