Code cleanup
This commit is contained in:
parent
c8047987b4
commit
3e9109b4c7
|
@ -16,8 +16,9 @@
|
|||
|
||||
package dorkbox.network.connection
|
||||
|
||||
class DisconnectMessage {
|
||||
class DisconnectMessage(val closeEverything: Boolean) {
|
||||
companion object {
|
||||
val INSTANCE = DisconnectMessage()
|
||||
val CLOSE_FOR_SESSION = DisconnectMessage(false)
|
||||
val CLOSE_EVERYTHING = DisconnectMessage(true)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright 2023 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.streaming
|
||||
|
||||
import com.esotericsoftware.kryo.Kryo
|
||||
import com.esotericsoftware.kryo.Serializer
|
||||
import com.esotericsoftware.kryo.io.Input
|
||||
import com.esotericsoftware.kryo.io.Output
|
||||
|
||||
internal class StreamingControlSerializer: Serializer<StreamingControl>() {
|
||||
override fun write(kryo: Kryo, output: Output, data: StreamingControl) {
|
||||
output.writeByte(data.state.ordinal)
|
||||
output.writeBoolean(data.isFile)
|
||||
output.writeVarInt(data.streamId, true)
|
||||
output.writeVarLong(data.totalSize, true)
|
||||
}
|
||||
|
||||
override fun read(kryo: Kryo, input: Input, type: Class<out StreamingControl>): StreamingControl {
|
||||
val stateOrdinal = input.readByte().toInt()
|
||||
val isFile = input.readBoolean()
|
||||
val state = StreamingState.entries.first { it.ordinal == stateOrdinal }
|
||||
val streamId = input.readVarInt(true)
|
||||
val totalSize = input.readVarLong(true)
|
||||
|
||||
return StreamingControl(state, isFile, streamId, totalSize)
|
||||
}
|
||||
}
|
|
@ -20,26 +20,8 @@ import com.esotericsoftware.kryo.Serializer
|
|||
import com.esotericsoftware.kryo.io.Input
|
||||
import com.esotericsoftware.kryo.io.Output
|
||||
|
||||
class StreamingControlSerializer: Serializer<StreamingControl>() {
|
||||
override fun write(kryo: Kryo, output: Output, data: StreamingControl) {
|
||||
output.writeByte(data.state.ordinal)
|
||||
output.writeBoolean(data.isFile)
|
||||
output.writeVarInt(data.streamId, true)
|
||||
output.writeVarLong(data.totalSize, true)
|
||||
}
|
||||
|
||||
override fun read(kryo: Kryo, input: Input, type: Class<out StreamingControl>): StreamingControl {
|
||||
val stateOrdinal = input.readByte().toInt()
|
||||
val isFile = input.readBoolean()
|
||||
val state = StreamingState.entries.first { it.ordinal == stateOrdinal }
|
||||
val streamId = input.readVarInt(true)
|
||||
val totalSize = input.readVarLong(true)
|
||||
|
||||
return StreamingControl(state, isFile, streamId, totalSize)
|
||||
}
|
||||
}
|
||||
|
||||
class StreamingDataSerializer: Serializer<StreamingData>() {
|
||||
internal class StreamingDataSerializer: Serializer<StreamingData>() {
|
||||
override fun write(kryo: Kryo, output: Output, data: StreamingData) {
|
||||
output.writeVarInt(data.streamId, true)
|
||||
// we re-use this data when streaming data to the remote endpoint, so we don't write out the payload here, we do it in another place
|
|
@ -1,120 +0,0 @@
|
|||
/*
|
||||
* Copyright 2020 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.handshake
|
||||
|
||||
import org.agrona.collections.IntArrayList
|
||||
|
||||
/**
|
||||
* An allocator for port numbers.
|
||||
*
|
||||
* The allocator accepts a base number `p` and a maximum count `n | n > 0`, and will allocate
|
||||
* up to `n` numbers, in a random order, in the range `[p, p + n - 1`.
|
||||
*
|
||||
* @param basePort The base port
|
||||
* @param numberOfPortsToAllocate The maximum number of ports that will be allocated
|
||||
*
|
||||
* @throws IllegalArgumentException If the port range is not valid
|
||||
*/
|
||||
class PortAllocator(basePort: Int, numberOfPortsToAllocate: Int) {
|
||||
private val minPort: Int
|
||||
private val maxPort: Int
|
||||
|
||||
private val portShuffleReset: Int
|
||||
private var portShuffleCount: Int
|
||||
private val freePorts: IntArrayList
|
||||
|
||||
init {
|
||||
if (basePort !in 1..65535) {
|
||||
throw IllegalArgumentException("Base port $basePort must be in the range [1, 65535]")
|
||||
}
|
||||
|
||||
minPort = basePort
|
||||
maxPort = Math.max(basePort+1, basePort + (numberOfPortsToAllocate - 1))
|
||||
|
||||
if (maxPort !in (basePort + 1)..65535) {
|
||||
throw IllegalArgumentException("Uppermost port $maxPort must be in the range [$basePort, 65535]")
|
||||
}
|
||||
|
||||
// every time we add 25% of ports back (via 'free'), reshuffle the ports
|
||||
portShuffleReset = numberOfPortsToAllocate/4
|
||||
portShuffleCount = portShuffleReset
|
||||
|
||||
freePorts = IntArrayList()
|
||||
|
||||
for (port in basePort..maxPort) {
|
||||
freePorts.addInt(port)
|
||||
}
|
||||
|
||||
freePorts.shuffle()
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate `count` number of ports.
|
||||
*
|
||||
* @param count The number of ports that will be allocated
|
||||
*
|
||||
* @return An array of allocated ports
|
||||
*
|
||||
* @throws PortAllocationException If there are fewer than `count` ports available to allocate
|
||||
*/
|
||||
fun allocate(count: Int): IntArray {
|
||||
if (freePorts.size < count) {
|
||||
throw IllegalArgumentException("Too few ports available to allocate $count ports")
|
||||
}
|
||||
|
||||
// reshuffle the ports once we need to re-allocate a new port
|
||||
if (portShuffleCount <= 0) {
|
||||
portShuffleCount = portShuffleReset
|
||||
freePorts.shuffle()
|
||||
}
|
||||
|
||||
val result = IntArray(count)
|
||||
for (index in 0 until count) {
|
||||
val lastValue = freePorts.size - 1
|
||||
val removed = freePorts.removeAt(lastValue)
|
||||
result[index] = removed
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees the given ports. Has no effect if the given port is outside of the range considered by the allocator.
|
||||
*
|
||||
* @param ports The array of ports to free
|
||||
*/
|
||||
fun free(ports: IntArray) {
|
||||
ports.forEach {
|
||||
free(it)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Free a given port.
|
||||
* <p>
|
||||
* Has no effect if the given port is outside of the range considered by the allocator.
|
||||
*
|
||||
* @param port The port
|
||||
*/
|
||||
fun free(port: Int) {
|
||||
if (port in minPort..maxPort) {
|
||||
// add at the end (so we don't have unnecessary array resizes)
|
||||
freePorts.addInt(freePorts.size, port)
|
||||
|
||||
portShuffleCount--
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2020 dorkbox, llc
|
||||
* Copyright 2023 dorkbox, llc
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -21,7 +21,7 @@ import com.esotericsoftware.kryo.io.Input
|
|||
import com.esotericsoftware.kryo.io.Output
|
||||
import kotlin.coroutines.Continuation
|
||||
|
||||
class ContinuationSerializer() : Serializer<Continuation<*>>() {
|
||||
internal class ContinuationSerializer() : Serializer<Continuation<*>>() {
|
||||
init {
|
||||
isImmutable = true
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ import java.lang.reflect.Method
|
|||
* Internal message to invoke methods remotely.
|
||||
*/
|
||||
@Suppress("ConstantConditionIf")
|
||||
class MethodRequestSerializer<CONNECTION: Connection>(private val methodCache: Int2ObjectHashMap<Array<CachedMethod>>) : Serializer<MethodRequest>() {
|
||||
internal class MethodRequestSerializer<CONNECTION: Connection>(private val methodCache: Int2ObjectHashMap<Array<CachedMethod>>) : Serializer<MethodRequest>() {
|
||||
override fun write(kryo: Kryo, output: Output, methodRequest: MethodRequest) {
|
||||
val method = methodRequest.cachedMethod
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2020 dorkbox, llc
|
||||
* Copyright 2023 dorkbox, llc
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -20,7 +20,7 @@ import com.esotericsoftware.kryo.Serializer
|
|||
import com.esotericsoftware.kryo.io.Input
|
||||
import com.esotericsoftware.kryo.io.Output
|
||||
|
||||
class MethodResponseSerializer() : Serializer<MethodResponse>() {
|
||||
internal class MethodResponseSerializer() : Serializer<MethodResponse>() {
|
||||
override fun write(kryo: Kryo, output: Output, response: MethodResponse) {
|
||||
output.writeInt(response.packedId)
|
||||
kryo.writeClassAndObject(output, response.result)
|
||||
|
|
|
@ -56,7 +56,7 @@ import java.lang.reflect.Proxy
|
|||
* If the impl object 'lives' on the SERVER, then the server must tell the client about the iface ID
|
||||
*/
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
class RmiClientSerializer<CONNECTION: Connection>: Serializer<Any>() {
|
||||
internal class RmiClientSerializer<CONNECTION: Connection>: Serializer<Any>() {
|
||||
override fun write(kryo: Kryo, output: Output, proxyObject: Any) {
|
||||
val handler = Proxy.getInvocationHandler(proxyObject) as RmiClient
|
||||
output.writeBoolean(handler.isGlobal)
|
||||
|
|
|
@ -75,7 +75,7 @@ import dorkbox.network.serialization.KryoWriter
|
|||
* If the impl object 'lives' on the SERVER, then the server must tell the client about the iface ID
|
||||
*/
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
class RmiServerSerializer<CONNECTION: Connection> : Serializer<Any>(false) {
|
||||
internal class RmiServerSerializer<CONNECTION: Connection> : Serializer<Any>(false) {
|
||||
|
||||
override fun write(kryo: Kryo, output: Output, `object`: Any) {
|
||||
val kryoExtra = kryo as KryoWriter<CONNECTION>
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright 2023 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.serialization
|
||||
|
||||
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.DisconnectMessage
|
||||
|
||||
internal class DisconnectSerializer: Serializer<DisconnectMessage>() {
|
||||
override fun write(kryo: Kryo, output: Output, `object`: DisconnectMessage) {
|
||||
output.writeBoolean(`object`.closeEverything)
|
||||
}
|
||||
|
||||
override fun read(kryo: Kryo, input: Input, type: Class<out DisconnectMessage>): DisconnectMessage {
|
||||
val closeEverything = input.readBoolean()
|
||||
return if (closeEverything) {
|
||||
DisconnectMessage.CLOSE_EVERYTHING
|
||||
} else {
|
||||
DisconnectMessage.CLOSE_FOR_SESSION
|
||||
}
|
||||
}
|
||||
}
|
|
@ -182,6 +182,7 @@ open class Serialization<CONNECTION: Connection>(private val references: Boolean
|
|||
private val streamingControlSerializer = StreamingControlSerializer()
|
||||
private val streamingDataSerializer = StreamingDataSerializer()
|
||||
private val pingSerializer = PingSerializer()
|
||||
private val disconnectSerializer = DisconnectSerializer()
|
||||
|
||||
internal val fileContentsSerializer = FileContentsSerializer<CONNECTION>()
|
||||
|
||||
|
@ -434,7 +435,7 @@ open class Serialization<CONNECTION: Connection>(private val references: Boolean
|
|||
|
||||
kryo.register(Ping::class.java, pingSerializer)
|
||||
kryo.register(HandshakeMessage::class.java)
|
||||
kryo.register(DisconnectMessage::class.java)
|
||||
kryo.register(DisconnectMessage::class.java, disconnectSerializer)
|
||||
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
|
|
Loading…
Reference in New Issue