Update dependency and use custom de/encoder for netty

This commit is contained in:
Anthony Calosa
2019-11-01 12:41:30 +08:00
parent 85eb740264
commit 31182289b7
23 changed files with 172 additions and 39 deletions

View File

@@ -21,7 +21,7 @@
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.7</version>
<version>3.8.1</version>
</dependency>
</dependencies>

View File

@@ -81,17 +81,17 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>24.1-android</version>
<version>28.1-android</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.7</version>
<version>1.4.9</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.7</version>
<version>3.8.1</version>
</dependency>
<dependency>
<groupId>xmlpull</groupId>

View File

@@ -48,6 +48,7 @@
-keep class com.google.guava.** { *; }
-keep class com.google.common.** { *; }
-keep class io.sentry.event.Event { *; }
-keep class io.netty.util.internal.logging.** { *; }
-keepclassmembers class com.badlogic.gdx.backends.android.AndroidInput* {
<init>(com.badlogic.gdx.Application, android.content.Context, java.lang.Object, com.badlogic.gdx.backends.android.AndroidApplicationConfiguration);

View File

@@ -14,6 +14,7 @@ import android.graphics.BitmapFactory;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.PowerManager;
@@ -71,7 +72,8 @@ public class Main extends AndroidApplication {
Main.this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
initialize(Forge.getApp(new AndroidClipboard(), adapter, assetsDir));
boolean value = Build.VERSION.SDK_INT >= 26;
initialize(Forge.getApp(new AndroidClipboard(), adapter, assetsDir, value));
}
/*@Override

View File

@@ -142,12 +142,12 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>24.1-android</version>
<version>28.1-android</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.10</version>
<version>1.4.11.1</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
@@ -180,7 +180,7 @@
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.7</version>
<version>3.8.1</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>

View File

@@ -3,6 +3,7 @@ package forge.screens.home;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import forge.GuiBase;
import forge.UiCommand;
import forge.ai.AIOption;
import forge.deck.*;
@@ -258,6 +259,9 @@ public class VLobby implements ILobbyView {
addPlayerBtn.setEnabled(activePlayersNum < MAX_PLAYERS);
final boolean allowNetworking = lobby.isAllowNetworking();
GuiBase.setNetworkplay(allowNetworking);
ImmutableList<VariantCheckBox> vntBoxes = null;
if (allowNetworking) {
vntBoxes = vntBoxesNetwork;

View File

@@ -49,6 +49,9 @@ public final class Main {
//setup GUI interface
GuiBase.setInterface(new GuiDesktop());
//set PropertyConfig log4j to true
GuiBase.setpropertyConfig(true);
//install our error handler
ExceptionHandler.registerErrorHandling();

View File

@@ -29,7 +29,7 @@ public class Main extends IOSApplication.Delegate {
final IOSApplicationConfiguration config = new IOSApplicationConfiguration();
config.useAccelerometer = false;
config.useCompass = false;
final ApplicationListener app = Forge.getApp(new IOSClipboard(), new IOSAdapter(), assetsDir);
final ApplicationListener app = Forge.getApp(new IOSClipboard(), new IOSAdapter(), assetsDir, false);
final IOSApplication iosApp = new IOSApplication(app, config);
return iosApp;
}

View File

@@ -93,7 +93,7 @@ public class Main {
config.useHDPI = desktopMode; // enable HiDPI on Mac OS
new LwjglApplication(Forge.getApp(new LwjglClipboard(), new DesktopAdapter(switchOrientationFile),
desktopMode ? desktopModeAssetsDir : assetsDir), config);
desktopMode ? desktopModeAssetsDir : assetsDir, true), config);
}
private static class DesktopAdapter implements IDeviceAdapter {

View File

@@ -48,17 +48,17 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>24.1-android</version>
<version>28.1-android</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.7</version>
<version>1.4.9</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.7</version>
<version>3.8.1</version>
</dependency>
<dependency>
<groupId>com.badlogicgames.gdx</groupId>

View File

@@ -67,11 +67,12 @@ public class Forge implements ApplicationListener {
public static boolean enablePreloadExtendedArt = false;
public static String locale = "en-US";
public static ApplicationListener getApp(Clipboard clipboard0, IDeviceAdapter deviceAdapter0, String assetDir0) {
public static ApplicationListener getApp(Clipboard clipboard0, IDeviceAdapter deviceAdapter0, String assetDir0, boolean value) {
if (GuiBase.getInterface() == null) {
clipboard = clipboard0;
deviceAdapter = deviceAdapter0;
GuiBase.setInterface(new GuiMobile(assetDir0));
GuiBase.setpropertyConfig(value);
}
return app;
}

View File

@@ -4,6 +4,7 @@ import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import forge.GuiBase;
import forge.deck.CardPool;
import forge.deck.Deck;
import forge.deck.DeckSection;
@@ -525,6 +526,9 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView {
updateVariantSelection();
final boolean allowNetworking = lobby.isAllowNetworking();
GuiBase.setNetworkplay(allowNetworking);
for (int i = 0; i < cbPlayerCount.getSelectedItem(); i++) {
final boolean hasPanel = i < playerPanels.size();
if (i < playerCount) {

View File

@@ -53,21 +53,24 @@ public class ControlWinLose {
view.hide();
saveOptions();
MatchController.getHostedMatch().continueMatch();
try { MatchController.getHostedMatch().continueMatch();
} catch (NullPointerException e) {}
}
/** Action performed when "restart" button is pressed in default win/lose UI. */
public void actionOnRestart() {
view.hide();
saveOptions();
MatchController.getHostedMatch().restartMatch();
try { MatchController.getHostedMatch().restartMatch();
} catch (NullPointerException e) {}
}
/** Action performed when "quit" button is pressed in default win/lose UI. */
public void actionOnQuit() {
// Reset other stuff
saveOptions();
MatchController.getHostedMatch().endCurrentGame();
try { MatchController.getHostedMatch().endCurrentGame();
} catch (NullPointerException e) {}
view.hide();
}

View File

@@ -39,22 +39,22 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>24.1-android</version>
<version>28.1-android</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.10</version>
<version>1.4.11.1</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.7</version>
<version>3.8.1</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.0.25.Final</version>
<version>4.1.43.Final</version>
<scope>compile</scope>
</dependency>
<dependency>
@@ -72,6 +72,11 @@
<artifactId>slf4j-simple</artifactId>
<version>1.7.22</version>
</dependency>
<dependency>
<groupId>org.mapdb</groupId>
<artifactId>elsa</artifactId>
<version>3.0.0-M7</version>
</dependency>
</dependencies>
</project>

View File

@@ -13,6 +13,8 @@ public class FThreads {
* @param mustBeEDT &emsp; boolean: true = exception if not EDT, false = exception if EDT
*/
public static void assertExecutedByEdt(final boolean mustBeEDT) {
if (GuiBase.isNetworkplay())
return; //don't check for networkplay
if (isGuiThread() != mustBeEDT) {
final StackTraceElement[] trace = Thread.currentThread().getStackTrace();
final String methodName = trace[2].getClassName() + "." + trace[2].getMethodName();

View File

@@ -4,6 +4,8 @@ import forge.interfaces.IGuiBase;
public class GuiBase {
private static IGuiBase guiInterface;
private static boolean propertyConfig = true;
private static boolean networkplay = false;
public static IGuiBase getInterface() {
return guiInterface;
@@ -11,4 +13,16 @@ public class GuiBase {
public static void setInterface(IGuiBase i0) {
guiInterface = i0;
}
public static void setpropertyConfig(boolean value) {
propertyConfig = value;
}
public static boolean isNetworkplay() {
return networkplay;
}
public static void setNetworkplay(boolean value) {
networkplay = value;
}
public static boolean getpropertyConfig() {
return propertyConfig;
}
}

View File

@@ -0,0 +1,41 @@
package forge.net;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufInputStream;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.serialization.ClassResolver;
import org.mapdb.elsa.ElsaObjectInputStream;
public class CustomObjectDecoder extends LengthFieldBasedFrameDecoder {
private final ClassResolver classResolver;
public CustomObjectDecoder(ClassResolver classResolver) {
this(1048576, classResolver);
}
public CustomObjectDecoder(int maxObjectSize, ClassResolver classResolver) {
super(maxObjectSize, 0, 4, 0, 4);
this.classResolver = classResolver;
}
protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
ByteBuf frame = (ByteBuf) super.decode(ctx, in);
if (frame == null) {
return null;
} else {
ElsaObjectInputStream ois = new ElsaObjectInputStream(new ByteBufInputStream(frame, true));
Object var5;
try {
var5 = ois.readObject();
} finally {
ois.close();
}
return var5;
}
}
public static int maxObjectsize = 10000000; //10megabyte???
}

View File

@@ -0,0 +1,39 @@
package forge.net;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufOutputStream;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import org.mapdb.elsa.ElsaObjectOutputStream;
import java.io.Serializable;
public class CustomObjectEncoder extends MessageToByteEncoder<Serializable> {
private static final byte[] LENGTH_PLACEHOLDER = new byte[4];
public CustomObjectEncoder() {
}
protected void encode(ChannelHandlerContext ctx, Serializable msg, ByteBuf out) throws Exception {
int startIdx = out.writerIndex();
ByteBufOutputStream bout = new ByteBufOutputStream(out);
ElsaObjectOutputStream oout = null;
try {
bout.write(LENGTH_PLACEHOLDER);
oout = new ElsaObjectOutputStream(bout);
oout.writeObject(msg);
oout.flush();
} finally {
if (oout != null) {
oout.close();
} else {
bout.close();
}
}
int endIdx = out.writerIndex();
out.setInt(startIdx, endIdx - startIdx - 4);
}
}

View File

@@ -40,7 +40,7 @@ public abstract class GameProtocolHandler<T> extends ChannelInboundHandlerAdapte
}
final Object[] args = event.getObjects();
protocolMethod.checkArgs(args);
//protocolMethod.checkArgs(args);
final Object toInvoke = getToInvoke(ctx);

View File

@@ -12,13 +12,13 @@ public final class GameProtocolSender {
}
public void send(final ProtocolMethod method, final Object... args) {
method.checkArgs(args);
//method.checkArgs(args);
remote.send(new GuiGameEvent(method, args));
}
@SuppressWarnings("unchecked")
public <T> T sendAndWait(final ProtocolMethod method, final Object... args) {
method.checkArgs(args);
//method.checkArgs(args);
try {
final Object returned = remote.sendAndWait(new GuiGameEvent(method, args));
method.checkReturnValue(returned);

View File

@@ -65,7 +65,7 @@ public enum ProtocolMethod {
confirm (Mode.SERVER, Boolean.TYPE, CardView.class, String.class, Boolean.TYPE, List/*String*/.class),
getChoices (Mode.SERVER, List.class, String.class, Integer.TYPE, Integer.TYPE, List.class, Object.class, Function.class),
order (Mode.SERVER, List.class, String.class, String.class, Integer.TYPE, Integer.TYPE, List.class, List.class, CardView.class, Boolean.TYPE),
sideboard (Mode.SERVER, List.class, CardPool.class, CardPool.class),
sideboard (Mode.SERVER, List.class, CardPool.class, CardPool.class, String.class),
chooseSingleEntityForEffect(Mode.SERVER, GameEntityView.class, String.class, List.class, DelayedReveal.class, Boolean.TYPE),
chooseEntitiesForEffect(Mode.SERVER, GameEntityView.class, String.class, List.class, Integer.TYPE, Integer.TYPE, DelayedReveal.class),
manipulateCardList (Mode.SERVER, List.class, String.class, Iterable.class, Iterable.class, Boolean.TYPE, Boolean.TYPE, Boolean.TYPE),
@@ -156,8 +156,17 @@ public enum ProtocolMethod {
public void checkArgs(final Object[] args) {
for (int iArg = 0; iArg < args.length; iArg++) {
final Object arg = args[iArg];
final Class<?> type = this.args[iArg];
Object arg = null;
Class<?> type = null;
try {
arg = args[iArg];
if (this.args.length > iArg)
type = this.args[iArg];
}
catch (ArrayIndexOutOfBoundsException ex){ ex.printStackTrace(); }
catch(ConcurrentModificationException ex) { ex.printStackTrace(); }
if (arg != null)
if (type != null)
if (!ReflectionUtil.isInstance(arg, type)) {
throw new InternalError(String.format("Protocol method %s: illegal argument (%d) of type %s, %s expected", name(), iArg, arg.getClass().getName(), type.getName()));
}

View File

@@ -1,5 +1,7 @@
package forge.net.client;
import forge.net.CustomObjectDecoder;
import forge.net.CustomObjectEncoder;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
@@ -12,8 +14,6 @@ import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.serialization.ClassResolvers;
import io.netty.handler.codec.serialization.ObjectDecoder;
import io.netty.handler.codec.serialization.ObjectEncoder;
import java.util.List;
import java.util.concurrent.TimeoutException;
@@ -58,8 +58,8 @@ public class FGameClient implements IToServer {
public void initChannel(final SocketChannel ch) throws Exception {
final ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(
new ObjectEncoder(),
new ObjectDecoder(ClassResolvers.cacheDisabled(null)),
new CustomObjectEncoder(),
new CustomObjectDecoder(CustomObjectDecoder.maxObjectsize, ClassResolvers.cacheDisabled(null)),
new MessageHandler(),
new LobbyUpdateHandler(),
new GameClientHandler(FGameClient.this));

View File

@@ -6,6 +6,8 @@ import forge.interfaces.IGuiGame;
import forge.interfaces.ILobbyListener;
import forge.match.LobbySlot;
import forge.match.LobbySlotType;
import forge.net.CustomObjectDecoder;
import forge.net.CustomObjectEncoder;
import forge.net.event.LobbyUpdateEvent;
import forge.net.event.LoginEvent;
import forge.net.event.LogoutEvent;
@@ -25,8 +27,6 @@ import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.serialization.ClassResolvers;
import io.netty.handler.codec.serialization.ObjectDecoder;
import io.netty.handler.codec.serialization.ObjectEncoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
@@ -40,6 +40,8 @@ import java.util.Enumeration;
import java.util.Map;
import org.apache.log4j.PropertyConfigurator;
import io.netty.util.internal.logging.InternalLoggerFactory;
import io.netty.util.internal.logging.Log4JLoggerFactory;
import org.fourthline.cling.UpnpService;
import org.fourthline.cling.UpnpServiceImpl;
import org.fourthline.cling.support.igd.PortMappingListener;
@@ -85,6 +87,7 @@ public final class FServerManager {
*/
public static FServerManager getInstance() {
if (instance == null) {
if(GuiBase.getpropertyConfig())
PropertyConfigurator.configure(ForgeConstants.ASSETS_DIR + "/src/main/resources/log4jConfig.config");
instance = new FServerManager();
}
@@ -93,16 +96,18 @@ public final class FServerManager {
public void startServer(final int port) {
try {
InternalLoggerFactory.setDefaultFactory(Log4JLoggerFactory.INSTANCE);
final ServerBootstrap b = new ServerBootstrap()
.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override public final void initChannel(final SocketChannel ch) {
@Override
public final void initChannel(final SocketChannel ch) throws Exception {
final ChannelPipeline p = ch.pipeline();
p.addLast(
new ObjectEncoder(),
new ObjectDecoder(ClassResolvers.cacheDisabled(null)),
new CustomObjectEncoder(),
new CustomObjectDecoder(CustomObjectDecoder.maxObjectsize, ClassResolvers.cacheDisabled(null)),
new MessageHandler(),
new RegisterClientHandler(),
new LobbyInputHandler(),