RMI proxy objects no longer save "globally", but instead now are saved per connection
This commit is contained in:
parent
779861b072
commit
c117c90ee5
|
@ -30,7 +30,7 @@ import dorkbox.network.connection.UdpMediaDriverConnection
|
||||||
import dorkbox.network.handshake.ClientHandshake
|
import dorkbox.network.handshake.ClientHandshake
|
||||||
import dorkbox.network.rmi.RemoteObject
|
import dorkbox.network.rmi.RemoteObject
|
||||||
import dorkbox.network.rmi.RemoteObjectStorage
|
import dorkbox.network.rmi.RemoteObjectStorage
|
||||||
import dorkbox.network.rmi.RmiManagerForConnections
|
import dorkbox.network.rmi.RmiManagerConnections
|
||||||
import dorkbox.network.rmi.TimeoutException
|
import dorkbox.network.rmi.TimeoutException
|
||||||
import dorkbox.util.exceptions.SecurityException
|
import dorkbox.util.exceptions.SecurityException
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
@ -72,7 +72,7 @@ open class Client<CONNECTION : Connection>(config: Configuration = Configuration
|
||||||
private val previousClosedConnectionActivity: Long = 0
|
private val previousClosedConnectionActivity: Long = 0
|
||||||
|
|
||||||
private val handshake = ClientHandshake(logger, config, crypto, listenerManager)
|
private val handshake = ClientHandshake(logger, config, crypto, listenerManager)
|
||||||
private val rmiConnectionSupport = RmiManagerForConnections(logger, rmiGlobalSupport, serialization, actionDispatch)
|
private val rmiConnectionSupport = RmiManagerConnections(logger, rmiGlobalSupport, serialization, actionDispatch)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
// have to do some basic validation of our configuration
|
// have to do some basic validation of our configuration
|
||||||
|
@ -93,7 +93,7 @@ open class Client<CONNECTION : Connection>(config: Configuration = Configuration
|
||||||
/**
|
/**
|
||||||
* So the client class can get remote objects that are THE SAME OBJECT as if called from a connection
|
* So the client class can get remote objects that are THE SAME OBJECT as if called from a connection
|
||||||
*/
|
*/
|
||||||
override fun getRmiConnectionSupport(): RmiManagerForConnections {
|
override fun getRmiConnectionSupport(): RmiManagerConnections {
|
||||||
return rmiConnectionSupport
|
return rmiConnectionSupport
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,8 +22,8 @@ import dorkbox.network.ServerConfiguration
|
||||||
import dorkbox.network.aeron.CoroutineIdleStrategy
|
import dorkbox.network.aeron.CoroutineIdleStrategy
|
||||||
import dorkbox.network.connection.ping.PingMessage
|
import dorkbox.network.connection.ping.PingMessage
|
||||||
import dorkbox.network.ipFilter.IpFilterRule
|
import dorkbox.network.ipFilter.IpFilterRule
|
||||||
import dorkbox.network.rmi.RmiManagerForConnections
|
import dorkbox.network.rmi.RmiManagerConnections
|
||||||
import dorkbox.network.rmi.RmiMessageManager
|
import dorkbox.network.rmi.RmiManagerGlobal
|
||||||
import dorkbox.network.rmi.messages.RmiMessage
|
import dorkbox.network.rmi.messages.RmiMessage
|
||||||
import dorkbox.network.serialization.KryoExtra
|
import dorkbox.network.serialization.KryoExtra
|
||||||
import dorkbox.network.serialization.NetworkSerializationManager
|
import dorkbox.network.serialization.NetworkSerializationManager
|
||||||
|
@ -133,7 +133,7 @@ internal constructor(val type: Class<*>, internal val config: Configuration) : A
|
||||||
// we only want one instance of these created. These will be called appropriately
|
// we only want one instance of these created. These will be called appropriately
|
||||||
val settingsStore: SettingsStore
|
val settingsStore: SettingsStore
|
||||||
|
|
||||||
internal val rmiGlobalSupport = RmiMessageManager(logger, actionDispatch, config.serialization)
|
internal val rmiGlobalSupport = RmiManagerGlobal(logger, actionDispatch, config.serialization)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
logger.error("NETWORK STACK IS ONLY IPV4 AT THE MOMENT. IPV6 is in progress!")
|
logger.error("NETWORK STACK IS ONLY IPV4 AT THE MOMENT. IPV6 is in progress!")
|
||||||
|
@ -318,8 +318,8 @@ internal constructor(val type: Class<*>, internal val config: Configuration) : A
|
||||||
* Used for the client, because the client only has ONE ever support connection, and it allows us to create connection specific objects
|
* Used for the client, because the client only has ONE ever support connection, and it allows us to create connection specific objects
|
||||||
* from a "global" context
|
* from a "global" context
|
||||||
*/
|
*/
|
||||||
internal open fun getRmiConnectionSupport() : RmiManagerForConnections {
|
internal open fun getRmiConnectionSupport() : RmiManagerConnections {
|
||||||
return RmiManagerForConnections(logger, rmiGlobalSupport, serialization, actionDispatch)
|
return RmiManagerConnections(logger, rmiGlobalSupport, serialization, actionDispatch)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -124,7 +124,7 @@ internal class RmiClient(val isGlobal: Boolean,
|
||||||
// manage all of the RemoteObject proxy methods
|
// manage all of the RemoteObject proxy methods
|
||||||
when (method) {
|
when (method) {
|
||||||
closeMethod -> {
|
closeMethod -> {
|
||||||
rmiObjectCache.removeProxyObject(rmiObjectId)
|
connection.rmiConnectionSupport.removeProxyObject(rmiObjectId)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,14 +20,32 @@ import dorkbox.network.connection.EndPoint
|
||||||
import dorkbox.network.rmi.messages.ConnectionObjectCreateRequest
|
import dorkbox.network.rmi.messages.ConnectionObjectCreateRequest
|
||||||
import dorkbox.network.rmi.messages.ConnectionObjectCreateResponse
|
import dorkbox.network.rmi.messages.ConnectionObjectCreateResponse
|
||||||
import dorkbox.network.serialization.NetworkSerializationManager
|
import dorkbox.network.serialization.NetworkSerializationManager
|
||||||
|
import dorkbox.util.collections.LockFreeIntMap
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import mu.KLogger
|
import mu.KLogger
|
||||||
|
|
||||||
internal class RmiManagerForConnections(logger: KLogger,
|
internal class RmiManagerConnections(logger: KLogger,
|
||||||
val rmiGlobalSupport: RmiMessageManager,
|
val rmiGlobalSupport: RmiManagerGlobal,
|
||||||
private val serialization: NetworkSerializationManager,
|
private val serialization: NetworkSerializationManager,
|
||||||
actionDispatch: CoroutineScope) : RmiObjectCache(logger, actionDispatch) {
|
actionDispatch: CoroutineScope) : RmiObjectCache(logger, actionDispatch) {
|
||||||
|
|
||||||
|
private val proxyObjects = LockFreeIntMap<RemoteObject>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a proxy object from the system
|
||||||
|
*/
|
||||||
|
fun removeProxyObject(rmiId: Int) {
|
||||||
|
proxyObjects.remove(rmiId)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getProxyObject(rmiId: Int): RemoteObject? {
|
||||||
|
return proxyObjects[rmiId]
|
||||||
|
}
|
||||||
|
|
||||||
|
fun saveProxyObject(rmiId: Int, remoteObject: RemoteObject) {
|
||||||
|
proxyObjects.put(rmiId, remoteObject)
|
||||||
|
}
|
||||||
|
|
||||||
private fun <Iface> createProxyObject(isGlobalObject: Boolean,
|
private fun <Iface> createProxyObject(isGlobalObject: Boolean,
|
||||||
connection: Connection,
|
connection: Connection,
|
||||||
endPoint: EndPoint<*>,
|
endPoint: EndPoint<*>,
|
||||||
|
@ -37,7 +55,7 @@ internal class RmiManagerForConnections(logger: KLogger,
|
||||||
// so we can just instantly create the proxy object (or get the cached one)
|
// so we can just instantly create the proxy object (or get the cached one)
|
||||||
var proxyObject = getProxyObject(objectId)
|
var proxyObject = getProxyObject(objectId)
|
||||||
if (proxyObject == null) {
|
if (proxyObject == null) {
|
||||||
proxyObject = RmiMessageManager.createProxyObject(isGlobalObject, connection, serialization, rmiGlobalSupport, endPoint.type.simpleName, objectId, interfaceClass)
|
proxyObject = RmiManagerGlobal.createProxyObject(isGlobalObject, connection, serialization, rmiGlobalSupport, endPoint.type.simpleName, objectId, interfaceClass)
|
||||||
saveProxyObject(objectId, proxyObject)
|
saveProxyObject(objectId, proxyObject)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +113,7 @@ internal class RmiManagerForConnections(logger: KLogger,
|
||||||
// this means we could register this object.
|
// this means we could register this object.
|
||||||
|
|
||||||
// next, scan this object to see if there are any RMI fields
|
// next, scan this object to see if there are any RMI fields
|
||||||
RmiMessageManager.scanImplForRmiFields(logger, implObject) {
|
RmiManagerGlobal.scanImplForRmiFields(logger, implObject) {
|
||||||
saveImplObject(it)
|
saveImplObject(it)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -110,4 +128,9 @@ internal class RmiManagerForConnections(logger: KLogger,
|
||||||
|
|
||||||
connection.send(response)
|
connection.send(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun close() {
|
||||||
|
proxyObjects.clear()
|
||||||
|
super.close()
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -26,17 +26,17 @@ import dorkbox.network.rmi.messages.MethodRequest
|
||||||
import dorkbox.network.rmi.messages.MethodResponse
|
import dorkbox.network.rmi.messages.MethodResponse
|
||||||
import dorkbox.network.serialization.NetworkSerializationManager
|
import dorkbox.network.serialization.NetworkSerializationManager
|
||||||
import dorkbox.util.classes.ClassHelper
|
import dorkbox.util.classes.ClassHelper
|
||||||
|
import dorkbox.util.collections.LockFreeIntMap
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import mu.KLogger
|
import mu.KLogger
|
||||||
import java.lang.reflect.Proxy
|
import java.lang.reflect.Proxy
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
internal class RmiMessageManager(logger: KLogger,
|
internal class RmiManagerGlobal(logger: KLogger,
|
||||||
actionDispatch: CoroutineScope,
|
actionDispatch: CoroutineScope,
|
||||||
internal val serialization: NetworkSerializationManager) : RmiObjectCache(logger, actionDispatch) {
|
internal val serialization: NetworkSerializationManager) : RmiObjectCache(logger, actionDispatch) {
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a proxy object that implements the specified interface, and the methods invoked on the proxy object will be invoked
|
* Returns a proxy object that implements the specified interface, and the methods invoked on the proxy object will be invoked
|
||||||
* remotely.
|
* remotely.
|
||||||
|
@ -74,7 +74,7 @@ internal class RmiMessageManager(logger: KLogger,
|
||||||
// This is the interface inheritance by the proxy object
|
// This is the interface inheritance by the proxy object
|
||||||
val interfaces: Array<Class<*>> = arrayOf(RemoteObject::class.java, interfaceClass)
|
val interfaces: Array<Class<*>> = arrayOf(RemoteObject::class.java, interfaceClass)
|
||||||
|
|
||||||
return Proxy.newProxyInstance(RmiMessageManager::class.java.classLoader, interfaces, proxyObject) as RemoteObject
|
return Proxy.newProxyInstance(RmiManagerGlobal::class.java.classLoader, interfaces, proxyObject) as RemoteObject
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -129,41 +129,9 @@ internal class RmiMessageManager(logger: KLogger,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* called on "client"
|
|
||||||
*/
|
|
||||||
private fun onGenericObjectResponse(endPoint: EndPoint<*>, connection: Connection, logger: KLogger,
|
|
||||||
isGlobal: Boolean, rmiId: Int, callback: suspend (Int, Any) -> Unit,
|
|
||||||
rmiObjectCache: RmiObjectCache, serialization: NetworkSerializationManager) {
|
|
||||||
|
|
||||||
// we only create the proxy + execute the callback if the RMI id is valid!
|
|
||||||
if (rmiId == RemoteObjectStorage.INVALID_RMI) {
|
|
||||||
logger.error {
|
|
||||||
"RMI ID '${rmiId}' is invalid. Unable to create RMI object on server."
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val interfaceClass = ClassHelper.getGenericParameterAsClassForSuperClass(RemoteObjectCallback::class.java, callback.javaClass, 1)
|
private val proxyObjects = LockFreeIntMap<RemoteObject>()
|
||||||
|
|
||||||
// create the client-side proxy object, if possible
|
|
||||||
var proxyObject = rmiObjectCache.getProxyObject(rmiId)
|
|
||||||
if (proxyObject == null) {
|
|
||||||
proxyObject = createProxyObject(isGlobal, connection, serialization, rmiObjectCache, endPoint.type.simpleName, rmiId, interfaceClass)
|
|
||||||
rmiObjectCache.saveProxyObject(rmiId, proxyObject)
|
|
||||||
}
|
|
||||||
|
|
||||||
// this should be executed on a NEW coroutine!
|
|
||||||
endPoint.actionDispatch.launch {
|
|
||||||
try {
|
|
||||||
callback(rmiId, proxyObject)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
logger.error("Error getting or creating the remote object $interfaceClass", e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// this is used for all connection specific ones as well.
|
// this is used for all connection specific ones as well.
|
||||||
private val remoteObjectCreationCallbacks = RemoteObjectStorage(logger)
|
private val remoteObjectCreationCallbacks = RemoteObjectStorage(logger)
|
||||||
|
@ -243,17 +211,52 @@ internal class RmiMessageManager(logger: KLogger,
|
||||||
remoteObjectCreationCallbacks.close()
|
remoteObjectCreationCallbacks.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* called on "client"
|
||||||
|
*/
|
||||||
|
private fun onGenericObjectResponse(endPoint: EndPoint<*>, connection: Connection, logger: KLogger,
|
||||||
|
isGlobal: Boolean, rmiId: Int, callback: suspend (Int, Any) -> Unit,
|
||||||
|
rmiObjectCache: RmiObjectCache, serialization: NetworkSerializationManager) {
|
||||||
|
|
||||||
|
// we only create the proxy + execute the callback if the RMI id is valid!
|
||||||
|
if (rmiId == RemoteObjectStorage.INVALID_RMI) {
|
||||||
|
logger.error {
|
||||||
|
"RMI ID '${rmiId}' is invalid. Unable to create RMI object on server."
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val interfaceClass = ClassHelper.getGenericParameterAsClassForSuperClass(RemoteObjectCallback::class.java, callback.javaClass, 1)
|
||||||
|
|
||||||
|
// create the client-side proxy object, if possible. This MUST be an object that is saved for the connection
|
||||||
|
var proxyObject = connection.rmiConnectionSupport.getProxyObject(rmiId)
|
||||||
|
if (proxyObject == null) {
|
||||||
|
proxyObject = createProxyObject(isGlobal, connection, serialization, rmiObjectCache, endPoint.type.simpleName, rmiId, interfaceClass)
|
||||||
|
connection.rmiConnectionSupport.saveProxyObject(rmiId, proxyObject)
|
||||||
|
}
|
||||||
|
|
||||||
|
// this should be executed on a NEW coroutine!
|
||||||
|
endPoint.actionDispatch.launch {
|
||||||
|
try {
|
||||||
|
callback(rmiId, proxyObject)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logger.error("Error getting or creating the remote object $interfaceClass", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* on the connection+client to get a global remote object (that exists on the server)
|
* on the connection+client to get a global remote object (that exists on the server)
|
||||||
*/
|
*/
|
||||||
fun <Iface> getGlobalRemoteObject(connection: Connection, endPoint: EndPoint<*>, objectId: Int, interfaceClass: Class<Iface>): Iface {
|
fun <Iface> getGlobalRemoteObject(connection: Connection, endPoint: EndPoint<*>, objectId: Int, interfaceClass: Class<Iface>): Iface {
|
||||||
// this immediately returns BECAUSE the object must have already been created on the server (this is why we specify the rmiId)!
|
// this immediately returns BECAUSE the object must have already been created on the server (this is why we specify the rmiId)!
|
||||||
|
|
||||||
// so we can just instantly create the proxy object (or get the cached one)
|
// so we can just instantly create the proxy object (or get the cached one). This MUST be an object that is saved for the connection
|
||||||
var proxyObject = getProxyObject(objectId)
|
var proxyObject = connection.rmiConnectionSupport.getProxyObject(objectId)
|
||||||
if (proxyObject == null) {
|
if (proxyObject == null) {
|
||||||
proxyObject = createProxyObject(true, connection, serialization, this, endPoint.type.simpleName, objectId, interfaceClass)
|
proxyObject = createProxyObject(true, connection, serialization, this, endPoint.type.simpleName, objectId, interfaceClass)
|
||||||
saveProxyObject(objectId, proxyObject)
|
connection.rmiConnectionSupport.saveProxyObject(objectId, proxyObject)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
|
@ -15,7 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package dorkbox.network.rmi
|
package dorkbox.network.rmi
|
||||||
|
|
||||||
import dorkbox.util.collections.LockFreeIntMap
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import mu.KLogger
|
import mu.KLogger
|
||||||
|
|
||||||
|
@ -29,7 +28,6 @@ internal open class RmiObjectCache(logger: KLogger, actionDispatch: CoroutineSco
|
||||||
|
|
||||||
private val responseStorage = RmiResponseManager(logger, actionDispatch)
|
private val responseStorage = RmiResponseManager(logger, actionDispatch)
|
||||||
private val implObjects = RemoteObjectStorage(logger)
|
private val implObjects = RemoteObjectStorage(logger)
|
||||||
private val proxyObjects = LockFreeIntMap<RemoteObject>()
|
|
||||||
|
|
||||||
fun saveImplObject(rmiObject: Any): Int {
|
fun saveImplObject(rmiObject: Any): Int {
|
||||||
return implObjects.register(rmiObject)
|
return implObjects.register(rmiObject)
|
||||||
|
@ -48,21 +46,6 @@ internal open class RmiObjectCache(logger: KLogger, actionDispatch: CoroutineSco
|
||||||
return implObjects.remove(rmiId) as T?
|
return implObjects.remove(rmiId) as T?
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes a proxy object from the system
|
|
||||||
*/
|
|
||||||
fun removeProxyObject(rmiId: Int) {
|
|
||||||
proxyObjects.remove(rmiId)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getProxyObject(rmiId: Int): RemoteObject? {
|
|
||||||
return proxyObjects[rmiId]
|
|
||||||
}
|
|
||||||
|
|
||||||
fun saveProxyObject(rmiId: Int, remoteObject: RemoteObject) {
|
|
||||||
proxyObjects.put(rmiId, remoteObject)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getResponseStorage(): RmiResponseManager {
|
fun getResponseStorage(): RmiResponseManager {
|
||||||
return responseStorage
|
return responseStorage
|
||||||
}
|
}
|
||||||
|
@ -70,6 +53,5 @@ internal open class RmiObjectCache(logger: KLogger, actionDispatch: CoroutineSco
|
||||||
open fun close() {
|
open fun close() {
|
||||||
responseStorage.close()
|
responseStorage.close()
|
||||||
implObjects.close()
|
implObjects.close()
|
||||||
proxyObjects.clear()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user