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.rmi.RemoteObject
|
||||
import dorkbox.network.rmi.RemoteObjectStorage
|
||||
import dorkbox.network.rmi.RmiManagerForConnections
|
||||
import dorkbox.network.rmi.RmiManagerConnections
|
||||
import dorkbox.network.rmi.TimeoutException
|
||||
import dorkbox.util.exceptions.SecurityException
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -72,7 +72,7 @@ open class Client<CONNECTION : Connection>(config: Configuration = Configuration
|
|||
private val previousClosedConnectionActivity: Long = 0
|
||||
|
||||
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 {
|
||||
// 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
|
||||
*/
|
||||
override fun getRmiConnectionSupport(): RmiManagerForConnections {
|
||||
override fun getRmiConnectionSupport(): RmiManagerConnections {
|
||||
return rmiConnectionSupport
|
||||
}
|
||||
|
||||
|
|
|
@ -22,8 +22,8 @@ import dorkbox.network.ServerConfiguration
|
|||
import dorkbox.network.aeron.CoroutineIdleStrategy
|
||||
import dorkbox.network.connection.ping.PingMessage
|
||||
import dorkbox.network.ipFilter.IpFilterRule
|
||||
import dorkbox.network.rmi.RmiManagerForConnections
|
||||
import dorkbox.network.rmi.RmiMessageManager
|
||||
import dorkbox.network.rmi.RmiManagerConnections
|
||||
import dorkbox.network.rmi.RmiManagerGlobal
|
||||
import dorkbox.network.rmi.messages.RmiMessage
|
||||
import dorkbox.network.serialization.KryoExtra
|
||||
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
|
||||
val settingsStore: SettingsStore
|
||||
|
||||
internal val rmiGlobalSupport = RmiMessageManager(logger, actionDispatch, config.serialization)
|
||||
internal val rmiGlobalSupport = RmiManagerGlobal(logger, actionDispatch, config.serialization)
|
||||
|
||||
init {
|
||||
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
|
||||
* from a "global" context
|
||||
*/
|
||||
internal open fun getRmiConnectionSupport() : RmiManagerForConnections {
|
||||
return RmiManagerForConnections(logger, rmiGlobalSupport, serialization, actionDispatch)
|
||||
internal open fun getRmiConnectionSupport() : RmiManagerConnections {
|
||||
return RmiManagerConnections(logger, rmiGlobalSupport, serialization, actionDispatch)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -124,7 +124,7 @@ internal class RmiClient(val isGlobal: Boolean,
|
|||
// manage all of the RemoteObject proxy methods
|
||||
when (method) {
|
||||
closeMethod -> {
|
||||
rmiObjectCache.removeProxyObject(rmiObjectId)
|
||||
connection.rmiConnectionSupport.removeProxyObject(rmiObjectId)
|
||||
return null
|
||||
}
|
||||
|
||||
|
|
|
@ -20,14 +20,32 @@ import dorkbox.network.connection.EndPoint
|
|||
import dorkbox.network.rmi.messages.ConnectionObjectCreateRequest
|
||||
import dorkbox.network.rmi.messages.ConnectionObjectCreateResponse
|
||||
import dorkbox.network.serialization.NetworkSerializationManager
|
||||
import dorkbox.util.collections.LockFreeIntMap
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import mu.KLogger
|
||||
|
||||
internal class RmiManagerForConnections(logger: KLogger,
|
||||
val rmiGlobalSupport: RmiMessageManager,
|
||||
internal class RmiManagerConnections(logger: KLogger,
|
||||
val rmiGlobalSupport: RmiManagerGlobal,
|
||||
private val serialization: NetworkSerializationManager,
|
||||
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,
|
||||
connection: Connection,
|
||||
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)
|
||||
var proxyObject = getProxyObject(objectId)
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -95,7 +113,7 @@ internal class RmiManagerForConnections(logger: KLogger,
|
|||
// this means we could register this object.
|
||||
|
||||
// next, scan this object to see if there are any RMI fields
|
||||
RmiMessageManager.scanImplForRmiFields(logger, implObject) {
|
||||
RmiManagerGlobal.scanImplForRmiFields(logger, implObject) {
|
||||
saveImplObject(it)
|
||||
}
|
||||
} else {
|
||||
|
@ -110,4 +128,9 @@ internal class RmiManagerForConnections(logger: KLogger,
|
|||
|
||||
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.serialization.NetworkSerializationManager
|
||||
import dorkbox.util.classes.ClassHelper
|
||||
import dorkbox.util.collections.LockFreeIntMap
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import mu.KLogger
|
||||
import java.lang.reflect.Proxy
|
||||
import java.util.*
|
||||
|
||||
internal class RmiMessageManager(logger: KLogger,
|
||||
internal class RmiManagerGlobal(logger: KLogger,
|
||||
actionDispatch: CoroutineScope,
|
||||
internal val serialization: NetworkSerializationManager) : RmiObjectCache(logger, actionDispatch) {
|
||||
companion object {
|
||||
|
||||
/**
|
||||
* Returns a proxy object that implements the specified interface, and the methods invoked on the proxy object will be invoked
|
||||
* remotely.
|
||||
|
@ -74,7 +74,7 @@ internal class RmiMessageManager(logger: KLogger,
|
|||
// This is the interface inheritance by the proxy object
|
||||
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)
|
||||
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private val proxyObjects = LockFreeIntMap<RemoteObject>()
|
||||
|
||||
// this is used for all connection specific ones as well.
|
||||
private val remoteObjectCreationCallbacks = RemoteObjectStorage(logger)
|
||||
|
@ -243,17 +211,52 @@ internal class RmiMessageManager(logger: KLogger,
|
|||
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)
|
||||
*/
|
||||
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)!
|
||||
|
||||
// so we can just instantly create the proxy object (or get the cached one)
|
||||
var proxyObject = getProxyObject(objectId)
|
||||
// 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 = connection.rmiConnectionSupport.getProxyObject(objectId)
|
||||
if (proxyObject == null) {
|
||||
proxyObject = createProxyObject(true, connection, serialization, this, endPoint.type.simpleName, objectId, interfaceClass)
|
||||
saveProxyObject(objectId, proxyObject)
|
||||
connection.rmiConnectionSupport.saveProxyObject(objectId, proxyObject)
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
|
@ -15,7 +15,6 @@
|
|||
*/
|
||||
package dorkbox.network.rmi
|
||||
|
||||
import dorkbox.util.collections.LockFreeIntMap
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import mu.KLogger
|
||||
|
||||
|
@ -29,7 +28,6 @@ internal open class RmiObjectCache(logger: KLogger, actionDispatch: CoroutineSco
|
|||
|
||||
private val responseStorage = RmiResponseManager(logger, actionDispatch)
|
||||
private val implObjects = RemoteObjectStorage(logger)
|
||||
private val proxyObjects = LockFreeIntMap<RemoteObject>()
|
||||
|
||||
fun saveImplObject(rmiObject: Any): Int {
|
||||
return implObjects.register(rmiObject)
|
||||
|
@ -48,21 +46,6 @@ internal open class RmiObjectCache(logger: KLogger, actionDispatch: CoroutineSco
|
|||
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 {
|
||||
return responseStorage
|
||||
}
|
||||
|
@ -70,6 +53,5 @@ internal open class RmiObjectCache(logger: KLogger, actionDispatch: CoroutineSco
|
|||
open fun close() {
|
||||
responseStorage.close()
|
||||
implObjects.close()
|
||||
proxyObjects.clear()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user