diff --git a/src/dorkbox/network/connection/ConnectionImpl.java b/src/dorkbox/network/connection/ConnectionImpl.java index 9f65f4cf..edbc5f73 100644 --- a/src/dorkbox/network/connection/ConnectionImpl.java +++ b/src/dorkbox/network/connection/ConnectionImpl.java @@ -63,7 +63,7 @@ import java.util.concurrent.atomic.AtomicLong; @SuppressWarnings("unused") @Sharable public -class ConnectionImpl extends ChannelInboundHandlerAdapter implements Connection, ListenerBridge, ConnectionBridge { +class ConnectionImpl extends ChannelInboundHandlerAdapter implements ICryptoConnection, Connection, ListenerBridge, ConnectionBridge { 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 * clobber each other */ - final + public final ParametersWithIV getCryptoParameters() { 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 * 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() { 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 int getRegisteredId(final T object) { // 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 */ @@ -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 Object getImplementationObject(final int objectID) { diff --git a/src/dorkbox/network/connection/ICryptoConnection.java b/src/dorkbox/network/connection/ICryptoConnection.java new file mode 100644 index 00000000..f84732c7 --- /dev/null +++ b/src/dorkbox/network/connection/ICryptoConnection.java @@ -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(); +} diff --git a/src/dorkbox/network/connection/IRmiConnection.java b/src/dorkbox/network/connection/IRmiConnection.java new file mode 100644 index 00000000..36b6aa91 --- /dev/null +++ b/src/dorkbox/network/connection/IRmiConnection.java @@ -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 + */ + int getRegisteredId(final T object); +} diff --git a/src/dorkbox/network/connection/KryoExtra.java b/src/dorkbox/network/connection/KryoExtra.java index 1c0b98be..7d4a8a98 100644 --- a/src/dorkbox/network/connection/KryoExtra.java +++ b/src/dorkbox/network/connection/KryoExtra.java @@ -36,7 +36,7 @@ import java.io.IOException; * Nothing in this class is thread safe */ public -class KryoExtra extends Kryo { +class KryoExtra extends Kryo { /** * bit masks */ @@ -53,7 +53,7 @@ class KryoExtra extends Kryo { private final ByteBufOutput writer = new ByteBufOutput(); // volatile to provide object visibility for entire class - public volatile ConnectionImpl connection; + public volatile IRmiConnection connection; private final GCMBlockCipher aesEngine = new GCMBlockCipher(new AESFastEngine()); @@ -124,7 +124,7 @@ class KryoExtra extends Kryo { } 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 this.connection = connection; @@ -217,7 +217,7 @@ class KryoExtra extends Kryo { } 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 this.connection = connection; @@ -305,7 +305,7 @@ class KryoExtra extends Kryo { } 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 this.connection = connection; @@ -443,7 +443,7 @@ class KryoExtra extends Kryo { } 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 this.connection = connection; diff --git a/src/dorkbox/network/rmi/RemoteObjectSerializer.java b/src/dorkbox/network/rmi/RemoteObjectSerializer.java index 8a73fcfb..5f902302 100644 --- a/src/dorkbox/network/rmi/RemoteObjectSerializer.java +++ b/src/dorkbox/network/rmi/RemoteObjectSerializer.java @@ -38,7 +38,6 @@ import com.esotericsoftware.kryo.Kryo; import com.esotericsoftware.kryo.Serializer; import com.esotericsoftware.kryo.io.Input; import com.esotericsoftware.kryo.io.Output; -import dorkbox.network.connection.ConnectionImpl; import dorkbox.network.connection.KryoExtra; /** @@ -72,8 +71,6 @@ class RemoteObjectSerializer extends Serializer { T read(Kryo kryo, Input input, Class type) { KryoExtra kryoExtra = (KryoExtra) kryo; int objectID = input.readInt(true); - - final ConnectionImpl connection = kryoExtra.connection; - return (T) connection.getProxyObject(objectID, type); + return (T) kryoExtra.connection.getProxyObject(objectID, type); } }