Commit 18ace6da authored by Daniel Wolf's avatar Daniel Wolf
Browse files

Replace complex types with arrays

By using locking and indices no complex data types are needed.
parent 120885e8
......@@ -31,32 +31,38 @@ import kotlin.concurrent.write
* You can contact the developer at daniel.wolf@frostnerd.com.
*/
class TunnelHandle(var proxy: Proxy?,
private val forwardedPacketStore: ForwardedPacketStore,
class TunnelHandle(proxy: Proxy,
forwardedPacketStore: ForwardedPacketStore,
val trafficStats: TrafficStats) {
private val maxConcurrentAnswerSize = 100
private var forwardedPacketStore:ForwardedPacketStore? = forwardedPacketStore
var proxy: Proxy? = proxy
@Volatile
private var metaIndex = 0
// Writing is adding bytes to send to the device (or polling data), reading are meta
private val meta = SparseArray<Any>()
private val byteOutput = LinkedList<ByteArray>()
private val meta = arrayOfNulls<Any>(maxConcurrentAnswerSize)
private val byteOutput = arrayOfNulls<ByteArray>(maxConcurrentAnswerSize)
@Volatile
private var byteCounter = 0
private var byteReadCounter = 0
@Volatile
private var byteWriteCounter = 0
@Volatile
internal var needsLocking:Boolean = true
fun addMeta(token: DeviceWriteToken, data: Any) {
meta.put(token.hashCode(), data)
meta[token.index] = data
}
fun getMeta(token: DeviceWriteToken): Any? = meta[token.hashCode()]
fun getMetaAndRemove(token: DeviceWriteToken): Any? = meta.let {
val hash = token.hashCode()
val data = it[hash]
it.remove(hash)
data
fun getMeta(token: DeviceWriteToken): Any? = meta[token.index]
fun getMetaAndRemove(token: DeviceWriteToken): Any? {
val data = meta[token.index]
meta[token.index] = null
return data
}
fun removeMeta(token: DeviceWriteToken) {
val hash = token.hashCode()
meta.remove(hash)
meta[token.index] = null
}
fun protectSocket(socket: DatagramSocket) {
......@@ -75,59 +81,56 @@ class TunnelHandle(var proxy: Proxy?,
if(bytes.isNotEmpty()) {
if(needsLocking) {
synchronized(byteOutput) {
byteOutput.add(bytes)
byteCounter++
byteOutput[byteWriteCounter++ % maxConcurrentAnswerSize] = bytes
}
} else {
byteOutput.add(bytes)
byteCounter++
byteOutput[byteWriteCounter++ % maxConcurrentAnswerSize] = bytes
}
trafficStats.packetsQueuedToDevice++
trafficStats.bytesQueuedToDevice += bytes.size
}
}
fun hasDataForDevice():Boolean = byteCounter > 0
fun hasDataForDevice():Boolean = byteReadCounter != byteWriteCounter
internal fun pollBytesToDevice():ByteArray? {
return if(needsLocking) {
synchronized(byteOutput) {
byteCounter--
byteOutput.poll()
byteOutput[byteReadCounter++ % maxConcurrentAnswerSize]
}
} else {
byteCounter--
byteOutput.poll()
byteOutput[byteReadCounter++ % maxConcurrentAnswerSize]
}
}
fun readInTheFuture(token: DeviceWriteToken, socket: java.io.Closeable) {
forwardedPacketStore.addForwardedQuestion(token, socket)
forwardedPacketStore?.addForwardedQuestion(token, socket)
trafficStats.openSockets++
trafficStats.totalSockets++
}
fun addForwardedPacket(futureAnswer: FutureAnswer) {
forwardedPacketStore.addForwardedQuestion(futureAnswer)
forwardedPacketStore?.addForwardedQuestion(futureAnswer)
trafficStats.openSockets++
trafficStats.totalSockets++
}
fun cleanupReceivedAnswer(futureAnswer: FutureAnswer) {
forwardedPacketStore.cleanup(futureAnswer)
forwardedPacketStore?.cleanup(futureAnswer)
removeMeta(futureAnswer.deviceWriteToken)
trafficStats.openSockets--
}
fun issueDeviceWriteToken(): DeviceWriteToken {
return DeviceWriteToken()
return DeviceWriteToken(metaIndex++ % maxConcurrentAnswerSize)
}
fun clear(stop: Boolean = true) {
if (stop) proxy = null
meta.clear()
byteOutput.clear()
if (stop) {
proxy = null
forwardedPacketStore = null
}
}
}
class DeviceWriteToken internal constructor()
class DeviceWriteToken internal constructor(internal val index:Int)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment