Skip to content
Snippets Groups Projects
Commit 3c641a0d authored by Janne Mareike Koschinski's avatar Janne Mareike Koschinski
Browse files

Implement extended features

parent 7b10813d
No related branches found
No related tags found
No related merge requests found
Showing
with 105 additions and 97 deletions
......@@ -5,7 +5,11 @@ import android.arch.lifecycle.Observer
import android.content.*
import android.net.ConnectivityManager
import android.os.Binder
import de.kuschku.libquassel.protocol.*
import de.kuschku.libquassel.protocol.ClientData
import de.kuschku.libquassel.protocol.Protocol
import de.kuschku.libquassel.protocol.Protocol_Feature
import de.kuschku.libquassel.protocol.Protocol_Features
import de.kuschku.libquassel.quassel.QuasselFeatures
import de.kuschku.libquassel.session.*
import de.kuschku.quasseldroid.BuildConfig
import de.kuschku.quasseldroid.Keys
......@@ -272,7 +276,7 @@ class QuasselService : DaggerLifecycleService(),
clientData = ClientData(
identifier = "${resources.getString(R.string.app_name)} ${BuildConfig.VERSION_NAME}",
buildDate = Instant.ofEpochSecond(BuildConfig.GIT_COMMIT_DATE),
clientFeatures = Quassel_Features.of(*Quassel_Feature.validValues),
clientFeatures = QuasselFeatures.all(),
protocolFeatures = Protocol_Features.of(
Protocol_Feature.Compression,
Protocol_Feature.TLS
......
package de.kuschku.libquassel.protocol
import de.kuschku.libquassel.quassel.QuasselFeatures
import org.threeten.bp.Instant
data class ClientData(
val identifier: String,
val buildDate: Instant,
val clientFeatures: Quassel_Features,
val clientFeatures: QuasselFeatures,
val protocolFeatures: Protocol_Features,
val supportedProtocols: List<Protocol>
)
......@@ -40,6 +40,7 @@ class Message(
override val NONE = MessageType.of()
override fun of(bit: Int) = Flags.of<MessageType>(bit)
override fun of(vararg flags: MessageType) = Flags.of(*flags)
override fun of(flags: Iterable<MessageType>) = Flags.of(flags)
}
}
......@@ -54,6 +55,7 @@ class Message(
override val NONE = MessageFlag.of()
override fun of(bit: Int) = Flags.of<MessageFlag>(bit)
override fun of(vararg flags: MessageFlag) = Flags.of(*flags)
override fun of(flags: Iterable<MessageFlag>) = Flags.of(flags)
}
}
......
......@@ -2,8 +2,8 @@ package de.kuschku.libquassel.protocol
import de.kuschku.libquassel.protocol.primitive.serializer.StringSerializer
import de.kuschku.libquassel.quassel.BufferInfo
import de.kuschku.libquassel.quassel.LegacyFeature
import de.kuschku.libquassel.quassel.ProtocolFeature
import de.kuschku.libquassel.quassel.QuasselFeature
import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork
import de.kuschku.libquassel.util.Flags
import de.kuschku.libquassel.util.ShortFlags
......@@ -27,8 +27,8 @@ typealias Message_Types = Flags<Message_Type>
typealias Message_Flag = Message.MessageFlag
typealias Message_Flags = Flags<Message_Flag>
typealias Quassel_Feature = QuasselFeature
typealias Quassel_Features = Flags<Quassel_Feature>
typealias Legacy_Feature = LegacyFeature
typealias Legacy_Features = Flags<Legacy_Feature>
typealias Protocol_Feature = ProtocolFeature
typealias Protocol_Features = Flags<Protocol_Feature>
......
......@@ -12,13 +12,15 @@ object ClientInitAckSerializer : HandshakeMessageSerializer<HandshakeMessage.Cli
"CoreFeatures" to QVariant_(data.coreFeatures?.toInt(), Type.UInt),
"StorageBackends" to QVariant_(data.backendInfo, Type.QVariantList),
"Authenticator" to QVariant_(data.authenticatorInfo, Type.QVariantList),
"Configured" to QVariant_(data.coreConfigured, Type.Bool)
"Configured" to QVariant_(data.coreConfigured, Type.Bool),
"FeatureList" to QVariant_(data.featureList, Type.QStringList)
)
override fun deserialize(data: QVariantMap) = HandshakeMessage.ClientInitAck(
coreFeatures = Flags.Companion.of(data["CoreFeatures"].value(0)),
backendInfo = data["StorageBackends"].value(),
authenticatorInfo = data["Authenticators"].value(),
coreConfigured = data["Configured"].value()
coreConfigured = data["Configured"].value(),
featureList = data["FeatureList"].value(emptyList())
)
}
......@@ -11,12 +11,14 @@ object ClientInitSerializer : HandshakeMessageSerializer<HandshakeMessage.Client
"MsgType" to QVariant_("ClientInit", Type.QString),
"ClientVersion" to QVariant_(data.clientVersion, Type.QString),
"ClientDate" to QVariant_(data.buildDate, Type.QString),
"Features" to QVariant_(data.clientFeatures?.toInt(), Type.UInt)
"Features" to QVariant_(data.clientFeatures?.toInt(), Type.UInt),
"FeatureList" to QVariant_(data.featureList, Type.QStringList)
)
override fun deserialize(data: QVariantMap) = HandshakeMessage.ClientInit(
clientVersion = data["ClientVersion"].value(),
buildDate = data["ClientDate"].value(),
clientFeatures = Flags.of(data["Features"].value(0))
clientFeatures = Flags.of(data["Features"].value(0)),
featureList = data["FeatureList"].value(emptyList())
)
}
package de.kuschku.libquassel.protocol.message
import de.kuschku.libquassel.protocol.Legacy_Features
import de.kuschku.libquassel.protocol.QVariantList
import de.kuschku.libquassel.protocol.QVariantMap
import de.kuschku.libquassel.protocol.Quassel_Features
import de.kuschku.libquassel.protocol.value
sealed class HandshakeMessage {
class ClientInit(val clientVersion: String?, val buildDate: String?,
val clientFeatures: Quassel_Features?) : HandshakeMessage() {
class ClientInit(
val clientVersion: String?, val buildDate: String?,
val clientFeatures: Legacy_Features?, val featureList: List<String>
) : HandshakeMessage() {
override fun toString(): String {
return "ClientInit(clientVersion=$clientVersion, buildDate=$buildDate, clientFeatures=$clientFeatures)"
return "ClientInit(clientVersion=$clientVersion, buildDate=$buildDate, clientFeatures=$clientFeatures, featureList=$featureList)"
}
}
......@@ -20,11 +22,13 @@ sealed class HandshakeMessage {
}
}
class ClientInitAck(val coreFeatures: Quassel_Features?, val coreConfigured: Boolean?,
val backendInfo: QVariantList?,
val authenticatorInfo: QVariantList?) : HandshakeMessage() {
class ClientInitAck(
val coreFeatures: Legacy_Features?, val coreConfigured: Boolean?,
val backendInfo: QVariantList?, val authenticatorInfo: QVariantList?,
val featureList: List<String>
) : HandshakeMessage() {
override fun toString(): String {
return "ClientInitAck(coreFeatures=$coreFeatures, coreConfigured=$coreConfigured, backendInfo=$backendInfo, authenticatorInfo=$authenticatorInfo)"
return "ClientInitAck(coreFeatures=$coreFeatures, coreConfigured=$coreConfigured, backendInfo=$backendInfo, authenticatorInfo=$authenticatorInfo, featureList=$featureList)"
}
}
......
package de.kuschku.libquassel.protocol.primitive.serializer
import de.kuschku.libquassel.protocol.Quassel_Features
import de.kuschku.libquassel.quassel.QuasselFeatures
import de.kuschku.libquassel.util.nio.ChainedByteBuffer
import java.nio.ByteBuffer
object BoolSerializer : Serializer<Boolean> {
override fun serialize(buffer: ChainedByteBuffer, data: Boolean,
features: Quassel_Features) = buffer.put(
if (data) {
0x01
} else {
0x00
}.toByte()
)
override fun serialize(buffer: ChainedByteBuffer, data: Boolean, features: QuasselFeatures) =
buffer.put((if (data) 0x01 else 0x00).toByte())
override fun deserialize(buffer: ByteBuffer,
features: Quassel_Features) = buffer.get() != 0x00.toByte()
override fun deserialize(buffer: ByteBuffer, features: QuasselFeatures) =
buffer.get() != 0x00.toByte()
}
package de.kuschku.libquassel.protocol.primitive.serializer
import de.kuschku.libquassel.protocol.Buffer_Type
import de.kuschku.libquassel.protocol.Quassel_Features
import de.kuschku.libquassel.quassel.BufferInfo
import de.kuschku.libquassel.quassel.QuasselFeatures
import de.kuschku.libquassel.util.nio.ChainedByteBuffer
import java.nio.ByteBuffer
object BufferInfoSerializer : Serializer<BufferInfo> {
override fun serialize(buffer: ChainedByteBuffer, data: BufferInfo, features: Quassel_Features) {
override fun serialize(buffer: ChainedByteBuffer, data: BufferInfo, features: QuasselFeatures) {
IntSerializer.serialize(buffer, data.bufferId, features)
IntSerializer.serialize(buffer, data.networkId, features)
ShortSerializer.serialize(buffer, data.type.toShort(), features)
......@@ -15,7 +15,7 @@ object BufferInfoSerializer : Serializer<BufferInfo> {
StringSerializer.UTF8.serialize(buffer, data.bufferName, features)
}
override fun deserialize(buffer: ByteBuffer, features: Quassel_Features): BufferInfo {
override fun deserialize(buffer: ByteBuffer, features: QuasselFeatures): BufferInfo {
val bufferId = IntSerializer.deserialize(buffer, features)
val networkId = IntSerializer.deserialize(buffer, features)
val type = Buffer_Type.of(ShortSerializer.deserialize(buffer, features))
......
package de.kuschku.libquassel.protocol.primitive.serializer
import de.kuschku.libquassel.protocol.Quassel_Features
import de.kuschku.libquassel.quassel.QuasselFeatures
import de.kuschku.libquassel.util.nio.ChainedByteBuffer
import java.nio.ByteBuffer
object ByteArraySerializer : Serializer<ByteBuffer?> {
override fun serialize(buffer: ChainedByteBuffer, data: ByteBuffer?, features: Quassel_Features) {
override fun serialize(buffer: ChainedByteBuffer, data: ByteBuffer?, features: QuasselFeatures) {
if (data == null) {
IntSerializer.serialize(buffer, -1, features)
} else {
......@@ -14,7 +14,7 @@ object ByteArraySerializer : Serializer<ByteBuffer?> {
}
}
override fun deserialize(buffer: ByteBuffer, features: Quassel_Features): ByteBuffer? {
override fun deserialize(buffer: ByteBuffer, features: QuasselFeatures): ByteBuffer? {
val len = IntSerializer.deserialize(buffer, features)
return if (len == -1) {
null
......
package de.kuschku.libquassel.protocol.primitive.serializer
import de.kuschku.libquassel.protocol.Quassel_Features
import de.kuschku.libquassel.quassel.QuasselFeatures
import de.kuschku.libquassel.util.nio.ChainedByteBuffer
import java.nio.ByteBuffer
object ByteSerializer : Serializer<Byte> {
override fun serialize(buffer: ChainedByteBuffer, data: Byte, features: Quassel_Features) {
override fun serialize(buffer: ChainedByteBuffer, data: Byte, features: QuasselFeatures) {
buffer.put(data)
}
override fun deserialize(buffer: ByteBuffer, features: Quassel_Features): Byte {
override fun deserialize(buffer: ByteBuffer, features: QuasselFeatures): Byte {
return buffer.get()
}
}
package de.kuschku.libquassel.protocol.primitive.serializer
import de.kuschku.libquassel.protocol.Quassel_Features
import de.kuschku.libquassel.quassel.QuasselFeatures
import de.kuschku.libquassel.util.nio.ChainedByteBuffer
import java.nio.ByteBuffer
import java.nio.CharBuffer
object CharSerializer : Serializer<Char> {
private val byteBuffer = ByteBuffer.allocateDirect(2)
private val charBuffer = CharBuffer.allocate(1)
private val byteBufferIn = ByteBuffer.allocateDirect(2)
private val byteBufferOut = ByteBuffer.allocateDirect(2)
private val charBufferIn = CharBuffer.allocate(1)
private val charBufferOut = CharBuffer.allocate(1)
private val encoder = Charsets.UTF_16BE.newEncoder()
private val decoder = Charsets.UTF_16BE.newDecoder()
override fun serialize(buffer: ChainedByteBuffer, data: Char, features: Quassel_Features) {
synchronized(this) {
charBuffer.clear()
charBuffer.put(data)
charBuffer.flip()
byteBuffer.clear()
encoder.encode(charBuffer, byteBuffer, true)
byteBuffer.flip()
if (byteBuffer.remaining() == 2) {
buffer.put(byteBuffer)
override fun serialize(buffer: ChainedByteBuffer, data: Char, features: QuasselFeatures) {
charBufferIn.clear()
charBufferIn.put(data)
charBufferIn.flip()
byteBufferIn.clear()
encoder.encode(charBufferIn, byteBufferIn, true)
byteBufferIn.flip()
if (byteBufferIn.remaining() == 2) {
buffer.put(byteBufferIn)
} else {
buffer.putShort(0)
}
}
}
override fun deserialize(buffer: ByteBuffer, features: Quassel_Features): Char {
synchronized(this) {
byteBuffer.clear()
byteBuffer.putShort(buffer.short)
byteBuffer.flip()
charBuffer.clear()
decoder.decode(byteBuffer, charBuffer, true)
charBuffer.flip()
return if (charBuffer.remaining() == 1)
charBuffer.get()
override fun deserialize(buffer: ByteBuffer, features: QuasselFeatures): Char {
byteBufferOut.clear()
byteBufferOut.putShort(buffer.short)
byteBufferOut.flip()
charBufferOut.clear()
decoder.decode(byteBufferOut, charBufferOut, true)
charBufferOut.flip()
return if (charBufferOut.remaining() == 1)
charBufferOut.get()
else
'\u0000'
}
}
}
package de.kuschku.libquassel.protocol.primitive.serializer
import de.kuschku.libquassel.protocol.Quassel_Features
import de.kuschku.libquassel.quassel.QuasselFeatures
import de.kuschku.libquassel.util.nio.ChainedByteBuffer
import org.threeten.bp.*
import org.threeten.bp.temporal.ChronoField
......@@ -21,7 +21,7 @@ object DateTimeSerializer : Serializer<Temporal> {
}
}
override fun serialize(buffer: ChainedByteBuffer, data: Temporal, features: Quassel_Features) {
override fun serialize(buffer: ChainedByteBuffer, data: Temporal, features: QuasselFeatures) {
when (data) {
is LocalDateTime -> {
IntSerializer.serialize(buffer, data.getLong(JulianFields.JULIAN_DAY).toInt(), features)
......@@ -53,7 +53,7 @@ object DateTimeSerializer : Serializer<Temporal> {
}
}
override fun deserialize(buffer: ByteBuffer, features: Quassel_Features): Temporal {
override fun deserialize(buffer: ByteBuffer, features: QuasselFeatures): Temporal {
val julianDay = IntSerializer.deserialize(buffer, features).toLong()
val milliOfDay = IntSerializer.deserialize(buffer, features).toLong()
val timeSpec = TimeSpec.of(ByteSerializer.deserialize(buffer, features))
......
package de.kuschku.libquassel.protocol.primitive.serializer
import de.kuschku.libquassel.protocol.Quassel_Features
import de.kuschku.libquassel.quassel.QuasselFeatures
import de.kuschku.libquassel.quassel.syncables.interfaces.IDccConfig
import de.kuschku.libquassel.util.nio.ChainedByteBuffer
import java.nio.ByteBuffer
object DccConfig_IpDetectionModeSerializer : Serializer<IDccConfig.IpDetectionMode> {
override fun serialize(buffer: ChainedByteBuffer, data: IDccConfig.IpDetectionMode,
features: Quassel_Features) {
features: QuasselFeatures) {
buffer.put(data.value)
}
override fun deserialize(buffer: ByteBuffer,
features: Quassel_Features): IDccConfig.IpDetectionMode {
features: QuasselFeatures): IDccConfig.IpDetectionMode {
return IDccConfig.IpDetectionMode.of(buffer.get())
}
}
package de.kuschku.libquassel.protocol.primitive.serializer
import de.kuschku.libquassel.protocol.Quassel_Features
import de.kuschku.libquassel.quassel.QuasselFeatures
import de.kuschku.libquassel.quassel.syncables.interfaces.IDccConfig
import de.kuschku.libquassel.util.nio.ChainedByteBuffer
import java.nio.ByteBuffer
object DccConfig_PortSelectionModeSerializer : Serializer<IDccConfig.PortSelectionMode> {
override fun serialize(buffer: ChainedByteBuffer, data: IDccConfig.PortSelectionMode,
features: Quassel_Features) {
features: QuasselFeatures) {
buffer.put(data.value)
}
override fun deserialize(buffer: ByteBuffer,
features: Quassel_Features): IDccConfig.PortSelectionMode {
features: QuasselFeatures): IDccConfig.PortSelectionMode {
return IDccConfig.PortSelectionMode.of(buffer.get())
}
}
package de.kuschku.libquassel.protocol.primitive.serializer
import de.kuschku.libquassel.protocol.*
import de.kuschku.libquassel.protocol.QVariantMap
import de.kuschku.libquassel.protocol.QVariant_
import de.kuschku.libquassel.protocol.Type
import de.kuschku.libquassel.protocol.value
import de.kuschku.libquassel.quassel.QuasselFeatures
import de.kuschku.libquassel.util.nio.ChainedByteBuffer
import java.nio.ByteBuffer
object HandshakeVariantMapSerializer : Serializer<QVariantMap> {
override fun serialize(buffer: ChainedByteBuffer, data: QVariantMap, features: Quassel_Features) {
override fun serialize(buffer: ChainedByteBuffer, data: QVariantMap, features: QuasselFeatures) {
IntSerializer.serialize(buffer, data.size * 2, features)
data.entries.forEach { (key, value) ->
VariantSerializer.serialize(buffer, QVariant_(key, Type.QString), features)
......@@ -13,7 +17,7 @@ object HandshakeVariantMapSerializer : Serializer<QVariantMap> {
}
}
override fun deserialize(buffer: ByteBuffer, features: Quassel_Features): QVariantMap {
override fun deserialize(buffer: ByteBuffer, features: QuasselFeatures): QVariantMap {
val range = 0 until IntSerializer.deserialize(buffer, features) / 2
val pairs = range.map {
val keyRaw: ByteBuffer? = VariantSerializer.deserialize(buffer, features).value()
......
package de.kuschku.libquassel.protocol.primitive.serializer
import de.kuschku.libquassel.protocol.NetworkLayerProtocol
import de.kuschku.libquassel.protocol.Quassel_Features
import de.kuschku.libquassel.quassel.QuasselFeatures
import de.kuschku.libquassel.util.nio.ChainedByteBuffer
import java.net.Inet4Address
import java.net.Inet6Address
......@@ -9,7 +9,7 @@ import java.net.InetAddress
import java.nio.ByteBuffer
object HostAddressSerializer : Serializer<InetAddress> {
override fun serialize(buffer: ChainedByteBuffer, data: InetAddress, features: Quassel_Features) {
override fun serialize(buffer: ChainedByteBuffer, data: InetAddress, features: QuasselFeatures) {
when (data) {
is Inet4Address -> {
ByteSerializer.serialize(buffer, NetworkLayerProtocol.IPv4Protocol.value, features)
......@@ -29,7 +29,7 @@ object HostAddressSerializer : Serializer<InetAddress> {
}
}
override fun deserialize(buffer: ByteBuffer, features: Quassel_Features): InetAddress {
override fun deserialize(buffer: ByteBuffer, features: QuasselFeatures): InetAddress {
val type = ByteSerializer.deserialize(buffer, features)
return when (NetworkLayerProtocol.of(type)) {
NetworkLayerProtocol.IPv4Protocol -> {
......
package de.kuschku.libquassel.protocol.primitive.serializer
import de.kuschku.libquassel.protocol.Quassel_Features
import de.kuschku.libquassel.quassel.QuasselFeatures
import de.kuschku.libquassel.util.nio.ChainedByteBuffer
import java.nio.ByteBuffer
object IntSerializer : Serializer<Int> {
override fun serialize(buffer: ChainedByteBuffer, data: Int, features: Quassel_Features) {
override fun serialize(buffer: ChainedByteBuffer, data: Int, features: QuasselFeatures) {
buffer.putInt(data)
}
override fun deserialize(buffer: ByteBuffer, features: Quassel_Features): Int {
override fun deserialize(buffer: ByteBuffer, features: QuasselFeatures): Int {
return buffer.int
}
}
package de.kuschku.libquassel.protocol.primitive.serializer
import de.kuschku.libquassel.protocol.Quassel_Features
import de.kuschku.libquassel.quassel.QuasselFeatures
import de.kuschku.libquassel.util.nio.ChainedByteBuffer
import java.nio.ByteBuffer
object LongSerializer : Serializer<Long> {
override fun serialize(buffer: ChainedByteBuffer, data: Long, features: Quassel_Features) {
override fun serialize(buffer: ChainedByteBuffer, data: Long, features: QuasselFeatures) {
buffer.putLong(data)
}
override fun deserialize(buffer: ByteBuffer, features: Quassel_Features): Long {
override fun deserialize(buffer: ByteBuffer, features: QuasselFeatures): Long {
return buffer.long
}
}
package de.kuschku.libquassel.protocol.primitive.serializer
import de.kuschku.libquassel.protocol.Message
import de.kuschku.libquassel.protocol.Quassel_Features
import de.kuschku.libquassel.quassel.QuasselFeature
import de.kuschku.libquassel.util.hasFlag
import de.kuschku.libquassel.quassel.ExtendedFeature
import de.kuschku.libquassel.quassel.QuasselFeatures
import de.kuschku.libquassel.util.nio.ChainedByteBuffer
import org.threeten.bp.Instant
import java.nio.ByteBuffer
object MessageSerializer : Serializer<Message> {
override fun serialize(buffer: ChainedByteBuffer, data: Message,
features: Quassel_Features) {
override fun serialize(buffer: ChainedByteBuffer, data: Message, features: QuasselFeatures) {
IntSerializer.serialize(buffer, data.messageId, features)
IntSerializer.serialize(buffer, data.time.epochSecond.toInt(), features)
IntSerializer.serialize(buffer, data.type.toInt(), features)
ByteSerializer.serialize(buffer, data.flag.toByte(), features)
BufferInfoSerializer.serialize(buffer, data.bufferInfo, features)
StringSerializer.UTF8.serialize(buffer, data.sender, features)
if (features.hasFlag(QuasselFeature.SenderPrefixes))
if (features.hasFeature(ExtendedFeature.SenderPrefixes))
StringSerializer.UTF8.serialize(buffer, data.senderPrefixes, features)
StringSerializer.UTF8.serialize(buffer, data.content, features)
}
override fun deserialize(buffer: ByteBuffer,
features: Quassel_Features): Message {
override fun deserialize(buffer: ByteBuffer, features: QuasselFeatures): Message {
return Message(
messageId = IntSerializer.deserialize(buffer, features),
time = Instant.ofEpochSecond(IntSerializer.deserialize(buffer, features).toLong()),
......@@ -33,7 +30,7 @@ object MessageSerializer : Serializer<Message> {
),
bufferInfo = BufferInfoSerializer.deserialize(buffer, features),
sender = StringSerializer.UTF8.deserialize(buffer, features) ?: "",
senderPrefixes = if (features.hasFlag(QuasselFeature.SenderPrefixes))
senderPrefixes = if (features.hasFeature(ExtendedFeature.SenderPrefixes))
StringSerializer.UTF8.deserialize(buffer, features) ?: "" else "",
content = StringSerializer.UTF8.deserialize(buffer, features) ?: ""
)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment