From 026afa7f731092b59ea943d6987f3102b8149b50 Mon Sep 17 00:00:00 2001 From: Jonathan Coates Date: Sun, 6 Jun 2021 19:26:20 +0100 Subject: [PATCH] Put some limits on various external queues Ideally turtle functions would error, but wrangling that is more pain than it's worth. --- config/checkstyle/suppressions.xml | 3 --- .../dan200/computercraft/core/apis/HTTPAPI.java | 14 ++++++++++---- .../computercraft/core/apis/http/Resource.java | 2 +- .../core/apis/http/ResourceGroup.java | 3 +++ .../core/apis/http/ResourceQueue.java | 4 +++- .../shared/turtle/core/TurtleBrain.java | 11 +++-------- 6 files changed, 20 insertions(+), 17 deletions(-) diff --git a/config/checkstyle/suppressions.xml b/config/checkstyle/suppressions.xml index ede3f3dea..647da4baa 100644 --- a/config/checkstyle/suppressions.xml +++ b/config/checkstyle/suppressions.xml @@ -7,9 +7,6 @@ - - - diff --git a/src/main/java/dan200/computercraft/core/apis/HTTPAPI.java b/src/main/java/dan200/computercraft/core/apis/HTTPAPI.java index 396232e92..2ba8f744b 100644 --- a/src/main/java/dan200/computercraft/core/apis/HTTPAPI.java +++ b/src/main/java/dan200/computercraft/core/apis/HTTPAPI.java @@ -37,7 +37,7 @@ public class HTTPAPI implements ILuaAPI { private final IAPIEnvironment apiEnvironment; - private final ResourceGroup checkUrls = new ResourceGroup<>(); + private final ResourceGroup checkUrls = new ResourceGroup<>( ResourceGroup.DEFAULT ); private final ResourceGroup requests = new ResourceQueue<>( () -> ComputerCraft.httpMaxRequests ); private final ResourceGroup websockets = new ResourceGroup<>( () -> ComputerCraft.httpMaxWebsockets ); @@ -127,7 +127,10 @@ public final Object[] request( IArguments args ) throws LuaException HttpRequest request = new HttpRequest( requests, apiEnvironment, address, postString, headers, binary, redirect ); // Make the request - request.queue( r -> r.request( uri, httpMethod ) ); + if( !request.queue( r -> r.request( uri, httpMethod ) ) ) + { + throw new LuaException( "Too many ongoing HTTP requests" ); + } return new Object[] { true }; } @@ -138,12 +141,15 @@ public final Object[] request( IArguments args ) throws LuaException } @LuaFunction - public final Object[] checkURL( String address ) + public final Object[] checkURL( String address ) throws LuaException { try { URI uri = HttpRequest.checkUri( address ); - new CheckUrl( checkUrls, apiEnvironment, address, uri ).queue( CheckUrl::run ); + if( !new CheckUrl( checkUrls, apiEnvironment, address, uri ).queue( CheckUrl::run ) ) + { + throw new LuaException( "Too many ongoing checkUrl calls" ); + } return new Object[] { true }; } diff --git a/src/main/java/dan200/computercraft/core/apis/http/Resource.java b/src/main/java/dan200/computercraft/core/apis/http/Resource.java index b17b06d23..142fb1dca 100644 --- a/src/main/java/dan200/computercraft/core/apis/http/Resource.java +++ b/src/main/java/dan200/computercraft/core/apis/http/Resource.java @@ -97,7 +97,7 @@ public final void close() tryClose(); } - public boolean queue( Consumer task ) + public final boolean queue( Consumer task ) { @SuppressWarnings( "unchecked" ) T thisT = (T) this; diff --git a/src/main/java/dan200/computercraft/core/apis/http/ResourceGroup.java b/src/main/java/dan200/computercraft/core/apis/http/ResourceGroup.java index 6533c3622..8411eebbe 100644 --- a/src/main/java/dan200/computercraft/core/apis/http/ResourceGroup.java +++ b/src/main/java/dan200/computercraft/core/apis/http/ResourceGroup.java @@ -18,6 +18,9 @@ */ public class ResourceGroup> { + public static final int DEFAULT_LIMIT = 512; + public static final IntSupplier DEFAULT = () -> DEFAULT_LIMIT; + private static final IntSupplier ZERO = () -> 0; final IntSupplier limit; diff --git a/src/main/java/dan200/computercraft/core/apis/http/ResourceQueue.java b/src/main/java/dan200/computercraft/core/apis/http/ResourceQueue.java index c0f8c2ac2..0b79c8f5e 100644 --- a/src/main/java/dan200/computercraft/core/apis/http/ResourceQueue.java +++ b/src/main/java/dan200/computercraft/core/apis/http/ResourceQueue.java @@ -38,8 +38,10 @@ public synchronized void shutdown() public synchronized boolean queue( Supplier resource ) { if( !active ) return false; + if( super.queue( resource ) ) return true; + if( pending.size() > DEFAULT_LIMIT ) return false; - if( !super.queue( resource ) ) pending.add( resource ); + pending.add( resource ); return true; } diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java index b70d410b1..798ace936 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java @@ -503,20 +503,15 @@ public void addFuel( int fuel ) setFuelLevel( getFuelLevel() + addition ); } - private int issueCommand( ITurtleCommand command ) - { - commandQueue.offer( new TurtleCommandQueueEntry( ++commandsIssued, command ) ); - return commandsIssued; - } - @Nonnull @Override public MethodResult executeCommand( @Nonnull ITurtleCommand command ) { if( getWorld().isClientSide ) throw new UnsupportedOperationException( "Cannot run commands on the client" ); + if( commandQueue.size() > 16 ) return MethodResult.of( false, "Too many ongoing turtle commands" ); - // Issue command - int commandID = issueCommand( command ); + commandQueue.offer( new TurtleCommandQueueEntry( ++commandsIssued, command ) ); + int commandID = commandsIssued; return new CommandCallback( commandID ).pull; }