Moved isEncrypted() check into KryoExtra, added register(Class<?> clazz,

int id);
This commit is contained in:
nathan 2018-01-13 23:59:36 +01:00
parent b4394e6755
commit a474da5c68
2 changed files with 63 additions and 32 deletions

View File

@ -66,7 +66,7 @@ import io.netty.buffer.ByteBuf;
/** /**
* Threads reading/writing, it messes up a single instance. it is possible to use a single kryo with the use of synchronize, however - that * Threads reading/writing, it messes up a single instance. it is possible to use a single kryo with the use of synchronize, however - that
* defeats the point of multi-threaded * defeats the point of having multi-threaded serialization
*/ */
@SuppressWarnings({"unused", "StaticNonFinalField"}) @SuppressWarnings({"unused", "StaticNonFinalField"})
public public
@ -81,8 +81,6 @@ class CryptoSerializationManager implements dorkbox.network.util.CryptoSerializa
@Property @Property
public static boolean useUnsafeMemory = false; public static boolean useUnsafeMemory = false;
private static final String OBJECT_ID = "objectID";
public static public static
CryptoSerializationManager DEFAULT() { CryptoSerializationManager DEFAULT() {
return DEFAULT(true, true); return DEFAULT(true, true);
@ -133,6 +131,15 @@ class CryptoSerializationManager implements dorkbox.network.util.CryptoSerializa
this.serializer = serializer; this.serializer = serializer;
} }
} }
private static class ClassSerializer1 {
final Class<?> clazz;
final int id;
ClassSerializer1(final Class<?> clazz, final int id) {
this.clazz = clazz;
this.id = id;
}
}
private static class ClassSerializer2 { private static class ClassSerializer2 {
final Class<?> clazz; final Class<?> clazz;
final Serializer<?> serializer; final Serializer<?> serializer;
@ -178,7 +185,7 @@ class CryptoSerializationManager implements dorkbox.network.util.CryptoSerializa
// used to track which interface -> implementation, for use by RMI // used to track which interface -> implementation, for use by RMI
private final IntMap<Class<?>> rmiIdToImpl = new IntMap<Class<?>>(); private final IntMap<Class<?>> rmiIdToImpl = new IntMap<Class<?>>();
private final IntMap<Class<?>> rmiIdToIface = new IntMap<Class<?>>(); private final IntMap<Class<?>> rmiIdToIface = new IntMap<Class<?>>();
private final IdentityMap<Class<?>, Class<?>> rmiIfacetoImpl = new IdentityMap<Class<?>, Class<?>>(); private final IdentityMap<Class<?>, Class<?>> rmiIfaceToImpl = new IdentityMap<Class<?>, Class<?>>();
private final IdentityMap<Class<?>, Class<?>> rmiImplToIface = new IdentityMap<Class<?>, Class<?>>(); private final IdentityMap<Class<?>, Class<?>> rmiImplToIface = new IdentityMap<Class<?>, Class<?>>();
/** /**
@ -230,7 +237,7 @@ class CryptoSerializationManager implements dorkbox.network.util.CryptoSerializa
// This has to be for each kryo instance! // This has to be for each kryo instance!
InvocationResultSerializer resultSerializer = new InvocationResultSerializer(kryo); InvocationResultSerializer resultSerializer = new InvocationResultSerializer(kryo);
resultSerializer.removeField(OBJECT_ID); resultSerializer.removeField("objectID");
kryo.register(InvokeMethodResult.class, resultSerializer); kryo.register(InvokeMethodResult.class, resultSerializer);
kryo.register(InvocationHandler.class, invocationSerializer); kryo.register(InvocationHandler.class, invocationSerializer);
@ -246,6 +253,10 @@ class CryptoSerializationManager implements dorkbox.network.util.CryptoSerializa
ClassSerializer classSerializer = (ClassSerializer) clazz; ClassSerializer classSerializer = (ClassSerializer) clazz;
kryo.register(classSerializer.clazz, classSerializer.serializer); kryo.register(classSerializer.clazz, classSerializer.serializer);
} }
else if (clazz instanceof ClassSerializer1) {
ClassSerializer1 classSerializer = (ClassSerializer1) clazz;
kryo.register(classSerializer.clazz, classSerializer.id);
}
else if (clazz instanceof ClassSerializer2) { else if (clazz instanceof ClassSerializer2) {
ClassSerializer2 classSerializer = (ClassSerializer2) clazz; ClassSerializer2 classSerializer = (ClassSerializer2) clazz;
kryo.register(classSerializer.clazz, classSerializer.serializer, classSerializer.id); kryo.register(classSerializer.clazz, classSerializer.serializer, classSerializer.id);
@ -312,6 +323,34 @@ class CryptoSerializationManager implements dorkbox.network.util.CryptoSerializa
return this; return this;
} }
/**
* Registers the class using the specified ID. If the ID is
* already in use by the same type, the old entry is overwritten. If the ID
* is already in use by a different type, a {@link KryoException} is thrown.
* Registering a primitive also affects the corresponding primitive wrapper.
* <p/>
* IDs must be the same at deserialization as they were for serialization.
*
* @param id Must be >= 0. Smaller IDs are serialized more efficiently. IDs
* 0-8 are used by default for primitive types and String, but
* these IDs can be repurposed.
*/
@Override
public synchronized
RmiSerializationManager register(Class<?> clazz, int id) {
if (initialized) {
logger.warn("Serialization manager already initialized. Ignoring duplicate register(Class, int) call.");
}
else if (clazz.isInterface()) {
throw new IllegalArgumentException("Cannot register an interface for serialization. It must be an implementation.");
}
else {
classesToRegister.add(new ClassSerializer1(clazz, id));
}
return this;
}
/** /**
* Registers the class using the lowest, next available integer ID and the specified serializer. If the class is already registered, the * Registers the class using the lowest, next available integer ID and the specified serializer. If the class is already registered, the
* existing entry is updated with the new serializer. Registering a primitive also affects the corresponding primitive wrapper. * existing entry is updated with the new serializer. Registering a primitive also affects the corresponding primitive wrapper.
@ -372,7 +411,7 @@ class CryptoSerializationManager implements dorkbox.network.util.CryptoSerializa
public synchronized public synchronized
RmiSerializationManager registerRmiInterface(Class<?> ifaceClass) { RmiSerializationManager registerRmiInterface(Class<?> ifaceClass) {
if (initialized) { if (initialized) {
logger.warn("Serialization manager already initialized. Ignoring duplicate registerRemote(Class, Class) call."); logger.warn("Serialization manager already initialized. Ignoring duplicate registerRemote(Class) call.");
return this; return this;
} }
@ -404,11 +443,10 @@ class CryptoSerializationManager implements dorkbox.network.util.CryptoSerializa
usesRmi = true; usesRmi = true;
classesToRegister.add(new RemoteImplClass(ifaceClass, implClass)); classesToRegister.add(new RemoteImplClass(ifaceClass, implClass));
// this MUST BE UNIQUE otherwise unexpected things can happen. // this MUST BE UNIQUE otherwise unexpected and BAD things can happen.
Class<?> a = this.rmiIfacetoImpl.put(ifaceClass, implClass); Class<?> a = this.rmiIfaceToImpl.put(ifaceClass, implClass);
Class<?> b = this.rmiImplToIface.put(implClass, ifaceClass); Class<?> b = this.rmiImplToIface.put(implClass, ifaceClass);
// this MUST BE UNIQUE otherwise unexpected things can happen.
if (a != null || b != null) { if (a != null || b != null) {
throw new IllegalArgumentException("Unable to override interface (" + ifaceClass + ") and implementation (" + implClass + ") " + throw new IllegalArgumentException("Unable to override interface (" + ifaceClass + ") and implementation (" + implClass + ") " +
"because they have already been overridden by something else. It is critical that they are" + "because they have already been overridden by something else. It is critical that they are" +
@ -494,7 +532,7 @@ class CryptoSerializationManager implements dorkbox.network.util.CryptoSerializa
@Override @Override
public public
Class<?> getRmiImpl(Class<?> iface) { Class<?> getRmiImpl(Class<?> iface) {
return rmiIfacetoImpl.get(iface); return rmiIfaceToImpl.get(iface);
} }
/** /**
@ -526,16 +564,6 @@ class CryptoSerializationManager implements dorkbox.network.util.CryptoSerializa
kryoPool.put(kryo); kryoPool.put(kryo);
} }
/**
* Determines if this buffer is encrypted or not.
*/
public static
boolean isEncrypted(final ByteBuf buffer) {
// read off the magic byte
byte magicByte = buffer.getByte(buffer.readerIndex());
return (magicByte & KryoExtra.crypto) == KryoExtra.crypto;
}
/** /**
* Writes the class and object using an available kryo instance * Writes the class and object using an available kryo instance
*/ */

View File

@ -39,6 +39,21 @@ interface RmiSerializationManager extends SerializationManager {
@Override @Override
RmiSerializationManager register(Class<?> clazz); RmiSerializationManager register(Class<?> clazz);
/**
* Registers the class using the specified ID. If the ID is
* already in use by the same type, the old entry is overwritten. If the ID
* is already in use by a different type, a {@link KryoException} is thrown.
* Registering a primitive also affects the corresponding primitive wrapper.
* <p/>
* IDs must be the same at deserialization as they were for serialization.
*
* @param id Must be >= 0. Smaller IDs are serialized more efficiently. IDs
* 0-8 are used by default for primitive types and String, but
* these IDs can be repurposed.
*/
@Override
RmiSerializationManager register(Class<?> clazz, int id);
/** /**
* Registers the class using the lowest, next available integer ID and the * Registers the class using the lowest, next available integer ID and the
* specified serializer. If the class is already registered, the existing * specified serializer. If the class is already registered, the existing
@ -134,16 +149,4 @@ interface RmiSerializationManager extends SerializationManager {
* @param implClass The implementation class of the interface * @param implClass The implementation class of the interface
*/ */
<Iface, Impl extends Iface> RmiSerializationManager registerRmiImplementation(Class<Iface> ifaceClass, Class<Impl> implClass); <Iface, Impl extends Iface> RmiSerializationManager registerRmiImplementation(Class<Iface> ifaceClass, Class<Impl> implClass);
/**
* This method overrides the interface -> implementation. This is so incoming proxy objects will get auto-changed into their correct
* implementation type, so this side of the connection knows what to do with the proxy object.
* <p>
* NOTE: You must have ALREADY registered the implementation class. This method just enables the proxy magic.
* This is for the "server" side, where "server" means the connection side where the implementation is used.
*
* @param ifaceClass The interface used to access the remote object
* @param implClass The implementation class of the interface
*/
// RmiSerializationManager rmiImplementation();
} }