mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2024-12-14 04:00:30 +00:00
Add config options for a global bandwidth limit
This uses Netty's global traffic shaping handlers to limit the rate at which packets can be sent and received. If the bandwidth limit is hit, we'll start dropping packets, which will mean remote servers send traffic to us at a much slower pace. This isn't perfect, as there is only a global limit, and not a per-computer one. As a result, its possible for one computer to use all/most bandwidth, and thus slow down other computers. This would be something to improve on in the future. However, I've spent a lot of time reading the netty source code and docs, and the implementation for that is significantly more complex, and one I'm not comfortable working on right now. For the time being, this satisfies the issues in #33 and hopefully alleviates server owner's concerns about the http API. Remaining problems can either be solved by moderation (with help of the //computercraft track` command) or future updates. Closes #33
This commit is contained in:
parent
227b444d81
commit
f74c4cc83c
@ -52,6 +52,8 @@ public final class ComputerCraft
|
||||
|
||||
public static int httpMaxRequests = 16;
|
||||
public static int httpMaxWebsockets = 4;
|
||||
public static int httpDownloadBandwidth = 32 * 1024 * 1024;
|
||||
public static int httpUploadBandwidth = 32 * 1024 * 1024;
|
||||
|
||||
public static boolean enableCommandBlock = false;
|
||||
public static int modemRange = 64;
|
||||
|
@ -20,6 +20,8 @@ import io.netty.handler.codec.http.websocketx.WebSocketHandshakeException;
|
||||
import io.netty.handler.ssl.SslContext;
|
||||
import io.netty.handler.ssl.SslContextBuilder;
|
||||
import io.netty.handler.timeout.ReadTimeoutException;
|
||||
import io.netty.handler.traffic.AbstractTrafficShapingHandler;
|
||||
import io.netty.handler.traffic.GlobalTrafficShapingHandler;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.net.ssl.SSLException;
|
||||
@ -28,9 +30,7 @@ import javax.net.ssl.TrustManagerFactory;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
import java.security.KeyStore;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.SynchronousQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
@ -38,10 +38,8 @@ import java.util.concurrent.TimeUnit;
|
||||
*/
|
||||
public final class NetworkUtils
|
||||
{
|
||||
public static final ExecutorService EXECUTOR = new ThreadPoolExecutor(
|
||||
4, Integer.MAX_VALUE,
|
||||
60L, TimeUnit.SECONDS,
|
||||
new SynchronousQueue<>(),
|
||||
public static final ScheduledThreadPoolExecutor EXECUTOR = new ScheduledThreadPoolExecutor(
|
||||
4,
|
||||
ThreadUtils.builder( "Network" )
|
||||
.setPriority( Thread.MIN_PRIORITY + (Thread.NORM_PRIORITY - Thread.MIN_PRIORITY) / 2 )
|
||||
.build()
|
||||
@ -52,6 +50,15 @@ public final class NetworkUtils
|
||||
.build()
|
||||
);
|
||||
|
||||
public static final AbstractTrafficShapingHandler SHAPING_HANDLER = new GlobalTrafficShapingHandler(
|
||||
EXECUTOR, ComputerCraft.httpUploadBandwidth, ComputerCraft.httpDownloadBandwidth
|
||||
);
|
||||
|
||||
static
|
||||
{
|
||||
EXECUTOR.setKeepAliveTime( 60, TimeUnit.SECONDS );
|
||||
}
|
||||
|
||||
private NetworkUtils()
|
||||
{
|
||||
}
|
||||
@ -107,6 +114,16 @@ public final class NetworkUtils
|
||||
}
|
||||
}
|
||||
|
||||
public static void reloadConfig()
|
||||
{
|
||||
SHAPING_HANDLER.configure( ComputerCraft.httpUploadBandwidth, ComputerCraft.httpDownloadBandwidth );
|
||||
}
|
||||
|
||||
public static void reset()
|
||||
{
|
||||
SHAPING_HANDLER.trafficCounter().resetCumulativeTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link InetSocketAddress} from a {@link java.net.URI}.
|
||||
*
|
||||
|
@ -167,6 +167,7 @@ public class HttpRequest extends Resource<HttpRequest>
|
||||
}
|
||||
|
||||
ChannelPipeline p = ch.pipeline();
|
||||
p.addLast( NetworkUtils.SHAPING_HANDLER );
|
||||
if( sslContext != null )
|
||||
{
|
||||
p.addLast( sslContext.newHandler( ch.alloc(), uri.getHost(), socketAddress.getPort() ) );
|
||||
|
@ -145,6 +145,7 @@ public class Websocket extends Resource<Websocket>
|
||||
protected void initChannel( SocketChannel ch )
|
||||
{
|
||||
ChannelPipeline p = ch.pipeline();
|
||||
p.addLast( NetworkUtils.SHAPING_HANDLER );
|
||||
if( sslContext != null )
|
||||
{
|
||||
p.addLast( sslContext.newHandler( ch.alloc(), uri.getHost(), socketAddress.getPort() ) );
|
||||
|
@ -6,6 +6,7 @@
|
||||
package dan200.computercraft.shared;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.core.apis.http.NetworkUtils;
|
||||
import dan200.computercraft.core.computer.MainThread;
|
||||
import dan200.computercraft.core.tracking.Tracking;
|
||||
import dan200.computercraft.shared.command.CommandComputerCraft;
|
||||
@ -83,6 +84,7 @@ public final class CommonHooks
|
||||
ComputerCraft.serverComputerRegistry.reset();
|
||||
WirelessNetwork.resetNetworks();
|
||||
Tracking.reset();
|
||||
NetworkUtils.reset();
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
@ -91,6 +93,7 @@ public final class CommonHooks
|
||||
ComputerCraft.serverComputerRegistry.reset();
|
||||
WirelessNetwork.resetNetworks();
|
||||
Tracking.reset();
|
||||
NetworkUtils.reset();
|
||||
}
|
||||
|
||||
public static final ResourceLocation LOOT_TREASURE_DISK = new ResourceLocation( ComputerCraft.MOD_ID, "treasure_disk" );
|
||||
|
@ -12,6 +12,7 @@ import com.google.common.base.CaseFormat;
|
||||
import com.google.common.base.Converter;
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.api.turtle.event.TurtleAction;
|
||||
import dan200.computercraft.core.apis.http.NetworkUtils;
|
||||
import dan200.computercraft.core.apis.http.options.Action;
|
||||
import dan200.computercraft.core.apis.http.options.AddressRuleConfig;
|
||||
import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer;
|
||||
@ -56,6 +57,9 @@ public final class Config
|
||||
private static final ConfigValue<Integer> httpMaxRequests;
|
||||
private static final ConfigValue<Integer> httpMaxWebsockets;
|
||||
|
||||
private static final ConfigValue<Integer> httpDownloadBandwidth;
|
||||
private static final ConfigValue<Integer> httpUploadBandwidth;
|
||||
|
||||
private static final ConfigValue<Boolean> commandBlockEnabled;
|
||||
private static final ConfigValue<Integer> modemRange;
|
||||
private static final ConfigValue<Integer> modemHighAltitudeRange;
|
||||
@ -187,6 +191,20 @@ public final class Config
|
||||
.comment( "The number of websockets a computer can have open at one time. Set to 0 for unlimited." )
|
||||
.defineInRange( "max_websockets", ComputerCraft.httpMaxWebsockets, 1, Integer.MAX_VALUE );
|
||||
|
||||
builder
|
||||
.comment( "Limits bandwidth used by computers" )
|
||||
.push( "bandwidth" );
|
||||
|
||||
httpDownloadBandwidth = builder
|
||||
.comment( "The number of bytes which can be downloaded in a second. This is shared across all computers. (bytes/s)" )
|
||||
.defineInRange( "global_download", ComputerCraft.httpDownloadBandwidth, 1, Integer.MAX_VALUE );
|
||||
|
||||
httpUploadBandwidth = builder
|
||||
.comment( "The number of bytes which can be uploaded in a second. This is shared across all computers. (bytes/s)" )
|
||||
.defineInRange( "global_upload", ComputerCraft.httpUploadBandwidth, 1, Integer.MAX_VALUE );
|
||||
|
||||
builder.pop();
|
||||
|
||||
builder.pop();
|
||||
}
|
||||
|
||||
@ -329,6 +347,8 @@ public final class Config
|
||||
|
||||
ComputerCraft.httpMaxRequests = httpMaxRequests.get();
|
||||
ComputerCraft.httpMaxWebsockets = httpMaxWebsockets.get();
|
||||
ComputerCraft.httpDownloadBandwidth = httpDownloadBandwidth.get();
|
||||
NetworkUtils.reloadConfig();
|
||||
|
||||
// Peripheral
|
||||
ComputerCraft.enableCommandBlock = commandBlockEnabled.get();
|
||||
|
Loading…
Reference in New Issue
Block a user