KryoExtra no longer depends on concrete 'connection' implementation,

now uses crypto + rmi interfaces
This commit is contained in:
nathan 2016-03-20 08:02:30 +01:00
parent 2988ae4bb0
commit 0d768dd321
5 changed files with 105 additions and 15 deletions

View File

@ -63,7 +63,7 @@ import java.util.concurrent.atomic.AtomicLong;
@SuppressWarnings("unused") @SuppressWarnings("unused")
@Sharable @Sharable
public public
class ConnectionImpl extends ChannelInboundHandlerAdapter implements Connection, ListenerBridge, ConnectionBridge { class ConnectionImpl extends ChannelInboundHandlerAdapter implements ICryptoConnection, Connection, ListenerBridge, ConnectionBridge {
private final org.slf4j.Logger logger; private final org.slf4j.Logger logger;
@ -155,7 +155,7 @@ class ConnectionImpl extends ChannelInboundHandlerAdapter implements Connection,
* because multiple protocols can be performing crypto AT THE SAME TIME, and so we have to make sure that operations don't * because multiple protocols can be performing crypto AT THE SAME TIME, and so we have to make sure that operations don't
* clobber each other * clobber each other
*/ */
final public final
ParametersWithIV getCryptoParameters() { ParametersWithIV getCryptoParameters() {
return this.channelWrapper.cryptoParameters(); return this.channelWrapper.cryptoParameters();
} }
@ -167,7 +167,7 @@ class ConnectionImpl extends ChannelInboundHandlerAdapter implements Connection,
* The 12 bytes IV is created during connection registration, and during the AES-GCM crypto, we override the last 8 with this * The 12 bytes IV is created during connection registration, and during the AES-GCM crypto, we override the last 8 with this
* counter, which is also transmitted as an optimized int. (which is why it starts at 0, so the transmitted bytes are small) * counter, which is also transmitted as an optimized int. (which is why it starts at 0, so the transmitted bytes are small)
*/ */
final public final
long getNextGcmSequence() { long getNextGcmSequence() {
return aes_gcm_iv.getAndIncrement(); return aes_gcm_iv.getAndIncrement();
} }
@ -1104,6 +1104,12 @@ class ConnectionImpl extends ChannelInboundHandlerAdapter implements Connection,
} }
} }
/**
* Used by RMI
*
* @return the registered ID for a specific object. This is used by the "local" side when setting up the to fetch an object for the
* "remote" side for RMI
*/
public public
<T> int getRegisteredId(final T object) { <T> int getRegisteredId(final T object) {
// always check local before checking global, because less contention on the synchronization // always check local before checking global, because less contention on the synchronization
@ -1122,7 +1128,7 @@ class ConnectionImpl extends ChannelInboundHandlerAdapter implements Connection,
} }
/** /**
* Used by the LOCAL side, to get the proxy object as an interface * Used by RMI for the LOCAL side, to get the proxy object as an interface
* *
* @param type must be the interface the proxy will bind to * @param type must be the interface the proxy will bind to
*/ */
@ -1142,7 +1148,7 @@ class ConnectionImpl extends ChannelInboundHandlerAdapter implements Connection,
} }
/** /**
* This is used by the REMOTE side, to get the implementation * This is used by RMI for the REMOTE side, to get the implementation
*/ */
public public
Object getImplementationObject(final int objectID) { Object getImplementationObject(final int objectID) {

View File

@ -0,0 +1,42 @@
/*
* Copyright 2010 dorkbox, llc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dorkbox.network.connection;
import org.bouncycastle.crypto.params.ParametersWithIV;
/**
* Supporting methods for encrypting data to a remote endpoint
*/
public
interface ICryptoConnection extends IRmiConnection {
/**
* This is the per-message sequence number.
*
* The IV for AES-GCM must be 12 bytes, since it's 4 (salt) + 8 (external counter) + 4 (GCM counter)
* The 12 bytes IV is created during connection registration, and during the AES-GCM crypto, we override the last 8 with this
* counter, which is also transmitted as an optimized int. (which is why it starts at 0, so the transmitted bytes are small)
*/
long getNextGcmSequence();
/**
* @return a threadlocal AES key + IV. key=32 byte, iv=12 bytes (AES-GCM implementation). This is a threadlocal
* because multiple protocols can be performing crypto AT THE SAME TIME, and so we have to make sure that operations don't
* clobber each other
*/
ParametersWithIV getCryptoParameters();
}

View File

@ -0,0 +1,45 @@
/*
* Copyright 2010 dorkbox, llc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dorkbox.network.connection;
import dorkbox.network.rmi.RemoteObject;
/**
* Supporting methods for RMI connections
*/
public
interface IRmiConnection {
/**
* Used by RMI for the LOCAL side, to get the proxy object as an interface
*
* @param type must be the interface the proxy will bind to
*/
RemoteObject getProxyObject(final int objectID, final Class<?> type);
/**
* This is used by RMI for the REMOTE side, to get the implementation
*/
Object getImplementationObject(final int objectID);
/**
* Used by RMI
*
* @return the registered ID for a specific object. This is used by the "local" side when setting up the to fetch an object for the
* "remote" side for RMI
*/
<T> int getRegisteredId(final T object);
}

View File

@ -36,7 +36,7 @@ import java.io.IOException;
* Nothing in this class is thread safe * Nothing in this class is thread safe
*/ */
public public
class KryoExtra extends Kryo { class KryoExtra<C extends ICryptoConnection> extends Kryo {
/** /**
* bit masks * bit masks
*/ */
@ -53,7 +53,7 @@ class KryoExtra extends Kryo {
private final ByteBufOutput writer = new ByteBufOutput(); private final ByteBufOutput writer = new ByteBufOutput();
// volatile to provide object visibility for entire class // volatile to provide object visibility for entire class
public volatile ConnectionImpl connection; public volatile IRmiConnection connection;
private final GCMBlockCipher aesEngine = new GCMBlockCipher(new AESFastEngine()); private final GCMBlockCipher aesEngine = new GCMBlockCipher(new AESFastEngine());
@ -124,7 +124,7 @@ class KryoExtra extends Kryo {
} }
public synchronized public synchronized
void writeCompressed(final ConnectionImpl connection, final ByteBuf buffer, final Object message) throws IOException { void writeCompressed(final C connection, final ByteBuf buffer, final Object message) throws IOException {
// required by RMI and some serializers to determine which connection wrote (or has info about) this object // required by RMI and some serializers to determine which connection wrote (or has info about) this object
this.connection = connection; this.connection = connection;
@ -217,7 +217,7 @@ class KryoExtra extends Kryo {
} }
public public
Object readCompressed(final ConnectionImpl connection, final ByteBuf buffer, int length) throws IOException { Object readCompressed(final C connection, final ByteBuf buffer, int length) throws IOException {
// required by RMI and some serializers to determine which connection wrote (or has info about) this object // required by RMI and some serializers to determine which connection wrote (or has info about) this object
this.connection = connection; this.connection = connection;
@ -305,7 +305,7 @@ class KryoExtra extends Kryo {
} }
public synchronized public synchronized
void writeCrypto(final ConnectionImpl connection, final ByteBuf buffer, final Object message) throws IOException { void writeCrypto(final C connection, final ByteBuf buffer, final Object message) throws IOException {
// required by RMI and some serializers to determine which connection wrote (or has info about) this object // required by RMI and some serializers to determine which connection wrote (or has info about) this object
this.connection = connection; this.connection = connection;
@ -443,7 +443,7 @@ class KryoExtra extends Kryo {
} }
public public
Object readCrypto(final ConnectionImpl connection, final ByteBuf buffer, int length) throws IOException { Object readCrypto(final C connection, final ByteBuf buffer, int length) throws IOException {
// required by RMI and some serializers to determine which connection wrote (or has info about) this object // required by RMI and some serializers to determine which connection wrote (or has info about) this object
this.connection = connection; this.connection = connection;

View File

@ -38,7 +38,6 @@ import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.Serializer; import com.esotericsoftware.kryo.Serializer;
import com.esotericsoftware.kryo.io.Input; import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output; import com.esotericsoftware.kryo.io.Output;
import dorkbox.network.connection.ConnectionImpl;
import dorkbox.network.connection.KryoExtra; import dorkbox.network.connection.KryoExtra;
/** /**
@ -72,8 +71,6 @@ class RemoteObjectSerializer<T> extends Serializer<T> {
T read(Kryo kryo, Input input, Class type) { T read(Kryo kryo, Input input, Class type) {
KryoExtra kryoExtra = (KryoExtra) kryo; KryoExtra kryoExtra = (KryoExtra) kryo;
int objectID = input.readInt(true); int objectID = input.readInt(true);
return (T) kryoExtra.connection.getProxyObject(objectID, type);
final ConnectionImpl connection = kryoExtra.connection;
return (T) connection.getProxyObject(objectID, type);
} }
} }