Code cleanup

This commit is contained in:
Robinson 2023-09-21 11:22:36 +02:00
parent c8047987b4
commit 3e9109b4c7
No known key found for this signature in database
GPG Key ID: 8E7DB78588BD6F5C
11 changed files with 92 additions and 149 deletions

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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

View File

@ -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--
}
}
}

View File

@ -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
}

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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>

View File

@ -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
}
}
}

View File

@ -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")