Skip to content
Snippets Groups Projects
Verified Commit fd2bd2eb authored by Janne Mareike Koschinski's avatar Janne Mareike Koschinski Committed by Janne Mareike Koschinski
Browse files

Cleanup the modules and improve documentation

parent 7f3268d2
No related branches found
No related tags found
No related merge requests found
Showing
with 65 additions and 520 deletions
......@@ -6,7 +6,7 @@ kotlinBitflagsVersion=1.1.0
sl4jVersion=1.7.30
testcontainersCiVersion=1.1.0
GROUP=de.justjanne.libquassel
VERSION_NAME=0.1.0
VERSION_NAME=0.2.0
POM_URL=https://git.kuschku.de/justJanne/libquassel
POM_SCM_URL=https://git.kuschku.de/justJanne/libquassel
POM_SCM_CONNECTION=scm:git:https://git.kuschku.de/justJanne/libquassel.git
......
......@@ -3,7 +3,7 @@ plugins {
}
dependencies {
api(project(":libquassel-messages"))
api(project(":libquassel-protocol"))
val testcontainersCiVersion: String by project
testImplementation("de.justjanne", "testcontainers-ci", testcontainersCiVersion)
......
......@@ -23,21 +23,21 @@ import de.justjanne.bitflags.of
import de.justjanne.libquassel.client.io.CoroutineChannel
import de.justjanne.libquassel.client.testutil.QuasselCoreContainer
import de.justjanne.libquassel.client.testutil.TestX509TrustManager
import de.justjanne.libquassel.messages.handshake.ClientInitSerializer
import de.justjanne.libquassel.messages.handshake.ClientLoginSerializer
import de.justjanne.libquassel.messages.handshake.CoreSetupDataSerializer
import de.justjanne.libquassel.messages.handshake.HandshakeMessage
import de.justjanne.libquassel.messages.handshake.HandshakeSerializers
import de.justjanne.libquassel.protocol.connection.ConnectionHeader
import de.justjanne.libquassel.protocol.connection.ConnectionHeaderSerializer
import de.justjanne.libquassel.protocol.connection.ClientHeader
import de.justjanne.libquassel.protocol.connection.ClientHeaderSerializer
import de.justjanne.libquassel.protocol.connection.CoreHeaderSerializer
import de.justjanne.libquassel.protocol.connection.ProtocolFeature
import de.justjanne.libquassel.protocol.connection.ProtocolInfoSerializer
import de.justjanne.libquassel.protocol.connection.ProtocolMeta
import de.justjanne.libquassel.protocol.connection.ProtocolVersion
import de.justjanne.libquassel.protocol.features.FeatureSet
import de.justjanne.libquassel.protocol.io.ChainedByteBuffer
import de.justjanne.libquassel.protocol.serializers.HandshakeSerializers
import de.justjanne.libquassel.protocol.serializers.handshake.ClientInitSerializer
import de.justjanne.libquassel.protocol.serializers.handshake.ClientLoginSerializer
import de.justjanne.libquassel.protocol.serializers.handshake.CoreSetupDataSerializer
import de.justjanne.libquassel.protocol.serializers.qt.HandshakeMapSerializer
import de.justjanne.libquassel.protocol.serializers.qt.IntSerializer
import de.justjanne.libquassel.protocol.types.HandshakeMessage
import de.justjanne.libquassel.protocol.variant.into
import de.justjanne.testcontainersci.api.providedContainer
import de.justjanne.testcontainersci.extension.CiContainers
......@@ -80,17 +80,17 @@ class EndToEndTest {
println("Writing protocol")
write(sizePrefix = false) {
ConnectionHeaderSerializer.serialize(
ClientHeaderSerializer.serialize(
it,
ConnectionHeader(
ClientHeader(
features = ProtocolFeature.of(
ProtocolFeature.Compression,
ProtocolFeature.TLS
),
versions = listOf(
ProtocolMeta(
0x0000u,
ProtocolVersion.Datastream,
0x0000u,
),
)
),
......@@ -100,19 +100,19 @@ class EndToEndTest {
println("Reading protocol")
read(4) {
val protocol = ProtocolInfoSerializer.deserialize(it, connectionFeatureSet)
val protocol = CoreHeaderSerializer.deserialize(it, connectionFeatureSet)
assertEquals(
ProtocolFeature.of(
ProtocolFeature.TLS,
ProtocolFeature.Compression
),
protocol.flags
protocol.features
)
println("Negotiated protocol $protocol")
if (protocol.flags.contains(ProtocolFeature.TLS)) {
if (protocol.features.contains(ProtocolFeature.TLS)) {
channel.enableTLS(sslContext)
}
if (protocol.flags.contains(ProtocolFeature.Compression)) {
if (protocol.features.contains(ProtocolFeature.Compression)) {
channel.enableCompression()
}
}
......
plugins {
id("com.vanniktech.maven.publish")
}
dependencies {
api(project(":libquassel-protocol"))
val testcontainersCiVersion: String by project
testImplementation("de.justjanne", "testcontainers-ci", testcontainersCiVersion)
val sl4jVersion: String by project
testImplementation("org.slf4j", "slf4j-simple", sl4jVersion)
}
POM_ARTIFACT_ID=libquassel-messages
POM_NAME=libquassel Messages
POM_DESCRIPTION=Library implementing Quassel's RPC messages for Kotlin
/*
* Quasseldroid - Quassel client for Android
*
* Copyright (c) 2021 Janne Mareike Koschinski
* Copyright (c) 2021 The Quassel Project
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3 as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.justjanne.libquassel.messages.testutil
import java.nio.ByteBuffer
@Suppress("NOTHING_TO_INLINE")
inline fun byteBufferOf(
vararg elements: Byte
): ByteBuffer = ByteBuffer.wrap(byteArrayOf(*elements))
@Suppress("NOTHING_TO_INLINE")
inline fun byteBufferOf(
vararg elements: UByte
): ByteBuffer = ByteBuffer.wrap(ubyteArrayOf(*elements).toByteArray())
@Suppress("NOTHING_TO_INLINE")
inline fun byteBufferOf(): ByteBuffer =
ByteBuffer.allocateDirect(0)
/*
* Quasseldroid - Quassel client for Android
*
* Copyright (c) 2021 Janne Mareike Koschinski
* Copyright (c) 2021 The Quassel Project
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3 as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.justjanne.libquassel.messages.testutil
import de.justjanne.libquassel.messages.handshake.HandshakeSerializer
import de.justjanne.libquassel.protocol.features.FeatureSet
import de.justjanne.libquassel.protocol.serializers.Serializer
import de.justjanne.libquassel.protocol.serializers.qt.HandshakeMapSerializer
import org.hamcrest.Matcher
import org.hamcrest.MatcherAssert.assertThat
import org.junit.jupiter.api.Assertions.assertEquals
import java.nio.ByteBuffer
fun <T> deserialize(
serializer: Serializer<T>,
buffer: ByteBuffer,
featureSet: FeatureSet = FeatureSet.all()
): T {
val result = serializer.deserialize(buffer, featureSet)
assertEquals(0, buffer.remaining())
return result
}
fun <T> testDeserialize(
serializer: HandshakeSerializer<T>,
matcher: Matcher<in T>,
buffer: ByteBuffer,
featureSet: FeatureSet = FeatureSet.all()
) {
val map = deserialize(HandshakeMapSerializer, buffer, featureSet)
val after = serializer.deserialize(map)
assertThat(after, matcher)
}
fun <T> testDeserialize(
serializer: HandshakeSerializer<T>,
data: T,
buffer: ByteBuffer,
featureSet: FeatureSet = FeatureSet.all()
) {
val map = deserialize(HandshakeMapSerializer, buffer, featureSet)
val after = serializer.deserialize(map)
assertEquals(data, after)
}
/*
* Quasseldroid - Quassel client for Android
*
* Copyright (c) 2021 Janne Mareike Koschinski
* Copyright (c) 2021 The Quassel Project
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3 as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.justjanne.libquassel.protocol.testutil.matchers
import org.hamcrest.BaseMatcher
import org.hamcrest.Description
class BomMatcherChar(private val expected: Char) : BaseMatcher<Char>() {
private val malformed = charArrayOf(
'\uFFFE', '\uFEFF', '\uFFFD', ''
)
override fun describeTo(description: Description?) {
description?.appendText(expected.toString())
}
override fun matches(item: Any?): Boolean {
if (item is Char) {
return (item == expected) || (item in malformed && expected in malformed)
}
return false
}
}
/*
* Quasseldroid - Quassel client for Android
*
* Copyright (c) 2021 Janne Mareike Koschinski
* Copyright (c) 2021 The Quassel Project
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3 as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.justjanne.libquassel.protocol.testutil.matchers
import org.hamcrest.BaseMatcher
import org.hamcrest.Description
class BomMatcherString(private val expected: String?) : BaseMatcher<String?>() {
private val malformed = charArrayOf(
'￾', ''
)
override fun describeTo(description: Description?) {
description?.appendText(expected)
}
override fun matches(item: Any?) =
(item as? String)?.endsWith(expected?.trimStart(*malformed) ?: "") == true
}
/*
* Quasseldroid - Quassel client for Android
*
* Copyright (c) 2021 Janne Mareike Koschinski
* Copyright (c) 2021 The Quassel Project
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3 as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.justjanne.libquassel.protocol.testutil.matchers
import de.justjanne.libquassel.protocol.io.contentToString
import de.justjanne.libquassel.protocol.io.isEmpty
import org.hamcrest.BaseMatcher
import org.hamcrest.Description
import java.nio.ByteBuffer
class ByteBufferMatcher(buffer: ByteBuffer?) : BaseMatcher<ByteBuffer>() {
private val expected = buffer?.let { original ->
val copy = ByteBuffer.allocateDirect(original.limit())
original.rewind()
copy.put(original)
copy.rewind()
original.rewind()
copy
}
override fun describeTo(description: Description?) {
description?.appendText(expected?.contentToString())
}
override fun describeMismatch(item: Any?, description: Description?) {
description?.appendText("was ")
description?.appendText((item as? ByteBuffer)?.rewind()?.contentToString())
}
override fun matches(item: Any?): Boolean {
val actual = item as? ByteBuffer
if (actual.isEmpty() && expected.isEmpty()) {
return true
}
return actual?.rewind()?.contentToString() == expected?.rewind()?.contentToString()
}
}
/*
* Quasseldroid - Quassel client for Android
*
* Copyright (c) 2021 Janne Mareike Koschinski
* Copyright (c) 2021 The Quassel Project
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3 as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.justjanne.libquassel.protocol.testutil.matchers
import org.hamcrest.BaseMatcher
import org.hamcrest.Description
class MapMatcher<K, V>(
private val expected: Map<K, V>
) : BaseMatcher<Map<K, V>>() {
override fun describeTo(description: Description?) {
description?.appendText(expected.toString())
}
override fun describeMismatch(item: Any?, description: Description?) {
if (item is Map<*, *>) {
for (key in expected.keys) {
if (!item.containsKey(key)) {
description?.appendText(" did not have key $key")
}
if (expected[key] != item[key]) {
description?.appendText(" key $key was: ${item[key]} instead of ${expected[key]}")
}
}
} else {
description?.appendText("was: $item")
}
}
override fun matches(item: Any?): Boolean {
if (item is Map<*, *>) {
for (key in expected.keys) {
if (!item.containsKey(key)) {
return false
}
if (expected[key] != item[key]) {
return false
}
}
return true
} else {
return false
}
}
}
/*
* Quasseldroid - Quassel client for Android
*
* Copyright (c) 2021 Janne Mareike Koschinski
* Copyright (c) 2021 The Quassel Project
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3 as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.justjanne.libquassel.protocol.testutil.matchers
import org.hamcrest.BaseMatcher
import org.hamcrest.Description
import org.threeten.bp.Instant
import org.threeten.bp.LocalDate
import org.threeten.bp.LocalDateTime
import org.threeten.bp.LocalTime
import org.threeten.bp.OffsetDateTime
import org.threeten.bp.ZonedDateTime
import org.threeten.bp.temporal.Temporal
class TemporalMatcher<T : Temporal>(
private val expected: T
) : BaseMatcher<T>() {
override fun describeTo(description: Description?) {
description?.appendText(expected.toString())
}
override fun matches(item: Any?): Boolean {
return when {
expected is ZonedDateTime && item is ZonedDateTime ->
expected == item
expected is ZonedDateTime && item is OffsetDateTime ->
expected.toOffsetDateTime() == item
expected is OffsetDateTime && item is OffsetDateTime ->
expected == item
expected is LocalDateTime && item is LocalDateTime ->
expected == item
expected is LocalTime && item is LocalTime ->
expected == item
expected is LocalDate && item is LocalDate ->
expected == item
expected is Instant && item is Instant ->
expected == item
else ->
false
}
}
}
/*
* Quasseldroid - Quassel client for Android
*
* Copyright (c) 2021 Janne Mareike Koschinski
* Copyright (c) 2021 The Quassel Project
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3 as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.justjanne.libquassel.messages.testutil
import de.justjanne.libquassel.messages.handshake.HandshakeSerializer
import de.justjanne.libquassel.protocol.features.FeatureSet
import de.justjanne.libquassel.protocol.io.ChainedByteBuffer
import de.justjanne.libquassel.protocol.serializers.Serializer
import de.justjanne.libquassel.protocol.serializers.qt.HandshakeMapSerializer
import de.justjanne.libquassel.protocol.testutil.matchers.ByteBufferMatcher
import org.hamcrest.MatcherAssert.assertThat
import java.nio.ByteBuffer
fun <T> serialize(
serializer: Serializer<T>,
data: T,
featureSet: FeatureSet = FeatureSet.all()
): ByteBuffer {
val buffer = ChainedByteBuffer()
serializer.serialize(buffer, data, featureSet)
return buffer.toBuffer()
}
fun <T> testSerialize(
serializer: HandshakeSerializer<T>,
data: T,
buffer: ByteBuffer,
featureSet: FeatureSet = FeatureSet.all()
) {
val map = serializer.serialize(data)
val after = serialize(HandshakeMapSerializer, map, featureSet)
assertThat(after, ByteBufferMatcher(buffer))
}
-----BEGIN CERTIFICATE-----
MIIFHzCCAwegAwIBAgIUEV/Rf5DceQhjul2yqHDa/ODr5+YwDQYJKoZIhvcNAQEL
BQAwHjEcMBoGA1UEAwwTcXVhc3NlbHRlc3QuaW52YWxpZDAgFw0yMTAyMDgyMzM5
MjRaGA8yMTIxMDExNTIzMzkyNFowHjEcMBoGA1UEAwwTcXVhc3NlbHRlc3QuaW52
YWxpZDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAM2OZTae4BKzppB2
nEF2e2oGLl1YGaCfqaVeQjKNS3DY8fjIG9lb6hDzE1MneoGtou7TafWvqh2u1Q8p
aRNpcW+ftTqcUecGPuMTQHHSWjZJDocvH2vG5xM48u5DqLNUThs7eEoPis7AGpus
7xm8wmjGokKYZb6WdXGLcOEPLb2ZSQH4MRHkAMtM1zF3/L0bYzRLil9+aQ6y0P3/
4hRfUiy5ZkIiPS3+fJPOj/ZaABukLtffWicbeAvNDk7Jp2FvoVfXPXU14CXQaV16
BhfCbWHamUM4d0ZWu85J8Jbon+JRfmIvg+0z4nlZaJ6a23nkO4ljL6IKdwlEUYbM
uZ4bimCxmk2g3t27DxDBYAeudCQYQjvlA7fYf9b2tBjdvVx7BRyFk09Z+zSWKXVx
67iL5nURY8iOY+sHF7t/D/vbDx1/nDkXZPxEl1jZlDnu2xCkM8sYgocXsfjIaW3f
1dcGJ6lr50g69LgTBBuT2Db3Li91nAr3s+V5Urf1CcTMFipNAdeY3qN717LzKsJS
FpjAtvUJQhPin9Is0AZkYCrDxIYZJYgQZaeDCrXRQwoS8qIhXWbgHXRPUTwgGzmS
og62+rfwn3JDRDKOGuiYIc8uhBj0mOOV/GBegFg1cskaX+EMvdurx2jyNc6y1JOG
WJHZ2ctMSHlkm4/vG9lEHoW43HcPAgMBAAGjUzBRMB0GA1UdDgQWBBQ4uKrImjUv
C/TJhb03I3YJEjgjrjAfBgNVHSMEGDAWgBQ4uKrImjUvC/TJhb03I3YJEjgjrjAP
BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4ICAQCMahqY1LVdSny9oc7B
AGET5Y/sTdALZN/GslYWjY9iTNx4kXz6u0654onDTBHZ6c+8+dmZdWFrdPTzJuJX
dB4HqQyY2tLhR3N44F6LRkx97klbvSscMJr3QK4344AtksbEq1BGeDCm5VeaZZJU
A+WSNXjJC22EFR5RLftdArRquJVcwCDPWI1lf/iv/iXJPpv8Mq5qFpY1Agusi/sv
PLO6GVV2qPADoI0NjgYCjJ2VVJQeHasFCC+izihmrTQUMc4G/JF9gHMPOLRofm32
zMQ8LK+iWa9p+VoRbdnsWDw4Fy9s34VXuT5ijAz6KbQ8v9alQv6VfYwnZCrylyKH
K3vWg7g1tlyMZP7ExzHfu428lVmYZbf1k7GUA+2Qu9s/jPfszwQzdDnr5dN9jCUj
CIqLXoHZeyIc2Cxu1KMaZvkPVn2/zJUa3RNLfcl+1pGOCwaUd5lcGtdzrk/9lZwR
zHh9nvQWPAE2r36E7CtOgy0uMIfFdNnDc1iYKU2I9075k+bo7y4zvO9gQx3dmkxU
SCm2sKQzkScSBPtCBtsfKfN4csL5FyLevl7C5izpQqtChqLZu9XXDNVTE7jd48Wy
VrIlBGHwGkksmYUqALI81bvBaOZ1GytAIMbRNQ8YRLIPvjuL/CorfqrR5kEKXqsd
eZw3w5qGASg6Xk0d9OxKyjHKeQ==
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
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
jwfYNzNlv1pDyVGAaI8oMDXRMaZ3
-----END PRIVATE KEY-----
......@@ -19,7 +19,16 @@
package de.justjanne.libquassel.protocol.connection
data class ConnectionHeader(
/**
* Model encapsulating the client side of protocol negotiation
*/
data class ClientHeader(
/**
* Supported protocol features
*/
val features: ProtocolFeatures,
/**
* Supported protocol version/meta pairs
*/
val versions: List<ProtocolMeta>
)
......@@ -28,7 +28,10 @@ import de.justjanne.libquassel.protocol.serializers.qt.UByteSerializer
import de.justjanne.libquassel.protocol.serializers.qt.UIntSerializer
import java.nio.ByteBuffer
object ConnectionHeaderSerializer : Serializer<ConnectionHeader> {
/**
* Serializer for a [ClientHeader]
*/
object ClientHeaderSerializer : Serializer<ClientHeader> {
private const val magic: UInt = 0x42b3_3f00u
private const val featureMask: UInt = 0x0000_00ffu
private const val lastMagic: UByte = 0x80u
......@@ -69,14 +72,14 @@ object ConnectionHeaderSerializer : Serializer<ConnectionHeader> {
return list
}
override fun serialize(buffer: ChainedByteBuffer, data: ConnectionHeader, featureSet: FeatureSet) {
override fun serialize(buffer: ChainedByteBuffer, data: ClientHeader, featureSet: FeatureSet) {
UIntSerializer.serialize(buffer, addMagic(data.features.toBits()), featureSet)
writeList(buffer, data.versions, featureSet) {
ProtocolMetaSerializer.serialize(buffer, it, featureSet)
}
}
override fun deserialize(buffer: ByteBuffer, featureSet: FeatureSet) = ConnectionHeader(
override fun deserialize(buffer: ByteBuffer, featureSet: FeatureSet) = ClientHeader(
features = ProtocolFeature.of(
removeMagic(UIntSerializer.deserialize(buffer, featureSet))
),
......
......@@ -19,7 +19,16 @@
package de.justjanne.libquassel.protocol.connection
data class ProtocolInfo(
val flags: ProtocolFeatures,
val meta: ProtocolMeta,
/**
* Model encapsulating the core side of protocol negotiation
*/
data class CoreHeader(
/**
* Supported protocol features
*/
val features: ProtocolFeatures,
/**
* Chosen protocol version/meta pair
*/
val version: ProtocolMeta,
)
......@@ -27,13 +27,16 @@ import de.justjanne.libquassel.protocol.serializers.Serializer
import de.justjanne.libquassel.protocol.serializers.qt.UByteSerializer
import java.nio.ByteBuffer
object ProtocolInfoSerializer : Serializer<ProtocolInfo> {
override fun serialize(buffer: ChainedByteBuffer, data: ProtocolInfo, featureSet: FeatureSet) {
UByteSerializer.serialize(buffer, data.flags.toBits(), featureSet)
ProtocolMetaSerializer.serialize(buffer, data.meta, featureSet)
/**
* Serializer for a [CoreHeader]
*/
object CoreHeaderSerializer : Serializer<CoreHeader> {
override fun serialize(buffer: ChainedByteBuffer, data: CoreHeader, featureSet: FeatureSet) {
UByteSerializer.serialize(buffer, data.features.toBits(), featureSet)
ProtocolMetaSerializer.serialize(buffer, data.version, featureSet)
}
override fun deserialize(buffer: ByteBuffer, featureSet: FeatureSet) = ProtocolInfo(
override fun deserialize(buffer: ByteBuffer, featureSet: FeatureSet) = CoreHeader(
ProtocolFeature.of(UByteSerializer.deserialize(buffer, featureSet)),
ProtocolMetaSerializer.deserialize(buffer, featureSet)
)
......
......@@ -23,11 +23,19 @@ import de.justjanne.bitflags.Flag
import de.justjanne.bitflags.Flags
import de.justjanne.bitflags.toEnumSet
/**
* Model representing protocol-level features
*/
enum class ProtocolFeature(
override val value: UByte,
) : Flag<UByte> {
None(0x00u),
/**
* Model representing whether TLS is supported
*/
TLS(0x01u),
/**
* Model representing whether DEFLATE compression is supported
*/
Compression(0x02u);
companion object : Flags<UByte, ProtocolFeature> {
......@@ -36,4 +44,7 @@ enum class ProtocolFeature(
}
}
/**
* Model representing a bitfield of [ProtocolFeature] flags
*/
typealias ProtocolFeatures = Set<ProtocolFeature>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment